Skip to content

fix(distribution): preserve exact releases and make publication retryable - #283

Merged
lemon07r merged 8 commits into
masterfrom
fix/release-hosted-recovery
Sep 30, 2026
Merged

lemon07r merged 8 commits into
masterfrom
fix/release-hosted-recovery

Conversation

@lemon07r

@lemon07r lemon07r commented Sep 29, 2026 •

Copy link
Copy Markdown
Collaborator

Release retries could replace published assets, downgrade rolling tags, or block PyPI behind npm. This change preserves existing release assets and versioned images, verifies Docker archives against the exact release manifest, serializes each publication channel, and promotes only the newest published stable release. npm and PyPI now have separate retryable jobs. Manual recovery uses explicit tag checkout and can select GitHub-hosted runners; a nonpublishing mode rehearses all six binary targets and package builds from an exact commit.

The dependency refresh uses Rust 1.88 compatibility fallback. It updates 79 compatible version families, including Tantivy 0.26.2, tree-sitter 0.26.13, reqwest 0.13.5 and console 0.16.6. Release compiler, Zig, build tools, Actions, grammar revisions/checksums, and existing Docker base families are pinned. HCL uses its existing audited Git revision. model2vec, ONNX Runtime/ort, tokenizers and GPU runtime floors remain unchanged because their newer versions require behavior or hardware migration evidence. Tantivy 0.26.2 still uses lru 0.16.4, so its narrowly justified advisory waiver remains, alongside the two existing unmaintained transitive dependency waivers.

Both wrappers now run verified caches offline, select the exact requested release, publish downloads atomically, bound requests, validate archives without unsafe bulk extraction, quote shims safely, and preserve child exit/signal behavior. No runtime dependency was added. Node 18 and Python 3.9 remain supported, with Linux and Windows regression jobs.

Validation: locked workspace tests, all-target Clippy/check, formatting, dependency/security/usage checks; 15 release-tool fixtures and local wrapper fixtures; Actionlint with ShellCheck. The test run exposed a pre-existing process-global hydration counter race; the counter now belongs to its test-only metadata store. The full 1,251-task Semble comparison has exact equality for all 12,510 ordered paths, line spans and scores, with unchanged retrieval metrics; frozen fixture JSON/content/raw scores also match. CI36670853279 passed stable, actual Rust1.88, Windows and Linux/Windows Node18+Python3.9 floors. Nonpublishing rehearsal36670324320 passed all13 jobs and all6 archives: exact manifest hashes/layout verified, GNUglibc2.28 and staticmusl checked, npm package and Python wheel/sdist validated. A final prerelease fix preserves the raw GitHub tag in the Python package despite PyPI normalization; an actual prerelease wheel/sdist build and Twine check pass. Final candidate82382c0 passed all6CI jobs in36671953456, including actualRust1.88 and Linux/Windows runtimefloors.

Release tooling deliberately runs on pinned Python3.11 or the Ubuntu24.04 system Python; its type unions and hashlib.file_digest do not belong to the Python3.9 wrapper runtime. No committed package version bump is introduced. The release helper and workflow accept hyphenated prerelease tags. Docker recovery uses current workflow recipes with the verified historical binary. Push builds compare checkout against the event commit, while publication retries independently reject changed published assets.

Copilot AI balanced review requested due to automatic review settings September 29, 2026 21:53

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.

Copilot was unable to review this pull request because the user who requested the review has reached their quota limit.

@coderabbitai

coderabbitai Bot commented Sep 29, 2026 •

Copy link
Copy Markdown

Review in Change Stack →

Navigate logical layers of code changes, visualize relationships, and explore their blast radius.

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Repository: VeraTools/vera/.coderabbit.yaml

Review profile: ASSERTIVE

Plan: Advanced

Run ID: 70b19280-386b-4a0e-8cf9-a73ee39db8c8

📥 Commits

Reviewing files that changed from the base of the PR and between 68806fd and b814c8b.

📒 Files selected for processing (2)
  • .github/workflows/release.yml
  • CONTRIBUTING.md

Included review availability: This review used your included allowance. Your plan provides up to 2 included reviews per hour; 1 remain after this review.


📝 Walkthrough

Walkthrough

The release workflow accepts a manually selected tag or uses the pushed tag. It supports GitHub-hosted runners for build, release, and Docker jobs. It uses the selected tag for checkout, version extraction, release preparation, publication, and Docker image versioning.

Changes

Release workflow

