ci/woodpecker/push/main-amd64-build Pipeline was successful
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.
124 lines
4.5 KiB
Bash
124 lines
4.5 KiB
Bash
#!/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
|