diff --git a/AGENTS.md b/AGENTS.md index c874569..01f9076 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -48,6 +48,128 @@ uv run python -m unittest discover -s tests - Keep module-level constants near the top of each module, after imports - Prefer specific package/module names over broad `helpers` or `utils` modules +## Release process + +- The tagged source commit must already contain the package version it + releases. Do not make the release workflow edit `pyproject.toml`. +- The tag must be `vMAJOR.MINOR.PATCH`, and `.github/workflows/release.yml` + verifies that it matches `project.version` before building GitHub release + assets and publishing to PyPI. +- Prepare releases on a branch from current `main`. Set `VERSION`, then run: + +```sh +set -euo pipefail + +VERSION=0.1.1 +BRANCH="release-v${VERSION}" + +git fetch origin --tags --prune +git switch main +git pull --ff-only +git switch -c "${BRANCH}" + +uv run python - "${VERSION}" <<'PY' +from pathlib import Path +import re +import sys + +version = sys.argv[1] +path = Path("pyproject.toml") +text = path.read_text() +new_text = re.sub( + r'(?m)^version = "[^"]+"$', + f'version = "{version}"', + text, + count=1, +) +if new_text == text: + raise SystemExit("pyproject.toml version was not updated") +path.write_text(new_text) +PY + +uv lock +``` + +- Validate before opening the PR: + +```sh +set -euo pipefail + +uv lock --check +npx --yes markdownlint-cli2 +uv run ruff check . +uv run ruff format --check . +uv run pyright +uv run python -m unittest discover -s tests +uv build --wheel --sdist --out-dir /tmp/src-py-lib-release-check --no-create-gitignore +rm -rf /tmp/src-py-lib-release-check +``` + +- Commit, push, open the PR, wait for checks, then merge it. If review is + required, stop after `gh pr checks` and ask for review before merging. + +```sh +set -euo pipefail + +VERSION=0.1.1 +BRANCH="release-v${VERSION}" +GH_REPO="sourcegraph/src-py-lib" + +git add pyproject.toml uv.lock +git commit -m "Release v${VERSION}" +git push -u origin "${BRANCH}" + +gh pr create \ + --repo "${GH_REPO}" \ + --base main \ + --head "${BRANCH}" \ + --title "Release v${VERSION}" \ + --body "Bump src-py-lib package metadata to ${VERSION}." + +gh pr checks "${BRANCH}" --repo "${GH_REPO}" --watch --fail-fast +gh pr merge "${BRANCH}" --repo "${GH_REPO}" --squash --delete-branch +``` + +- Tag the merged `main` commit. Do not tag a branch commit. + +```sh +set -euo pipefail + +VERSION=0.1.1 + +git fetch origin --tags --prune +git switch main +git pull --ff-only +git tag "v${VERSION}" +git push origin "v${VERSION}" +``` + +- Watch the release workflow and confirm the GitHub release and PyPI project. + +```sh +set -euo pipefail + +VERSION=0.1.1 +GH_REPO="sourcegraph/src-py-lib" + +RUN_ID="$( + gh run list \ + --repo "${GH_REPO}" \ + --workflow release.yml \ + --branch "v${VERSION}" \ + --limit 1 \ + --json databaseId \ + --jq '.[0].databaseId // empty' +)" +test -n "${RUN_ID}" +gh run watch "${RUN_ID}" --repo "${GH_REPO}" --exit-status +gh release view "v${VERSION}" --repo "${GH_REPO}" +uvx --from pip pip index versions src-py-lib +``` + +- If a pushed tag points at the wrong commit, move it only after explicit + human approval. + ## Before finishing changes - Re-read edited files for organization and stale comments diff --git a/pyproject.toml b/pyproject.toml index 24cd7d3..664ad0a 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -10,7 +10,7 @@ dev = [ [project] name = "src-py-lib" -version = "0.1.0" +version = "0.1.1" description = "Reusable libraries for Sourcegraph projects" readme = "README.md" requires-python = ">=3.11" diff --git a/uv.lock b/uv.lock index 8325c53..00f8ab9 100644 --- a/uv.lock +++ b/uv.lock @@ -254,7 +254,7 @@ wheels = [ [[package]] name = "src-py-lib" -version = "0.1.0" +version = "0.1.1" source = { editable = "." } dependencies = [ { name = "httpx" },