name: Release # Checkout, interpolation and caching conventions match ci.yaml -- see the header there # for why there are no JS actions and why every `${{ }}` goes through `env:`. on: push: tags: - 'v*' workflow_dispatch: # A tag is not normally re-pushed, so this mostly matters when one is force-moved during # a botched release -- the superseded run stops holding runner slots. concurrency: group: release-${{ github.ref }} cancel-in-progress: true env: REPO_URL: https://git.ryuvia.com/niklas/terdut-operator.git REGISTRY: git.ryuvia.com IMAGE: git.ryuvia.com/niklas/terdut-operator jobs: # Gates every publishing job below. A tag that fails here publishes nothing: the # image and the chart are both downstream of it. No Postgres service, unlike # terdut-server's: this suite drives envtest (a fake API server), not a real database. test: runs-on: ubuntu-latest container: image: golang:1.26.6-bookworm volumes: - go-mod-cache:/go/pkg/mod - go-build-cache:/root/.cache/go-build - gobin-cache:/go/bin steps: - name: Checkout env: REF_NAME: ${{ github.ref_name }} run: git clone --depth=1 --branch "$REF_NAME" "$REPO_URL" . - name: Format, lint and test run: make fmt lint test # Host mode on purpose (no `container:`): this is the only context with a Docker CLI # pointed at the dind daemon. A `container:` job would sit on the dind bridge with no # docker socket at all -- same reason terdut-server's image job runs on the host. image: needs: test runs-on: ubuntu-latest steps: - name: Checkout env: REF_NAME: ${{ github.ref_name }} run: git clone --depth=1 --branch "$REF_NAME" "$REPO_URL" . - name: Log in to the registry env: TOKEN: ${{ secrets.REGISTRY_TOKEN }} run: echo "$TOKEN" | docker login "$REGISTRY" -u niklas --password-stdin # buildx setup, the platform list and why there is no QEMU all live on the `push` # target now, so the same command publishes from a laptop and from here. - name: Build and push env: REF_NAME: ${{ github.ref_name }} run: make push VERSION="$REF_NAME" # Also host mode: helm is baked into the runner image, and a `container:` job could # not install it -- get.helm.sh is unreachable from the dind bridge. chart: needs: test runs-on: ubuntu-latest steps: - name: Checkout env: REF_NAME: ${{ github.ref_name }} run: git clone --depth=1 --branch "$REF_NAME" "$REPO_URL" . # One publisher, triggered by the tag -- same reasoning as terdut-server's own # chart job: a workflow triggered by the main push cannot know the version it is # about to be tagged with, so there is no second publisher racing this one. - name: Refuse a non-version tag env: REF_NAME: ${{ github.ref_name }} run: | set -eu if ! echo "$REF_NAME" | grep -qE '^v[0-9]'; then echo "::error::refusing to publish a chart for non-version tag ${REF_NAME}" exit 1 fi # Render before publishing, so a template that does not compile is found here, # not by Flux after the chart is already in the registry. - name: Lint and render the chart run: make helm-lint - name: Package and push env: REF_NAME: ${{ github.ref_name }} TOKEN: ${{ secrets.REGISTRY_TOKEN }} run: | set -eu echo "$TOKEN" | helm registry login "$REGISTRY" -u niklas --password-stdin make helm-package helm-push VERSION="$REF_NAME" # Host mode, like image and chart: this needs a docker daemon to run trivy in, and a # `container:` job would sit on the dind bridge with none. # # Scans the pushed image, not a local one -- trivy cannot read a locally built image # on this runner (no docker socket in a container job, no shared filesystem with the # dind sidecar), so it pulls from the registry. Runs after `image` rather than gating # it: a red scan does not unpublish anything -- it means do not bump the wrapper # chart in Ryuvia/charts to this version. This pipeline does not deploy. scan-image: needs: image runs-on: ubuntu-latest steps: - name: Checkout env: REF_NAME: ${{ github.ref_name }} run: git clone --depth=1 --branch "$REF_NAME" "$REPO_URL" . - name: Scan the pushed image (trivy) env: TRIVY_USERNAME: niklas TRIVY_PASSWORD: ${{ secrets.REGISTRY_TOKEN }} REF_NAME: ${{ github.ref_name }} run: make security-image VERSION="$REF_NAME"