Skip to content

[SG-4909] build: publish to PyPI as tirith-iac-governance - #284

Open
refeed wants to merge 1 commit into
mainfrom
pypi/release-prep
Open

[SG-4909] build: publish to PyPI as tirith-iac-governance#284
refeed wants to merge 1 commit into
mainfrom
pypi/release-prep

Conversation

@refeed

@refeed refeed commented Aug 24, 2026

Copy link
Copy Markdown
Member

Makes this repository publishable, and moves every install instruction off git URLs.

Warning

Do not merge until you are ready to tag 1.3.0 straight afterwards. deploy_docs.yml
publishes the docs site on every push to main, and this PR changes those docs to say
pip install tirith-iac-governance — which does not work until the release is actually cut.

Why

Installing tirith means a git URL today. That needs git and the network at build time, resolves no
wheels, and put us one deleted branch away from an unbuildable image — which already happened
once
.
Three separate CI integrations each carry a comment explaining why pip install tirith is the wrong
command.

The name

tirith-iac-governance — matching the action, the wfstep, the GitLab component and the step
template /stackguardian/tirith-iac-governance:1. Verified free on both indexes before choosing it.

The import and the console script are still tirith. pip install tirith still installs an
unrelated monitoring project that has held that name since October 2016, so the README says so
plainly rather than leaving people to discover it.

py-tirith, the name setup.py declared until now, stays reserved on both indexes — it costs
nothing and appears throughout years of our own git pins.

Packaging, in order of how badly it was needed

pyproject.toml had no [build-system] table at all builds fell back to legacy setup.py semantics against whatever setuptools was around
the version lived in two files kept in step by hand, with nothing asserting they agreed. setup.py now reads src/tirith/__init__.py, which is what tirith --version already reported
license="Apache" not an SPDX identifier, and LICENSE was never declared
classifiers claimed 3.8/3.9 and Pre-Alpha CI tests 3.8–3.12, and this ships in production pipelines
MANIFEST.in listed four directories that this repository does not have
setup_requires=["pytest-runner"] deprecated, and forces a download at install time for a runner nothing invokes

Left alone deliberately: the package_data for tirith.tui and the tui extra's
python_version >= "3.9" markers. Both correct, both load-bearing.

The release workflow

release-pypi.yml publishes over Trusted Publishing, so there is no API token anywhere —
id-token: write is granted to the publish job alone.

It triggers on bare semver, matching every tag since 1.0.0-beta.2; tools/bump_version.py had
been printing instructions for a v prefix that no tag has used since 2022, now fixed to agree.

Two guards earn their place:

  • guard refuses to publish when the tag and the shipped version disagree. A PyPI version can be
    yanked but never replaced, so this has to fail before anything is built.
  • the wheel data-file check asserts the TUI stylesheet and bundled examples are inside. A wheel
    missing them still installs and still starts — it renders unstyled with an empty playground, which
    is a worse failure than not starting, and one no import check would catch.

Build & test triggers on bare push: so it already fires on a tag, but nothing gates on it — hence
publish needs build needs test explicitly.

Verified locally

  • python -m build → sdist + wheel, twine check PASSED on both (which also validates the
    README renders as a PyPI description — it cannot be corrected after upload)
  • metadata reads Name: tirith-iac-governance, Version: 1.3.0, License: Apache-2.0
  • the wheel carries tirith/tui/app.css and all five bundled examples
  • clean venv: tirith --version1.3.0, import tirith works, and a real policy evaluates
    against tests/providers/infracost/
  • pip install '<wheel>[tui]' resolves app.css through importlib.resources
  • 754 tests pass. The 10 failures on my machine are the skipif(is_on_github_actions())
    terraform-binary tests, which CI skips and which fail here only because terraform is not installed
  • black --check clean across 108 files; the Docusaurus site builds with no broken links

Not in this PR

Tagging and publishing; and flipping the action, the wfstep and the GitLab component off their git
pins — each needs its own guard rewritten in the same commit, so none of them can be split off
casually. Details in SG-4909.

Until now the only way to install tirith was a git URL. That needs git and the
network at build time, resolves no wheels, and put us one deleted branch away
from an unbuildable image -- which already happened once. Every consumer,
including three separate CI integrations, carried a comment explaining why
`pip install tirith` is the wrong command.

The distribution is `tirith-iac-governance`, matching the action, the wfstep,
the GitLab component and the step template. The import and the console script
are still `tirith`. `pip install tirith` still gets an unrelated project that
has held the name on PyPI since 2016, so the README says so plainly rather than
leaving people to find out.

Packaging, in order of how badly it was needed:

- pyproject.toml had no [build-system] at all, so builds fell back to legacy
  setup.py semantics against whatever setuptools was around.
- The version lived in two files kept in step by hand, and nothing asserted
  they agreed. setup.py now reads src/tirith/__init__.py, which is what
  `tirith --version` already reported.
