Files
MoShiro/ci/release-main-images.sh
T
2026-10-06 15:18:12 +08:00

117 lines
4.2 KiB
Bash

#!/usr/bin/env bash
# Manually build and push selected linux/amd64 OCI images from main.
set -euo pipefail
root="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
registry="${ZOT_REGISTRY:-registry.oeo.one}"
work="$root/.release/main-fastlane"
buildah_home="/home/justme/woodpecker/buildah-home/main-fastlane"
mkdir -p "$work" "$buildah_home"
export HOME="$buildah_home"
export BUILDAH_HOME="$buildah_home"
export REGISTRY_AUTH_FILE="$work/zot-auth.json"
[[ "${CI_PIPELINE_EVENT:-}" == manual && "${CI_COMMIT_BRANCH:-}" == main ]] || {
echo "fast-lane images can only be published by a manual run on main" >&2
exit 2
}
manual_targets=""
if [[ -n "${FASTLANE_COMPONENTS:-}" && -n "${FASTLANE_BASE_SHA:-}" ]]; then
echo "set only one of FASTLANE_COMPONENTS or FASTLANE_BASE_SHA" >&2
exit 2
elif [[ -n "${FASTLANE_COMPONENTS:-}" ]]; then
manual_targets="$(python3 -c '
import sys
allowed = {"backend", "agent", "probe"}
requested = {part.strip() for part in sys.argv[1].split(",") if part.strip()}
unknown = requested - allowed
if not requested or unknown:
raise SystemExit("invalid FASTLANE_COMPONENTS: " + ", ".join(sorted(unknown or {"empty list"})))
print("\n".join(name for name in ("backend", "agent", "probe") if name in requested))
' "$FASTLANE_COMPONENTS")"
elif [[ -n "${FASTLANE_BASE_SHA:-}" ]]; then
[[ "$FASTLANE_BASE_SHA" =~ ^[0-9a-fA-F]{7,40}$ ]] || {
echo "FASTLANE_BASE_SHA must be a commit SHA" >&2
exit 2
}
if ! git cat-file -e "${FASTLANE_BASE_SHA}^{commit}" 2>/dev/null; then
git fetch --no-tags origin "$FASTLANE_BASE_SHA"
fi
base_sha="$(git rev-parse "${FASTLANE_BASE_SHA}^{commit}")"
git merge-base --is-ancestor "$base_sha" "${CI_COMMIT_SHA:-HEAD}" || {
echo "FASTLANE_BASE_SHA must be an ancestor of the selected main commit" >&2
exit 2
}
export CI_PIPELINE_FILES="$(git diff --name-only "$base_sha" "${CI_COMMIT_SHA:-HEAD}" | python3 -c 'import json,sys; print(json.dumps(sys.stdin.read().splitlines()))')"
export FASTLANE_FILES_ARE_JSON=true
else
# A manual run may follow several pushes; rebuild all images unless the caller
# explicitly chooses components or supplies a base SHA for change detection.
manual_targets=$'backend\nagent\nprobe'
fi
[[ -n "${ZOT_USERNAME:-}" && -n "${ZOT_SECRET:-}" ]] || {
echo "Zot credentials are required" >&2
exit 2
}
if [[ -n "$manual_targets" ]]; then
targets="$manual_targets"
else
targets="$(python3 "$root/ci/main-fastlane.py")"
fi
if [[ -z "$targets" ]]; then
echo "no runtime image changes detected; skipping container builds"
exit 0
fi
echo "affected linux/amd64 images: ${targets//$'\n'/, }"
logged_in=false
for attempt in 1 2 3 4; do
if buildah login --tls-verify=true --username "$ZOT_USERNAME" --password-stdin "$registry" <<< "$ZOT_SECRET" >/dev/null; then
logged_in=true
break
fi
if [[ "$attempt" -lt 4 ]]; then
echo "Zot login attempt $attempt failed; retrying in 3 seconds" >&2
sleep 3
fi
done
[[ "$logged_in" == true ]] || { echo "could not authenticate to Zot after 4 attempts" >&2; exit 1; }
publish_node_image() {
local component="$1" context="$work/$1" image="$registry/monitor/monitor-$1"
local local_image="localhost/monitor-$component:main-amd64"
python3 "$root/ci/main-fastlane.py" --stage "$component" --destination "$context"
buildah bud --layers --network host --tls-verify=true --arch amd64 \
--build-arg APP_VERSION=main \
-f "$context/Containerfile" -t "$local_image" "$context"
for tag in main-amd64 main; do
local pushed=false
for attempt in 1 2 3; do
if buildah push --tls-verify=true "$local_image" "docker://$image:$tag"; then
pushed=true
break
fi
if [[ "$attempt" -lt 3 ]]; then
echo "Zot push for $component:$tag attempt $attempt failed; retrying in 5 seconds" >&2
sleep 5
fi
done
[[ "$pushed" == true ]] || { echo "could not push $component:$tag after 3 attempts" >&2; return 1; }
echo "pushed Zot image $image:$tag"
done
}
while IFS= read -r component; do
[[ -n "$component" ]] || continue
case "$component" in
backend) bash "$root/ci/release-linux.sh" amd64 backend ;;
agent|probe) publish_node_image "$component" ;;
*) echo "unknown affected image: $component" >&2; exit 2 ;;
esac
done <<< "$targets"