🤖 ci: unify :main and release image builds via goreleaser #480
Workflow file for this run
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| name: CI | |
| on: | |
| pull_request: | |
| merge_group: | |
| types: [checks_requested] | |
| push: | |
| branches: | |
| - main | |
| permissions: | |
| contents: read | |
| jobs: | |
| changes: | |
| name: Detect changed paths | |
| runs-on: depot-ubuntu-24.04 | |
| permissions: | |
| contents: read | |
| pull-requests: read | |
| outputs: | |
| go: ${{ steps.merge_group_defaults.outputs.go || steps.filter.outputs.go }} | |
| workflows: ${{ steps.merge_group_defaults.outputs.workflows || steps.filter.outputs.workflows }} | |
| publish: ${{ steps.merge_group_defaults.outputs.publish || steps.filter.outputs.publish }} | |
| terraform: ${{ steps.merge_group_defaults.outputs.terraform || steps.filter.outputs.terraform }} | |
| steps: | |
| - name: Checkout | |
| uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4.3.1 | |
| with: | |
| # Required so paths-filter can diff push events using github.event.before without fetching. | |
| fetch-depth: 0 | |
| persist-credentials: false | |
| - name: Set merge-group defaults | |
| if: github.event_name == 'merge_group' | |
| id: merge_group_defaults | |
| run: | | |
| { | |
| echo "go=true" | |
| echo "workflows=true" | |
| echo "publish=false" | |
| echo "terraform=true" | |
| } >> "$GITHUB_OUTPUT" | |
| - name: Detect changed paths | |
| if: github.event_name != 'merge_group' | |
| id: filter | |
| uses: dorny/paths-filter@de90cc6fb38fc0963ad72b210f1f284cd68cea36 # v3.0.2 | |
| with: | |
| filters: | | |
| go: | |
| - '**/*.go' | |
| - 'go.mod' | |
| - 'go.sum' | |
| - 'vendor/**' | |
| - 'Makefile' | |
| - '.golangci.yml' | |
| - '.golangci.yaml' | |
| - 'hack/update-reference-docs.sh' | |
| - 'hack/crd-ref-docs/**' | |
| - 'docs/reference/api/**' | |
| workflows: | |
| - '.github/workflows/**' | |
| - '.github/actionlint.yaml' | |
| - '.github/actionlint.yml' | |
| publish: | |
| - '**/*.go' | |
| - 'go.mod' | |
| - 'go.sum' | |
| - 'vendor/**' | |
| - '.goreleaser.yaml' | |
| - 'Dockerfile*' | |
| - 'Dockerfile.goreleaser' | |
| terraform: | |
| - 'terraform/**' | |
| - '.github/workflows/ci.yaml' | |
| lint: | |
| needs: changes | |
| if: github.event_name == 'merge_group' || (needs.changes.outputs.go == 'true' && (github.event_name != 'push' || github.actor != 'github-merge-queue[bot]')) | |
| runs-on: depot-ubuntu-24.04-8 | |
| timeout-minutes: 20 | |
| env: | |
| GOFLAGS: -mod=vendor | |
| steps: | |
| - name: Checkout | |
| uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4.3.1 | |
| with: | |
| persist-credentials: false | |
| - name: Set up Go | |
| uses: actions/setup-go@40f1582b2485089dde7abd97c1529aa768e1baff # v5.6.0 | |
| with: | |
| go-version-file: go.mod | |
| cache: true | |
| - name: Verify vendor is up to date | |
| run: | | |
| go mod tidy | |
| go mod vendor | |
| git diff --exit-code -- go.mod go.sum vendor/ | |
| - name: Verify API reference docs are up to date | |
| run: | | |
| bash ./hack/update-reference-docs.sh | |
| git diff --exit-code -- docs/reference/api/ | |
| - name: Run golangci-lint | |
| run: go tool golangci-lint run --timeout=5m ./... | |
| - name: Run golangci-lint formatter checks | |
| run: go tool golangci-lint fmt --diff | |
| - name: Run govulncheck | |
| run: go tool govulncheck ./... | |
| scan-fs: | |
| name: Trivy filesystem scan | |
| needs: changes | |
| if: github.event_name == 'merge_group' || ((needs.changes.outputs.go == 'true' || needs.changes.outputs.workflows == 'true') && (github.event_name != 'push' || github.actor != 'github-merge-queue[bot]')) | |
| runs-on: depot-ubuntu-24.04-8 | |
| timeout-minutes: 20 | |
| permissions: | |
| contents: read | |
| steps: | |
| - name: Checkout | |
| uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4.3.1 | |
| with: | |
| persist-credentials: false | |
| - name: Trivy filesystem scan | |
| uses: aquasecurity/trivy-action@b6643a29fecd7f34b3597bc6acb0a98b03d33ff8 # v0.33.1 | |
| with: | |
| scan-type: fs | |
| scan-ref: . | |
| skip-dirs: vendor | |
| severity: HIGH,CRITICAL | |
| exit-code: '1' | |
| test: | |
| needs: changes | |
| if: github.event_name == 'merge_group' || (needs.changes.outputs.go == 'true' && (github.event_name != 'push' || github.actor != 'github-merge-queue[bot]')) | |
| runs-on: depot-ubuntu-24.04-8 | |
| timeout-minutes: 30 | |
| steps: | |
| - name: Checkout | |
| uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4.3.1 | |
| with: | |
| persist-credentials: false | |
| - name: Setup Go | |
| uses: actions/setup-go@40f1582b2485089dde7abd97c1529aa768e1baff # v5.6.0 | |
| with: | |
| go-version-file: go.mod | |
| cache: true | |
| - name: Verify vendor is up to date | |
| run: | | |
| go mod tidy | |
| go mod vendor | |
| git diff --exit-code -- go.mod go.sum vendor/ | |
| - name: Setup envtest assets | |
| env: | |
| GOFLAGS: -mod=vendor | |
| run: | | |
| KUBEBUILDER_ASSETS_PATH="$(go run ./vendor/sigs.k8s.io/controller-runtime/tools/setup-envtest use 1.35.x --bin-dir "${{ github.workspace }}/bin/envtest" -p path)" | |
| echo "KUBEBUILDER_ASSETS=${KUBEBUILDER_ASSETS_PATH}" >> "$GITHUB_ENV" | |
| - name: Run tests | |
| env: | |
| GOFLAGS: -mod=vendor | |
| KUBEBUILDER_ASSETS: ${{ env.KUBEBUILDER_ASSETS }} | |
| run: go test ./... -count=1 | |
| - name: Build | |
| env: | |
| GOFLAGS: -mod=vendor | |
| run: go build ./... | |
| e2e-kind: | |
| name: E2E (Kind + CNPG + Templates) | |
| needs: [changes, test] | |
| if: needs.changes.outputs.go == 'true' && (github.event_name != 'push' || github.actor != 'github-merge-queue[bot]') | |
| runs-on: depot-ubuntu-24.04-8 | |
| timeout-minutes: 45 | |
| steps: | |
| # ---- PR fast-path: skip heavy E2E on pull requests ---- | |
| - name: Skip full E2E on pull requests | |
| if: github.event_name == 'pull_request' | |
| run: | | |
| echo "::notice::Skipping full E2E on ${GITHUB_EVENT_NAME}; runs in merge queue and on push to main." | |
| # ---- Full CNPG + Templates E2E (merge queue + push) ---- | |
| - name: Checkout | |
| if: github.event_name != 'pull_request' | |
| uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4.3.1 | |
| with: | |
| persist-credentials: false | |
| - name: Setup Go | |
| if: github.event_name != 'pull_request' | |
| uses: actions/setup-go@40f1582b2485089dde7abd97c1529aa768e1baff # v5.6.0 | |
| with: | |
| go-version-file: go.mod | |
| cache: true | |
| - name: Create Kind cluster | |
| if: github.event_name != 'pull_request' | |
| uses: helm/kind-action@a1b0e391336a6ee6713a0583f8c6240d70863de3 # v1.12.0 | |
| with: | |
| cluster_name: e2e | |
| - name: Build binary | |
| if: github.event_name != 'pull_request' | |
| env: | |
| GOFLAGS: -mod=vendor | |
| CGO_ENABLED: "0" | |
| GOOS: linux | |
| GOARCH: amd64 | |
| run: | | |
| mkdir -p linux/amd64 | |
| go build -o linux/amd64/coder-k8s ./ | |
| - name: Build and load image | |
| if: github.event_name != 'pull_request' | |
| run: | | |
| docker build -f Dockerfile.goreleaser -t ghcr.io/coder/coder-k8s:e2e . | |
| kind load docker-image ghcr.io/coder/coder-k8s:e2e --name e2e | |
| - name: Apply namespace, CRDs, and RBAC | |
| if: github.event_name != 'pull_request' | |
| run: | | |
| kubectl apply -f config/e2e/namespace.yaml | |
| kubectl apply -f config/crd/bases/ | |
| kubectl apply -f config/rbac/ | |
| - name: Enable aggregated API server | |
| if: github.event_name != 'pull_request' | |
| run: | | |
| kubectl apply -f deploy/apiserver-service.yaml | |
| kubectl apply -f deploy/apiserver-apiservice.yaml | |
| - name: Deploy coder-k8s (controller + aggregated API server) | |
| if: github.event_name != 'pull_request' | |
| run: kubectl apply -f config/e2e/deployment.yaml | |
| - name: Wait for operator and APIService | |
| if: github.event_name != 'pull_request' | |
| run: | | |
| kubectl wait --for=condition=Available deploy/coder-k8s -n coder-system --timeout=120s | |
| kubectl wait --for=condition=Available apiservice/v1alpha1.aggregation.coder.com --timeout=180s | |
| - name: Install CloudNativePG operator | |
| if: github.event_name != 'pull_request' | |
| run: | | |
| kubectl apply --server-side -f https://raw.githubusercontent.com/cloudnative-pg/cloudnative-pg/v1.25.0/releases/cnpg-1.25.0.yaml | |
| kubectl wait --for=condition=Available deploy/cnpg-controller-manager -n cnpg-system --timeout=180s | |
| - name: Provision PostgreSQL and CoderControlPlane | |
| if: github.event_name != 'pull_request' | |
| run: kubectl apply -f examples/cloudnativepg/ | |
| - name: Wait for PostgreSQL | |
| if: github.event_name != 'pull_request' | |
| run: kubectl -n coder wait --for=condition=Ready cluster/coder-db --timeout=600s | |
| - name: Wait for Coder deployment | |
| if: github.event_name != 'pull_request' | |
| run: kubectl -n coder rollout status deployment/coder --timeout=600s | |
| - name: Wait for CoderControlPlane readiness | |
| if: github.event_name != 'pull_request' | |
| run: | | |
| kubectl -n coder wait --for=jsonpath='{.status.phase}'=Ready codercontrolplane/coder --timeout=600s | |
| kubectl -n coder wait --for=jsonpath='{.status.operatorAccessReady}'=true codercontrolplane/coder --timeout=600s | |
| - name: Verify operator token secret | |
| if: github.event_name != 'pull_request' | |
| run: | | |
| TOKEN_SECRET=$(kubectl -n coder get codercontrolplane coder -o jsonpath='{.status.operatorTokenSecretRef.name}') | |
| test -n "$TOKEN_SECRET" | |
| kubectl -n coder get secret "$TOKEN_SECRET" | |
| - name: Create CoderTemplate via kubectl | |
| if: github.event_name != 'pull_request' | |
| run: kubectl apply -f config/e2e/codertemplate.yaml | |
| - name: Verify CoderTemplate exists | |
| if: github.event_name != 'pull_request' | |
| run: | | |
| kubectl -n coder get codertemplates | |
| kubectl -n coder get codertemplate default.e2e-template -o yaml | |
| # ---- Failure diagnostics ---- | |
| - name: Dump cluster state on failure | |
| if: failure() && github.event_name != 'pull_request' | |
| run: | | |
| echo "=== Pods (all namespaces) ===" | |
| kubectl get pods -A || true | |
| echo "" | |
| echo "=== APIService ===" | |
| kubectl describe apiservice v1alpha1.aggregation.coder.com || true | |
| echo "" | |
| echo "=== coder-k8s logs ===" | |
| kubectl -n coder-system logs deploy/coder-k8s --tail=200 || true | |
| echo "" | |
| echo "=== CoderControlPlane ===" | |
| kubectl -n coder describe codercontrolplane coder || true | |
| echo "" | |
| echo "=== Coder deployment logs ===" | |
| kubectl -n coder logs deploy/coder --tail=200 || true | |
| echo "" | |
| echo "=== CNPG controller logs ===" | |
| kubectl -n cnpg-system logs deploy/cnpg-controller-manager --tail=200 || true | |
| image-scan: | |
| name: Trivy image scan | |
| needs: changes | |
| if: github.event_name == 'merge_group' || (needs.changes.outputs.publish == 'true' && (github.event_name != 'push' || github.actor != 'github-merge-queue[bot]')) | |
| runs-on: depot-ubuntu-24.04-8 | |
| timeout-minutes: 20 | |
| steps: | |
| - name: Checkout | |
| uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4.3.1 | |
| with: | |
| persist-credentials: false | |
| - name: Setup Go | |
| uses: actions/setup-go@40f1582b2485089dde7abd97c1529aa768e1baff # v5.6.0 | |
| with: | |
| go-version-file: go.mod | |
| cache: true | |
| - name: Build linux/amd64 binary for image | |
| env: | |
| GOFLAGS: -mod=vendor | |
| CGO_ENABLED: "0" | |
| GOOS: linux | |
| GOARCH: amd64 | |
| run: | | |
| mkdir -p linux/amd64 | |
| go build -o linux/amd64/coder-k8s ./ | |
| - name: Build local image | |
| run: docker build -f Dockerfile.goreleaser -t coder-k8s:scan . | |
| - name: Trivy image scan | |
| uses: aquasecurity/trivy-action@b6643a29fecd7f34b3597bc6acb0a98b03d33ff8 # v0.33.1 | |
| with: | |
| scan-type: image | |
| image-ref: coder-k8s:scan | |
| severity: HIGH,CRITICAL | |
| exit-code: '1' | |
| terraform: | |
| name: Terraform (fmt/validate/tflint/trivy) | |
| needs: changes | |
| if: github.event_name == 'merge_group' || (needs.changes.outputs.terraform == 'true' && (github.event_name != 'push' || github.actor != 'github-merge-queue[bot]')) | |
| runs-on: depot-ubuntu-24.04 | |
| timeout-minutes: 20 | |
| permissions: | |
| contents: read | |
| steps: | |
| - name: Checkout | |
| uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4.3.1 | |
| with: | |
| persist-credentials: false | |
| - name: Setup Terraform | |
| uses: hashicorp/setup-terraform@b9cd54a3c349d3f38e8881555d616ced269862dd # v3.1.2 | |
| with: | |
| terraform_version: 1.14.4 | |
| - name: terraform fmt (check) | |
| working-directory: terraform | |
| run: terraform fmt -check -diff -recursive | |
| - name: terraform init (backend disabled) | |
| working-directory: terraform | |
| run: terraform init -backend=false -lockfile=readonly -input=false | |
| - name: terraform validate | |
| working-directory: terraform | |
| run: terraform validate -no-color | |
| - name: Setup TFLint | |
| uses: terraform-linters/setup-tflint@4cb9feea73331a35b422df102992a03a44a3bb33 # v6.2.1 | |
| with: | |
| tflint_version: v0.61.0 | |
| - name: tflint | |
| working-directory: terraform | |
| run: | | |
| tflint --init | |
| tflint --recursive | |
| - name: Trivy config scan (Terraform) | |
| uses: aquasecurity/trivy-action@b6643a29fecd7f34b3597bc6acb0a98b03d33ff8 # v0.33.1 | |
| with: | |
| scan-type: config | |
| scan-ref: terraform/ | |
| trivyignores: terraform/.trivyignore | |
| severity: HIGH,CRITICAL | |
| exit-code: '1' | |
| lint-actions: | |
| name: Lint GitHub Actions | |
| needs: changes | |
| if: github.event_name == 'merge_group' || (needs.changes.outputs.workflows == 'true' && (github.event_name != 'push' || github.actor != 'github-merge-queue[bot]')) | |
| runs-on: depot-ubuntu-24.04 | |
| permissions: | |
| contents: read | |
| env: | |
| GOFLAGS: -mod=vendor | |
| steps: | |
| - name: Checkout | |
| uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4.3.1 | |
| with: | |
| persist-credentials: false | |
| - name: Setup Go | |
| uses: actions/setup-go@40f1582b2485089dde7abd97c1529aa768e1baff # v5.6.0 | |
| with: | |
| go-version-file: go.mod | |
| cache: true | |
| - name: Run actionlint | |
| run: go tool actionlint | |
| - name: Run zizmor | |
| uses: zizmorcore/zizmor-action@0dce2577a4760a2749d8cfb7a84b7d5585ebcb7d # v0.5.0 | |
| with: | |
| advanced-security: false | |
| online-audits: false | |
| inputs: .github/workflows | |
| codex-comments: | |
| name: Codex Comments | |
| if: github.event_name == 'pull_request' | |
| runs-on: depot-ubuntu-24.04 | |
| permissions: | |
| contents: read | |
| pull-requests: read | |
| steps: | |
| - name: Checkout | |
| uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4.3.1 | |
| with: | |
| fetch-depth: 0 | |
| persist-credentials: false | |
| - name: Check unresolved Codex comments | |
| env: | |
| GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} | |
| run: ./scripts/check_codex_comments.sh ${{ github.event.pull_request.number }} | |
| publish-main: | |
| name: Publish GHCR :main | |
| needs: [changes, test, lint, scan-fs, lint-actions, e2e-kind, image-scan, terraform] | |
| if: | | |
| always() && | |
| github.event_name == 'push' && | |
| github.ref == 'refs/heads/main' && | |
| needs.changes.outputs.publish == 'true' && | |
| (needs.test.result == 'success' || needs.test.result == 'skipped') && | |
| (needs.lint.result == 'success' || needs.lint.result == 'skipped') && | |
| (needs.scan-fs.result == 'success' || needs.scan-fs.result == 'skipped') && | |
| (needs.lint-actions.result == 'success' || needs.lint-actions.result == 'skipped') && | |
| (needs.e2e-kind.result == 'success' || needs.e2e-kind.result == 'skipped') && | |
| (needs.image-scan.result == 'success' || needs.image-scan.result == 'skipped') && | |
| (needs.terraform.result == 'success' || needs.terraform.result == 'skipped') | |
| runs-on: depot-ubuntu-24.04-8 | |
| timeout-minutes: 30 | |
| permissions: | |
| contents: read | |
| packages: write | |
| steps: | |
| - name: Checkout | |
| uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4.3.1 | |
| with: | |
| fetch-depth: 0 | |
| persist-credentials: false | |
| - name: Setup Go | |
| uses: actions/setup-go@40f1582b2485089dde7abd97c1529aa768e1baff # v5.6.0 | |
| with: | |
| go-version-file: go.mod | |
| cache: false | |
| - name: Set up Docker Buildx | |
| uses: docker/setup-buildx-action@8d2750c68a42422c14e847fe6c8ac0403b4cbd6f # v3.12.0 | |
| - name: Log in to GitHub Container Registry | |
| uses: docker/login-action@c94ce9fb468520275223c153574b00df6fe4bcc9 # v3.7.0 | |
| with: | |
| registry: ghcr.io | |
| username: ${{ github.actor }} | |
| password: ${{ secrets.GITHUB_TOKEN }} | |
| - name: Run GoReleaser (:main) | |
| uses: goreleaser/goreleaser-action@e435ccd777264be153ace6237001ef4d979d3a7a # v6.4.0 | |
| with: | |
| distribution: goreleaser | |
| version: "~> v2" | |
| args: release --clean --skip=announce | |
| env: | |
| GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} | |
| GORELEASER_CURRENT_TAG: v0.0.0-main | |
| GORELEASER_CHANNEL: main | |
| - name: Trivy image scan (:main) | |
| uses: aquasecurity/trivy-action@b6643a29fecd7f34b3597bc6acb0a98b03d33ff8 # v0.33.1 | |
| with: | |
| scan-type: image | |
| image-ref: ghcr.io/coder/coder-k8s:main | |
| severity: HIGH,CRITICAL | |
| exit-code: '1' |