Shared conventions, vendored release scripts and convergence tooling for the SisyphusMD projects.
  • Shell 69.1%
  • Python 30.9%
Find a file
Repository files (latest commit first)
Filename Latest commit message Latest commit date
renovate 25fc2c80d5
All checks were successful
CI / Shell scripts (push) Successful in 10s
CI / Lint and test the standard's own code (push) Successful in 27s
CI / The standard can actually be vendored (push) Successful in 19s
Merge pull request 'chore(deps): update dependency ruff to v0.16.8' (#18) from renovate/ruff-0.16.x into main
2026-09-16 09:13:05 -07:00
.forgejo/workflows chore(deps): update dependency ruff to v0.16.8 2026-09-16 16:12:51 +00:00
migrations chore: initialise the shared project standard (its lock provenance needs a commit) 2026-08-22 14:20:24 -07:00
shared feat(retry): also retry a step the runner's resolver failed (a DNS outage inside brew test left a run red that nothing in the repo could have prevented) 2026-09-16 07:19:52 -07:00
tests feat(retry): also retry a step the runner's resolver failed (a DNS outage inside brew test left a run red that nothing in the repo could have prevented) 2026-09-16 07:19:52 -07:00
tools fix(vendor): retire dropped files and swap by rename rather than truncating (a copy-only vendor left both halves of a rename in place under a lock that named neither, and rewriting a running script's inode resumed bash at a stale offset) 2026-08-23 14:58:45 -07:00
.gitignore chore: initialise the shared project standard (its lock provenance needs a commit) 2026-08-22 14:20:24 -07:00
.renovaterc.json ci: give the standard its own gate (its scripts were linted only downstream) 2026-08-22 16:23:42 -07:00
CONVENTIONS.md feat(renovate): re-vendor the standard when the pin moves (Renovate can raise PROJECT_STANDARD but cannot fetch the tag it then names, so every bump landed red and got closed as obsolete) 2026-08-23 14:58:45 -07:00
pyproject.toml fix(lint): exempt the deferred import in config, not with a noqa the sibling flags 2026-08-22 16:31:28 -07:00
README.md chore: initialise the shared project standard (its lock provenance needs a commit) 2026-08-22 14:20:24 -07:00
VARIANCE.md docs(variance): record why only the MAC half of the privacy guard converges 2026-08-28 22:30:37 -07:00

project-standard

The shared conventions and vendored tooling behind whiskerless and dreame-valetudo.

  • CONVENTIONS.md — the rules both projects follow.
  • VARIANCE.md — the differences that are deliberate. Anything not in here is drift.
  • shared/ — the files that are literally the same in both projects.
  • tools/ — vendor them in, and check they have not been edited in place.

How this works

Shared files are vendored — physically copied and committed into each consumer, with STANDARD.lock recording the source tag and every file's SHA-256.

There is deliberately no submodule, no runtime fetch, and no cross-repo package. A three-year-old tag of either project must still build and release with this repository unreachable. That is the only reason a shared standard is safe here, and it is worth more than any convenience a live dependency would buy.

# Update a consumer to the current standard
python3 tools/vendor.py ../whiskerless
python3 tools/vendor.py ../dreame-valetudo

# What a consumer runs in CI (stdlib only, no network)
python3 tools/check.py .

The one rule that makes it work

Never improve a shared helper by editing the vendored copy. Change it here, re-vendor both projects, land them together.

tools/check.py fails when a copy is edited in place, which is precisely the failure that drove these two projects apart: someone improves a helper in one repo, the sibling never learns about it, and a year later there are four divergent behaviours across two files that started identical.

A worked example — changelog-section.sh had drifted into two versions, each better in ways the other was not:

From Improvement the sibling was missing
Dreame fails loudly when the version heading is absent, instead of emitting empty release notes
Dreame stops at any ## heading, not only bracketed ones
Whisk strips the leading blank line
Whisk stops at link-reference definitions, which a Keep a Changelog file collects at the foot

Four improvements, two from each side, in a twenty-line script with no project-specific content.

Testing the standard itself

./tests/test-release-common.sh

Network-free. Covers the guards that must hold before any request goes out — chiefly the tag validator, whose output is interpolated straight into URL paths, so it refuses traversal (../../etc/passwd), injection (v0.2.0;rm -rf /), whitespace and malformed versions. Also pins the safe defaults: REL_REPLACE_POLICY=immutable, every request profile time-bounded, and mutations never retried.

Per-project parameters

packaging/project.env holds each project's own values and is not vendored or locked — it is the parameter file, not shared content.

PROJECT_REPO_SLUG="SisyphusMD/whiskerless"

Adding a file to the standard

  1. It must be genuinely project-agnostic, or parameterised through project.env.
  2. Merge the union of both projects' versions — assume each side knows something the other does not, because so far each side always has.
  3. Test it against both repos' real data before vendoring.
  4. Re-vendor both, land together.