Skip to content

ci: unignore the tracked JWT rotation fixtures so release-plz runs - #274

Merged
rubenhensen merged 1 commit into
mainfrom
ci/unignore-jwt-rotation-fixtures
Jul 30, 2026
Merged

ci: unignore the tracked JWT rotation fixtures so release-plz runs#274
rubenhensen merged 1 commit into
mainfrom
ci/unignore-jwt-rotation-fixtures

Conversation

@rubenhensen

Copy link
Copy Markdown
Contributor

Root .gitignore's *.pem matches the four fixtures #241 committed under pg-pkg/testdata/jwt_rotation/, leaving them tracked and ignored. release-plz refuses to run against a repo in that state:

ERROR failed to update packages
  1: the working directory of this project has uncommitted changes. If these files
     are both committed and in .gitignore, either delete them or remove them from
     .gitignore.
     ["pg-pkg/testdata/jwt_rotation/priv_a.pem", …]

So delivery.yml's Release-plz PR job has failed on every push to main since #241 landed on 2026-07-16. Twelve runs, most recently 30448113952. Release-plz release is a separate job and was unaffected, which is why releases kept tagging and nothing looked broken.

The visible damage is PR #187 (chore: release), still open and last updated 2026-07-16. It is missing the version bumps and changelog entries for everything merged after that date, including the wire-compat gate, COMPATIBILITY.md, cargo-semver-checks and the oasdiff gate.

The change

One negation, scoped to that one directory so no other .pem is unignored:

