diff --git a/.github/workflows/release-version.yml b/.github/workflows/release-version.yml new file mode 100644 index 0000000..36f80f3 --- /dev/null +++ b/.github/workflows/release-version.yml @@ -0,0 +1,69 @@ +# Cuts a BCQuality content release on demand (roughly monthly), NOT on every +# commit. Run this workflow manually once the `main` content is ready, and choose +# whether to bump the minor (usual periodic content update) or the major +# (breaking change). +# +# The version is a `major.minor` value derived from existing git tags — there is +# no VERSION file. The minor is a monotonic counter: it only ever increments and +# never resets, even across a major bump, so it uniquely identifies a release. +# This workflow computes the next version and tags the current commit as +# `v{major}.{minor}`. + +name: Release version + +on: + workflow_dispatch: + inputs: + bump: + description: Which part to bump + type: choice + options: + - minor + - major + default: minor + +# Only tag creation needs write. +permissions: + contents: write + +concurrency: + group: release-version + cancel-in-progress: false + +jobs: + release: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + with: + fetch-depth: 0 + + - name: Compute and tag release + shell: bash + run: | + git fetch --tags --force --quiet + tags="$(git tag -l | grep -E '^v[0-9]+\.[0-9]+$' || true)" + + if [[ -z "$tags" ]]; then + # First release. + major=1 + minor=0 + else + latest_major="$(printf '%s\n' "$tags" | sed -E 's/^v([0-9]+)\..*/\1/' | sort -n | tail -1)" + latest_minor="$(printf '%s\n' "$tags" | sed -E 's/^v[0-9]+\.([0-9]+)$/\1/' | sort -n | tail -1)" + minor=$(( latest_minor + 1 )) # monotonic, never resets + if [[ "${{ inputs.bump }}" == "major" ]]; then + major=$(( latest_major + 1 )) + else + major="$latest_major" + fi + fi + + tag="v${major}.${minor}" + if git rev-parse -q --verify "refs/tags/${tag}" >/dev/null; then + echo "::error::Tag ${tag} already exists" + exit 1 + fi + git tag "$tag" "${{ github.sha }}" + git push origin "$tag" + echo "Released BCQuality ${tag} at ${{ github.sha }}" diff --git a/README.md b/README.md index ddab523..6abf98a 100644 --- a/README.md +++ b/README.md @@ -136,6 +136,18 @@ For the end-to-end flow — from orchestrator trigger through to how output reac │ └── /skills/ ``` +## Versioning + +BCQuality content is released on demand — roughly monthly, not on every commit. A +release is a `major.minor` value derived from git tags, cut manually via the +`Release version` workflow: pick whether to bump the minor or the major, and it +computes the next version and tags the current `main` as `v{major}.{minor}`. + +- Bump the **minor** for the usual periodic content update; bump the **major** + only for a breaking change. +- The minor is a **monotonic counter** — it only ever increments and never + resets, even across a major bump — so it uniquely identifies a release. + ## Contributing Contributions are welcome. Before submitting a PR: