diff --git a/README.md b/README.md index 40789e3..7e4bc5f 100644 --- a/README.md +++ b/README.md @@ -2,74 +2,109 @@ Shared reusable GitHub Actions workflows and composite actions for the Defguard repositories. -## Caller pattern +## Ref policy: pinned semver + Renovate -### Reusable workflows +**Product repos pin a specific semver tag.** No floating `@v1` in committed caller workflow files. -Product repos reference workflows from this repo by major tag: +```yaml +# Correct: pinned to a specific release +uses: defguard/ci-workflows/.github/workflows/rehearsal.yml@v1.0.0 +``` ```yaml +# Incorrect: floating major tag -- do not commit this uses: defguard/ci-workflows/.github/workflows/rehearsal.yml@v1 ``` -Passing inputs and secrets explicitly per the workflow's contract: +**Renovate keeps the pin current.** A regex manager in the shared Renovate preset (`renovate/default.json`) scans product-repo workflow files for `DefGuard/ci-workflows/.+@vX.Y.Z` and opens a single grouped PR when a new tag is published. The fix-still-lands-once property is preserved - just behind a merge button. + +**`@v1` exists as a convenience pointer** for local/dispatch use, but product repos **must not reference it** in committed workflow files. + +### How to cut a release + +After a reviewed PR merges to `main`: + +```sh +git checkout main +git pull +git tag -a v1.0.1 -m "v1.0.1: description of change" +git tag -f v1 +git push origin v1.0.1 +git push origin v1 --force +``` + +Renovate will then open a PR in each product repo to bump the pinned ref from `@v1.0.0` to `@v1.0.1`. + +Breaking changes require a new major tag (`v2`) and a migration guide before the old major line is retired. + +## Thin-caller pattern + +**A product repo's caller workflow is a pure pass-through.** It contains only the `uses:` call plus triggers and concurrency controls - no pre/post jobs, no additional steps. ```yaml +# Example: defguard/.github/workflows/rehearsal.yml +name: Weekly Release Rehearsal +on: + schedule: + - cron: '0 8 * * 1' # Monday 08:00 UTC + workflow_dispatch: + +concurrency: + group: rehearsal-${{ github.ref }} + cancel-in-progress: true + jobs: rehearsal: - uses: defguard/ci-workflows/.github/workflows/rehearsal.yml@v1 + uses: defguard/ci-workflows/.github/workflows/rehearsal.yml@v1.0.0 with: publish: false + branch: dev secrets: - MATRIX_WEBHOOK: ${{ secrets.MATRIX_WEBHOOK }} + MATRIX_WEBHOOK_URL: ${{ secrets.MATRIX_WEBHOOK_URL }} + GHCR_READ_TOKEN: ${{ secrets.GHCR_READ_TOKEN }} ``` +**Rationale:** this guarantees rehearsal and release call the exact same underlying jobs with no hidden divergence. If a repo needs a repo-specific step, extract it into ci-workflows behind a parameter - do not add it to the caller. + ### Composite actions +Composite actions are called from steps within any workflow (reusable or caller): + ```yaml steps: - - uses: defguard/ci-workflows/actions/alert@v1 + - uses: defguard/ci-workflows/actions/alert@v1.0.0 with: alert-key: rehearsal-dev title: "Rehearsal failed on dev" labels: release-blocker github-token: ${{ secrets.GITHUB_TOKEN }} - matrix-webhook: ${{ secrets.MATRIX_WEBHOOK }} ``` -## Versioning +## Parity rule -This repo uses a **moving major tag** convention: +**Any change to a release build path must land in this repo first.** -- `v1` always points to the latest stable release on the v1 line -- `v1.x.x` tags pin a specific release -- Product repos pin `@v1`; the tag is moved deliberately after review +A PR touching a product repo's release caller workflow (beyond a ref bump) is a red flag - the shared workflow here must be updated instead. The weekly release rehearsal exercises the shared workflow automatically. Rehearsal and release must call the same underlying jobs, so divergence between what is rehearsed and what actually ships is impossible. -To advance `v1` to a new commit after a reviewed change: +## Repo layout -```sh -git tag -a v1.x.x -m "v1.x.x" -git tag -f v1 -git push origin v1.x.x -git push origin v1 --force ``` - -Breaking changes require a new major tag (`v2`) and a migration guide before the old major tag is retired. - -## Parity rule - -**Any change to a release build path must land in this repo first.** - -A PR touching a product repo's release caller workflow is a red flag - update the shared workflow here instead, so the weekly release rehearsal exercises the change automatically. Rehearsal and release must call the same underlying jobs. +ci-workflows/ + .github/ + workflows/ # Reusable workflow_call workflows + actions/ # Composite actions + renovate/ # Shared Renovate preset (default.json) + README.md +``` ## Contents | Path | Type | Purpose | |------|------|---------| | `.github/workflows/lint.yml` | CI workflow | actionlint + shellcheck on every PR to this repo | -| `.github/workflows/hello-world.yml` | Reusable workflow | Caller-pattern probe (temporary; replaced by real workflows as they are added) | - -More workflows and composite actions will be added here as the release-process smoothing initiative progresses. +| `.github/workflows/hello-world.yml` | Reusable workflow | Minimal `workflow_call` probe for cross-repo caller validation | +| `actions/` | Composite actions | Shared actions for alerting, readiness checks, etc. (populated by subsequent tickets) | +| `renovate/default.json` | Renovate preset | Shared config extended by all product repos | ## Developing diff --git a/actions/.gitkeep b/actions/.gitkeep new file mode 100644 index 0000000..e69de29