build-push: workflow_dispatch input to rebuild a single image leg #41

Merged
jknapp merged 1 commits from feat/single-leg-dispatch into trunk 2026-11-12 15:57:30 +00:00
Owner

What

Adds an optional workflow_dispatch string input only to build-push.yaml so one image leg can be rebuilt without a ~1h full run (Gitea has no single-job rerun).

Dispatch syntax

only = comma list (spaces ignored), empty = build everything (identical to a push):

  • cac:php85 (publishes cac:php85 + cac:latest), cac-fpm:php84, cac-litespeed:php83, cac-lsphp:php82
  • bare family = all PHP versions: cac, cac-fpm, cac-litespeed, cac-lsphp
  • shared-httpd, shared-ols
  • combos: cac:php85,cac-fpm:php85,shared-httpd
    Anything else (typo, php99, shared-httpd:php85, ,) fails the plan job with plan-legs: ... and nothing builds.

How it works

A job-level if: cannot see matrix, so a new plan job (checkout + .gitea/scripts/plan-legs.sh) emits a filtered phpver JSON array per matrix family (cac, cac_fpm, cac_litespeed, cac_lsphp) and true/false for shared_httpd/shared_ols. Each image job has needs: plan, if: needs.plan.outputs.X != '[]' (or == 'true'), and matrix.phpver: ${{ fromJSON(needs.plan.outputs.X) }}. Unselected jobs are skipped outright. The input reaches the script via env: (never interpolated into run:). Build steps are untouched. Shell-Checks is unchanged except plan-legs.sh is added to its shellcheck list.

Push trigger is still trunk only; this branch push does not trigger the workflow.

Tests

scripts/tests/multiarch-workflow.test.py: 12 existing + 12 new (24 pass). New tests run the real script against inputs (single leg, family, list, whitespace, dupes, empty/push = full set [82,83,84,85], 17 bad values must exit 2 with no output) and check the wiring (needs/if/fromJSON per job, env-passed input, Shell-Checks ungated). Against the old workflow: 5 fail; with the script removed: 8 fail. One existing assertion (literal matrix list) was updated to expect the fromJSON form.

Caveat (unverified until first dispatch)

Dynamic matrix from needs outputs (fromJSON) requires the act_runner/Gitea in use to support it; not tested on a live runner. Gitea reports version 28.1.0. Do not merge-and-dispatch blind: the first real use is the test. Not merged / not dispatched.

🤖 Generated with Claude Code

https://claude.ai/code/session_0185ukXjXyosSkunDsdWz3mb

## What Adds an optional `workflow_dispatch` string input `only` to `build-push.yaml` so one image leg can be rebuilt without a ~1h full run (Gitea has no single-job rerun). ## Dispatch syntax `only` = comma list (spaces ignored), empty = build everything (identical to a push): - `cac:php85` (publishes cac:php85 + cac:latest), `cac-fpm:php84`, `cac-litespeed:php83`, `cac-lsphp:php82` - bare family = all PHP versions: `cac`, `cac-fpm`, `cac-litespeed`, `cac-lsphp` - `shared-httpd`, `shared-ols` - combos: `cac:php85,cac-fpm:php85,shared-httpd` Anything else (typo, `php99`, `shared-httpd:php85`, `,`) fails the `plan` job with `plan-legs: ...` and nothing builds. ## How it works A job-level `if:` cannot see `matrix`, so a new `plan` job (checkout + `.gitea/scripts/plan-legs.sh`) emits a filtered phpver JSON array per matrix family (`cac`, `cac_fpm`, `cac_litespeed`, `cac_lsphp`) and `true/false` for `shared_httpd`/`shared_ols`. Each image job has `needs: plan`, `if: needs.plan.outputs.X != '[]'` (or `== 'true'`), and `matrix.phpver: ${{ fromJSON(needs.plan.outputs.X) }}`. Unselected jobs are skipped outright. The input reaches the script via `env:` (never interpolated into `run:`). Build steps are untouched. Shell-Checks is unchanged except `plan-legs.sh` is added to its shellcheck list. Push trigger is still `trunk` only; this branch push does not trigger the workflow. ## Tests `scripts/tests/multiarch-workflow.test.py`: 12 existing + 12 new (24 pass). New tests run the real script against inputs (single leg, family, list, whitespace, dupes, empty/push = full set `[82,83,84,85]`, 17 bad values must exit 2 with no output) and check the wiring (needs/if/fromJSON per job, env-passed input, Shell-Checks ungated). Against the old workflow: 5 fail; with the script removed: 8 fail. One existing assertion (literal matrix list) was updated to expect the `fromJSON` form. ## Caveat (unverified until first dispatch) Dynamic matrix from `needs` outputs (`fromJSON`) requires the act_runner/Gitea in use to support it; not tested on a live runner. Gitea reports version 28.1.0. Do not merge-and-dispatch blind: the first real use is the test. Not merged / not dispatched. 🤖 Generated with [Claude Code](https://claude.com/claude-code) https://claude.ai/code/session_0185ukXjXyosSkunDsdWz3mb
jknapp added 1 commit 2026-11-12 15:52:14 +00:00
Gitea cannot re-run one job and a full run takes ~1h. Add a plan job that
turns the optional `only` input (e.g. cac:php85) into one filtered matrix per
image family; image jobs take their matrix from it and are skipped when empty.
Push events / empty input plan the full set as before. Unknown values fail
the plan job. Tests added to multiarch-workflow.test.py.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0185ukXjXyosSkunDsdWz3mb
jknapp merged commit 2b308e9192 into trunk 2026-11-12 15:57:30 +00:00
jknapp deleted branch feat/single-leg-dispatch 2026-11-12 15:57:31 +00:00
Sign in to join this conversation.
No Reviewers
No labels
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: cloud-hosting-platform/cloud-apache-container#41