Layer / File(s) Summary
Tag selection and build validation
.github/workflows/release.yml, CONTRIBUTING.md
The workflow accepts a manual tag, sets RELEASE_TAG, and serializes releases by tag. Build jobs can use GitHub-hosted runners, check out the selected tag, and validate its format and commit. The guide explains how to dispatch a recovery run with an existing tag.
Release preparation and publication
.github/workflows/release.yml
The release job can use GitHub-hosted runners. It uses RELEASE_TAG for checkout, package version extraction, manifest and changelog generation, release publication, and prerelease detection.
Docker build tag and runner selection
.github/workflows/release.yml
Docker jobs can use GitHub-hosted runners and use RELEASE_TAG for checkout and image version extraction.

Priority: ➖ Normal

Estimated code review effort: 3 (Moderate) | ~20 minutes

Change: Feature

Merge Risk: ⚪ Minimal · up to b814c

No actionable release-workflow issue is established; the change is ready to merge subject to normal checks.

Security Architecture Review

Security architecture risk: 🟡 Moderate · up to b814c

The recovery path preserves existing publishing permissions, but its newest-tag restriction is only documented: selecting an older tag can roll back shared Docker image tags. Publication also resolves the tag again rather than using one verified commit throughout. These risks depend on trusted release operations; dispatch authorization and tag protections could not be confirmed.

Retained concerns

  • Medium · security · observed: The new recovery entrypoint accepts older valid tags and publishes them to the shared cpu, cuda, rocm, and openvino Docker tags. The documented newest-tag restriction is not enforced. Serialization does not prevent an older recovery from replacing a newer image, potentially undoing security fixes for consumers of those mutable tags. Unconditional mutable publication predates this PR, but manual historical-tag recovery newly exposes it without another tag push.
  • Medium · security · inferred: Each build and publisher independently resolves the selected tag; build validation checks only its local checkout against its local tag reference. No verified commit is passed to downstream checkouts. If an actor can move the tag during execution, artifacts and secret-bearing publication code can come from different commits under the same version. This is conditional on tag mutation being permitted; publication authority already existed, and no new credential scope is demonstrated.
Security review details

Security Blast Radius

  • observed — The publication boundary covers repository release assets, npm and PyPI wrapper publication, and four GHCR image variants, including their shared mutable tags. Exact package-token scope and the population of downstream consumers are not established by the workflow.

Security Findings and Attack Paths

  • inferred — An authorized dispatcher can select a historical version and replace shared Docker tags with older binaries. No tag mutation is needed. The GitHub Release latest check does not govern Docker publication, so consumers following those image tags can receive a rollback even when the recovered release is not marked latest.
  • inferred — If tag mutation is permitted, changing the selected tag between checkouts can substitute publication sources after a successful build. Selected-tag manifest and package code executes with npm/PyPI credentials available. This is not an anonymous attack path, and a tag writer already had substantial release authority in the parent workflow.

Trust Boundaries and Controls

  • observed — The tag input is passed through the environment and validated in Bash rather than interpolated into executable shell source. Both publisher jobs wait for build success. These controls establish format and ordering, but not release freshness or a single immutable commit identity.

Resilience and Maintainability Implications

  • inferred — Per-variant concurrency limits simultaneous mutable image publication. The Docker retry prunes its builder and republishes both tag forms, but interruption between pushes can leave mutable and versioned tags inconsistent; there is no compensating rollback in the workflow. This pre-existing behavior remains relevant when recovering a partially completed release.

Hardening Proposals

  • proposed — Resolve the selected tag once and bind every build and publication checkout to that commit. Enforce newest-only recovery until historical recovery can publish versioned outputs without rolling back mutable channels; perform mutable-channel promotion under its publication lock.
🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check. Docstring coverage is scoped to functions touched by this diff. Analyzed 0 functions across 0…
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly describes the main changes: preserving exact releases and enabling retryable publication.

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@lemon07r
lemon07r force-pushed the fix/release-hosted-recovery branch from 1292ebc to b814c8b Compare September 29, 2026 21:54

@devin-ai-integration devin-ai-integration Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Devin Review found 1 potential issue.

Devin Review

Comment on lines +6 to +15
workflow_dispatch:
inputs:
tag:
description: 'Existing release tag to publish (never moves the tag)'
required: true
type: string
use_github_runners:
description: 'Use GitHub-hosted runners when Blacksmith is unavailable'
type: boolean
default: false

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🔴 Older recovery replaces current Docker images

Dispatching an older tag makes docker push its binaries to the mutable image tags. Those tags then serve the older release instead of the latest one.

Learn more

