mirror of
https://github.com/cozystack/cozystack.git
synced 2026-10-23 03:27:50 +09:00
The shell translator rewrites test bodies and loses Bats reporting. The unit lane needs complete TAP results and JUnit reports without changing how live-cluster suites run. Sourced production helpers still need a dash pass, and unit test bodies need nounset without exporting shell options into subprocesses. Assisted-by: LLM Signed-off-by: Myasnikov Daniil <myasnikovdaniil2001@gmail.com>
101 lines
4.5 KiB
Bash
101 lines
4.5 KiB
Bash
#!/usr/bin/env bats
|
|
# Asserts that no first-party image repository is pinned at more than one
|
|
# digest across the committed tree.
|
|
#
|
|
# Promotion retags by digest: hack/promote-retag.sh copies every collected
|
|
# <repo>@<digest> to <repo>:<stable-version>. Two different digests under one
|
|
# repository therefore produce two copies competing for the same destination
|
|
# tag. The first wins, the second hits the write-once guard, and the promotion
|
|
# fails — on release day, in a workflow that runs once per release.
|
|
#
|
|
# This is not hypothetical. platform-migrations was pinned twice: once in
|
|
# packages/core/platform/values.yaml (stamped by its Makefile) and once as
|
|
# .backupStrategyController.chBackupClientImage, which had no producer at all
|
|
# and so froze at v1.4.0-rc.2 while the other advanced to v1.5.0. v1.6.0 is the
|
|
# first release cut through the promote path rather than a full rebuild, so it
|
|
# would have been the first to hit it.
|
|
#
|
|
# The general invariant is cheaper to hold than the specific one: a duplicate
|
|
# pin can arise from any package reusing another's image, which the tree does
|
|
# deliberately (backupstrategy-controller reuses platform-migrations as a
|
|
# curl+jq runner rather than shipping a second one-binary tag).
|
|
#
|
|
# Harness compatibility note: CI runs this file under Bats through
|
|
# `make bats-unit-tests`. It also remains compatible with the narrower legacy
|
|
# `hack/cozytest.sh` translator, so it avoids `run`, `$status`, `$output`,
|
|
# `skip`, and setup()/teardown(). Paths stay repo-root-relative for both
|
|
# runners.
|
|
#
|
|
# Run with: bats hack/image-pin-consistency.bats
|
|
|
|
load test_helper
|
|
|
|
@test "no image repository is pinned at more than one digest" {
|
|
tmp=$(mktemp -d)
|
|
|
|
# Drive the real promotion selector rather than a reimplementation of it, so
|
|
# this tracks whatever set promotion actually acts on. `env -u REGISTRY`:
|
|
# the CI workflow exports REGISTRY=<OCIR build registry> for every job, but
|
|
# the committed tree vendors its digests under the script's default
|
|
# ghcr.io/cozystack/cozystack — inheriting the ambient value would filter for
|
|
# the wrong registry and match nothing.
|
|
rc=0
|
|
env -u REGISTRY hack/promote-retag.sh v9.9.9 --dry-run \
|
|
>"$tmp/out" 2>"$tmp/err" || rc=$?
|
|
if [ "$rc" -ne 0 ]; then
|
|
echo "promote-retag.sh exited $rc" >&2
|
|
cat "$tmp/err" >&2
|
|
rm -rf "$tmp"
|
|
return "$rc"
|
|
fi
|
|
|
|
# Every planned copy ends in docker://<repo>:v9.9.9. A repository appearing
|
|
# twice means two source digests aimed at one destination tag.
|
|
sed -n 's|.*docker://\(.*\):v9\.9\.9$|\1|p' "$tmp/out" | sort > "$tmp/dests"
|
|
dupes=$(uniq -d < "$tmp/dests")
|
|
|
|
if [ -n "$dupes" ]; then
|
|
echo "these repositories are pinned at more than one digest, so promotion" >&2
|
|
echo "would try to retag several digests to the same stable tag and fail:" >&2
|
|
printf '%s\n' "$dupes" >&2
|
|
echo >&2
|
|
echo "Offending pins:" >&2
|
|
for repo in $dupes; do
|
|
grep -rn --include='*.yaml' --include='*.tag' --exclude-dir=charts \
|
|
-- "${repo#ghcr.io/cozystack/cozystack/}" packages/ >&2 || true
|
|
done
|
|
echo >&2
|
|
echo "Give the duplicate key a producer that stamps the same ref (see" >&2
|
|
echo "packages/core/platform/Makefile), or drop the duplicate pin." >&2
|
|
rm -rf "$tmp"
|
|
return 1
|
|
fi
|
|
rm -rf "$tmp"
|
|
}
|
|
|
|
@test "platform-migrations is pinned identically in both consumers" {
|
|
# The specific instance, pinned separately so a regression names its cause
|
|
# rather than only tripping the general check above. The two must match
|
|
# exactly, not merely resolve to the same digest: backupstrategy-controller
|
|
# renders its copy into a Pod spec, so a stale tag string there is what an
|
|
# operator reads when asking what is running.
|
|
a=$(yq -r '.migrations.image' packages/core/platform/values.yaml)
|
|
b=$(yq -r '.backupStrategyController.chBackupClientImage' \
|
|
packages/system/backupstrategy-controller/values.yaml)
|
|
c=$(yq -r '.backupStrategyController.rabbitmqBackupClientImage' \
|
|
packages/system/backupstrategy-controller/values.yaml)
|
|
|
|
if [ "$a" != "$b" ] || [ "$a" != "$c" ]; then
|
|
echo "platform-migrations pins have drifted:" >&2
|
|
echo " packages/core/platform/values.yaml .migrations.image" >&2
|
|
echo " $a" >&2
|
|
echo " backupstrategy-controller/values.yaml .chBackupClientImage" >&2
|
|
echo " $b" >&2
|
|
echo " backupstrategy-controller/values.yaml .rabbitmqBackupClientImage" >&2
|
|
echo " $c" >&2
|
|
echo >&2
|
|
echo "packages/core/platform/Makefile stamps all three; do not hand-edit any." >&2
|
|
return 1
|
|
fi
|
|
}
|