Releases: zmaril/housekeeping
Release list
v0.21.0
Adds the strict-status-checks check, and fixes three defects in v0.20.0 that
surfaced while rolling it out across the fleet — two of which made v0.20.0's own
housekeeper fix unsafe to run.
Fixed
fix ci-existsno longer overwrites existing CI: it wrote
.github/workflows/ci.ymlunconditionally, butci-existsfails two different
ways — no CI at all, or CI that exists and is merely missing a test/lint/fmt step
for some language — and the scaffold only answers the first. On a repo whose CI
simply lacked a rust step, the fix replaced the entire hand-written workflow with
a generic stub. It now scaffolds only when there is no workflow at all, and
otherwise prints the missing steps to add by hand.lockfilesno longer demands a lockfile that cannot exist: a package
declaring no dependencies has no lockfile to produce (bun deletes an empty one
outright), so the only way to pass was to fabricate a foreign lockfile. Such a
package is now skipped, and the skip is surfaced in the note rather than passing
silently. An unparseable manifest still counts as having dependencies, so a broken
file can't quietly downgrade the check.lockfilesgained anignorelist: nested-aware detection started grading
packages whose lockfiles are gitignored on purpose. A repo can now exempt those
directories with[lockfiles] ignore = ["spike", "crates/demo"].repo-metaignores markers inside fenced code blocks:read_markersscanned
the whole README and let later matches win, so a README documenting the marker
syntax had its own fenced example parsed as the declaration — silently overriding
the real markers above it. housekeeping's own README hit this, and
housekeeper fix repo-metawould have pushed the doc placeholder over the repo's
real description and topics.
New checks
strict-status-checks(required, fixable): the default branch must require
branches be up to date before merging — GitHub'srequired_status_checks.strict,
read from the ruleset or classic protection (OR-ing, likerequired-checks). With
it on, a PR can only merge once its branch is current, so CI reruns against the true
merged state and two individually-green PRs from stale bases can't silently break
main. Also recommends the repo-level "Always suggest updating pull request branches"
setting (allow_update_branch). The fix sets the strict policy on the default-branch
ruleset and turnsallow_update_branchon (needs admin; required status checks must
exist first).
v0.20.0
First release cut since v0.19.0. It consolidates the batch of checks, commands,
and verdict changes that landed on main after v0.19.0 (none of which were tagged
individually) into a single release.
New checks
coverage(recommended, advisory): every detected language ecosystem
(rust, js, python) must wire up some coverage tool — presence-only, not a
threshold. Accepts a config file, a CI step or task-runner target, or a manifest
dependency; skips when no rust/js/python ecosystem is present.allow-auto-merge(recommended, fixable): asserts GitHub'sallow_auto_merge
setting matches a declared preference (default off); opt in with
[allow-auto-merge] enabled = true. The fix PATCHes the setting to match.artifacts-built(recommended, warns): for every build artifact detection
finds (napi addon, PyO3/maturin wheel, Magnus/rb-sys gem, Tauri app, web/site
bundle, compiled binary), greps the workflows for the build step it needs and
reports the ones with no coverage; conservative static parse, so it warns rather
than gates.pinned-versions(recommended, check-only): flags floating version
specifiers per ecosystem (npm/bun exact semver, python==X.Y.Z, ruby= X.Y.Z,
actions a 40-char commit SHA; cargo advisory by default sinceCargo.lockpins
the build). Configure scope via[pinned-versions]; no auto-fix.dependabot-automerge(recommended, fixable): when a repo opts in with
[allow-auto-merge] dependabot = true, wants a workflow that auto-merges
dependabot's non-major PRs once their required checks go green (also requires
enabled = true). The fix writes.github/workflows/dependabot-automerge.yml.
New commands
housekeeper detect: prints the repo's detected ecosystems, typed-language
layers, and build artifacts, plus the recommended fleet setup per ecosystem
(--jsonfor machine output). Backed by a new artifact-detection layer in
languages.pythat reads source manifests and skips vendored/build trees.housekeeper new <name> --flavor rust|bun|python: scaffolds a
fleet-compliant repo skeleton (CI/housekeeping workflows, committed git hooks,
.housekeeping.toml, LICENSE,scripts/dev.sh, dependabot config, CODEOWNERS,
notes/design.md), then prints the human next steps it can't do itself. The
opt-in--dependabot-automergeflag (off by default) additionally writes the
dependabot-automergeworkflow and sets[allow-auto-merge] enabled = true, dependabot = true, so the new repo passes that check out of the gate.
Changed verdicts / behavior
lockfilesgit-history staleness fallback: for ecosystems with no native
sync check (ruby's Gemfile.lock, go's go.sum), the check now compares commit
timestamps and flags a lockfile whose manifest was committed in a strictly later
commit as likely stale; it also distinguishes a gitignored lockfile and falls
back to the heuristic when a native tool is absent. Verdict change: can now fail
ruby/go repos carrying a stale-by-history lockfile.- Nested-aware ecosystem detection:
detect_ecosystemsnow returns one
Ecosystemper location (each carrying itsdir) instead of probing only the
repo root, so nested manifests undercrates/*are detected.lockfiles,
dependabot,ci-exists,coverage, andgitignorenow grade nested packages
per-directory, so repos with nested packages (entl, disponent) may now fail for
genuinely-ungraded nested lockfiles, dependabot coverage, or CI. Closes #90. repo-metareconciles a README declaration: description and topics are
declared at the top of the README via<!-- housekeeper:description ... -->and
<!-- housekeeper:topics a, b, c -->markers, and the check asserts GitHub's
actual values match them (README = source of truth; topics validated to GitHub's
rules). Verdict change: a repo with no markers now fails with an adoption nudge.
housekeeper fix repo-metapushes the declared values to GitHub, or — when a
repo has no markers yet — seeds them into the README from GitHub's current values.bunlockfile check no longer runspostinstall: the frozen
bun install --dry-runnow passes--ignore-scripts(matching npm), so a repo
whose postinstall needs network/tools is no longer falsely flaggedbun.lock
out of sync after the frozen check itself passed.- ruby
testsignal recognizes theruby -Itest test/...idiom:ci-exists
now credits ruby tests run that way, so it no longer under-credits ruby.
v0.19.0 — per-repo `only` targeting for managed-config
- Per-repo
onlytargeting for[[policy.managed-config]]: an optionalonly = ["owner/repo", …]allow-list restricts a fleet-owned config to just the members that actually use it, instead of syncing byte-identically to every in-scope member. Emptyonly(the default) keeps today's apply-to-every-in-scope-member behavior; a non-empty list scopes both the sync and the drift notes to the listed repos, emitting askipped (not in only list)row for the rest. Values must match[[member]].repoexactly, and unknown repos are tolerated — a listed repo that isn't a member simply never matches. Lets a config like biome, used by only a subset of the fleet, target precisely. (#68)
Usage: uses: zmaril/housekeeping@v0.19.0
v0.18.0 — PR-context grading + ruleset-bypass
PR-context grading: ci-green / branch-protection / required-checks grade main's runs or repo settings — nothing a PR can change — so on pull_request events they demote to recommended (warn, with an explanatory note). Push/schedule/local runs keep them hard; the captain still catches rot. Ends the admin-merge treadmill.
ruleset-bypass (new, recommended, fixable): gating rulesets must name a bypass actor — rulesets ignore gh pr merge --admin without one. housekeeper fix ruleset-bypass grants Repository admin / always.
Hardening: hooks and tests strip GIT_DIR/GIT_INDEX_FILE/GIT_WORK_TREE so suites running under git hooks can never operate on the real repo.
Full notes in CHANGELOG.md.
v0.17.0 — scripts check + serve + fleet dashboard
scriptscheck (required): shell scripts live underscripts/, a
scripts/dev.shstands up the basic dev environment, and the README points at
it. Hidden and vendored trees (.githooks/,node_modules/, …) are never
scanned — git hooks belong in.githooks/. Configurable via[scripts]
(dir,dev,allow). Housekeeping now ships its ownscripts/dev.sh.- Fleet dashboard now carries a second table: every open PR and issue across
the fleet, one row each, with the repo as a column (PRs first, then issues,
each linking to GitHub) and a per-fleet count. Open issues/PRs are folded into
the audit payload (fetch_activity), so the dashboard stays a pure view. - New
housekeeper serve housecaptain.tomlcommand: serves the dashboard from a
local web server with a Regenerate button — and an optional 60s
auto-refresh — that re-audits the fleet on demand. The static--htmlfile
output is untouched; the live controls are injected only into the served page. housekeeper fleetnow audits members concurrently (a thread pool,
results still in fleet order), so a full re-audit drops to about the slowest
single repo instead of the sum — roughly 3× faster on the powderworks fleet.- Dashboard legend spells out the glyphs —
warnis now
"recommended, not required" andfailis "required", with hover tooltips —
so a!cell reads as advisory rather than mysterious.
v0.15.0 — stylelint, vale, codespell + managed configs
stylelintcheck (recommended): stylesheets present → config + CI wiring; skips when there's no CSS.valecheck (recommended):.vale.ini(+StylesPath) + CI wiring, for prose style and terminology.codespellcheck (recommended): codespell in CI — low-noise spelling, split from vale (which false-positives on jargon). codespell flags only known misspellings.- Managed configs: the fleet captain can own a check's config under
.fleet/and push it outward as isolated PRs viahousekeeper captain --sync-configs(action inputsync-configs). Distribution, not a fix — members adopt at their own pace. stray-todosfix: marker match tightened so it no longer flags enum/object keys namedTodoor the word "todo" mid-sentence.
Pin the full version: uses: zmaril/housekeeping@v0.15.0.
v0.14.0 — stray-todos
Adds the stray-todos check (TODO/TBD/FIXME/WIP markers must live in the todo file). Fleet members should bump to this from v0.9.0 so the fleet-locked stray-todos = required policy resolves. See the changelog.
v0.9.0 — continue-on-error, reproducible-toolchain, codeowners
Re-baselined from v1.9.0 to 0.x (housekeeping is pre-1.0). Same release, renamed. See the changelog.