Files
MoShiro/ci/release-linux.sh
T
justme 7a71bf57f9 feat: update controls in the admin, release token scope, build info in CI images
The versions page shows each node's update state with update buttons, API
tokens get a release scope that can only register releases (used by CI), and
the CI image and release builds now pass the tag, commit and build time.
2026-10-06 22:56:56 +08:00

124 lines
4.5 KiB
Bash
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
#!/usr/bin/env bash
# Build a framework-dependent Backend OCI image for the requested arch; publishing is optional.
set -euo pipefail
arch="${1:?usage: release-linux.sh <amd64|arm64>}"
root="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
tag="${CI_COMMIT_TAG:-}"
if [[ -n "$tag" ]]; then
[[ "$tag" =~ ^v[0-9]+\.[0-9]+\.[0-9]+(-[0-9A-Za-z.-]+)?$ ]] || {
echo "release must run from a vMAJOR.MINOR.PATCH tag" >&2
exit 2
}
version="${tag#v}"
else
[[ "${CI_PIPELINE_EVENT:-}" == push && "${CI_COMMIT_BRANCH:-}" == main && "${CI_COMMIT_MESSAGE:-}" == *"[CI]"* ]] || {
echo "untagged backend builds require a main push with [CI] in the commit message" >&2
exit 2
}
version=main
fi
image_publish="${IMAGE_PUBLISH:-true}"
[[ "$image_publish" == true || "$image_publish" == false ]] || {
echo "IMAGE_PUBLISH must be true or false" >&2; exit 2;
}
if [[ "$image_publish" == true ]]; then
[[ -n "${ZOT_USERNAME:-}" && -n "${ZOT_SECRET:-}" ]] || {
echo "Zot credentials are required" >&2; exit 2;
}
fi
case "$arch" in
amd64|arm64) ;;
*) echo "unsupported architecture: $arch" >&2; exit 2 ;;
esac
project_version="$(sed -n 's#.*<Version>\(.*\)</Version>.*#\1#p' "$root/backend/Directory.Build.props" | head -1)"
if [[ -n "$tag" && "$version" != "$project_version" ]]; then
echo "tag version $version does not match project version $project_version" >&2
exit 1
fi
registry="${ZOT_REGISTRY:-registry.oeo.one}"
image="${ZOT_IMAGE_REPOSITORY:-$registry/monitor/monitor-backend}"
output="$root/.release/linux-$arch/backend"
build_root="$root/.release/build/linux-$arch-backend"
container_context="$root/.release/container/linux-$arch"
mkdir -p "$output" "$build_root" "$container_context/app" "$container_context/data"
# 构建信息:tag 发布用 tag,main 构建用 main-<提交>
export MONITOR_TAG="${MONITOR_TAG:-${tag:-main-${CI_COMMIT_SHA:0:10}}}"
export MONITOR_COMMIT="${MONITOR_COMMIT:-${CI_COMMIT_SHA:0:10}}"
export MONITOR_BUILT_AT="${MONITOR_BUILT_AT:-$(date -u +%Y-%m-%dT%H:%M:%SZ)}"
(cd "$root/backend" && dotnet publish src/Monitor.Backend \
-m:3 -c Release --no-self-contained \
-p:DebugType=none -p:DebugSymbols=false \
-p:UseAppHost=false -p:OpenApiGenerateDocuments=false \
--artifacts-path "$build_root" -o "$output")
find "$output" -type f -name '*.pdb' -delete
cp -a "$output/." "$container_context/app/"
: > "$container_context/data/.keep"
# Woodpecker's local backend isolates HOME per workflow. Keep Buildah's image
# store outside that temporary directory so the runtime base image is reusable
# across releases. Separate stores avoid concurrent amd64/arm64 writers.
buildah_home="${BUILDAH_HOME:-/home/justme/woodpecker/buildah-home/$arch}"
mkdir -p "$buildah_home"
export HOME="$buildah_home"
local_image="localhost/monitor-backend:$version-$arch"
buildah bud --tls-verify=true --arch "$arch" \
--build-arg "APP_VERSION=$version" \
-f "$root/packaging/container/Backend.Containerfile" \
-t "$local_image" "$container_context"
if [[ "$image_publish" == false ]]; then
echo "built local Backend image for $arch; not publishing it"
exit 0
fi
export REGISTRY_AUTH_FILE="$root/.release/auth/zot-linux-$arch.json"
mkdir -p "$(dirname "$REGISTRY_AUTH_FILE")"
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; }
push_tag() {
local target_tag="$1" pushed=false
for attempt in 1 2 3; do
if buildah push --tls-verify=true "$local_image" "docker://$image:$target_tag"; then
pushed=true
break
fi
if [[ "$attempt" -lt 3 ]]; then
echo "Zot push attempt $attempt failed; retrying in 5 seconds" >&2
sleep 5
fi
done
[[ "$pushed" == true ]] || { echo "could not push image to Zot after 3 attempts" >&2; return 1; }
echo "pushed Zot image $image:$target_tag"
}
if [[ -n "${IMAGE_TAGS:-}" ]]; then
IFS=',' read -r -a image_tags <<< "$IMAGE_TAGS"
((${#image_tags[@]} > 0)) || { echo "IMAGE_TAGS must contain at least one tag" >&2; exit 2; }
for image_tag in "${image_tags[@]}"; do
[[ "$image_tag" =~ ^[A-Za-z0-9_][A-Za-z0-9_.-]{0,127}$ ]] || {
echo "invalid image tag: $image_tag" >&2
exit 2
}
push_tag "$image_tag"
done
else
push_tag "$version-$arch"
if [[ -z "$tag" ]]; then
push_tag "$version"
fi
fi