- license="Apache" was not an SPDX identifier; LICENSE was never declared.
- The classifiers advertised 3.8 and 3.9 while CI tested 3.8 through 3.12, and
  claimed Pre-Alpha on a release used in production pipelines.
- MANIFEST.in listed four directories this repository does not have.
- setup_requires=["pytest-runner"] is deprecated and forced a download on
  install for a runner nothing invokes.

release-pypi.yml publishes over Trusted Publishing, so there is no API token
anywhere. It triggers on bare semver, matching every tag since 1.0.0-beta.2 --
bump_version.py had been printing instructions for a `v` prefix that no tag has
used since 2022. A guard job refuses to publish when the tag and the shipped
version disagree, because a PyPI version can be yanked but never replaced, and
a build job asserts the wheel carries the TUI stylesheet and examples: without
them the interface still starts, unstyled and with an empty playground, which
no import check would catch.

Docs, README and the install hints printed at runtime all move to the PyPI
command. The README's four screenshots and four relative links are now absolute
-- PyPI renders that file as the project description and resolves neither.
@notion-workspace

Copy link
Copy Markdown

@sonarqubecloud

Copy link
Copy Markdown

❌ The last analysis has failed.

See analysis details on SonarQube Cloud

@codecov

codecov Bot commented Aug 24, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.

Files with missing lines Coverage Δ
src/tirith/__init__.py 100.00% <100.00%> (ø)
src/tirith/tui/__init__.py 50.00% <ø> (ø)
src/tirith/tui/cli.py 66.66% <ø> (ø)
src/tirith/tui/examples.py 84.74% <ø> (ø)
🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR updates the project’s packaging and documentation to support publishing to PyPI under the new distribution name tirith-iac-governance (while keeping the import/module/CLI name as tirith), and removes install instructions that rely on git URLs.

Changes:

  • Updates packaging metadata (distribution name, version sourcing, license metadata, build-system) to make builds PEP 517–compliant and publishable.
  • Updates TUI/help text, tests, and docs to instruct pip install tirith-iac-governance / pip install 'tirith-iac-governance[tui]'.
  • Adds a GitHub Actions workflow to build/test/validate artifacts and publish via Trusted Publishing.

Reviewed changes

Copilot reviewed 18 out of 18 changed files in this pull request and generated 3 comments.

Show a summary per file
File Description
tools/bump_version.py Uses src/tirith/__init__.py as the single version source; updates tagging instructions.
tests/tui/test_ui_cli.py Updates expected messaging to reference the new PyPI distribution name.
tests/tui/test_app.py Updates importorskip reason text to the new install command.
src/tirith/tui/examples.py Updates docstring text to the new distribution name.
src/tirith/tui/cli.py Updates TUI-extra install instructions (removes git URL).
src/tirith/tui/init.py Updates missing-extra hint to the new distribution name.
src/tirith/init.py Bumps version to 1.3.0.
setup.py Renames distribution, reads version from src/tirith/__init__.py, corrects license metadata, classifiers, and removes deprecated setup_requires.
README.md Replaces git URL installs with PyPI installs; makes links render on PyPI by using absolute URLs.
pyproject.toml Adds [build-system] to make builds PEP 517 compliant/reproducible.
MANIFEST.in Cleans up sdist manifest; ensures LICENSE and TUI data files are included.
documentation/src/pages/index.js Updates install command shown on the docs homepage.
documentation/docs/tirith-usage/interactive-interface.md Updates TUI install instructions to the new distribution name.
documentation/docs/tirith-usage/ci-integration.md Updates CI install instructions to use pinned PyPI versions.
documentation/docs/tirith-installation/quick-intallation.md Updates quick install steps to use PyPI and removes git prerequisite.
documentation/docs/getting-started-with-tirith.md Updates install command for the interactive interface.
CHANGELOG.md Adds a 1.3.0 entry and documents packaging changes and new install name.
.github/workflows/release-pypi.yml Adds a release pipeline (guard/test/build/publish) using OIDC Trusted Publishing.

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment on lines +14 to +16
# Bare semver, because that is what every tag since 1.0.0-beta.2 uses. The two `v`-prefixed
# tags are from 2022 and abandoned. The trailing `*` catches prereleases like 1.3.0-beta.1.
tags: ["[0-9]+.[0-9]+.[0-9]+*"]
Comment on lines +92 to +96
css = [n for n in names if n.endswith("tui/app.css")]
examples = [n for n in names if "/tui/examples/" in n and n.endswith(("about.md", "policy.json", "input.json"))]
print(f"stylesheet={css} example files={len(examples)}")
if not css or len(examples) < 3:
sys.exit("wheel is missing TUI package data")
Comment thread src/tirith/__init__.py
__version__ = "1.2.0"
__version__ = "1.3.0"
__author__ = "StackGuardian"
__license__ = "Apache"
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.

4 participants