!pg-pkg/testdata/jwt_rotation/*.pem

The fixtures are throwaway RSA keypairs for middleware::auth::tests::test_jwt_key_refresh_on_rotation and are already in history. This changes how git treats them, not what is committed.

Verification

git ls-files -ci --exclude-standard is the check: it lists files that are both tracked and ignored, and on main it returns those four. On this branch it returns nothing, and release-plz update gets past the working-directory check and starts resolving versions.

Both were run locally against a clone of this branch and a control clone of main.

Not in this PR

Nothing in CI reports this class, so the same mistake can land again the same way. A step that fails when git ls-files -ci --exclude-standard is non-empty would have caught it in #241's own PR. Left out here to keep the fix reviewable on its own; noted in #273.

Closes #273

Root .gitignore's `*.pem` matches the four fixtures #241 committed under
pg-pkg/testdata/jwt_rotation/, leaving them tracked *and* ignored. release-plz
refuses to run against a repo in that state, so delivery.yml's `Release-plz PR`
job has failed on every push to main since #241 landed on 2026-07-16, twelve
runs. `Release-plz release` is a separate job and was unaffected, which is why
releases kept working and nothing looked broken.

The visible damage is PR #187 (`chore: release`), still open and last updated
2026-07-16, so it is missing the version bumps and changelog entries for
everything merged after that date.

The negation is scoped to that one directory, so no other .pem is unignored.
The fixtures are throwaway RSA keypairs for a single regression test and are
already in history; this changes how git treats them, not what is committed.

Closes #273
@dobby-coder
dobby-coder Bot requested a review from leonbotros July 30, 2026 19:00
@rubenhensen
rubenhensen merged commit a55c6a0 into main Jul 30, 2026
30 checks passed
rubenhensen added a commit that referenced this pull request Jul 30, 2026
Brings in the 0.6.2/0.3.7/0.6.0/0.1.3 release (#187) and the .gitignore fix
(#274). Two conflicts:

- .gitignore: took main's wording, which is what #274 actually shipped. The
  spike carried an earlier, terser version of the same fix.
- cryptify's pg-core requirement moved 0.6.1 -> 0.6.2 by hand. release-plz
  maintains these reqs on unpublished members too (pg-pkg carries one), but it
  could not touch cryptify's during #187 because cryptify was not yet a member.

Merged rather than rebased on purpose: rebasing replays all 296 imported
commits onto main and discards the subtree merge.
@dobby-coder
dobby-coder Bot deleted the ci/unignore-jwt-rotation-fixtures branch August 2, 2026 20:01
rubenhensen added a commit that referenced this pull request Aug 4, 2026
Review fixes on #287, all four verified against the repo first.

- Line 13 still said `cargo fmt --manifest-path pg-<crate>/...`, which
  expands to pg-cryptify now that the matrix keys on the crate directory.
  The file contradicted the bullet six lines above it.
- The import bullet over-counted: ba380a1 carries 17 closing references,
  not 18. #273 came from a55c6a0 (#274), an ordinary commit the day
  before, so the original range e642786..origin/main swept in keywords
  the import never carried. 16 no-ops, not 17. Records the range mistake
  itself, since the bullet's command is what the next agent runs.
- #146 stood four days, not five, and the bullet now says it was
  reopened -- a reader who checks and finds it open doubts the rest.
- links = "sqlite3" is declared by libsqlite3-sys, not rusqlite; the
  relative clause named the wrong claimant. Confirmed with cargo
  metadata: rusqlite, sqlx and sqlx-sqlite all declare none. The error
  came in from #285's body, so it was inherited rather than invented.
- The cryptify image bullet read present-tense, but build/scan/finalize
  are all gated on vars.PUBLISH_CRYPTIFY_IMAGE and skip while it is
  unset. CLAUDE.md is auto-loaded, so a present-tense claim about a job
  that does not run is the expensive kind of wrong.

The required-checks parenthetical held up, and is now stronger for being
challenged: branch protection on main requires exactly the two Wire compat
contexts. That list lives in classic branch protection, NOT in the main
ruleset (which has no required_status_checks rule), and dobby-coder gets
403 on the protection endpoint -- so an agent reading the ruleset alone
concludes nothing is required. Worth documenting, so it is.
rubenhensen added a commit that referenced this pull request Aug 4, 2026
Both findings re-derived before applying; both hold.

The vector was wrong, and wrongly framed. ba380a1 has a single parent, so
PR #277 was squash-merged, and squash_merge_commit_message = COMMIT_MESSAGES
concatenates every imported commit message into the merge body -- 1678 lines
carrying all 17 refs. That is what closed #146, four seconds after it landed.
The history re-attach (9887e1a, a two-parent merge) carries no keywords of its
own and landed thirteen minutes later, when #146 was already closed, so it
cannot be the cause. The bullet said the opposite, which would teach the next
agent that a plain squash merge of an import PR is safe. It is sufficient on
its own, and it fires precisely because squashing concatenates the messages
while discarding the history. That also surfaces a cheaper defusal than
filter-repo: edit the squash body at merge time, no SHA rewrite.

The commit_id heuristic was falsified by the bullet's own example. It claimed
a keyword close carries a commit_id and a hand close does not, but #273 --
named right there as legitimately closed by a55c6a0, whose message ends in
Closes #273 -- has commit_id: null. The discriminator is where the keyword
sat: a commit-message keyword is attributed to the commit and carries the sha,
a PR-body keyword is attributed to the PR and carries null. #146 has the sha
because PR #277's body said only Closes #255; #273 has null because PR #274's
body said Closes #273. So null means "not attributed to a commit", not
"closed by hand", and the old rule would have called a real keyword close a
hand close.

Also fixed a stale cross-reference: the squash setting is documented in the
release-plz bullet above, not below.
rubenhensen added a commit that referenced this pull request Aug 4, 2026
* docs: true up CLAUDE.md with the cryptify workspace merge

Root CLAUDE.md still described a four-crate workspace with cryptify as a
separate repo, and mentioned cryptify zero times, though ba380a1 (#277)
merged it as a fifth member on 2026-07-31. Found while reconciling the
#247 map tree (#281).

What was stale or missing:

- Workspace members, the per-crate CI invocations (cryptify has no
  features of its own, so --all-targets), and the check-context rename
  from Test workspace (core) to Test workspace (pg-core) that came with
  keying the matrices on the crate directory.
- The standing sqlx<->rusqlite coupling the merge deliberately bought:
  one links = "sqlite3" claimant per graph, optional deps in the graph
  whether enabled or not, so sqlx 0.9 + rusqlite 0.39 is the only
  intersecting pair and every rusqlite bump waits on sqlx's ceiling.
- api-diff.yml is now a two-spec matrix, and its single fail-on and
  include-checks literals are load-bearing: both pg-pkg/tests/api_gate.rs
  and cryptify's in-crate api_gate_tests grep for exactly one of each.
- Two Docker builds, cryptify's built from the repo root, both on
  rust:1.96.1-slim-trixie.
- cryptify's release-plz entry, and the hand-placed cryptify-v0.1.27
  floor tag that stops release-plz changelogging the whole import.
- cryptify/CLAUDE.md exists, so root is no longer the single home.
- cryptify keeps a renamed rand08 dev-dependency because pg-core's
  Sealer/TestSetup are still on rand 0.8 while the crate runs 0.10.

Two facts the reconciliation itself established:

- pg-core 0.6.2 is the first published release off the abandoned irma
  0.2.1 and reqwest 0.11 (#263), which is why pg-compat's =0.6.1 pin
  resolves a tree unlike the workspace's -- and that pin plus
  COMPATIBILITY.md's crates.io reader row are now a release behind, with
  no gate reading them (#268).
- A history-preserving import silently closes issues here: the cryptify
  re-attach carried 18 closing keywords resolved against this repo's
  numbering and closed live issue #146. Includes the audit command and
  the timeline query that distinguishes a keyword close from a hand one.

* docs: correct the counts, the links declarant and the format matrix

Review fixes on #287, all four verified against the repo first.

- Line 13 still said `cargo fmt --manifest-path pg-<crate>/...`, which
  expands to pg-cryptify now that the matrix keys on the crate directory.
  The file contradicted the bullet six lines above it.
- The import bullet over-counted: ba380a1 carries 17 closing references,
  not 18. #273 came from a55c6a0 (#274), an ordinary commit the day
  before, so the original range e642786..origin/main swept in keywords
  the import never carried. 16 no-ops, not 17. Records the range mistake
  itself, since the bullet's command is what the next agent runs.
- #146 stood four days, not five, and the bullet now says it was
  reopened -- a reader who checks and finds it open doubts the rest.
- links = "sqlite3" is declared by libsqlite3-sys, not rusqlite; the
  relative clause named the wrong claimant. Confirmed with cargo
  metadata: rusqlite, sqlx and sqlx-sqlite all declare none. The error
  came in from #285's body, so it was inherited rather than invented.
- The cryptify image bullet read present-tense, but build/scan/finalize
  are all gated on vars.PUBLISH_CRYPTIFY_IMAGE and skip while it is
  unset. CLAUDE.md is auto-loaded, so a present-tense claim about a job
  that does not run is the expensive kind of wrong.

The required-checks parenthetical held up, and is now stronger for being
challenged: branch protection on main requires exactly the two Wire compat
contexts. That list lives in classic branch protection, NOT in the main
ruleset (which has no required_status_checks rule), and dobby-coder gets
403 on the protection endpoint -- so an agent reading the ruleset alone
concludes nothing is required. Worth documenting, so it is.

* docs: fix the close vector and the commit_id rule in the import bullet

Both findings re-derived before applying; both hold.

The vector was wrong, and wrongly framed. ba380a1 has a single parent, so
PR #277 was squash-merged, and squash_merge_commit_message = COMMIT_MESSAGES
concatenates every imported commit message into the merge body -- 1678 lines
carrying all 17 refs. That is what closed #146, four seconds after it landed.
The history re-attach (9887e1a, a two-parent merge) carries no keywords of its
own and landed thirteen minutes later, when #146 was already closed, so it
cannot be the cause. The bullet said the opposite, which would teach the next
agent that a plain squash merge of an import PR is safe. It is sufficient on
its own, and it fires precisely because squashing concatenates the messages
while discarding the history. That also surfaces a cheaper defusal than
filter-repo: edit the squash body at merge time, no SHA rewrite.

The commit_id heuristic was falsified by the bullet's own example. It claimed
a keyword close carries a commit_id and a hand close does not, but #273 --
named right there as legitimately closed by a55c6a0, whose message ends in
Closes #273 -- has commit_id: null. The discriminator is where the keyword
sat: a commit-message keyword is attributed to the commit and carries the sha,
a PR-body keyword is attributed to the PR and carries null. #146 has the sha
because PR #277's body said only Closes #255; #273 has null because PR #274's
body said Closes #273. So null means "not attributed to a commit", not
"closed by hand", and the old rule would have called a real keyword close a
hand close.

Also fixed a stale cross-reference: the squash setting is documented in the
release-plz bullet above, not below.

* docs: state both import close-vectors, drop the unverified defusal

Cycle-3 review findings, both re-derived from primary sources first.

The blocking one is right and my previous fix overcorrected. "Preserving
the history is not the trigger" is false as a general rule, and the
counterexample is the case the bullet cites as its own guard. Measured on
postguard-js: import PR #137 merged with a REAL two-parent merge commit
(b1bb2ee, three-line message, zero closing keywords, no squash body
anywhere), and js#128/#129 closed six seconds later attributed to imported
commits a0ce27f/2acf42f -- single-parent, committed 2026-06-04 -- then
reopened fifteen minutes later. In the history-preserving case GitHub never
reads the merge commit's message; it attributes the closes to the imported
commits once they become reachable from the default branch.

What postguard's own incident supports is weaker than what I wrote: the
squash body got there first, and by the time 9887e1a landed all 17 targets
were already closed, so GitHub had nothing left to close. That vector was
untested here, not disproven. The bullet now states both as independently
sufficient, which also matters because the squash-body defusal does not
exist on vector 2 -- there is no body to edit.

Dropped the commit_message-on-PUT-/pulls/N/merge recipe rather than keep it.
The REST reference words that field "Extra detail to append to automatic
commit message" and documents nothing about merge_method=squash, so whether
it replaces the concatenated body is unverified -- and if it appends, the
defusal silently no-ops and every keyword still fires. Recorded as an open
question to confirm on a throwaway repo, not as a recipe.

Non-blocking: the sqlx ceiling is binding today, not future. rusqlite 0.40.0
wants libsqlite3-sys ^0.38.0 and 0.40.1 wants ^0.38.1, both published and
unyanked, both outside sqlx-sqlite 0.9.0's >=0.30.1, <0.38.0 -- so a lone
rusqlite bump does not resolve at all. "Future" invited a reader to treat
the current pins as headroom and misdiagnose the resolver error.
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.

release-plz PR job has been failing on main since #241 (tracked-and-ignored .pem fixtures)

1 participant