mirror of
https://github.com/kevinveenbirkenbach/computer-playbook.git
synced 2026-11-06 10:59:59 +00:00
OpenSSF Scorecard reports no fuzzer integration (code scanning alert 507, issue #853). tests/fuzz/_yaml_bootstrap.py is an atheris harness that feeds arbitrary input to utils.yaml_bootstrap.load_block and fails whenever the reader accepts a document that load_yaml_str parses differently or rejects. That is the contract the module's docstring states, and the existing property test only samples it. The leading underscore keeps unittest discovery from importing it, because atheris is only installed with the fuzz extra. cron-security-fuzz.yml runs the harness for 15 minutes every Sunday and on demand, on ubuntu-latest, and uploads crashing inputs as the fuzz-crashes artifact. atheris 3.1.0 ships x86_64 manylinux wheels for CPython 3.12 to 3.14 only, so it lives in its own `fuzz` extra and stays out of every other install path. tests/fuzz/ is not part of `make test`. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
98 lines
15 KiB
Markdown
98 lines
15 KiB
Markdown
# GitHub Actions 🎬
|
||
|
||
This page catalogs every GitHub Actions workflow defined under the [workflows directory](../../../../../.github/workflows/). It lists each workflow together with a short description, its triggers, and the inputs it accepts.
|
||
|
||
For the CI **flow** (orchestrator stages, gates, fork-PR handling) see [pipeline.md](../../../artefact/git/pipeline.md). For the **repository variables** that control CI behaviour see [configuration.md](configuration.md). For the **naming and shell-extraction conventions** that every workflow file MUST follow see [workflow.md](../../../artefact/files/github/workflow.md). For the **branch-prefix scopes** referenced by the PR entry workflow see [branch.md](../../../artefact/git/branch.md). For the **mirror architecture** referenced by the image workflows see [mirror.md](../../../artefact/image/mirror.md).
|
||
|
||
## What GitHub Actions are 📘
|
||
|
||
GitHub Actions is GitHub's built-in CI/CD system. Each YAML file under `.github/workflows/` is one *workflow*; a workflow contains one or more *jobs*, and each job runs a sequence of *steps* on a hosted or self-hosted runner. Workflows are started by *triggers* declared in the `on:` section. The most common triggers in this repository are:
|
||
|
||
- `push`: fires when commits land on a branch.
|
||
- `pull_request` / `pull_request_target`: fires on PR lifecycle events (`opened`, `synchronize`, `reopened`, `ready_for_review`, `closed`, `converted_to_draft`). The `_target` variant runs with the base-branch secrets and is used to grant fork PRs controlled access to privileged steps.
|
||
- `schedule`: cron-based periodic runs (UTC).
|
||
- `workflow_dispatch`: manual run from the GitHub UI or `gh workflow run`, optionally with inputs.
|
||
- `workflow_call`: the workflow is a *reusable workflow* and is only started by another workflow that calls it via `uses:`.
|
||
- `delete`: fires when a branch or tag is deleted.
|
||
|
||
Workflows communicate through *inputs* (on `workflow_call` / `workflow_dispatch`), *outputs*, *concurrency groups* (which cancel or serialize runs with the same group key), and the `GITHUB_TOKEN` / repository secrets and variables. The entry points of this repository (`entry-*.yml`) translate external triggers into a call to the central [call-orchestrator.yml](../../../../../.github/workflows/call-orchestrator.yml). Most other workflows are reusable building blocks invoked from the orchestrator.
|
||
|
||
## Workflow catalog 📚
|
||
|
||
Trigger column legend: **auto** = fires automatically (push, pull_request, schedule, delete); **manual** = `workflow_dispatch`; **reusable** = `workflow_call`. Multiple values mean the workflow accepts any of them.
|
||
|
||
### Entry points 🚪
|
||
|
||
| Workflow | Description | Trigger | Inputs |
|
||
|---|---|---|---|
|
||
| [entry-pr-change-orchestrate.yml](../../../../../.github/workflows/entry-pr-change-orchestrate.yml): `🔀 Pull Request` | Detects PR scope from changed files + branch prefix, then conditionally calls the orchestrator. A maintainer `🛡️ Trusted` label builds the privileged images from the PR head — see [pipeline.md](../../../artefact/git/pipeline.md#trusted-fork-prs-). A `🧩 Subset` label pins the deploy matrix to the roles listed in the PR body — see [pipeline.md](../../../artefact/git/pipeline.md#subset-label-). | auto (`pull_request` & `pull_request_target`: opened, synchronize, reopened, ready_for_review, labeled) | none |
|
||
| [entry-push-latest.yml](../../../../../.github/workflows/entry-push-latest.yml): `📤 Push` | Syncs `main` from the configured source repository, then runs the orchestrator on pushes to `main`, `feature/**`, `hotfix/**`, `fix/**`, `update/**`, `chore/**`, `alert-autofix-*`; on tagged `main` it also calls `call-release-version.yml`. Respects the `CI_SYNC_MAIN_SOURCE_REPOSITORY` and `CI_RUN_ON_MAIN` repository variables, see [configuration.md](configuration.md). | auto (`push`) | none |
|
||
| [entry-manual-steer.yml](../../../../../.github/workflows/entry-manual-steer.yml): `🕹️ Manual` | Manual dispatch of the full orchestrator for a chosen app whitelist. The `whitelist` input accepts the `__ALL__` sentinel for forced full deploy; see the "Diff-driven app selection" subsection in [pipeline.md](../../../artefact/git/pipeline.md). | manual | `distros` (optional; empty spreads the rows over every declared distro), `filesystem` (optional; empty spreads them over `zfs`, `btrfs`, `ext4`), `whitelist` (optional; `__ALL__` forces full deploy, empty triggers diff derivation, any other value is verbatim), `lifecycles`, `mode` (default `auto`), `priority` (optional; priority rows get chunks of their own, the regular chunks run after them), `offset` (default `0`; a row count or a selection token naming where the regular line resumes), `chunk_gate` (default `true`), `sweep` (optional; empty means the run number) |
|
||
| [entry-cancel-superseded.yml](../../../../../.github/workflows/entry-cancel-superseded.yml): `🚫 Cancel: Superseded Runs` | Cancels the runs superseded by a newer one on the same branch or PR via the API, for the case where the concurrency group fails to reap its occupant and the newer run parks on `pending` behind it — see [cancel/README.md](../../../../../scripts/github/cancel/README.md). Carries no concurrency group of its own, otherwise it would queue behind the run it has to free, and only touches the workflows that share the group it backs up. The push job skips `main` like the `global-ci-*` group it backs up, see [configuration.md](configuration.md). | auto (`push` except `main`, `pull_request_target`: opened, synchronize, reopened, ready_for_review, labeled) | none |
|
||
| [entry-pr-closed-cancel-workflows.yml](../../../../../.github/workflows/entry-pr-closed-cancel-workflows.yml): `🚫 Cancel: PR Runs on Close` | Cancels active workflow runs for a PR when it is closed or converted to draft. | auto (`pull_request_target`: closed, converted_to_draft) | none |
|
||
| [entry-delete-branch.yml](../../../../../.github/workflows/entry-delete-branch.yml): `🚫 Cancel: Runs on Branch Delete` | Enters the push-entry concurrency group for the deleted branch so that any in-flight run on it is cancelled; a fallback step cancels remaining runs via the API. | auto (`delete`) | none |
|
||
|
||
### Orchestration 🎵
|
||
|
||
| Workflow | Description | Trigger | Inputs |
|
||
|---|---|---|---|
|
||
| [call-orchestrator.yml](../../../../../.github/workflows/call-orchestrator.yml): `🎵 CI: Orchestrator` | Central coordinator. Runs fork-prereq wait, security, linting, CI image build, code tests, code-quality gate, DNS tests, mirror, deploy tests as a serial chain of chunk blocks (each chunk's discover job renders the sweep's plan table via `cli.meta.ci.plan` into the run summary), install tests, `test-workspace`, final `done` gate. | reusable | `distros` (optional; empty spreads the rows over every declared distro), `filesystem` (optional; empty spreads them over `zfs`, `btrfs`, `ext4`), `whitelist` (optional), `priority` (optional; app ids sorted to the head of the list and cut into chunks of their own, so every priority row is deployed before the first regular one starts, and deployed in every combination it can take: each variant × each offered mode × Tor and clearnet, in one sweep), `mode` (default `auto`), `sweep`, `resume_from_chunk` (default `0`), `chunk_gate` (default `true`), `image_wait_attempts` (default `1980`), `image_wait_sleep_seconds` (default `10`), `workspace` (default `auto`) |
|
||
|
||
### Security and linting 🛡️🔍
|
||
|
||
| Workflow | Description | Trigger | Inputs |
|
||
|---|---|---|---|
|
||
| [cron-security-codeql.yml](../../../../../.github/workflows/cron-security-codeql.yml): `🔐 Scan with CodeQL` | CodeQL static analysis. Invoked by [call-orchestrator.yml](../../../../../.github/workflows/call-orchestrator.yml) so every CI run produces a single scan; additionally runs on a weekly cron so coverage does not drop when no pushes land on `main`. See [pipeline.md](../../../artefact/git/pipeline.md) for the gating behaviour. | reusable, auto (`schedule`: weekly Mon 00:00 UTC) | none |
|
||
| [cron-security-fuzz.yml](../../../../../.github/workflows/cron-security-fuzz.yml): `🧬 Fuzz parsers` | Runs the [atheris](https://github.com/google/atheris) harness [_yaml_bootstrap.py](../../../../../tests/fuzz/_yaml_bootstrap.py) for 15 minutes and uploads every crashing input as the `fuzz-crashes` artifact. Reproduce one locally with `pip install -e ".[fuzz]"` and `python3 tests/fuzz/_yaml_bootstrap.py <crash-file>`. | auto (`schedule`: weekly Sun 04:00 UTC), manual | none |
|
||
| [call-lint.yml](../../../../../.github/workflows/call-lint.yml): `🧹 Lint` | Runs `make lint` (every lint check in parallel: action, ansible, javascript, makefile, markdown, mermaid, packages, playwright, python, shellcheck) plus a hadolint SARIF job on `Dockerfile`. | reusable, manual | none |
|
||
|
||
### CI images 🐳
|
||
|
||
| Workflow | Description | Trigger | Inputs |
|
||
|---|---|---|---|
|
||
| [call-images-build-ci.yml](../../../../../.github/workflows/call-images-build-ci.yml): `🖼️ Build: CI Images (all distros)` | Builds the per-distro CI base images consumed by all test jobs. | reusable | `distros` (required), `checkout_ref` (optional), `image_tag` (default `ci-${github.sha}`), `concurrency_channel` (default `default`) |
|
||
| [cron-images-cleanup-ci.yml](../../../../../.github/workflows/cron-images-cleanup-ci.yml): `🧹 Prune CI images` | Deletes CI images from GHCR older than N days. | auto (`schedule`: weekly Mon 00:00 UTC), manual | `days` (default `7`) |
|
||
|
||
### Image mirroring 🪞
|
||
|
||
| Workflow | Description | Trigger | Inputs |
|
||
|---|---|---|---|
|
||
| [call-images-mirror-missing.yml](../../../../../.github/workflows/call-images-mirror-missing.yml): `🪞 Mirror: Docker Hub → GHCR (only missing)` | Mirrors only the upstream images that are not yet in GHCR. Called from the orchestrator before deploy tests. | reusable | `ghcr_namespace`, `ghcr_prefix` (default `mirror`), `repo_root` (default `.`), `source_repository`, `source_ref`, plus throttling knobs |
|
||
| [cron-images-mirror-all.yml](../../../../../.github/workflows/cron-images-mirror-all.yml): `🪞 Mirror all images` | Full nightly mirror of every referenced upstream image into GHCR. | auto (`schedule`: daily 00:00 UTC), manual | `ghcr_namespace`, `ghcr_prefix` (default `mirror`), `repo_root` (default `.`), `images_per_hour` (throttle) |
|
||
| [entry-manual-mirror-cleanup.yml](../../../../../.github/workflows/entry-manual-mirror-cleanup.yml): `🧹 Images: Cleanup GHCR` | Deletes GHCR mirror packages by prefix and visibility. Supports `dry_run`. | manual | `ghcr_namespace`, `ghcr_prefix` (default `mirror`), `visibility` (`private`/`public`/`internal`, default `private`), `dry_run` |
|
||
|
||
### Code tests 🧪
|
||
|
||
| Workflow | Description | Trigger | Inputs |
|
||
|---|---|---|---|
|
||
| [call-test.yml](../../../../../.github/workflows/call-test.yml): `🧪 Test` | Runs `make test` (unit, integration, lint and external tests in parallel) on the runner host. | reusable, manual | none |
|
||
|
||
### Infrastructure tests 🌐📦💻📥
|
||
|
||
| Workflow | Description | Trigger | Inputs |
|
||
|---|---|---|---|
|
||
| [call-test-dns.yml](../../../../../.github/workflows/call-test-dns.yml): `💬 Test: DNS` | Validates DNS resolution across target distributions. | reusable, manual | `distros` (required on call; default `debian` on manual) |
|
||
| [call-test-deploy.yml](../../../../../.github/workflows/call-test-deploy.yml): `🚀 Test: Deploy` | Deploys one chunk of the sweep. Every matrix row is a single `role#variant` carrying the deploy mode, onion state, distro and filesystem the rotation assigned it: `swarm` rows get a simulated 3-node DinD cluster with an NFS server plus a drain/reschedule state-survival assertion, `compose` and `host` rows run the single-node drill. When `whitelist` is empty, the discover job derives one from the branch's diff vs `origin/main`; see the "Diff-driven app selection" subsection in [pipeline.md](../../../artefact/git/pipeline.md). A row marked 📖 -- the role's smallest variant, see [instructions.md](instructions.md) -- replays the role README's `### Production` block on the same runner once the deploy has released it. | reusable | `index`, `sweep` (required), `distros` (optional pool), `filesystem` (optional pool), `whitelist` (optional; explicit value wins over diff), `priority`, `lifecycles`, `modes` (default `auto`), `tor`, `marker` |
|
||
| [call-test-install-make.yml](../../../../../.github/workflows/call-test-install-make.yml): `📥 Test: Install Make` | Validates the `make install` entry points. | reusable | none |
|
||
| [call-test-install-pkgmgr.yml](../../../../../.github/workflows/call-test-install-pkgmgr.yml): `📥 Test: Install Package Manager` | Validates installation via the upstream package manager. | reusable | none |
|
||
| [call-test-workspace.yml](../../../../../.github/workflows/call-test-workspace.yml): `💻 Test: Workspace` | Builds and exercises the dev-runtime image matrix. | reusable, manual | none |
|
||
|
||
### Release and maintenance 🚀🔄
|
||
|
||
| Workflow | Description | Trigger | Inputs |
|
||
|---|---|---|---|
|
||
| [call-release-version.yml](../../../../../.github/workflows/call-release-version.yml): `🚀 Release: Version Logic` | Releases a specific version tag (build + publish). Called from `entry-push-latest.yml` on tagged pushes. | reusable, manual | `tag` (required, e.g. `v1.2.3`) |
|
||
| [cron-release-highest.yml](../../../../../.github/workflows/cron-release-highest.yml): `🚀 Release missing tag` | Scheduled backfill: finds the highest tag without a release and triggers `call-release-version.yml` for it. | auto (`schedule`: daily 00:00 UTC), manual | none |
|
||
| [cron-cleanup-stale.yml](../../../../../.github/workflows/cron-cleanup-stale.yml): `🧹 Prune stale data` | Marks and closes stale issues and PRs, deletes inactive branches, and prunes old GHCR CI image versions. | auto (`schedule`: daily 00:00 UTC), manual | none |
|
||
| [cron-update.yml](../../../../../.github/workflows/cron-update.yml): `🔄 Update versions` | Updates Docker image versions and other pinned dependencies; opens an update PR via a GitHub App installation token so PR-lifecycle events fire on the resulting PR. Both jobs are gated behind the `CI_ENABLE_AUTO_UPDATES` repository variable, see [configuration.md](configuration.md). Requires the `BOT_APP_CLIENT_ID` and `BOT_APP_PRIVATE_KEY` repository secrets, see [secrets.md](secrets.md). | auto (`push` to `main`, `schedule`: daily 00:30 UTC), manual | none |
|
||
| [entry-pr-open-dependabot-close.yml](../../../../../.github/workflows/entry-pr-open-dependabot-close.yml): `🚫 Dependabot: Close while auto-updates disabled` | Auto-closes Dependabot PRs while `CI_ENABLE_AUTO_UPDATES` is not set to `true`, so Dependabot honours the same gate as the workflow-driven update jobs. See [configuration.md](configuration.md). | auto (`pull_request_target`: opened, reopened) | none |
|
||
|
||
## Changing workflows ✍️
|
||
|
||
Before adding or editing a workflow file:
|
||
|
||
1. Follow the naming schema and shell-extraction rules in [workflow.md](../../../artefact/files/github/workflow.md).
|
||
2. If the change affects the CI flow (stages, gates, order), also update [pipeline.md](../../../artefact/git/pipeline.md).
|
||
3. If the change adds or removes a repository variable, also update [configuration.md](configuration.md).
|
||
4. Update the relevant row in this page so the catalog stays accurate.
|