diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index d4c4f78..9e31463 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -3,6 +3,7 @@ name: release on: push: branches: [main] + tags: ["v*"] pull_request: workflow_dispatch: @@ -97,3 +98,53 @@ jobs: name: glean-code-pyz path: ${{ runner.temp }}/glean-code.pyz if-no-files-found: error + + # A tag is the release marker; __version__ is the per-PR build identity. This + # job turns `git push origin vX.Y.Z` into a GitHub Release with the zipapp + # attached, so there is something to download that is not a CI artifact + # expiring in 90 days. + publish: + name: publish ${{ github.ref_name }} + if: startsWith(github.ref, 'refs/tags/v') + needs: test + runs-on: ubuntu-latest + permissions: + contents: write # required to create a release + steps: + - uses: actions/checkout@v4 + + - uses: actions/setup-python@v5 + with: + python-version: "3.13" + + - name: Refuse to publish a tag that disagrees with __version__ + env: + TAG: ${{ github.ref_name }} + run: | + have=$(python3 -c "import re;print(re.search(r'__version__ = \"([^\"]+)\"', open('glean_code/__init__.py').read()).group(1))") + want="${TAG#v}" + if [ "$have" != "$want" ]; then + echo "::error::tag $TAG does not match __version__ $have" + exit 1 + fi + echo "tag $TAG matches __version__ $have" + + - name: Build the zipapp + env: + PYTHONPYCACHEPREFIX: ${{ runner.temp }}/pycache + run: | + python -c " + import pathlib, install + out = install.build_zipapp(pathlib.Path('glean-code.pyz')) + print(f'built {out} ({out.stat().st_size / 1024:.0f} KB)') + " + + - name: Create the release + env: + GH_TOKEN: ${{ github.token }} + TAG: ${{ github.ref_name }} + run: | + gh release create "$TAG" glean-code.pyz \ + --title "Glean Code $TAG" \ + --generate-notes \ + --verify-tag diff --git a/CLAUDE.md b/CLAUDE.md index 82a8c84..bf316d1 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -104,7 +104,15 @@ python3 tools/set_version.py 41 # or set it explicitly ``` The `version` job in `release.yml` fails a PR whose `__version__` does not match its -number. `client.USER_AGENT` and the auth/doctor User-Agents all derive from +number. + +Tags are the release marker, separate from the per-PR build identity. Pushing +`v` runs the `publish` job, which refuses a tag that disagrees with +`__version__`, builds the zipapp and creates a GitHub Release with it attached: + +```bash +git tag -a v0.2.41 -m "Glean Code v0.2.41" && git push origin v0.2.41 +``` `client.USER_AGENT` and the auth/doctor User-Agents all derive from `__version__`, and a test asserts no string in `glean_code/` hardcodes a version — they were `"glean-code/0.1"` for 38 PRs and went stale immediately. diff --git a/glean_code/__init__.py b/glean_code/__init__.py index bf5c756..79f854b 100644 --- a/glean_code/__init__.py +++ b/glean_code/__init__.py @@ -1,5 +1,5 @@ """Glean Code. A local, terminal-first client for the Glean Client REST API.""" -__version__ = "0.2.40" +__version__ = "0.2.41" from . import auth_commands # noqa: F401 # registers /auth and help docs