diff --git a/.github/workflows/backport.yaml b/.github/workflows/backport.yaml new file mode 100644 index 00000000..23aa7592 --- /dev/null +++ b/.github/workflows/backport.yaml @@ -0,0 +1,36 @@ +name: Backport + +on: + pull_request_target: + types: [closed] + +permissions: + contents: write + pull-requests: write + +jobs: + backport: + name: Backport + runs-on: ${{ vars.RUNNER || 'ubuntu-latest' }} + timeout-minutes: 10 + if: > + github.event.pull_request.merged == true && + contains(toJSON(github.event.pull_request.labels), 'backport/') + steps: + - uses: step-security/harden-runner@9af89fc71515a100421586dfdb3dc9c984fbf411 # v2.19.4 + with: + egress-policy: audit + - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6 + with: + fetch-depth: 0 + + - uses: korthout/backport-action@d07416681cab29bf2661702f925f020aaa962997 # v3.4.1 + with: + github_token: ${{ secrets.GITHUB_TOKEN }} + label_pattern: "^backport/(.+)$" + pull_description: | + Backport of #${pull_number} to `${target_branch}`. + + Original PR: #${pull_number} + --- + ${pull_description} diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index b71a344a..9837b1f5 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -301,7 +301,7 @@ jobs: test-bench: name: Benchmark Tests runs-on: ${{ vars.RUNNER || 'ubuntu-latest' }} - timeout-minutes: 10 + timeout-minutes: 15 needs: changes if: needs.changes.outputs.go == 'true' steps: @@ -315,9 +315,51 @@ jobs: go-version: ${{ env.GO_VERSION }} cache: true - - name: Run benchmark tests + - name: Install benchstat + shell: bash -Eeuo pipefail {0} + run: go install golang.org/x/perf/cmd/benchstat@latest + + - name: Restore baseline benchmarks + uses: actions/cache/restore@0057852bfaa89a56745cba8c7296529d2fc39830 # v4.3.0 + with: + path: bench-baseline.txt + key: bench-baseline-${{ runner.os }}-${{ hashFiles('go.sum') }} + restore-keys: bench-baseline-${{ runner.os }}- + + - name: Run benchmarks shell: bash -Eeuo pipefail -x {0} - run: go test ./internal/... -bench=. -benchmem -run='^$' -timeout=5m + run: | + go test ./internal/... -bench=. -benchmem -run='^$' \ + -count=5 -timeout=10m | tee bench-current.txt + + - name: Compare with baseline + shell: bash -Eeuo pipefail {0} + run: | + if [[ -f bench-baseline.txt ]]; then + benchstat bench-baseline.txt bench-current.txt | tee bench-comparison.txt + { + echo "## Benchmark Comparison" + echo '```' + cat bench-comparison.txt + echo '```' + } >> "$GITHUB_STEP_SUMMARY" + else + echo "No baseline found; comparison will be available after the first main push." + echo "## Benchmark Results" >> "$GITHUB_STEP_SUMMARY" + echo "No baseline yet. One will be established on the next merge to main." >> "$GITHUB_STEP_SUMMARY" + fi + + - name: Promote current run as baseline (main only) + if: github.ref == 'refs/heads/main' && github.event_name == 'push' + shell: bash -Eeuo pipefail {0} + run: cp bench-current.txt bench-baseline.txt + + - name: Save baseline (main only) + if: github.ref == 'refs/heads/main' && github.event_name == 'push' + uses: actions/cache/save@0057852bfaa89a56745cba8c7296529d2fc39830 # v4.3.0 + with: + path: bench-baseline.txt + key: bench-baseline-${{ runner.os }}-${{ hashFiles('go.sum') }} test-integration: name: Integration Tests diff --git a/.github/workflows/release.yaml b/.github/workflows/release.yaml index 0b07a5d4..9f2f93ce 100644 --- a/.github/workflows/release.yaml +++ b/.github/workflows/release.yaml @@ -10,9 +10,10 @@ concurrency: cancel-in-progress: false permissions: + actions: read # For SLSA provenance contents: write packages: write - id-token: write # For cosign keyless signing + id-token: write # For cosign keyless signing env: GO_VERSION: "1.26" @@ -25,6 +26,9 @@ jobs: if: startsWith(github.ref, 'refs/tags/') runs-on: ubuntu-latest timeout-minutes: 30 + outputs: + hashes: ${{ steps.hash.outputs.hashes }} + digest: ${{ steps.build.outputs.digest }} steps: - uses: step-security/harden-runner@9af89fc71515a100421586dfdb3dc9c984fbf411 # v2.19.4 with: @@ -60,6 +64,12 @@ jobs: env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + - name: Generate provenance subjects + id: hash + shell: bash -Eeuo pipefail {0} + run: | + echo "hashes=$(cat goreleaser-dist/checksums.txt | base64 -w0)" >> "$GITHUB_OUTPUT" + - name: Build and push multi-arch image uses: docker/build-push-action@f9f3042f7e2789586610d6e8b85c8f03e5195baf # v7.2.0 id: build @@ -166,3 +176,33 @@ jobs: VERSION="${VERSION#v}" cosign sign --yes \ ${{ env.REGISTRY }}/${{ github.repository_owner }}/charts/attune:${VERSION} + + # SLSA Level 3 provenance for GoReleaser binary artifacts. + # Runs as a reusable workflow (required for non-forgeable provenance). + provenance: + name: Binary Provenance + needs: [release] + permissions: + actions: read + id-token: write + contents: write + uses: slsa-framework/slsa-github-generator/.github/workflows/generator_generic_slsa3.yml@f7dd8c54c2067bafc12ca7a55595d5ee9b75204a # v2.1.0 + with: + base64-subjects: "${{ needs.release.outputs.hashes }}" + upload-assets: true + + # SLSA Level 3 provenance for the container image. + container-provenance: + name: Container Provenance + needs: [release] + permissions: + actions: read + id-token: write + packages: write + uses: slsa-framework/slsa-github-generator/.github/workflows/generator_container_slsa3.yml@f7dd8c54c2067bafc12ca7a55595d5ee9b75204a # v2.1.0 + with: + image: ghcr.io/${{ github.repository }} + digest: ${{ needs.release.outputs.digest }} + registry-username: ${{ github.actor }} + secrets: + registry-password: ${{ secrets.GITHUB_TOKEN }} diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 4cc9727b..f5311bb7 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -230,6 +230,16 @@ chore: update controller-runtime to v0.24.1 - Add table-driven tests for new logic - Use `meta.SetStatusCondition()` for condition management +## Backporting Fixes to Release Branches + +When a fix merged to `main` should also go into a stable release branch, +add a `backport/` label to the PR (e.g., `backport/release-0.1`). +A GitHub Actions workflow will automatically cherry-pick the merge commit +and open a backport PR targeting that release branch. + +If the cherry-pick has conflicts, the backport PR is created with conflict +markers for manual resolution. + ## Code of Conduct This project follows the [CNCF Code of Conduct](https://github.com/cncf/foundation/blob/main/code-of-conduct.md). diff --git a/docs/logo.jpg b/docs/logo.jpg index e2ba72e4..e7047ea5 100644 Binary files a/docs/logo.jpg and b/docs/logo.jpg differ