The manual dispatch accepts any existing tag, while Build and push and the daemon retry both publish the mutable variant tags. The release job already determines whether the requested tag is latest, but that result is not available to the Docker job. An older release can therefore replace the current images even though its versioned image tags are correct.

Example: After v1.4.2 publishes ghcr.io/veratools/vera:cpu, dispatch v1.4.1 for recovery. Its Docker job republishes :cpu with v1.4.1, so consumers pulling :cpu get the older binary.

Recommended fix: Determine whether RELEASE_TAG is the latest eligible release before Docker publication. Publish mutable variant tags only for the latest release in both the Buildx and daemon paths; continue publishing version-specific tags for older releases.

Devin Review


Was this helpful? React with 👍 or 👎 to provide feedback.

@cubic-dev-ai cubic-dev-ai Bot left a comment •

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

3 issues found and verified against the latest diff

Prompt for AI agents (unresolved issues)

Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.


<file name=".github/workflows/release.yml">

<violation number="1" location=".github/workflows/release.yml:86">
P2: The hosted-runner recovery now uses the historical tag’s Dockerfiles, so a tag created before a Dockerfile or base-image fix cannot use that fix and may fail recovery. Keep this checkout on `${{ github.ref }}`; the downloaded binary remains pinned by `RELEASE_TAG`.</violation>

<violation number="2" location=".github/workflows/release.yml:92">
P2: This regex rejects valid hyphenated prerelease tags such as `v1.2.3-rc-1`, so those releases now fail before building. Allow hyphens in prerelease identifiers.</violation>

<violation number="3" location=".github/workflows/release.yml:93">
P3: The commit comparison in `Verify release tag` is tautological: since `actions/checkout@v4` was told to check out `ref: refs/tags/${{ env.RELEASE_TAG }}`, `HEAD` is by construction the tag's commit, so `git rev-parse HEAD` always equals `refs/tags/...^{commit}`. The check cannot detect a moved tag or an incorrect commit, which is the integrity failure the PR description claims it guards against. Keep the version-shape regex (that is the effective validation) and either drop the equality test or document it as a defense-in-depth check against a checkout malfunction rather than as commit validation.</violation>
</file>

Reply with feedback, questions, or to request a fix.

Re-trigger cubic

Comment thread .github/workflows/release.yml Outdated
steps:
- uses: actions/checkout@v4
with:
ref: refs/tags/${{ env.RELEASE_TAG }}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

P2: The hosted-runner recovery now uses the historical tag’s Dockerfiles, so a tag created before a Dockerfile or base-image fix cannot use that fix and may fail recovery. Keep this checkout on ${{ github.ref }}; the downloaded binary remains pinned by RELEASE_TAG.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At .github/workflows/release.yml, line 86:

<comment>The hosted-runner recovery now uses the historical tag’s Dockerfiles, so a tag created before a Dockerfile or base-image fix cannot use that fix and may fail recovery. Keep this checkout on `${{ github.ref }}`; the downloaded binary remains pinned by `RELEASE_TAG`.</comment>

<file context>
@@ -28,39 +43,54 @@ jobs:
     steps:
       - uses: actions/checkout@v4
+        with:
+          ref: refs/tags/${{ env.RELEASE_TAG }}
+          fetch-depth: 0
+
</file context>

Comment thread .github/workflows/release.yml Outdated
- name: Verify release tag
shell: bash
run: |
[[ "$RELEASE_TAG" =~ ^v[0-9]+\.[0-9]+\.[0-9]+(-[a-zA-Z0-9.]+)?$ ]]

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

P2: This regex rejects valid hyphenated prerelease tags such as v1.2.3-rc-1, so those releases now fail before building. Allow hyphens in prerelease identifiers.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At .github/workflows/release.yml, line 92:

<comment>This regex rejects valid hyphenated prerelease tags such as `v1.2.3-rc-1`, so those releases now fail before building. Allow hyphens in prerelease identifiers.</comment>

<file context>
@@ -28,39 +43,54 @@ jobs:
+      - name: Verify release tag
+        shell: bash
+        run: |
+          [[ "$RELEASE_TAG" =~ ^v[0-9]+\.[0-9]+\.[0-9]+(-[a-zA-Z0-9.]+)?$ ]]
+          test "$(git rev-parse HEAD)" = "$(git rev-parse "refs/tags/$RELEASE_TAG^{commit}")"
 
</file context>
Suggested change
[[ "$RELEASE_TAG" =~ ^v[0-9]+\.[0-9]+\.[0-9]+(-[a-zA-Z0-9.]+)?$ ]]
[[ "$RELEASE_TAG" =~ ^v[0-9]+\.[0-9]+\.[0-9]+(-[a-zA-Z0-9-]+(\.[a-zA-Z0-9-]+)*)?$ ]]

