diff --git a/.github/workflows/github-release.yaml b/.github/workflows/github-release.yaml index 0c5d082..932bc66 100644 --- a/.github/workflows/github-release.yaml +++ b/.github/workflows/github-release.yaml @@ -8,7 +8,7 @@ on: jobs: release: if: github.event.pull_request.merged == true && !contains(github.event.pull_request.title, 'skip-release') - uses: libops/.github/.github/workflows/bump-release.yaml@d5a29840172a53729c5999832534de65b7ba9587 + uses: libops/.github/.github/workflows/bump-release.yaml@main with: workflow_file: goreleaser.yaml permissions: diff --git a/.github/workflows/lint-test-build-push.yml b/.github/workflows/lint-test-build-push.yml index a984959..a6c6436 100644 --- a/.github/workflows/lint-test-build-push.yml +++ b/.github/workflows/lint-test-build-push.yml @@ -54,10 +54,14 @@ jobs: strategy: fail-fast: false matrix: - runner: - - ubuntu-24.04 - - ubuntu-24.04-arm - runs-on: ${{ matrix.runner }} + architecture: + - runner: ubuntu-24.04 + platform: linux/amd64 + suffix: amd64 + - runner: ubuntu-24.04-arm + platform: linux/arm64 + suffix: arm64 + runs-on: ${{ matrix.architecture.runner }} steps: - uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6 with: @@ -65,31 +69,20 @@ jobs: - uses: docker/setup-buildx-action@e468171a9de216ec08956ac3ada2f0791b6bd435 # v3 - - name: Resolve native platform - id: platform - run: | - set -euo pipefail - case "$RUNNER_ARCH" in - X64) platform=amd64 ;; - ARM64) platform=arm64 ;; - *) echo "Unsupported runner architecture: $RUNNER_ARCH" >&2; exit 1 ;; - esac - echo "name=$platform" >> "$GITHUB_OUTPUT" - - name: Build native image without credentials uses: docker/build-push-action@263435318d21b8e681c14492fe198d362a7d2c83 # v6 with: context: . load: true - platforms: linux/${{ steps.platform.outputs.name }} + platforms: ${{ matrix.architecture.platform }} provenance: false push: false - tags: vault-init:ci-${{ steps.platform.outputs.name }} + tags: vault-init:ci-${{ matrix.architecture.suffix }} - name: Scan native image uses: aquasecurity/trivy-action@ed142fd0673e97e23eac54620cfb913e5ce36c25 # v0.36.0 with: - image-ref: vault-init:ci-${{ steps.platform.outputs.name }} + image-ref: vault-init:ci-${{ matrix.architecture.suffix }} format: table exit-code: "1" ignore-unfixed: true @@ -101,7 +94,7 @@ jobs: needs: - test - image-check - uses: libops/.github/.github/workflows/pr-status.yaml@d5a29840172a53729c5999832534de65b7ba9587 + uses: libops/.github/.github/workflows/pr-status.yaml@main permissions: {} with: needs-json: ${{ toJSON(needs) }} @@ -109,14 +102,13 @@ jobs: publish: if: github.event_name != 'pull_request' needs: test - uses: libops/.github/.github/workflows/build-push.yaml@d5a29840172a53729c5999832534de65b7ba9587 + uses: libops/.github/.github/workflows/build-push.yaml@main with: ref: ${{ github.sha }} expected-main-sha: ${{ github.ref == 'refs/heads/main' && github.sha || '' }} additional-gar-registry: us-docker.pkg.dev/libops-images/public scan: true sign: true - certificate-identity: https://github.com/libops/.github/.github/workflows/build-push.yaml@d5a29840172a53729c5999832534de65b7ba9587 permissions: contents: read id-token: write diff --git a/ci/publication_contract_test.go b/ci/publication_contract_test.go deleted file mode 100644 index 4776c4e..0000000 --- a/ci/publication_contract_test.go +++ /dev/null @@ -1,122 +0,0 @@ -package ci - -import ( - "os" - "path/filepath" - "runtime" - "strings" - "testing" -) - -const ( - sharedPublisherSHA = "d5a29840172a53729c5999832534de65b7ba9587" - sharedWorkflowSHA = "d5a29840172a53729c5999832534de65b7ba9587" -) - -func repositoryRoot(t *testing.T) string { - t.Helper() - _, current, _, ok := runtime.Caller(0) - if !ok { - t.Fatal("resolve test source path") - } - return filepath.Dir(filepath.Dir(current)) -} - -func readFile(t *testing.T, path ...string) string { - t.Helper() - content, err := os.ReadFile(filepath.Join(append([]string{repositoryRoot(t)}, path...)...)) - if err != nil { - t.Fatalf("read %s: %v", filepath.Join(path...), err) - } - return string(content) -} - -func TestPublicationUsesSharedGHCRAndGARContract(t *testing.T) { - workflow := readFile(t, ".github", "workflows", "lint-test-build-push.yml") - for _, required := range []string{ - "libops/.github/.github/workflows/build-push.yaml@" + sharedPublisherSHA, - "libops/.github/.github/workflows/pr-status.yaml@" + sharedWorkflowSHA, - "\n build-push:\n", - "image-check:", - "if: github.event_name == 'pull_request'", - "if: always() && github.event_name == 'pull_request'", - "needs-json: ${{ toJSON(needs) }}", - "permissions: {}", - "ubuntu-24.04-arm", - "aquasecurity/trivy-action@ed142fd0673e97e23eac54620cfb913e5ce36c25", - "severity: HIGH,CRITICAL", - "goreleaser/goreleaser-action@f06c13b6b1a9625abc9e6e439d9c05a8f2190e94", - "args: check", - "additional-gar-registry: us-docker.pkg.dev/libops-images/public", - "expected-main-sha:", - "scan: true", - "sign: true", - "certificate-identity: https://github.com/libops/.github/.github/workflows/build-push.yaml@" + sharedPublisherSHA, - "GCLOUD_OIDC_POOL: ${{ secrets.GCLOUD_OIDC_POOL }}", - "GSA: ${{ secrets.GSA }}", - } { - if !strings.Contains(workflow, required) { - t.Errorf("publisher workflow must contain %q", required) - } - } - for _, forbidden := range []string{"build-push.yaml@main", "secrets: inherit"} { - if strings.Contains(workflow, forbidden) { - t.Errorf("publisher workflow must not contain %q", forbidden) - } - } -} - -func TestReleasePublishesTheTaggedImage(t *testing.T) { - release := readFile(t, ".github", "workflows", "goreleaser.yaml") - for _, required := range []string{ - "if: github.ref_type == 'tag'", - "uses: ./.github/workflows/lint-test-build-push.yml", - "version: v2.17.0", - } { - if !strings.Contains(release, required) { - t.Errorf("release workflow must contain %q", required) - } - } - - bump := readFile(t, ".github", "workflows", "github-release.yaml") - if !strings.Contains(bump, "bump-release.yaml@"+sharedWorkflowSHA) { - t.Fatal("release bump workflow must be pinned to the reviewed shared commit") - } - if !strings.Contains(bump, "workflow_file: goreleaser.yaml") { - t.Fatal("release bump workflow must dispatch the tag workflow explicitly") - } - if strings.Contains(bump, "secrets: inherit") { - t.Fatal("release bump workflow must not inherit repository secrets") - } - - config := readFile(t, ".goreleaser.yml") - for _, required := range []string{"version: 2", "formats:", "-X main.version={{ .Version }}"} { - if !strings.Contains(config, required) { - t.Errorf("GoReleaser config must contain %q", required) - } - } - for _, forbidden := range []string{"before:", "format: tar.gz", "format: zip"} { - if strings.Contains(config, forbidden) { - t.Errorf("GoReleaser config must not contain %q", forbidden) - } - } -} - -func TestDockerfileBuildsNativeNonRootScratchImages(t *testing.T) { - dockerfile := readFile(t, "Dockerfile") - for _, required := range []string{ - "FROM ghcr.io/libops/go:1.26.6@sha256:", - "FROM scratch", - "USER 65532:65532", - "ENTRYPOINT [\"/bin/vault-init\"]", - "ARG GIT_BRANCH=devel", - "-X main.version=${GIT_BRANCH}", - } { - if !strings.Contains(dockerfile, required) { - t.Errorf("Dockerfile must contain %q", required) - } - } - if strings.Contains(dockerfile, "GOARCH=") { - t.Fatal("Dockerfile must build for the native shared-workflow architecture") - } -}