rill-ci-guards: add GitHub Actions CI guards + local PII pre-push hook - #82
Merged
Merged
Conversation
CI (.github/workflows/ci.yml), runs on every PR to main:
- lint: bash -n over all bin/plugins/test shell files (gap-free
enumeration via git ls-files) + shellcheck pinned to v0.11.0
(sha256-verified download) at severity=warning
- test: every pure-shell test/cli suite (10, enumerated dynamically via
glob so future suites are picked up) on ubuntu + macos, no claude CLI
- guard: CJK allowlist scan + email/phone/secrets regex scan, each run
over the full tree and over the PR's commit messages
New guards (both cwd-independent, wired into test/run-all.sh):
- test/cli/cjk-guard.py: stdlib-only; tree mode filtered by
test/cjk-allowlist.txt, --raw parity mode (hit-set verified identical
to rg's \p{Hiragana}\p{Katakana}\p{Han} scan), --stdin mode for
commit messages (no allowlist)
- test/cli/pii-regex-guard.sh: generic email/phone/secret patterns only
(no private vocabulary), filtered by new test/pii-regex-allowlist.txt
(placeholder addresses, test fixtures, journal-timestamp filenames)
Local-only dev hook (mechanism only, never distributed to vaults):
- bin/hooks/pre-push-pii-mapping-check.sh: blocks pushes whose commits
(added diff lines or messages) contain private terms read from an
out-of-repo file ($RILL_DEV_PII_TERMS_FILE or
~/.config/rill-dev/pii-terms.txt); no-op when the file is absent;
handles the new-branch zero-SHA case via merge-base. Header documents
the role split against pre-commit-pii-check.sh (vault-content guard).
shellcheck adoption (warning tier now clean):
- bin/rill: drop dead SOURCES_DIR (SC2034); split declare/assign for
target in the command-link loop (SC2155)
- plugins/{twitter,voice-memo}/requires.sh: SC2088 disable with reason
(require_dir expands ~ itself)
- 5 plugin requires.sh: shellcheck source= directive for _lib.sh
- .shellcheckrc: policy doc; severity threshold lives on the command
line (rc-file severity is not honored, verified on v0.11.0)
…ntu leg The PR's own first CI run (the ubuntu leg this task could not exercise locally) failed 4 suites: eval-distribution, portability, codex-projection, track-managed-gitignore. Root cause, reproduced in an ubuntu:24.04 container: 39 standalone ((var++)) sites (29 in bin/rill, 10 in plugin adapters). When the variable is 0, the arithmetic command returns status 1; bash >= 4.1 honors set -e there and kills the script, while macOS bash 3.2 does not -- so every counter first-increment was a latent Linux crash. rill update died this way on ubuntu, cascading into the 4 suite failures. Mechanical fix, no semantic change: ((var++)) -> var=$((var + 1)), matching the assignment-form convention test/run-all.sh already documents. C-style for loops, awk, and jq (( usages are untouched. Verified: all 10 test/cli suites + both tree guards pass in an ubuntu:24.04 container as a non-root user (the checkpoint-hooks read-only case requires non-root, same as the CI runner), and the full macOS battery (shellcheck warning tier, bash -n, 10 suites, guards) stays green.
Follow-up to codex review: a tracked filename starting with '-' (e.g. '--include=x') would be parsed by grep as an option, and the previous 2>/dev/null swallowed the resulting error, so a PII-bearing file could go unscanned while the guard still exited 0. Pass the pattern with -e and terminate options with -- before the xargs-appended file list, and let grep errors reach stderr. Verified with a scratch repo containing a dash-prefixed tracked file: it is scanned and its hit reported.
Contributor
Author
|
Two follow-up commits after the PR's own first CI run (which was itself part of the verification):
Final state: CI green on all 4 checks (lint / test ubuntu / test macos / guard), codex review clean (0 findings). |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Closes the two guard gaps behind the 2026-07-06 PII incident: no CI, and push-time scans that only saw diff content.
.github/workflows/ci.yml— 3 jobs on every PR to main:lint:bash -nover allbin//plugins//test/shell files (gap-freegit ls-filesenumeration, verified against the tree) + shellcheck pinned to v0.11.0 (sha256-verified download) at--severity=warningtest: every pure-shelltest/cli/suite (10 today, enumerated via glob so future suites are picked up automatically) on ubuntu + macos; noclaudeCLI anywhereguard: CJK allowlist scan + email/phone/secrets regex scan, each run over the full tree and over the PR's commit messagestest/cli/cjk-guard.py(stdlib-only): tree mode filtered bytest/cjk-allowlist.txt;--rawparity mode (hit-set verified identical torg's\p{Hiragana}\p{Katakana}\p{Han}scan);--stdinfor commit messages (no allowlist)test/cli/pii-regex-guard.sh: generic email/phone/secret patterns only (no private vocabulary); per-value allowlisting — allowlisted matches are stripped and the remainder re-scanned, so a real secret sharing a line with a placeholder still failsbin/hooks/pre-push-pii-mapping-check.sh: local-only contributor hook; reads private terms from an out-of-repo file ($RILL_DEV_PII_TERMS_FILEor~/.config/rill-dev/pii-terms.txt), no-ops when absent, blocks on term hits in pushed diffs or commit messages (zero-SHA new-branch case via merge-base). Ships mechanism only.bin/rill, SC2088 disabled with reason at 2 call sites,source=directives added);.shellcheckrcdocuments the policy (rc-fileseverityis not honored by shellcheck v0.11.0 — verified — so the threshold lives on the command line)Verification
bash -n: 46 files, 0 failures; shellcheck v0.11.0--severity=warning: exit 0 over the 16-file inventory--rawhit-set diff vsrgreference scan = identical (20 hits, all allowlisted)test/cli/suites pass locally on macOS after thebin/rilledits (pipefail static audit included)pull_request-triggered workflow running on this PR is itself part of the verification — the ubuntu leg cannot be exercised locallyDeviations from the task Plan
git log base..headafter afetch-depth: 0checkout instead ofgh api(offline, no extra token scope).shellcheckrccarries policy documentation only;severity=warningmoved to the CI command line (rc-file support verified absent in v0.11.0)test/cjk-allowlist.txtheader updated (2 lines) to declare Python-re syntax, matching the implementationMerge is intentionally left to the repo owner (task ships up to PR creation only).
🤖 Generated with Claude Code