Comment thread .github/workflows/release.yml Outdated
Comment thread .github/workflows/release.yml Outdated
shell: bash
run: |
[[ "$RELEASE_TAG" =~ ^v[0-9]+\.[0-9]+\.[0-9]+(-[a-zA-Z0-9.]+)?$ ]]
test "$(git rev-parse HEAD)" = "$(git rev-parse "refs/tags/$RELEASE_TAG^{commit}")"

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

P3: The commit comparison in Verify release tag is tautological: since actions/checkout@v4 was told to check out ref: refs/tags/${{ env.RELEASE_TAG }}, HEAD is by construction the tag's commit, so git rev-parse HEAD always equals refs/tags/...^{commit}. The check cannot detect a moved tag or an incorrect commit, which is the integrity failure the PR description claims it guards against. Keep the version-shape regex (that is the effective validation) and either drop the equality test or document it as a defense-in-depth check against a checkout malfunction rather than as commit validation.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At .github/workflows/release.yml, line 93:

<comment>The commit comparison in `Verify release tag` is tautological: since `actions/checkout@v4` was told to check out `ref: refs/tags/${{ env.RELEASE_TAG }}`, `HEAD` is by construction the tag's commit, so `git rev-parse HEAD` always equals `refs/tags/...^{commit}`. The check cannot detect a moved tag or an incorrect commit, which is the integrity failure the PR description claims it guards against. Keep the version-shape regex (that is the effective validation) and either drop the equality test or document it as a defense-in-depth check against a checkout malfunction rather than as commit validation.</comment>

<file context>
@@ -28,39 +43,54 @@ jobs:
+        shell: bash
+        run: |
+          [[ "$RELEASE_TAG" =~ ^v[0-9]+\.[0-9]+\.[0-9]+(-[a-zA-Z0-9.]+)?$ ]]
+          test "$(git rev-parse HEAD)" = "$(git rev-parse "refs/tags/$RELEASE_TAG^{commit}")"
 
       - name: Install Rust toolchain
</file context>

@lemon07r lemon07r changed the title fix(release): allow recovery on GitHub-hosted runners fix(distribution): preserve exact releases and make publication retryable Sep 30, 2026

@cubic-dev-ai cubic-dev-ai Bot left a comment •

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

3 issues found across 27 reviewed files. 2 files intentionally excluded from review.

Prompt for AI agents (unresolved issues)

Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.


<file name="scripts/docker_publication.py">

<violation number="1" location="scripts/docker_publication.py:14">
P1: This helper cannot be imported on Python 3.9 because `str | None` is evaluated at definition time and PEP 604 unions require Python 3.10. Use a quoted annotation or `Optional[str]` so the supported Python 3.9 environment can run the release helper.</violation>
</file>

<file name="scripts/release_versions.py">

<violation number="1" location="scripts/release_versions.py:10">
P2: This annotation makes the new release helper fail on Python 3.9 before it can query releases. Quote the union annotation or add `from __future__ import annotations` so the helper keeps the repository's Python 3.9 floor.</violation>
</file>

<file name="packages/python-cli/tests/test_wrapper.py">

<violation number="1" location="packages/python-cli/tests/test_wrapper.py:107">
P3: `read_json` of the self-redirecting URL is expected to fail only after urllib's redirect cap, but `assertRaises(Exception)` would also pass if the request fails earlier for an unrelated reason. Assert `HTTPError` (urllib's `too many redirects` error) or `RuntimeError` instead so the test verifies the redirect bound rather than any failure.</violation>
</file>

Tip: Review your code locally with the cubic CLI to iterate faster.

Re-trigger cubic




def image_digest(image: str) -> str | None:

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

P1: This helper cannot be imported on Python 3.9 because str | None is evaluated at definition time and PEP 604 unions require Python 3.10. Use a quoted annotation or Optional[str] so the supported Python 3.9 environment can run the release helper.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At scripts/docker_publication.py, line 14:

<comment>This helper cannot be imported on Python 3.9 because `str | None` is evaluated at definition time and PEP 604 unions require Python 3.10. Use a quoted annotation or `Optional[str]` so the supported Python 3.9 environment can run the release helper.</comment>

