diff --git a/.claude/rules/releases-use-script.md b/.claude/rules/releases-use-script.md index e84ae3c..4d209a4 100644 --- a/.claude/rules/releases-use-script.md +++ b/.claude/rules/releases-use-script.md @@ -10,6 +10,7 @@ When the user asks for a "new release" (or equivalent wording), always use `.git - If bump type is unclear, ask a single clarifying question before running the script. - Do not manually edit `CHANGELOG.md`, `VERSION`, create tags, or craft release commits as a substitute for the script. - Run the script as the source of truth for release preparation steps. +- Open a PR against `main`; after merge, CI alone creates the tag and publishes the GitHub release. Do not run local `publish` when the release policy is present. Examples: - "new release" -> ask whether `major`, `minor`, or `patch`, then run `.github/scripts/release.sh `. diff --git a/.github/release-policy.json b/.github/release-policy.json new file mode 100644 index 0000000..2502b36 --- /dev/null +++ b/.github/release-policy.json @@ -0,0 +1,14 @@ +{ + "release_branch": "main", + "version": { + "path": "VERSION", + "format": "text" + }, + "mirrors": [], + "tag_prefix": "v", + "changelog": "CHANGELOG.md", + "outputs": { + "github_release": true, + "packages": [] + } +} diff --git a/.github/scripts/release.sh b/.github/scripts/release.sh index 11db1d9..29a0f06 100755 --- a/.github/scripts/release.sh +++ b/.github/scripts/release.sh @@ -17,7 +17,7 @@ This script: 3) Creates a commit 4) Leaves the commit on the current feature branch for a PR -After that PR merges, run publish on updated main to tag and push the merged commit. +After that PR merges, CI validates the merged commit, creates its tag and publishes the release. EOF } @@ -216,4 +216,4 @@ git commit -m "chore(release): ${tag}" echo "Release prepared." echo "- Version: ${effective_version} -> ${version} (VERSION file before bump: ${current_version})" echo "- Commit created locally: chore(release): ${tag}" -echo "- Open a PR to main, then run .github/scripts/release.sh publish on updated main." \ No newline at end of file +echo "- Open a PR to main; CI creates the tag and publishes the release after merge." \ No newline at end of file diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml new file mode 100644 index 0000000..378e6be --- /dev/null +++ b/.github/workflows/publish.yml @@ -0,0 +1,12 @@ +name: Publish release + +on: + push: + tags: ["v[0-9]*.[0-9]*.[0-9]*"] + +permissions: + contents: write + +jobs: + publish: + uses: BehindTheMusicTree/github-workflows/.github/workflows/release-github.yml@91a81d064801fe3c2e460882067220b3cb39d542 diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml new file mode 100644 index 0000000..c8f6f2d --- /dev/null +++ b/.github/workflows/release.yml @@ -0,0 +1,16 @@ +name: Release tag + +on: + push: + branches: [main] + +permissions: + contents: read + +jobs: + release-tag: + uses: BehindTheMusicTree/github-workflows/.github/workflows/release-tag.yml@73148058f64deee76f076689f72ca4455fb19ec1 + with: + app-id: ${{ vars.RELEASE_APP_ID }} + secrets: + release-app-private-key: ${{ secrets.RELEASE_APP_PRIVATE_KEY }} diff --git a/CHANGELOG.md b/CHANGELOG.md index 0910976..34032e7 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -52,6 +52,10 @@ All contributors (including maintainers) should update `CHANGELOG.md` when creat ## [Unreleased] +### Changed + +- Adopt CI-owned tags and changelog-based GitHub publication for this repository, preserving script-based release preparation. + ### Added - Verify existing npm artifacts by name, version and archive integrity when resuming partial multi-package publications. diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 924f363..5e50ddf 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -188,8 +188,10 @@ Releases are made from `main`. 1. Create a feature branch from an up-to-date `main`. 2. Run `.github/scripts/release.sh minor` (or `patch` / `major`) on the feature branch. The script updates the changelog and version and commits them without creating a tag. 3. Push the branch, open a PR to `main`, and merge it after review and checks. -4. Update a clean local `main` to the merged commit, then run `.github/scripts/release.sh publish`. The script checks that `main` matches `origin/main`, creates the version tag on the merged commit, and pushes it. -5. Optionally create a GitHub Release from that tag and include the version's changelog section. +4. CI validates the release policy, canonical `VERSION`, nonempty matching changelog notes and main ancestry. It creates an annotated tag on the exact merged commit through the release App. +5. The tag workflow publishes the GitHub Release using those changelog notes. Rerun a failed workflow to recover; an existing release is retained. Local `publish` is refused once `.github/release-policy.json` is present. + +Initial adoption keeps version 5.0.1 and creates no tag. App access and tag protections are activated separately in `github-config` before preparing a subsequent release. The reusable workflows in this repository remain pinned by consumers; this adoption does not repin them. ## License & Attribution diff --git a/README.md b/README.md index 2004eb8..dad711a 100644 --- a/README.md +++ b/README.md @@ -405,7 +405,7 @@ Before enabling a caller, configure separate tag rulesets: creation permits the Activation and changes to the contract must land in a separate push from a version bump. Activation validates the current version, mirrors and changelog but never tags it, including an existing version with no tag. A subsequent push with no bump also produces no tag. For an established contract, a bump must increase the version and leave the policy unchanged; all mirrors and its changelog section must match. The version comparison uses the push's before/after commits, never the current branch tip. Force pushes and newly created branch events fail closed. -Prepare version and changelog in a PR using the project's own tools. In this repository, `.github/scripts/release.sh major|minor|patch` prepares a commit on a feature branch. Its legacy `publish` command remains available to repositories without the CI policy; once `.github/release-policy.json` exists, manual publication is refused. This foundation PR does not activate automatic tagging for github-workflows itself. +Prepare version and changelog in a PR using the project's own tools. In this repository, `.github/scripts/release.sh major|minor|patch` prepares a commit on a feature branch. Its legacy `publish` command remains available to repositories without the CI policy; once `.github/release-policy.json` exists, manual publication is refused. This repository declares its own `VERSION` policy and uses pinned callers for tagging and GitHub publication. Initial adoption keeps version 5.0.1 and produces no tag; App access and protections are activated separately in `github-config`. Validation runs without App secrets and checks ancestry against fetched `origin/main`. A separate runner checks out only this repository's shared implementation at an immutable SHA, checks configuration, then requests an App token scoped to the caller repository and Contents write. The App-token action revokes it in its post step. No caller script or build runs in that job. Maintainers changing the Python implementation must commit it first and update **both** helper checkout SHAs in the reusable workflow to that reviewed snapshot. The outer workflow is independently pinned by each caller.