Skip to content

ci: add GitHub Actions workflow and fix packaging metadata - #6

Merged
danieyal merged 2 commits into
masterfrom
chore/ci-and-packaging
Jul 22, 2026
Merged

ci: add GitHub Actions workflow and fix packaging metadata#6
danieyal merged 2 commits into
masterfrom
chore/ci-and-packaging

Conversation

@danieyal

@danieyal danieyal commented Jul 22, 2026

Copy link
Copy Markdown
Owner

Phase 6b, part 1. Stacked on #5merge that first, and this PR's base retargets to master automatically. The diff shown here is only the CI/packaging work.

CI

.github/workflows/ci.yml, three jobs:

  • lintruff check, ruff format --check, mypy src/myinvois
  • testpytest -m "not live" across Python 3.11 / 3.12 / 3.13
  • packageuv build + scripts/check_dist.py, uploads the dists as an artifact

UV_LOCKED=1 so a stale uv.lock fails the build rather than silently resolving something other than what we run locally. Note UV_LOCKED, not UV_FROZEN--frozen skips re-locking without checking, which is not the guarantee we want.

Packaging bugs this surfaced

  • [project.urls] shipped placeholders. https://github.com/your-org/myinvois was being baked into the wheel METADATA and would have gone out with the first PyPI release. Corrected to danieyal/myinvois-python.
  • Development Status classifier 3 - Alpha4 - Beta, matching the README.

scripts/check_dist.py

