From 7c37693a7b6e8449794e4d9498a4dd30f356b0b8 Mon Sep 17 00:00:00 2001 From: Rafid Aslam Date: Tue, 8 Sep 2026 06:19:33 +0700 Subject: [PATCH 1/2] chore(release): 1.2.1 Promote the `Unreleased` changelog section, bump `setup.py` and `src/tirith/__init__.py`, and move the documentation's install pins onto the new tag. `tirith lint`, `tirith fmt`, the pre-commit hooks and `tirith ui` have been on `main` since 1.2.0 and were unreachable from a pinned install, so the editor page carried a note telling readers to install from `main` instead. The release contains them; the note goes, and the pre-commit `rev:` moves from `main` to the tag that publishes the hooks. The README's install-verification output is pinned to `__version__` by `tests/test_readme_is_current.py`, so it moves with the bump. Closes https://github.com/StackGuardian/tirith/issues/371 --- CHANGELOG.md | 2 +- README.md | 2 +- docs/platform-check.md | 2 +- .../docs/tirith-usage/ci-integration.md | 12 +++++----- .../docs/tirith-usage/cli-reference.md | 2 +- .../docs/tirith-usage/editor-and-local.md | 10 +------- .../docs/tirith-usage/ci-integration.md | 12 +++++----- .../static/docs/tirith-usage/cli-reference.md | 2 +- .../docs/tirith-usage/editor-and-local.md | 9 +------- documentation/static/llms-full.txt | 23 +++++++------------ setup.py | 2 +- src/tirith/__init__.py | 2 +- 12 files changed, 29 insertions(+), 51 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index e1d23841..b39d9b96 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,7 +8,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 -## [Unreleased] +## [1.2.1] - 2026-09-08 ### Added - `tirith lint`: check policy files for the mistakes that otherwise reach CI looking like real diff --git a/README.md b/README.md index 9fb57211..72b798c4 100644 --- a/README.md +++ b/README.md @@ -179,7 +179,7 @@ pip install -e . ``` tirith --version -tirith 1.2.0 +tirith 1.2.1 ``` Congratulations! Tirith has been setup in your system diff --git a/docs/platform-check.md b/docs/platform-check.md index 54eae4ec..ed424d71 100644 --- a/docs/platform-check.md +++ b/docs/platform-check.md @@ -71,7 +71,7 @@ fabricated one would be worse than an honest `null`. ```json { "schema_version": 1, - "generator": {"name": "tirith", "version": "1.2.0"}, + "generator": {"name": "tirith", "version": "1.2.1"}, "created_at": "2026-08-12T09:14:03Z", "input_kind": "terraform_plan", "origin": {"kind": "ci", "trigger_type": "tirith", "ci_run_url": "https://github.com/acme/infra/actions/runs/1"}, diff --git a/documentation/docs/tirith-usage/ci-integration.md b/documentation/docs/tirith-usage/ci-integration.md index eee22147..b3ad36c8 100644 --- a/documentation/docs/tirith-usage/ci-integration.md +++ b/documentation/docs/tirith-usage/ci-integration.md @@ -119,7 +119,7 @@ policy: image: python:3.12 needs: [plan] script: - - pip install "git+https://github.com/StackGuardian/tirith.git@1.2.0" + - pip install "git+https://github.com/StackGuardian/tirith.git@1.2.1" - tirith -policy-path .tirith/policies -input-path plan.json --fail-on-error ``` @@ -129,7 +129,7 @@ will never come, and the job hangs instead of failing. Tirith is **not on PyPI** — `pip install tirith` installs an unrelated project of the same name. Install from git, and pin a tag rather than tracking the default branch so a CI job cannot change -behaviour underneath you. `1.2.0` is the newest tag; +behaviour underneath you. `1.2.1` is the newest tag; `git ls-remote --tags https://github.com/StackGuardian/tirith.git` lists them. Python 3.8 or newer. To evaluate your organization's policies instead of the committed files, swap the last line for @@ -142,7 +142,7 @@ policy: variables: SG_ORG: my-org # SG_API_TOKEN comes from a masked CI/CD variable script: - - pip install "git+https://github.com/StackGuardian/tirith.git@1.2.0" + - pip install "git+https://github.com/StackGuardian/tirith.git@1.2.1" - tirith platform check --workflow-id my-repo --input-path plan.json --fail-on-error ``` @@ -154,7 +154,7 @@ Nothing above is GitLab-specific: any runner that can execute a container and pr the same way. The recipe is always the same three steps — 1. produce the input document (`terraform show -json tfplan > plan.json`); -2. `pip install "git+https://github.com/StackGuardian/tirith.git@1.2.0"`; +2. `pip install "git+https://github.com/StackGuardian/tirith.git@1.2.1"`; 3. `tirith -policy-path -input-path plan.json --fail-on-error` — and gate the job on the exit code, which every CI system does by default for a non-zero exit. @@ -182,7 +182,7 @@ pipelines: - step: name: Policy gate script: - - pip install "git+https://github.com/StackGuardian/tirith.git@1.2.0" + - pip install "git+https://github.com/StackGuardian/tirith.git@1.2.1" - tirith lint .tirith/policies # needs a build from main until the next release - tirith -policy-path .tirith/policies -input-path plan.json --fail-on-error ``` @@ -226,7 +226,7 @@ Catch a broken policy before it is committed, let alone before CI runs it. Tirit ```yaml title=".pre-commit-config.yaml" repos: - repo: https://github.com/StackGuardian/tirith - rev: main # 1.2.0 predates the hook; pin the first tag that includes it + rev: 1.2.1 # the first tag that publishes the hooks hooks: - id: tirith-lint - id: tirith-fmt diff --git a/documentation/docs/tirith-usage/cli-reference.md b/documentation/docs/tirith-usage/cli-reference.md index b8a726c5..e37d07d3 100644 --- a/documentation/docs/tirith-usage/cli-reference.md +++ b/documentation/docs/tirith-usage/cli-reference.md @@ -139,7 +139,7 @@ passed. This is the flag that makes the command usable as a CI gate; the full co ### `--version` -Prints the version number (for example `1.2.0`) and exits `0`. +Prints the version number (for example `1.2.1`) and exits `0`. ## Output streams diff --git a/documentation/docs/tirith-usage/editor-and-local.md b/documentation/docs/tirith-usage/editor-and-local.md index b7a7af4c..3464a288 100644 --- a/documentation/docs/tirith-usage/editor-and-local.md +++ b/documentation/docs/tirith-usage/editor-and-local.md @@ -13,14 +13,6 @@ site_name: Tirith slug: editor-and-local/ --- -:::note Not in 1.2.0 - -`tirith lint`, `tirith fmt` and the pre-commit hooks are on `main` and will be in the next -release. `pip install "git+https://github.com/StackGuardian/tirith.git@1.2.0"` does not have them; -install from `main` until then. - -::: - CI is the last place a policy should fail. This page is about the loop before that — running Tirith on your own machine, while the code is still being written. @@ -79,7 +71,7 @@ the interactive explorer — is ```yaml title=".pre-commit-config.yaml" repos: - repo: https://github.com/StackGuardian/tirith - rev: main # 1.2.0 predates the hooks; pin the first tag that includes them + rev: 1.2.1 # the first tag that publishes the hooks hooks: - id: tirith-lint - id: tirith-fmt diff --git a/documentation/static/docs/tirith-usage/ci-integration.md b/documentation/static/docs/tirith-usage/ci-integration.md index 89d8b37b..b15a23f4 100644 --- a/documentation/static/docs/tirith-usage/ci-integration.md +++ b/documentation/static/docs/tirith-usage/ci-integration.md @@ -107,7 +107,7 @@ policy: image: python:3.12 needs: [plan] script: - - pip install "git+https://github.com/StackGuardian/tirith.git@1.2.0" + - pip install "git+https://github.com/StackGuardian/tirith.git@1.2.1" - tirith -policy-path .tirith/policies -input-path plan.json --fail-on-error ``` @@ -117,7 +117,7 @@ will never come, and the job hangs instead of failing. Tirith is **not on PyPI** — `pip install tirith` installs an unrelated project of the same name. Install from git, and pin a tag rather than tracking the default branch so a CI job cannot change -behaviour underneath you. `1.2.0` is the newest tag; +behaviour underneath you. `1.2.1` is the newest tag; `git ls-remote --tags https://github.com/StackGuardian/tirith.git` lists them. Python 3.8 or newer. To evaluate your organization's policies instead of the committed files, swap the last line for @@ -130,7 +130,7 @@ policy: variables: SG_ORG: my-org # SG_API_TOKEN comes from a masked CI/CD variable script: - - pip install "git+https://github.com/StackGuardian/tirith.git@1.2.0" + - pip install "git+https://github.com/StackGuardian/tirith.git@1.2.1" - tirith platform check --workflow-id my-repo --input-path plan.json --fail-on-error ``` @@ -142,7 +142,7 @@ Nothing above is GitLab-specific: any runner that can execute a container and pr the same way. The recipe is always the same three steps — 1. produce the input document (`terraform show -json tfplan > plan.json`); -2. `pip install "git+https://github.com/StackGuardian/tirith.git@1.2.0"`; +2. `pip install "git+https://github.com/StackGuardian/tirith.git@1.2.1"`; 3. `tirith -policy-path -input-path plan.json --fail-on-error` — and gate the job on the exit code, which every CI system does by default for a non-zero exit. @@ -170,7 +170,7 @@ pipelines: - step: name: Policy gate script: - - pip install "git+https://github.com/StackGuardian/tirith.git@1.2.0" + - pip install "git+https://github.com/StackGuardian/tirith.git@1.2.1" - tirith lint .tirith/policies # needs a build from main until the next release - tirith -policy-path .tirith/policies -input-path plan.json --fail-on-error ``` @@ -214,7 +214,7 @@ Catch a broken policy before it is committed, let alone before CI runs it. Tirit ```yaml repos: - repo: https://github.com/StackGuardian/tirith - rev: main # 1.2.0 predates the hook; pin the first tag that includes it + rev: 1.2.1 # the first tag that publishes the hooks hooks: - id: tirith-lint - id: tirith-fmt diff --git a/documentation/static/docs/tirith-usage/cli-reference.md b/documentation/static/docs/tirith-usage/cli-reference.md index 23511a93..1691138f 100644 --- a/documentation/static/docs/tirith-usage/cli-reference.md +++ b/documentation/static/docs/tirith-usage/cli-reference.md @@ -132,7 +132,7 @@ passed. This is the flag that makes the command usable as a CI gate; the full co ### `--version` -Prints the version number (for example `1.2.0`) and exits `0`. +Prints the version number (for example `1.2.1`) and exits `0`. ## Output streams diff --git a/documentation/static/docs/tirith-usage/editor-and-local.md b/documentation/static/docs/tirith-usage/editor-and-local.md index f11b37f7..f2ce7b92 100644 --- a/documentation/static/docs/tirith-usage/editor-and-local.md +++ b/documentation/static/docs/tirith-usage/editor-and-local.md @@ -3,13 +3,6 @@ Source: https://stackguardian.github.io/tirith/docs/tirith-usage/editor-and-local/ Summary: VS Code tasks, a pre-commit hook, and the local loop to use when an AI agent is drafting the policy. -[NOTE] Not in 1.2.0 - -`tirith lint`, `tirith fmt` and the pre-commit hooks are on `main` and will be in the next -release. `pip install "git+https://github.com/StackGuardian/tirith.git@1.2.0"` does not have them; -install from `main` until then. - - CI is the last place a policy should fail. This page is about the loop before that — running Tirith on your own machine, while the code is still being written. @@ -68,7 +61,7 @@ the interactive explorer — is ```yaml repos: - repo: https://github.com/StackGuardian/tirith - rev: main # 1.2.0 predates the hooks; pin the first tag that includes them + rev: 1.2.1 # the first tag that publishes the hooks hooks: - id: tirith-lint - id: tirith-fmt diff --git a/documentation/static/llms-full.txt b/documentation/static/llms-full.txt index 1125c52f..f6e7291d 100644 --- a/documentation/static/llms-full.txt +++ b/documentation/static/llms-full.txt @@ -2773,7 +2773,7 @@ passed. This is the flag that makes the command usable as a CI gate; the full co ### `--version` -Prints the version number (for example `1.2.0`) and exits `0`. +Prints the version number (for example `1.2.1`) and exits `0`. ## Output streams @@ -2982,7 +2982,7 @@ policy: image: python:3.12 needs: [plan] script: - - pip install "git+https://github.com/StackGuardian/tirith.git@1.2.0" + - pip install "git+https://github.com/StackGuardian/tirith.git@1.2.1" - tirith -policy-path .tirith/policies -input-path plan.json --fail-on-error ``` @@ -2992,7 +2992,7 @@ will never come, and the job hangs instead of failing. Tirith is **not on PyPI** — `pip install tirith` installs an unrelated project of the same name. Install from git, and pin a tag rather than tracking the default branch so a CI job cannot change -behaviour underneath you. `1.2.0` is the newest tag; +behaviour underneath you. `1.2.1` is the newest tag; `git ls-remote --tags https://github.com/StackGuardian/tirith.git` lists them. Python 3.8 or newer. To evaluate your organization's policies instead of the committed files, swap the last line for @@ -3005,7 +3005,7 @@ policy: variables: SG_ORG: my-org # SG_API_TOKEN comes from a masked CI/CD variable script: - - pip install "git+https://github.com/StackGuardian/tirith.git@1.2.0" + - pip install "git+https://github.com/StackGuardian/tirith.git@1.2.1" - tirith platform check --workflow-id my-repo --input-path plan.json --fail-on-error ``` @@ -3017,7 +3017,7 @@ Nothing above is GitLab-specific: any runner that can execute a container and pr the same way. The recipe is always the same three steps — 1. produce the input document (`terraform show -json tfplan > plan.json`); -2. `pip install "git+https://github.com/StackGuardian/tirith.git@1.2.0"`; +2. `pip install "git+https://github.com/StackGuardian/tirith.git@1.2.1"`; 3. `tirith -policy-path -input-path plan.json --fail-on-error` — and gate the job on the exit code, which every CI system does by default for a non-zero exit. @@ -3045,7 +3045,7 @@ pipelines: - step: name: Policy gate script: - - pip install "git+https://github.com/StackGuardian/tirith.git@1.2.0" + - pip install "git+https://github.com/StackGuardian/tirith.git@1.2.1" - tirith lint .tirith/policies # needs a build from main until the next release - tirith -policy-path .tirith/policies -input-path plan.json --fail-on-error ``` @@ -3089,7 +3089,7 @@ Catch a broken policy before it is committed, let alone before CI runs it. Tirit ```yaml repos: - repo: https://github.com/StackGuardian/tirith - rev: main # 1.2.0 predates the hook; pin the first tag that includes it + rev: 1.2.1 # the first tag that publishes the hooks hooks: - id: tirith-lint - id: tirith-fmt @@ -3252,13 +3252,6 @@ Source: https://stackguardian.github.io/tirith/docs/tirith-usage/editor-and-loca Summary: VS Code tasks, a pre-commit hook, and the local loop to use when an AI agent is drafting the policy. ============================================================================== -[NOTE] Not in 1.2.0 - -`tirith lint`, `tirith fmt` and the pre-commit hooks are on `main` and will be in the next -release. `pip install "git+https://github.com/StackGuardian/tirith.git@1.2.0"` does not have them; -install from `main` until then. - - CI is the last place a policy should fail. This page is about the loop before that — running Tirith on your own machine, while the code is still being written. @@ -3317,7 +3310,7 @@ the interactive explorer — is ```yaml repos: - repo: https://github.com/StackGuardian/tirith - rev: main # 1.2.0 predates the hooks; pin the first tag that includes them + rev: 1.2.1 # the first tag that publishes the hooks hooks: - id: tirith-lint - id: tirith-fmt diff --git a/setup.py b/setup.py index 6dc8be09..517006c9 100644 --- a/setup.py +++ b/setup.py @@ -22,7 +22,7 @@ def read(*names, **kwargs): setup( name="py-tirith", - version="1.2.0", + version="1.2.1", license="Apache", description="Tirith simplifies defining Policy as Code.", long_description_content_type="text/markdown", diff --git a/src/tirith/__init__.py b/src/tirith/__init__.py index 4c2aac77..5b3bf7e1 100644 --- a/src/tirith/__init__.py +++ b/src/tirith/__init__.py @@ -2,6 +2,6 @@ tirith: Execute policies defined using Tirith (StackGuardian Policy Framework) """ -__version__ = "1.2.0" +__version__ = "1.2.1" __author__ = "StackGuardian" __license__ = "Apache" From 10bd6ac31baed6c9980a04f35ac16f89ed20343f Mon Sep 17 00:00:00 2001 From: Rafid Aslam Date: Tue, 8 Sep 2026 06:23:56 +0700 Subject: [PATCH 2/2] style: apply black 25.1.0 to the plan-diff report `Black linting` has been red on `main` since #291 landed: one stray blank line in `platform/report.py` and three call sites Black joins back onto a single line, all of which fit inside the configured 120 columns. Formatting only, no behaviour change; `tests/platform` passes unchanged. The job pins Black 25.1.0 deliberately, so this is what the tree is formatted for rather than whatever is newest today. --- src/tirith/platform/report.py | 1 - tests/platform/test_report_plan_attributes.py | 10 +++++----- tests/platform/test_report_plan_block.py | 4 +--- 3 files changed, 6 insertions(+), 9 deletions(-) diff --git a/src/tirith/platform/report.py b/src/tirith/platform/report.py index 7ccfd8fd..c8db3793 100644 --- a/src/tirith/platform/report.py +++ b/src/tirith/platform/report.py @@ -180,7 +180,6 @@ def _fit_plan_rows(entries): return bare[:PLAN_LINE_LIMIT], hidden_detail, len(bare) - PLAN_LINE_LIMIT - def summarize(policy_results): """ Collapse the results into counts plus a flat finding list. diff --git a/tests/platform/test_report_plan_attributes.py b/tests/platform/test_report_plan_attributes.py index bfb6e434..1108683d 100644 --- a/tests/platform/test_report_plan_attributes.py +++ b/tests/platform/test_report_plan_attributes.py @@ -12,9 +12,7 @@ def _render(changes): - return report.render_markdown( - {}, "COMPLETED", "https://example.invalid/run", plan={"resource_changes": changes} - ) + return report.render_markdown({}, "COMPLETED", "https://example.invalid/run", plan={"resource_changes": changes}) def _fence(body): @@ -106,8 +104,10 @@ def test_the_attribute_that_forces_a_replacement_is_named(): ) fence = _fence(body) assert "# forces replacement" in fence - assert [line for line in fence.splitlines() if "forces replacement" in line][0].lstrip().startswith( - "~ triggers_replace" + assert ( + [line for line in fence.splitlines() if "forces replacement" in line][0] + .lstrip() + .startswith("~ triggers_replace") ) diff --git a/tests/platform/test_report_plan_block.py b/tests/platform/test_report_plan_block.py index 2afd4dba..06118468 100644 --- a/tests/platform/test_report_plan_block.py +++ b/tests/platform/test_report_plan_block.py @@ -281,8 +281,6 @@ def test_the_plan_is_dropped_before_any_finding(): ] } plan = _plan(*[_change(f"aws_s3_bucket.b{i}", ["create"]) for i in range(20)]) - body = report.render_markdown( - results, "COMPLETED", "https://example.invalid/run", plan=plan, limit=3000 - ) + body = report.render_markdown(results, "COMPLETED", "https://example.invalid/run", plan=plan, limit=3000) assert "```diff" not in body assert "policy-a" in body