Skip to content

fix: releases that publish nothing, and docs naming the wrong encryption key (beads batch 7) - #189

Merged
GeiserX merged 2 commits into
mainfrom
fix/beads-batch-7
Aug 4, 2026
Merged

fix: releases that publish nothing, and docs naming the wrong encryption key (beads batch 7)#189
GeiserX merged 2 commits into
mainfrom
fix/beads-batch-7

Conversation

@GeiserX

@GeiserX GeiserX commented Aug 4, 2026

Copy link
Copy Markdown
Owner

gn6 + l7t — a release could go green having published nothing.

release.yml decided what to build from two hand-maintained regexes, both drifted from the Dockerfiles they mirror.

The UI regex named 13 of 27 modules, while the UI image does COPY app/ ./app/ — everything. A change to any of the other 14 (payouts, preflight, power, egress, lan_isolation, notify, …) set BUILD_UI=false → version step skipped → new_tag empty → tag, Release and build job all skipped. Skipped steps don't fail a run, so it reported success.

The worker regex omitted egress.py and state_backup.py — both COPY'd into the worker image and imported by worker_api at runtime. With build_worker=false the pipeline retags the previous image, so the worker ships under a new version tag containing old code, and verify-tags only runs docker manifest inspect, which a retag satisfies.

Neither is restated now: any app/ change builds the UI, and the worker list is parsed out of Dockerfile.worker at run time. A test asserts every module worker_api imports is actually in the worker image — the contract that decides whether a miss is a crash on the user's machine or a build failure here.

dxi — six places named the wrong key, harmfully.

They said CASHPILOT_SECRET_KEY encrypts credentials. It signs sessions; CASHPILOT_ENCRYPTION_KEY is the Fernet key at /data/.fernet_key. Follow the old advice and you believe your credentials are portable, never back up the key file, and lose every one the first time the volume is recreated. README already said this correctly — the other six contradicted it.

Fixed all six, named the key file so it can be backed up, and added the variable to the Unraid template (masked), since that's the whole configuration surface for those users.

Verification: 2476 tests, 95.13% coverage. Negative controls: narrowing the UI trigger fails 2 tests; restoring the index.md claim fails 2 more.

Summary by CodeRabbit

  • Documentation

    • Clarified that CASHPILOT_SECRET_KEY signs login sessions.
    • Added guidance for CASHPILOT_ENCRYPTION_KEY, which encrypts stored credentials.
    • Documented credential key storage, backup, recovery, and configuration options.
    • Updated the Unraid template with separate session-signing and encryption settings.
  • Bug Fixes

    • Improved release detection so UI and worker builds trigger for all relevant application and module changes.
  • Tests

    • Added coverage verifying release triggers, Dockerfile module packaging, and encryption-key documentation.

CashPilot-gn6 / CashPilot-l7t — release.yml decided what to build from
two hand-maintained regexes, and both had drifted from the Dockerfiles
they were meant to mirror.

The UI regex named 13 of 27 modules while the UI image does
COPY app/ ./app/ — the whole directory. A change to any of the other 14
(payouts, preflight, power, egress, lan_isolation, notify, ...) set
BUILD_UI=false, which skipped the version step, which left new_tag
empty, which skipped the tag, the GitHub Release and the entire build
job. Skipped steps do not fail a run, so the release went GREEN having
published nothing at all.

The worker regex omitted egress.py and state_backup.py, both COPY'd into
the worker image and imported by worker_api at runtime. With
build_worker=false the pipeline RETAGS the previous image, so the worker
could be published under a new version tag containing the previous
release's code — and verify-tags only runs docker manifest inspect,
which a retag satisfies.

Neither regex is restated now. Any change under app/ builds the UI,
because the image contains all of it; the worker list is parsed out of
Dockerfile.worker at run time, so the next module added to that image is
covered without anyone remembering. A test asserts every module
worker_api imports is one the worker image actually contains — the
contract that makes a miss a crash on the user's machine rather than a
build failure here.

CashPilot-dxi — six places told users CASHPILOT_SECRET_KEY encrypts
their credentials. It signs login sessions; CASHPILOT_ENCRYPTION_KEY is
the Fernet key, persisted at /data/.fernet_key. The advice was not
merely wrong but harmful: following it, a user believes their
credentials are portable, never backs up the key file, and loses every
stored credential the first time the volume is recreated. README.md
already said this correctly and the other six contradicted it.

All six corrected, the key file named so it can actually be backed up,
and the Unraid template — which is the entire configuration surface for
those users — now exposes CASHPILOT_ENCRYPTION_KEY, masked.

Negative controls: narrowing the UI trigger fails two tests, restoring
the index.md claim fails two more.
@coderabbitai

coderabbitai Bot commented Aug 4, 2026

Copy link
Copy Markdown

Review Change Stack

Warning

Review limit reached

@GeiserX, you've reached your PR review limit, so we couldn't start this review.

Next review available in: 53 minutes

You've used all free OSS reviews for now. Wait for the free limit to reset to keep reviewing this public repository.

How can I continue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews.

How do review limits work?

CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability.

For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window.

Please refer docs for additional details.

Review details
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: 90705925-e750-4cb9-9da4-fe9fcbb61765

📥 Commits

Reviewing files that changed from the base of the PR and between fcc1ae2 and bef4cbb.