Guards two mistakes that are unrecoverable once published, since a PyPI version can never be reused:

  1. py.typed and codes/_data/*.json ship only because of the data-includes entry. If that regresses the build still succeeds, but myinvois.codes raises at runtime on a wheel install and type-checkers silently ignore the package.
  2. The test signing key/cert must never ship. They are force-tracked in git for the byte-parity tests, which makes an accidental include plausible.

This also closes CERTIFY_BEFORE_PUBLIC from the Phase 4 notes — previously an open worry, now verified (neither wheel nor sdist ships tests/ or tests/fixtures/cert/*) and enforced in CI.

Formatting drift — please read

ruff format --check was already failing on 4 files on master before this PR: _async_client.py, services/async_document_types.py, services/models.py, tests/unit/test_async_client.py. All four were wrapped at ruff's default 88 columns instead of this project's configured line-length = 100 — i.e. Phase 6a (#4) was merged without ruff format ever being run against the project config. CI would have been red on arrival, so the fix is included here. It is pure line-rejoining, no semantic change.

Consequence worth noting: AGENTS.md had been asserting "ruff check, ruff format --check, mypy src all clean" while the format gate was red, and I repeated that claim in #5. AGENTS.md now records the drift and warns against copying a green-gates claim forward without re-running the commands.

Verification

Both new guards were negative-tested rather than assumed to work:

  • Tampering a wheel (drop py.typed, add a .pem) → both check_dist.py failure classes fire with actionable messages.
  • Adding a dependency without re-locking → the UV_LOCKED gate fires.

All four gates green locally: ruff check, ruff format --check, mypy src/myinvois, 284 tests.

Still TODO in Phase 6b

PyPI Trusted Publishing (gated on the package job — outward-facing, so worth confirming before the first publish), the remaining 7 document types, live sandbox verification, and the async test coverage gap noted in #5.

🤖 Generated with Claude Code

Summary by CodeRabbit

  • New Features
    • Added a pre-publish distribution verification step to ensure required runtime/type assets are included and sensitive or test/certificate-related files are excluded from shipped artifacts.
  • Documentation
    • Updated release-readiness/Phase 6b status guidance and clarified formatting drift and CI gate behavior.
    • Expanded CI documentation, including the CI job breakdown and lockfile-consistent install settings.
    • Updated project links and release configuration notes.
  • Chores
    • Updated PyPI “Development Status” classifier to Beta and refined publishing metadata.
    • Enhanced CI coverage: linting, formatting checks, type checks, unit tests (excluding live), and packaging validation.
  • Style
    • Minor formatting-only cleanups in code and unit tests.

@coderabbitai

coderabbitai Bot commented Jul 22, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 945203d3-c77c-4a05-ac4a-367ba304da2b

📥 Commits

Reviewing files that changed from the base of the PR and between d0bf781 and 9b311ef.

📒 Files selected for processing (3)
  • .github/workflows/ci.yml
  • AGENTS.md
  • scripts/check_dist.py
🚧 Files skipped from review as they are similar to previous changes (2)
  • .github/workflows/ci.yml
  • AGENTS.md

📝 Walkthrough

Walkthrough

The change adds GitHub Actions checks for linting, testing, and packaging; introduces distribution-content validation; updates package metadata and project status documentation; and applies formatting-only edits to source and test files.

Changes

CI and package readiness

Layer / File(s) Summary
Package metadata and distribution validation
pyproject.toml, scripts/check_dist.py
Package metadata now identifies the project as Beta and points to its repository. The new script validates wheel and sdist counts, required files, and forbidden archive contents.
CI quality and packaging gates
.github/workflows/ci.yml, src/myinvois/..., tests/unit/test_async_client.py
CI runs locked dependency installation, linting, formatting checks, type checks, tests across Python 3.11–3.13, distribution verification, and artifact upload. Source and async test formatting is normalized without behavior changes.
Project status and release documentation
AGENTS.md
Project notes document CI and packaging completion, resolved formatting drift, and remaining release and sandbox-verification tasks.

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

Sequence Diagram(s)

sequenceDiagram
  participant GitHubActions
  participant uv
  participant QualityTools
  participant Pytest
  participant PackageArtifacts
  GitHubActions->>uv: install and sync locked dependencies
  uv->>QualityTools: run ruff and mypy
  uv->>Pytest: run tests across Python versions
  uv->>PackageArtifacts: build distributions
  GitHubActions->>PackageArtifacts: verify and upload artifacts
Loading

Possibly related PRs

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly summarizes the main changes: adding a GitHub Actions workflow and updating packaging metadata.
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.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch chore/ci-and-packaging

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

@danieyal
danieyal changed the base branch from docs/refresh-readme-and-agents to master July 22, 2026 02:06

@coderabbitai coderabbitai 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.

Actionable comments posted: 3

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In @.github/workflows/ci.yml:
- Around line 3-25: Restrict the workflow’s default token permissions by adding
workflow-level contents read access, and update every actions/checkout@v4
invocation to disable persisted credentials with persist-credentials: false.
Apply these changes to the workflow configuration without altering job behavior.

In `@AGENTS.md`:
- Line 155: Update the CI documentation entry in AGENTS.md to state that the
workflow enforces dependency locking with UV_LOCKED=1, replacing the inaccurate
UV_FROZEN=1 reference. Preserve the existing description of CI jobs and
triggers, and accurately describe the resulting stale-lock behavior without
adding unrelated changes.

In `@scripts/check_dist.py`:
- Around line 93-98: Extend the required-member validation in the check_dist
logic to inspect the sdist member list as well as wheel_members. Reuse
REQUIRED_WHEEL_MEMBERS (or the appropriate shared required-resource set) and
append clear problems for missing py.typed and codes/_data/*.json resources in
the sdist, while preserving the existing wheel checks.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: c6f212d8-5851-4138-a353-5f6aaff558ff

📥 Commits

Reviewing files that changed from the base of the PR and between c47a089 and 63ddaf1.

📒 Files selected for processing (8)
  • .github/workflows/ci.yml
  • AGENTS.md
  • pyproject.toml
  • scripts/check_dist.py
  • src/myinvois/_async_client.py
  • src/myinvois/services/async_document_types.py
  • src/myinvois/services/models.py
  • tests/unit/test_async_client.py

Comment thread .github/workflows/ci.yml
Comment thread AGENTS.md Outdated
Comment thread scripts/check_dist.py Outdated
Phase 6b, part 1. Adds CI and closes the packaging issues it surfaced.

CI (.github/workflows/ci.yml), three jobs:
- lint: ruff check, ruff format --check, mypy src/myinvois
- test: pytest across Python 3.11/3.12/3.13, -m "not live"
- package: uv build + scripts/check_dist.py, uploads dists as an artifact

UV_LOCKED=1 so a stale uv.lock fails the build instead of silently
resolving something other than what developers run locally. Negative-tested
by adding a dependency without re-locking; the gate fires as intended.
(UV_LOCKED, not UV_FROZEN -- --frozen skips re-locking without checking.)

Packaging metadata:
- [project.urls] shipped placeholder https://github.com/your-org/myinvois
  into the wheel METADATA. Corrected to danieyal/myinvois-python. This would
  have gone out with the first PyPI release.
- Development Status classifier 3 - Alpha -> 4 - Beta, matching the README.

scripts/check_dist.py guards two unrecoverable release mistakes, since a
PyPI version can never be reused:
- py.typed and codes/_data/*.json only ship because of the data-includes
  entry. If that regresses the build still succeeds, but myinvois.codes
  raises at runtime on a wheel install and type-checkers ignore the package.
- The test signing key/cert must never ship. They are force-tracked in git
  for the byte-parity tests, which makes an accidental include plausible.
Negative-tested: tampering a wheel (drop py.typed, add a .pem) produces both
failures with actionable messages.

CERTIFY_BEFORE_PUBLIC from the Phase 4 notes is now resolved rather than
merely observed -- verified that neither the wheel nor the sdist ships
tests/ or tests/fixtures/cert/*, and check_dist.py enforces it in CI.

Formatting drift, fixed here because CI would otherwise be red on arrival:
ruff format --check failed on 4 pre-existing files on master
(_async_client.py, services/async_document_types.py, services/models.py,
tests/unit/test_async_client.py). All four were wrapped at ruff's default 88
columns instead of this project's configured line-length = 100, i.e. Phase 6a
was committed without ruff format ever being run against the project config.
The fix is pure line-rejoining; no semantic change.

That also means AGENTS.md had been asserting "ruff check, ruff format
--check, mypy src all clean" while the format gate was red. AGENTS.md now
records the drift and warns against copying a green-gates claim forward
without re-running the commands.

All four gates verified green locally: ruff check, ruff format --check,
mypy src/myinvois, and 284 tests.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@danieyal
danieyal force-pushed the chore/ci-and-packaging branch from 63ddaf1 to d0bf781 Compare July 22, 2026 02:27

@coderabbitai coderabbitai 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.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In @.github/workflows/ci.yml:
- Around line 13-18: Set UV_FROZEN to "1" specifically in the package job’s
environment, while retaining the global UV_LOCKED setting for lint and test
jobs. Override or scope the package job environment so its distribution
validation uses frozen mode instead of inheriting UV_LOCKED.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 9c79a275-c5b8-4847-88ca-5a623ee49b98

📥 Commits

Reviewing files that changed from the base of the PR and between 63ddaf1 and d0bf781.

📒 Files selected for processing (8)
  • .github/workflows/ci.yml
  • AGENTS.md
  • pyproject.toml
  • scripts/check_dist.py
  • src/myinvois/_async_client.py
  • src/myinvois/services/async_document_types.py
  • src/myinvois/services/models.py
  • tests/unit/test_async_client.py
🚧 Files skipped from review as they are similar to previous changes (7)
  • src/myinvois/services/async_document_types.py
  • pyproject.toml
  • src/myinvois/_async_client.py
  • src/myinvois/services/models.py
  • tests/unit/test_async_client.py
  • scripts/check_dist.py
  • AGENTS.md

Comment thread .github/workflows/ci.yml
All three CodeRabbit findings were valid.

1. Workflow permissions (.github/workflows/ci.yml)
   Added workflow-level `permissions: contents: read` and
   `persist-credentials: false` on all three checkout steps. Nothing in CI
   writes to the repo, and the workflow-level declaration also overrides a
   permissive repo/org default rather than inheriting it.

2. Stale AGENTS.md claim
   The GITHUB section still documented `UV_FROZEN=1`. That was written before
   I corrected the workflow to `UV_LOCKED=1` and never updated, so AGENTS.md
   described a guarantee the workflow does not make -- ironically the exact
   stale-doc failure the FORMATTING DRIFT note warns about. Now states
   UV_LOCKED and why --frozen is the wrong flag.

3. sdist required-member check (scripts/check_dist.py)
   Required data members were only validated in the wheel. `pip install
   --no-binary` builds from the sdist, so a data-includes regression there
   breaks installs just as badly and would have gone unnoticed. Renamed
   REQUIRED_WHEEL_MEMBERS -> REQUIRED_DATA_MEMBERS and checked both
   distributions, accounting for the sdist keeping the repo's `src/` prefix.
   Negative-tested: stripping py.typed and msic.json from the sdist alone now
   fails with both paths named, where previously it passed silently.

Not addressed: the "Docstring Coverage 0.00%" pre-merge warning. The module
has a full docstring explaining what it guards and why; the four remaining
symbols are private helpers whose names say what they do, which matches the
convention in scripts/extract_codes.py. Adding docstrings to satisfy a
threshold would be noise.

Gates green: ruff check, ruff format --check, mypy src/myinvois, 284 tests,
and the dist check against a fresh build.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@danieyal
danieyal merged commit 238e380 into master Jul 22, 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.

1 participant