Files
computer-playbook/scripts/tests/deploy/act/workflow.sh
T
kevinveenbirkenbachandClaude Opus 5 4e9ced67b7 feat(swarm): let the local loop drive the architecture axis
The axis was complete in CI and unusable from a workstation. Four separate
gaps, each invisible on a real runner, and each found by running the swarm loop
against it:

`INFINITO_ARCHITECTURES` as an exported variable did nothing, because the
workflow reads its pool from `inputs.architectures`. Passing the input alone did
not help either: ACT_ENV sets INFINITO_APP_DISCOVERY_RUNNER=host, so the
discovery that builds the matrix runs outside the act container, where a
workflow-level `env:` does not reach. This is why the distro axis is handed over
twice, as `distros=` and as `INFINITO_DISTROS`, and SWARM_ARCH now does the same
for the architecture.

The third gap is the sharpest: act does not resolve `${{ matrix.* }}` inside a
job-level `env:` block, so `INFINITO_ARCHITECTURE` reached the assertion empty
every time. Earlier runs only appeared to work because a stale local `.env`
supplied a value, and the assertion was therefore checking a leftover rather
than the row. It surfaced the moment that file was regenerated.

Fourth, act had no mapping for `ubuntu-24.04-arm`, the label RUNNERS
introduced, and skipped the job with a hint instead of failing. It maps to the
same runner image: locally the architecture is delivered by emulation, and the
runner's own hardware is not the promise being made.

`make binfmt` registers that emulation. The handler already existed for
compose-up; it gains a subcommand so the registration is reachable without a
privileged docker invocation, which is what an agent would otherwise have to
ask for every time. The emulation does not survive a swarm run, because act
starts further containers whose systemd clears the shared binfmt registry, so
this is needed often.

Without `arch=`, SWARM_ARCH resolves to the host's own architecture rather than
staying empty, which would now abort every unpinned local swarm run at the
assertion.

Verified: `make binfmt arch=s390x` takes a platform from `exec format error` to
`s390x`; `make -n swarm-zombie arch=arm64` carries arm64 through all three
levers and defaults to amd64 without it; shellcheck passes; a live run reached
`"architecture":"arm64"` with the arm64 glyph in its job title.

Not verified: that the runner-label mapping carries a swarm deploy to the end.
That run was stopped so a parallel agent could use the shared stack.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-09-19 11:57:03 +02:00

107 lines
3.8 KiB
Bash
Executable File

#!/usr/bin/env bash
set -euo pipefail
: "${ACT_WORKFLOW:?ACT_WORKFLOW is not set (e.g. .github/workflows/call-test-workspace.yml)}"
: "${ACT_EVENT:=workflow_dispatch}"
: "${ACT_JOB:=}"
: "${ACT_MATRIX:=}"
: "${ACT_CONTAINER_OPTIONS:=--privileged}"
: "${ACT_NETWORK:=host}"
: "${ACT_PULL:=false}"
: "${ACT_RM:=true}"
: "${ACT_PLATFORM_IMAGE:?ACT_PLATFORM_IMAGE is not set; source scripts/meta/env/load.sh or invoke via make}"
: "${ACT_BIND:=false}"
: "${ACT_INPUTS:=}"
: "${ACT_ENV:=}"
if [[ "${ACT_PLATFORM_IMAGE}" == local/act-runner-fixed:latest ]] &&
! docker image inspect "${ACT_PLATFORM_IMAGE}" >/dev/null 2>&1; then
bash "$(dirname "${BASH_SOURCE[0]}")/build_runner_image.sh"
fi
_act_cache_path="${ACT_ACTION_CACHE_PATH:-/tmp/actcache/act}" # nocheck: act-tool cache path, not a stack variable
_stale_mounts=$(mount | grep -E " on ${_act_cache_path}/[^ ]+ type devtmpfs " || true)
if [[ -n "${_stale_mounts}" ]]; then
echo "ERROR: stale devtmpfs bind-mounts inside ${_act_cache_path} block act from refreshing the actions cache." >&2
echo "Affected mountpoints:" >&2
echo "${_stale_mounts}" | awk '{print " " $3}' >&2
echo "Fix (run on the host, outside the agent sandbox):" >&2
echo " mount | awk -v p='${_act_cache_path}/' '\$5==\"devtmpfs\" && index(\$3,p)==1 {print \$3}' | sudo xargs -r umount" >&2
echo " sudo rm -rf ${_act_cache_path}" >&2
exit 3
fi
echo "=== act: workflow=${ACT_WORKFLOW} event=${ACT_EVENT} job=${ACT_JOB:-<all>} matrix=${ACT_MATRIX:-<none>} inputs=${ACT_INPUTS:-<none>} ==="
# Exception: act's bundled Actions schema (pkg/schema/workflow_schema.json, still
# true on main at v0.2.89) lacks the `queue` concurrency property that GitHub
# shipped on 2026-05-07, and rejects the whole workflow over it instead of
# ignoring it, so act is fed a copy without those lines.
# TODO: drop this sanitize step once act's schema knows `queue` --
# report https://github.com/nektos/act/issues/6095,
# fix in review https://github.com/nektos/act/pull/6152.
_act_queue_re='^[[:space:]]*queue:[[:space:]]*(single|max)[[:space:]]*$'
_act_sanitized="$(mktemp -d)"
trap 'rm -rf "${_act_sanitized}"' EXIT
_act_workflow="${_act_sanitized}/$(basename "${ACT_WORKFLOW}")"
if [[ -d "${ACT_WORKFLOW}" ]]; then
cp -r "${ACT_WORKFLOW}" "${_act_workflow}"
find "${_act_workflow}" -type f -name '*.y*ml' \
-exec sed -i -E "/${_act_queue_re}/d" {} +
else
grep -vE "${_act_queue_re}" "${ACT_WORKFLOW}" >"${_act_workflow}"
fi
cmd=(act "${ACT_EVENT}" -W "${_act_workflow}")
cmd+=(-P "ubuntu-latest=${ACT_PLATFORM_IMAGE}")
cmd+=(-P "ubuntu-24.04=${ACT_PLATFORM_IMAGE}")
cmd+=(-P "ubuntu-24.04-arm=${ACT_PLATFORM_IMAGE}")
cmd+=(-P "ubuntu-22.04=${ACT_PLATFORM_IMAGE}")
cmd+=(-P "ubuntu-20.04=${ACT_PLATFORM_IMAGE}")
if [[ -n "${ACT_JOB}" ]]; then
cmd+=(-j "${ACT_JOB}")
fi
if [[ -n "${ACT_MATRIX}" ]]; then
IFS=';' read -ra _act_matrix_filters <<<"${ACT_MATRIX}"
for pair in "${_act_matrix_filters[@]}"; do
cmd+=(--matrix "${pair}")
done
fi
if [[ -n "${ACT_INPUTS}" ]]; then
for pair in ${ACT_INPUTS}; do
cmd+=(--input "${pair}")
done
fi
if [[ -n "${ACT_ENV}" ]]; then
IFS=';' read -ra _act_env_pairs <<<"${ACT_ENV}"
for pair in "${_act_env_pairs[@]}"; do
pair="${pair#"${pair%%[![:space:]]*}"}"
pair="${pair%"${pair##*[![:space:]]}"}"
if [[ -n "${pair}" ]]; then
cmd+=(--env "${pair}")
fi
done
fi
if [[ -n "${ACT_CONTAINER_OPTIONS}" ]]; then
cmd+=(--container-options "${ACT_CONTAINER_OPTIONS}")
fi
if [[ -n "${ACT_NETWORK}" ]]; then
cmd+=(--network "${ACT_NETWORK}")
fi
cmd+=(--concurrent-jobs "1")
cmd+=(--pull="${ACT_PULL}")
cmd+=(--action-offline-mode)
cmd+=(--action-cache-path "${ACT_ACTION_CACHE_PATH:-/tmp/actcache/act}") # nocheck: act-tool cache path, not a stack variable
if [[ "${ACT_RM}" == "true" ]]; then
cmd+=(--rm)
fi
cmd+=(--cache-server-addr 127.0.0.1)
cmd+=(--artifact-server-addr 127.0.0.1)
if [[ "${ACT_BIND}" == "true" ]]; then
cmd+=(--bind)
fi
"${cmd[@]}"