Add cli/contributing/changelog/archive: a CLI that trims CHANGELOG.md
to the last N entries (default 7) and writes every older release to
its own file under docs/changelog/ named <padded-semver>-<date>.md
(7.0.0 → 007.000.000-2026-05-08.md). The padded form makes a directory
listing already chronological, and the index in CHANGELOG.md is
rebuilt from the archive directory listing on every run, so it never
drifts away from what is on disk. The tool is idempotent and never
overwrites an existing archive file.
Run the migration once to split the 44-entry CHANGELOG.md into 7
inline entries plus 37 archived per-release files, with the index at
the bottom of CHANGELOG.md linking each archive in descending order.
Add docs/contributing/actions/release.md as the contributor-facing
release procedure (versioning, active window vs. archive, cutting a
release end-to-end, CI hand-off on tag push) and add a docs README
under docs/changelog/ that explains the archive directory layout and
filename schema. Cross-link release.md from pipeline.md and add
"releases" to the actions/ scope description.
Documentation cleanup pass on every page touched in the previous
mapping refactor:
- Remove "is the SPOT for X" / "Single Point of Truth" self-labels
across docs/contributing/, docs/agents/, and docs/changelog/. The
rule in documentation.md forbids self-declared SPOT status; status
is conferred by readers cross-linking, not by the page asserting
it. Rephrase to descriptive phrasing ("This page covers X",
"describes X", "lists X") throughout.
- Drop the orphaned docs/contributing/tools/actions.md duplicate
(101 lines paralleling tools/github/actions/workflows.md, with no
inbound links).
- Fix em-dashes used as thought breaks in dockerfile.md, origin.md,
agents/style.css.md, and suppression.md per documentation.md.
- Unwrap soft-wrapped sentences in iam/common.md, iam/ldap.md,
iam/oidc.md, image/origin.md, requirements.md, and dockerfile.md
so each logical line carries one full sentence.
Add a unit test for the archive CLI under
tests/unit/cli/contributing/changelog/archive/test_main.py covering
_pad_version, _split_into_entries, idempotency, dry-run, no-overwrite
of existing archives, and the multi-run index rebuild.
Quote `# noqa:` in CHANGELOG.md prose with backticks so the
noqa-only-ruff-codes lint does not parse "for" as a non-ruff code.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
5.7 KiB
GitHub workflow files 🔄
This page covers the repository rules that govern GitHub Actions workflow files under .github/workflows/.
For the catalog of every workflow (description, triggers, inputs) see workflows.md.
For the script placement rule that applies to extracted shell helpers, see scripst.md.
Naming 🏷️
Every workflow MUST follow the schema "[Emoji] Category: Subject (Qualifier)".
- You MUST quote the
name:value in double quotes because the colon (:) in the name is a reserved YAML character. - You MUST place the emoji before the category, never after.
- You MUST NOT add emojis to
docs/agents/files, but workflowname:fields are not agent files and MUST use emojis. - The qualifier in parentheses is OPTIONAL. Use it only when two workflows share the same category and subject.
Emoji legend 📋
| Emoji | Category | Used for |
|---|---|---|
🔄 |
Update / Sync | Automated version or dependency updates |
🪞 |
Mirror | Image mirroring between registries |
🧹 |
Images | Image cleanup and pruning |
🐳 |
Build | Docker image builds |
🔍 |
Lint | Static analysis and linting |
🔒 |
Scan | Security scanning |
⚡ |
CI | CI entry points (push, pull request, manual) |
🎵 |
CI | CI orchestration and coordination workflows |
🚫 |
Cancel | Run cancellation on PR close or branch delete |
🧪 |
Test | Code tests (unit, integration, lint) |
💻 |
Test | Development environment tests |
💬 |
Test | DNS and network resolution tests |
📦 |
Test | Deployment tests |
📥 |
Test | Installation tests |
🚀 |
Release | Version release workflows |
Examples ✅
name: "🧪 Test: Code (Integration)"
name: "🪞 Mirror: Docker Hub → GHCR (only missing)"
name: "🚫 Cancel: PR Runs on Close"
Shell execution 📜
- Multi-line shell logic in workflow
run:blocks MUST be extracted into dedicated.shfiles underscripts/. - Workflow files MUST call those extracted
.shentry points instead of embedding longer shell programs inline. - Short single-command invocations MAY stay inline when they do not contain meaningful control flow.
- Inline shell in workflow files SHOULD stay limited to small command calls, environment wiring, or direct script invocation.
Disk space 💾
Deploy test workflows use the jlumbroso/free-disk-space action to reclaim runner space before Docker pulls start. Because the actual deploy runs inside the infinito container, the host's language toolchains, build packages, and default Docker layer cache are all dead weight and MUST be reclaimed aggressively.
| Option | Value | Reason |
|---|---|---|
tool-cache |
true |
Deploy runs inside the infinito container; host Node/Python/Go/Ruby toolchains go unused |
android |
true |
Android SDK is never needed; safe to remove |
dotnet |
true |
.NET SDK is never needed; safe to remove |
haskell |
true |
Haskell toolchain is never needed; safe to remove |
large-packages |
true |
Ansible, pip and gcc run inside the container, not on the host |
docker-images |
true |
Matrix jobs don't share a Docker layer cache; each runner pulls its own infinito image |
swap-storage |
true |
Default swap file is replaced by pierotofy/set-swap-space (see below) |
Set an option back to false only when a new host-side step in the same workflow genuinely needs the removed payload.
Swap 💾
Deploy test workflows enlarge host swap via enlarge_swap.sh to absorb transient memory spikes (e.g. PeerTube plugin install #162) that would otherwise trip the host OOM-killer on the 16 GB GitHub-hosted runner.
The script prefers /mnt when it is a separate partition (classic ubuntu-latest layout with /dev/sdb mounted at /mnt) and falls back to / otherwise. Current public runners no longer expose a separate /mnt, so the swapfile lands on / and must not starve the root filesystem.
Swap size is a fixed constant, not a "free space minus buffer" calculation. An earlier version took ~99 GB on a 145 GB root partition, leaving so little headroom that later Docker layer writes (Playwright test image pull) failed with no space left on device. A fixed cap is large enough to absorb the peertube spike and small enough that Docker layer writes keep succeeding throughout the 30+ min deploy.
| Argument | Default | Reason |
|---|---|---|
size-gb (positional) |
16 |
Empirically sufficient for the peertube memory spike (#162); raise only when a workload is proven to need more |
Workflow step invocation:
- name: Enlarge swap space
shell: bash
run: ./scripts/github/enlarge_swap.sh
Ordering:
- Swap step MUST run after
actions/checkoutbecause the script lives inside the repo. - Swap step SHOULD run after
jlumbroso/free-disk-spaceso the reclaimed disk on/is also a candidate target when/mntis crowded. - Swap step MUST run before any
make up/ container build step so the expanded swap is active when heavy-allocation work begins.
Swap is a host-kernel resource; see svc-opt-swapfile for why the in-stack swap role is intentionally skipped inside containers.
Separation of concerns 🧩
- GitHub workflow YAML MUST describe orchestration, permissions, triggers, inputs, and step order.
- Reusable shell behavior MUST live in script files, not in repeated workflow
run:blocks. - Non-shell helper logic MUST NOT be embedded as ad-hoc shell blobs inside workflow files.