📒 Files selected for processing (4)
  • docs/fleet.md
  • docs/getting-started.md
  • docs/index.md
  • tests/test_release_triggers.py
📝 Walkthrough

Walkthrough

The release workflow now detects UI changes from all app/ files and derives worker triggers from Dockerfile.worker. Documentation and the Unraid template separate session signing from credential encryption and document Fernet key storage.

Changes

Release trigger detection

Layer / File(s) Summary
Trigger logic and regression coverage
.github/workflows/release.yml, tests/test_release_triggers.py
UI builds now cover all app/ changes. Worker module triggers derive from Dockerfile.worker. Tests validate copied modules, imports, and trigger exclusivity.

Encryption-key documentation

Layer / File(s) Summary
Encryption-key contract and documentation
docs/fleet.md, docs/getting-started.md, docs/index.md, unraid/cashpilot.xml, tests/test_release_triggers.py
The documentation and Unraid template define CASHPILOT_ENCRYPTION_KEY for credential encryption, /data/.fernet_key for persistence, and CASHPILOT_SECRET_KEY for login-session signing. Tests verify the references.

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

Possibly related PRs

  • GeiserX/CashPilot#64: Both PRs update release workflow logic for UI and worker image rebuilds.
  • GeiserX/CashPilot#142: This PR documents and tests the same encryption-key behavior introduced there.
  • GeiserX/CashPilot#166: This PR derives worker triggers from Dockerfile.worker, including the copied module introduced there.
🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately summarizes the release-trigger fixes and encryption-key documentation corrections.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
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 fix/beads-batch-7

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.

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

Actionable comments posted: 1

🧹 Nitpick comments (1)
tests/test_release_triggers.py (1)

92-100: 🎯 Functional Correctness | 🔵 Trivial | ⚡ Quick win

Use syntax-aware import extraction.

Line 95 matches only one physical from app import ... form. It ignores import app.module, from app.module import name, relative imports, and multiline imports. If worker_api uses one of these forms, this test can pass while the worker image omits the dependency and fails at import time.

Parse worker_api.py with ast and compare every direct app dependency with worker_copied_modules().

🤖 Prompt for 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.

In `@tests/test_release_triggers.py` around lines 92 - 100, Replace the line-based
import parsing in the release-trigger test with AST-based analysis of
worker_api.py. Collect every direct app dependency from Import and ImportFrom
nodes, including app.module, from app.module imports, relative imports, and
multiline forms, then compare the normalized dependency names against
worker_copied_modules(). Preserve the existing filtering of private names and
missing-dependency assertion.
🤖 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 `@docs/index.md`:
- Line 129: Update the encryption-key description in the FAQ to state that
CASHPILOT_ENCRYPTION_KEY is used only when /data/.fernet_key is absent, matching
the precedence documented in getting-started.md; preserve the distinction from
CASHPILOT_SECRET_KEY.

---

Nitpick comments:
In `@tests/test_release_triggers.py`:
- Around line 92-100: Replace the line-based import parsing in the
release-trigger test with AST-based analysis of worker_api.py. Collect every
direct app dependency from Import and ImportFrom nodes, including app.module,
from app.module imports, relative imports, and multiline forms, then compare the
normalized dependency names against worker_copied_modules(). Preserve the
existing filtering of private names and missing-dependency assertion.
🪄 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: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: 55bdd152-565e-4e10-b123-372077054488

📥 Commits

Reviewing files that changed from the base of the PR and between d5dc9df and fcc1ae2.

📒 Files selected for processing (6)
  • .github/workflows/release.yml
  • docs/fleet.md
  • docs/getting-started.md
  • docs/index.md
  • tests/test_release_triggers.py
  • unraid/cashpilot.xml

Comment thread docs/index.md Outdated
From CodeRabbit on this PR, and correct. I wrote 'overridable via
CASHPILOT_ENCRYPTION_KEY', but app/database.py keeps the stored key and
logs a warning when the variable differs, because switching keys would
make every existing credential unreadable.

That wording is wrong exactly where it matters most. Someone restoring a
backup onto an instance that still has a stale key file would expect
their value to take effect; it is ignored, and the credentials they were
trying to recover stay unreadable. All three docs now state that the
variable is adopted only when /data/.fernet_key is absent — which is
also why setting it on a healthy instance is safe.

Pinned with a test that rejects the word 'overridable' on any line
naming the variable, and requires all three docs to state the
precedence.
@GeiserX

GeiserX commented Aug 4, 2026

Copy link
Copy Markdown
Owner Author

Fixed, and you were right about where it bites.

app/database.py keeps the stored key and logs a warning when CASHPILOT_ENCRYPTION_KEY differs — switching keys would make every existing credential unreadable. So "overridable" is wrong precisely in the restore case: someone putting their backup key on an instance that still has a stale /data/.fernet_key would expect it to take effect, and it is ignored.

All three docs now state it is adopted only when that file is absent — which is also the reason setting it on a healthy instance is safe rather than dangerous.

Pinned with a test that rejects "overridable" on any line naming the variable and requires all three docs to state the precedence, so the imprecision cannot come back quietly.

2478 tests, ruff clean.

@GeiserX
GeiserX merged commit 82cc414 into main Aug 4, 2026
6 checks passed
@GeiserX
GeiserX deleted the fix/beads-batch-7 branch August 4, 2026 08:21
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