ci: re-trigger (scale-set confirmed healthy via write-olt probe) #83
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 | |
| # Smart quality + security gate. PRs run the fast gate (lint / test / vuln); | |
| # pushes to main and version tags additionally build, scan (Trivy), and — on | |
| # tags — keyless-sign a multi-arch image to GHCR + DockerHub. A helm chart is | |
| # published to GitHub Pages from main. | |
| on: | |
| push: | |
| branches: [main] | |
| tags: ["v*.*.*"] | |
| pull_request: | |
| branches: [main] | |
| workflow_dispatch: | |
| concurrency: | |
| group: ci-${{ github.ref }} | |
| cancel-in-progress: true | |
| permissions: | |
| contents: read | |
| env: | |
| GO_VERSION: "1.26" | |
| GHCR_REGISTRY: ghcr.io | |
| IMAGE_NAME: ${{ github.repository }} | |
| jobs: | |
| # ======================================================================== | |
| # Lint — gofmt, go vet, golangci-lint (built with the runner's toolchain so | |
| # it is never "older than the targeted Go version" in go.mod). | |
| # ======================================================================== | |
| lint: | |
| name: Lint | |
| runs-on: k3s-ckt-runner | |
| steps: | |
| - uses: actions/checkout@v6 | |
| - uses: actions/setup-go@v6 | |
| with: | |
| go-version: ${{ env.GO_VERSION }} | |
| cache-dependency-path: go.sum | |
| - name: gofmt | |
| run: | | |
| unformatted=$(gofmt -l .) | |
| if [ -n "$unformatted" ]; then | |
| echo "::error::Not gofmt-formatted:"; echo "$unformatted"; exit 1 | |
| fi | |
| - name: go vet | |
| run: go vet ./... | |
| - name: golangci-lint | |
| run: | | |
| go install github.com/golangci/golangci-lint/v2/cmd/golangci-lint@v2.11.4 | |
| "$(go env GOPATH)/bin/golangci-lint" run --timeout=5m | |
| # ======================================================================== | |
| # Test — race detector + atomic coverage, uploaded to Codecov. | |
| # ======================================================================== | |
| test: | |
| name: Test | |
| runs-on: k3s-ckt-runner | |
| steps: | |
| - uses: actions/checkout@v6 | |
| - uses: actions/setup-go@v6 | |
| with: | |
| go-version: ${{ env.GO_VERSION }} | |
| cache-dependency-path: go.sum | |
| - run: go mod download | |
| - name: Install C toolchain (for -race / CGO) | |
| run: sudo apt-get update && sudo apt-get install -y --no-install-recommends gcc libc6-dev | |
| - name: test (race + coverage) | |
| run: go test -race -covermode=atomic -coverprofile=coverage.out -count=1 ./... | |
| - name: Upload coverage to Codecov | |
| uses: codecov/codecov-action@v5 | |
| env: | |
| CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }} | |
| with: | |
| files: ./coverage.out | |
| flags: unittests | |
| name: snmp-olt-zte | |
| fail_ci_if_error: false | |
| # ======================================================================== | |
| # Vuln — govulncheck against the toolchain pinned in go.mod, so reachable | |
| # stdlib CVEs fail the build. | |
| # ======================================================================== | |
| vuln: | |
| name: Govulncheck | |
| runs-on: k3s-ckt-runner | |
| steps: | |
| - uses: actions/checkout@v6 | |
| - uses: actions/setup-go@v6 | |
| with: | |
| go-version: ${{ env.GO_VERSION }} | |
| cache-dependency-path: go.sum | |
| - name: govulncheck | |
| run: | | |
| go install golang.org/x/vuln/cmd/govulncheck@latest | |
| "$(go env GOPATH)/bin/govulncheck" ./... | |
| # ======================================================================== | |
| # Image — multi-arch build → GHCR + DockerHub, Trivy scan (SARIF best-effort | |
| # to the Security tab), and keyless cosign signing on version tags. | |
| # Runs only on push to main / tags (never on PRs). | |
| # ======================================================================== | |
| image: | |
| name: Build, Scan & Sign Image | |
| runs-on: k3s-ckt-runner | |
| needs: [lint, test, vuln] | |
| if: github.event_name == 'push' && (github.ref == 'refs/heads/main' || startsWith(github.ref, 'refs/tags/v')) | |
| permissions: | |
| contents: read | |
| actions: read # codeql-action/upload-sarif needs this on private repos | |
| packages: write | |
| security-events: write | |
| id-token: write # keyless cosign (OIDC) | |
| steps: | |
| - uses: actions/checkout@v6 | |
| - name: Set up QEMU | |
| uses: docker/setup-qemu-action@v3 | |
| - name: Set up Buildx | |
| uses: docker/setup-buildx-action@v4 | |
| - name: Log in to GHCR | |
| uses: docker/login-action@v3 | |
| with: | |
| registry: ${{ env.GHCR_REGISTRY }} | |
| username: ${{ github.actor }} | |
| password: ${{ secrets.GITHUB_TOKEN }} | |
| - name: Log in to DockerHub | |
| uses: docker/login-action@v3 | |
| with: | |
| username: ${{ secrets.DOCKERHUB_USERNAME }} | |
| password: ${{ secrets.DOCKERHUB_TOKEN }} | |
| - name: Image metadata | |
| id: meta | |
| uses: docker/metadata-action@v6 | |
| with: | |
| images: | | |
| ${{ env.GHCR_REGISTRY }}/${{ env.IMAGE_NAME }} | |
| docker.io/${{ secrets.DOCKERHUB_USERNAME }}/${{ github.event.repository.name }} | |
| tags: | | |
| type=raw,value=latest,enable={{is_default_branch}} | |
| type=semver,pattern={{version}} | |
| type=semver,pattern={{major}}.{{minor}} | |
| type=sha,format=short | |
| - name: Build & push (amd64 + arm64) | |
| id: build | |
| uses: docker/build-push-action@v6 | |
| with: | |
| context: . | |
| target: prod | |
| platforms: linux/amd64,linux/arm64 | |
| push: true | |
| provenance: true | |
| sbom: true | |
| tags: ${{ steps.meta.outputs.tags }} | |
| labels: ${{ steps.meta.outputs.labels }} | |
| cache-from: type=gha | |
| cache-to: type=gha,mode=max | |
| # Registry references must be lowercase; github.repository is mixed-case | |
| # (Cepat-Kilat-Teknologi), so normalize it once for Trivy + cosign. | |
| - name: Lowercase image name | |
| id: img | |
| run: echo "name=$(echo "$IMAGE_NAME" | tr '[:upper:]' '[:lower:]')" >> "$GITHUB_OUTPUT" | |
| - name: Trivy image scan | |
| uses: aquasecurity/trivy-action@v0.36.0 | |
| with: | |
| image-ref: ${{ env.GHCR_REGISTRY }}/${{ steps.img.outputs.name }}@${{ steps.build.outputs.digest }} | |
| format: sarif | |
| output: trivy.sarif | |
| ignore-unfixed: true | |
| exit-code: "0" | |
| # Code scanning (SARIF) needs GitHub Advanced Security on private repos; | |
| # without it this upload is rejected, so treat it as best-effort. The | |
| # Trivy findings are still in the step log above. | |
| - name: Upload Trivy SARIF | |
| uses: github/codeql-action/upload-sarif@v4 | |
| if: always() | |
| continue-on-error: true | |
| with: | |
| sarif_file: trivy.sarif | |
| category: trivy | |
| - name: Install cosign | |
| if: startsWith(github.ref, 'refs/tags/v') | |
| uses: sigstore/cosign-installer@v3 | |
| - name: Sign image (keyless) | |
| if: startsWith(github.ref, 'refs/tags/v') | |
| run: | | |
| cosign sign --yes \ | |
| ${{ env.GHCR_REGISTRY }}/${{ steps.img.outputs.name }}@${{ steps.build.outputs.digest }} | |
| # ======================================================================== | |
| # Helm — publish the chart to GitHub Pages via chart-releaser (main only). | |
| # ======================================================================== | |
| helm-release: | |
| name: Publish Helm Chart | |
| runs-on: k3s-ckt-runner | |
| needs: [lint, test, vuln] | |
| if: github.event_name == 'push' && github.ref == 'refs/heads/main' | |
| permissions: | |
| contents: write | |
| steps: | |
| - uses: actions/checkout@v6 | |
| with: | |
| fetch-depth: 0 | |
| - name: Configure Git | |
| run: | | |
| git config user.name "$GITHUB_ACTOR" | |
| git config user.email "$GITHUB_ACTOR@users.noreply.github.com" | |
| - name: Install Helm | |
| uses: azure/setup-helm@v4 | |
| # The chart declares a bitnami redis subchart dependency; cr package | |
| # needs the repo definition to resolve it. | |
| - name: Add Helm repositories | |
| run: | | |
| helm repo add bitnami https://charts.bitnami.com/bitnami | |
| helm repo update | |
| - name: Run chart-releaser | |
| uses: helm/chart-releaser-action@v1.7.0 | |
| with: | |
| charts_dir: examples/helm | |
| skip_existing: "true" | |
| # Chart releases must not steal the "Latest" badge from app releases. | |
| mark_as_latest: false | |
| env: | |
| CR_TOKEN: "${{ secrets.GITHUB_TOKEN }}" |