<file context>
@@ -0,0 +1,56 @@
+
+
+
+def image_digest(image: str) -> str | None:
+    result = subprocess.run(
+        ["docker", "buildx", "imagetools", "inspect", image, "--format", "{{json .Manifest.Digest}}"],
</file context>
Suggested change
def image_digest(image: str) -> str | None:
def image_digest(image: str) -> "str | None":

Comment thread packages/python-cli/src/vera_ai_wrapper/__main__.py
Comment thread scripts/tests/test_release_tools.py
import sys


def newest_stable(releases: list[dict]) -> str | None:

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

P2: This annotation makes the new release helper fail on Python 3.9 before it can query releases. Quote the union annotation or add from __future__ import annotations so the helper keeps the repository's Python 3.9 floor.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At scripts/release_versions.py, line 10:

<comment>This annotation makes the new release helper fail on Python 3.9 before it can query releases. Quote the union annotation or add `from __future__ import annotations` so the helper keeps the repository's Python 3.9 floor.</comment>

<file context>
@@ -0,0 +1,32 @@
+import sys
+
+
+def newest_stable(releases: list[dict]) -> str | None:
+    versions = {}
+    for release in releases:
</file context>
Suggested change
def newest_stable(releases: list[dict]) -> str | None:
def newest_stable(releases: list[dict]) -> "str | None":

Comment thread scripts/tests/test_release_helper.py
self.assertEqual(len(self.seen), 2)

def test_requested_version_never_falls_back_to_latest(self):
with self.assertRaises(Exception):

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

P3: read_json of the self-redirecting URL is expected to fail only after urllib's redirect cap, but assertRaises(Exception) would also pass if the request fails earlier for an unrelated reason. Assert HTTPError (urllib's too many redirects error) or RuntimeError instead so the test verifies the redirect bound rather than any failure.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At packages/python-cli/tests/test_wrapper.py, line 107:

<comment>`read_json` of the self-redirecting URL is expected to fail only after urllib's redirect cap, but `assertRaises(Exception)` would also pass if the request fails earlier for an unrelated reason. Assert `HTTPError` (urllib's `too many redirects` error) or `RuntimeError` instead so the test verifies the redirect bound rather than any failure.</comment>

<file context>
@@ -0,0 +1,285 @@
+        self.assertEqual(len(self.seen), 2)
+
+    def test_requested_version_never_falls_back_to_latest(self):
+        with self.assertRaises(Exception):
+            wrapper.ensure_binary_installed()
+        self.assertEqual(self.seen, ["/releases/download/v1.4.0/release-manifest.json"])
</file context>

Comment thread packages/python-cli/tests/test_wrapper.py Outdated

@cubic-dev-ai cubic-dev-ai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

1 issue found across 6 files (changes from recent commits).

Prompt for AI agents (unresolved issues)

Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.


<file name="packages/python-cli/pyproject.toml">

<violation number="1" location="packages/python-cli/pyproject.toml:30">
P3: The file this config references, `release-version.txt`, is generated by release.yml into `packages/python-cli/src/vera_ai_wrapper/` at build time and is not tracked by git or covered by `.gitignore` (git check-ignore confirms). Any local or CI-dev `python -m build` leaves it in the working tree, polluting `git status` and risking an accidental commit of a stale exact tag that `package_version()` would then prefer. Add it to `.gitignore`.</violation>
</file>

Tip: Review your code locally with the cubic CLI to iterate faster.

Re-trigger cubic

where = ["src"]

[tool.setuptools.package-data]
vera_ai_wrapper = ["release-version.txt"]

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

P3: The file this config references, release-version.txt, is generated by release.yml into packages/python-cli/src/vera_ai_wrapper/ at build time and is not tracked by git or covered by .gitignore (git check-ignore confirms). Any local or CI-dev python -m build leaves it in the working tree, polluting git status and risking an accidental commit of a stale exact tag that package_version() would then prefer. Add it to .gitignore.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At packages/python-cli/pyproject.toml, line 30:

<comment>The file this config references, `release-version.txt`, is generated by release.yml into `packages/python-cli/src/vera_ai_wrapper/` at build time and is not tracked by git or covered by `.gitignore` (git check-ignore confirms). Any local or CI-dev `python -m build` leaves it in the working tree, polluting `git status` and risking an accidental commit of a stale exact tag that `package_version()` would then prefer. Add it to `.gitignore`.</comment>

<file context>
@@ -25,3 +25,6 @@ package-dir = {"" = "src"}
 where = ["src"]
+
+[tool.setuptools.package-data]
+vera_ai_wrapper = ["release-version.txt"]
</file context>

@lemon07r
lemon07r merged commit 5cf0ba0 into master Sep 30, 2026
7 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.

2 participants