Skip to content

Release automation: publish hindsight-sre to PyPI and image to GHCR - #6

Merged
dimittal merged 2 commits into
mainfrom
release/pypi-ghcr-automation
Nov 2, 2026
Merged

dimittal merged 2 commits into
mainfrom
release/pypi-ghcr-automation

Conversation

@dimittal

@dimittal dimittal commented Nov 2, 2026 •

Copy link
Copy Markdown
Contributor

What

Makes the launch quickstart work without cloning or building locally.

  • .github/workflows/release-pypi.yml — on a v* tag: checks the tag matches pyproject.toml's version, runs python -m build, twine check --strict, verifies the wheel contains hindsight/static/* and hindsight/sample-knowledge/, publishes hindsight-sre to PyPI with Trusted Publishing (OIDC, no token secret), then creates a GitHub release with the dists attached. workflow_dispatch is the dry run: it rewrites the version to <version>.dev<run_number> (so repeated dry runs never collide) and publishes to TestPyPI.

  • .github/workflows/release-image.yml — on a v* tag: builds amd64, runs scripts/demo-smoke.py against it, then builds linux/amd64,linux/arm64 and pushes ghcr.io/drdroidlab/hindsight:<version>, :<major>.<minor> and :latest (latest is skipped for PEP 440 pre-releases such as v0.2.0rc1) using GITHUB_TOKEN with packages: write. workflow_dispatch builds both platforms without pushing.

  • compose.yaml — image: ${HINDSIGHT_IMAGE:-ghcr.io/drdroidlab/hindsight:latest} plus build: .. Compose pulls the image when it isn't present and only builds with --build (verified: with image + build and no Dockerfile in the directory, docker compose create pulls). compose.demo.yaml is unchanged and still merges cleanly. .env.example documents HINDSIGHT_IMAGE for pinning.

  • Docs (README, docs/getting-started.md, docs/index.md, docs/operations.md) — engineers: uv tool install hindsight-sre (or pipx install hindsight-sre). Team leads: curl the compose file(s) from main, docker compose up -d, bootstrap. There's no git clone or --build; the from-clone --build path is still documented as a tip. Production deploys use a separate directory so demo data doesn't share a volume. docs/demo.md (screenshot recipe from a checkout) keeps --build on purpose.

  • MCP Registry readiness (so Hindsight can be listed without a second release):

    • README carries <!-- mcp-name: io.github.DrDroidLab/hindsight-sre -->, the ownership marker the registry looks for in the PyPI long description. I verified it's in the built wheel's METADATA.
    • The image has the label io.modelcontextprotocol.server.name=io.github.DrDroidLab/hindsight-sre (Dockerfile and metadata-action), plus the OCI title "Hindsight SRE".
    • server.json declares io.github.DrDroidLab/hindsight-sre, title Hindsight SRE (to stay distinct from io.github.Rbfinch/hindsight-mcp and Vectorize's Hindsight), and a PyPI package run as uvx hindsight-sre mcp-proxy. It lists the optional HINDSIGHT_SERVER, HINDSIGHT_API_KEY (secret) and HINDSIGHT_SCOPE variables; the credential file from hindsight login is the preferred source. It validates against the 2025-12-11 schema.
    • A new hindsight-sre console-script alias (same entry point as hindsight) makes uvx hindsight-sre … resolve.
    • The PyPI release job fails the tag if the server.json versions don't match pyproject.toml, so bump all three together.

Verification (local)

  • actionlint 1.7.7 (with shellcheck) on all workflows: clean
  • python -m build: wheel contains static/index.html, static/assets/{app.js,style.css} and 7 sample-knowledge files; twine check --strict passes
  • docker build . + scripts/demo-smoke.py: PASS
  • mkdocs build --strict: clean
  • docker compose -f compose.yaml -f compose.demo.yaml config --quiet: ok
  • ruff check, ruff format --check, mypy src/hindsight, pytest (85 passed): all pass

The workflows themselves haven't run yet. They only fire on a tag or a manual dispatch.

One-time maintainer setup (before the first tag)

PyPI / TestPyPI Trusted Publishing

  1. On https://pypi.org/manage/account/publishing/, add a pending publisher: project hindsight-sre, owner DrDroidLab, repository hindsight, workflow release-pypi.yml, environment pypi.
  2. Do the same on https://test.pypi.org/manage/account/publishing/ with environment testpypi.
  3. In repo Settings → Environments, create pypi (recommended: required reviewers and a deployment tag rule of v*) and testpypi.

GHCR
4. Settings → Actions → General → Workflow permissions: the job requests packages: write explicitly, so the default read-only setting is fine. Just make sure the org doesn't block Actions from publishing packages (org Settings → Packages).
5. After the first push, open the hindsight package under the DrDroidLab org, set visibility to Public (new GHCR packages are private, and docker compose pull would fail anonymously), and confirm it's linked to this repo (the OCI source label should link it automatically).

Release
6. Bump the version in pyproject.toml and both version fields in server.json together for each release.
7. Optionally run release-pypi via Run workflow to dry-run on TestPyPI, then push v0.1.0 (it must match pyproject.toml).

MCP Registry (after the first PyPI release is live)
8. Install mcp-publisher from the modelcontextprotocol/registry releases, then from the repo root run mcp-publisher login github (as a DrDroidLab member, for the io.github.DrDroidLab/ namespace) and mcp-publisher publish.

⚠️ The docs site deploys on merge to main, so the new install commands will 404 until v0.1.0 is published. Tag right after merging, or hold the merge until you're ready to tag.

🤖 Generated with Claude Code

dimittal and others added 2 commits November 2, 2026 14:50
- release-pypi.yml: on v* tags, build sdist/wheel, verify the tag matches
  pyproject, check the wheel bundles the UI and sample knowledge, publish
  hindsight-sre to PyPI via Trusted Publishing, and create the GitHub
  release. workflow_dispatch publishes a .devN build to TestPyPI.
- release-image.yml: on v* tags, smoke-test the image, then push
  ghcr.io/drdroidlab/hindsight:<version>, :<major>.<minor> and :latest
  for linux/amd64 and linux/arm64 using GITHUB_TOKEN.
- compose.yaml pulls ghcr.io/drdroidlab/hindsight:latest (overridable with
  HINDSIGHT_IMAGE) and keeps build: . for local builds.
- README and docs: engineers run `uv tool install hindsight-sre` (or pipx);
  team leads fetch the compose files and run `docker compose up -d`.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- README: `mcp-name: io.github.DrDroidLab/hindsight-sre` comment, which
  the registry checks in the PyPI long description.
- Dockerfile and GHCR metadata: io.modelcontextprotocol.server.name label
  and "Hindsight SRE" image title.
- server.json for io.github.DrDroidLab/hindsight-sre (title "Hindsight
  SRE"), a pypi package run as `uvx hindsight-sre mcp-proxy`.
- Add a `hindsight-sre` console script alias so that uvx command resolves.
- Release workflow fails the tag if server.json versions drift from
  pyproject.toml.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@dimittal
dimittal merged commit bb8704f into main Nov 2, 2026
6 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant