test(release): port promote-retag bats to the cozytest harness

hack/promote-retag_test.bats was written for upstream bats (run,
$status, $output, setup(), skip), but CI runs hack/*.bats through
hack/cozytest.sh, a pure-shell runner that has none of those. The first
'run' therefore died with 'cozytest.sh: run: not found', failing the
Unit & controller tests job.

Rewrite both cases in the cozytest idiom already used by
select-e2e_test.bats and check-host-runtime.bats: redirect to temp
files, capture the exit code with '|| rc=$?' so the harness's set -e
does not abort the expected-failure case, and assert with plain shell.
The selector logic under test is unchanged.

Assisted-By: Claude <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Signed-off-by: Myasnikov Daniil <myasnikovdaniil2001@gmail.com>
This commit is contained in:
Myasnikov DaniilandClaude Opus 4.8 committed 2026-07-06 10:03:49 +05:00
1 parent 6a2f392b41
commit 20c0806325
1 file changed
+31 -12
+31 -12
View File
@@ -7,30 +7,49 @@
# "--migrate-image=..." arg string — so the first skopeo copy to a registry CI
# cannot push to aborted the whole promotion. The selector must emit only
# cozystack-owned ($REGISTRY/...) refs.
setup() {
command -v yq >/dev/null 2>&1 || skip "yq (mikefarah) not installed"
yq --version 2>&1 | grep -q mikefarah || skip "yq is not mikefarah"
}
#
# Harness note: the CI path is hack/cozytest.sh, NOT real bats. cozytest.sh's
# awk parser recognizes only @test blocks and a bare `}` on its own line; there
# is no `run`, `$status`, `$output`, `skip`, or setup()/teardown(). Each test
# runs as a shell function under `set -eu -x`, so a non-zero exit aborts the
# test (that is the exit-0 assertion) and other expectations are direct shell
# tests. A test that expects a non-zero exit must capture it with `|| rc=$?`
# so the harness's `set -e` does not abort first. mikefarah yq is assumed
# present (provided by the test toolchain, like the other yq-using bats here).
#
# Run with: hack/cozytest.sh hack/promote-retag_test.bats
# (or `bats hack/promote-retag_test.bats` if the bats binary is
# installed; cozytest.sh is the CI path.)
@test "dry-run over the real tree retags only cozystack-owned refs" {
run hack/promote-retag.sh v9.9.9 --dry-run
[ "$status" -eq 0 ]
tmp=$(mktemp -d)
trap 'rm -rf "$tmp"' EXIT
# Under set -e a non-zero exit aborts the test — that is the exit-0 assertion.
hack/promote-retag.sh v9.9.9 --dry-run >"$tmp/out" 2>"$tmp/err"
# At least one cozystack-owned image is selected.
echo "$output" | grep -q 'docker://ghcr.io/cozystack/cozystack/'
grep -q 'docker://ghcr.io/cozystack/cozystack/' "$tmp/out"
# Every docker:// ref in the copy plan is under the cozystack registry — no
# third-party repos and no malformed arg-string refs leak through.
bad=$(echo "$output" | grep -oE 'docker://[^ ]+' | sed 's|docker://||' \
bad=$(grep -oE 'docker://[^ ]+' "$tmp/out" | sed 's|docker://||' \
| grep -vE '^ghcr\.io/cozystack/cozystack/' || true)
[ -z "$bad" ]
}
@test "REGISTRY override scopes the selection" {
REGISTRY="example.com/nope" run hack/promote-retag.sh v9.9.9 --dry-run
tmp=$(mktemp -d)
trap 'rm -rf "$tmp"' EXIT
# No cozystack images live under example.com/nope, so the selector finds
# nothing and exits non-zero rather than silently promoting the wrong set.
[ "$status" -ne 0 ]
echo "$output" | grep -q 'No cozystack-owned digest-pinned image refs found'
# Capture the exit status without tripping the harness's `set -e`.
rc=0
REGISTRY="example.com/nope" hack/promote-retag.sh v9.9.9 --dry-run \
>"$tmp/out" 2>"$tmp/err" || rc=$?
[ "$rc" -ne 0 ]
# The diagnostic is written to stderr.
grep -q 'No cozystack-owned digest-pinned image refs found' "$tmp/err"
}