feat: upadte
This commit is contained in:
Executable
+197
@@ -0,0 +1,197 @@
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
# Obtain a verified artifact for an exact git commit.
|
||||
# Build may have happened locally or in CI; this script only reports identity
|
||||
# after the artifact exists. Does not print tokens.
|
||||
#
|
||||
# Usage:
|
||||
# obtain.sh [--sha SHA] [--branch NAME] [--root DIR] [--timeout SEC]
|
||||
#
|
||||
# BUILD_VENUE (makefile.builder, default local):
|
||||
# local HEAD must be SHA; run `make -f makefile.builder docker` or `deb`
|
||||
# ci wait for the forge pipeline of this SHA, then inspect the image
|
||||
#
|
||||
# Exit:
|
||||
# 0 artifact verified; prints ARTIFACT= / DIGEST= / SHA= / VENUE=
|
||||
# 1 no pipeline, job failed, inspect failed
|
||||
# 2 usage / config
|
||||
# 3 forge CLI cannot read the project (ci venue)
|
||||
|
||||
usage() {
|
||||
sed -n '2,20p' "$0"
|
||||
}
|
||||
|
||||
sha=
|
||||
branch=
|
||||
root=
|
||||
timeout_sec=1200
|
||||
|
||||
while (($#)); do
|
||||
case "$1" in
|
||||
--sha) sha=$2; shift 2 ;;
|
||||
--branch) branch=$2; shift 2 ;;
|
||||
--root) root=$2; shift 2 ;;
|
||||
--timeout) timeout_sec=$2; shift 2 ;;
|
||||
-h|--help) usage; exit 0 ;;
|
||||
*) echo "Error: unknown argument: $1" >&2; usage >&2; exit 2 ;;
|
||||
esac
|
||||
done
|
||||
|
||||
if [[ -z "$root" ]]; then
|
||||
root=$(git rev-parse --show-toplevel 2>/dev/null || true)
|
||||
fi
|
||||
if [[ -z "$root" ]]; then
|
||||
echo "Error: --root must be a git project" >&2
|
||||
exit 2
|
||||
fi
|
||||
cd "$root"
|
||||
|
||||
if [[ -z "$sha" ]]; then
|
||||
sha=$(git rev-parse HEAD)
|
||||
else
|
||||
sha=$(git rev-parse "$sha")
|
||||
fi
|
||||
|
||||
# Load .env.builder without printing values; shell values win. Do not read `.env`.
|
||||
if [[ -f "$root/.env.builder" ]]; then
|
||||
while IFS='=' read -r key value; do
|
||||
key=${key%%[[:space:]]*}
|
||||
[[ -z "$key" || "$key" == \#* ]] && continue
|
||||
if [[ -n "${!key:-}" ]]; then
|
||||
continue
|
||||
fi
|
||||
value=${value%\"}; value=${value#\"}; value=${value%\'}; value=${value#\'}
|
||||
[[ -z "$value" ]] && continue
|
||||
printf -v "$key" '%s' "$value"
|
||||
export "$key"
|
||||
done < <(grep -v '^[[:space:]]*$' "$root/.env.builder")
|
||||
fi
|
||||
|
||||
script_dir=$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)
|
||||
version_sh=$script_dir/version.sh
|
||||
wait_ci=$script_dir/wait_ci.sh
|
||||
|
||||
venue=${BUILD_VENUE:-}
|
||||
registry=${DOCKER_REGISTRY:-}
|
||||
repository=${DOCKER_REPOSITORY:-}
|
||||
if [[ -f "$root/makefile.builder" ]]; then
|
||||
if [[ -z "$venue" ]]; then
|
||||
venue=$(make -s -C "$root" -f makefile.builder venue 2>/dev/null || true)
|
||||
fi
|
||||
if [[ -z "$registry" ]]; then
|
||||
registry=$(make -s -C "$root" -f makefile.builder print-DOCKER_REGISTRY 2>/dev/null || true)
|
||||
fi
|
||||
if [[ -z "$repository" ]]; then
|
||||
repository=$(make -s -C "$root" -f makefile.builder print-DOCKER_REPOSITORY 2>/dev/null || true)
|
||||
fi
|
||||
fi
|
||||
venue=${venue:-local}
|
||||
|
||||
docker_tag_for_sha() {
|
||||
local tmp tag
|
||||
tmp=$(mktemp -d "${TMPDIR:-/tmp}/builder-obtain.XXXXXX")
|
||||
git -C "$root" worktree add --detach "$tmp" "$sha" >/dev/null
|
||||
if [[ -n "$branch" ]]; then
|
||||
tag=$(CI_COMMIT_BRANCH="$branch" "$version_sh" -C "$tmp" --docker)
|
||||
else
|
||||
tag=$("$version_sh" -C "$tmp" --docker)
|
||||
fi
|
||||
git -C "$root" worktree remove --force "$tmp" >/dev/null
|
||||
printf '%s' "$tag"
|
||||
}
|
||||
|
||||
inspect_image() {
|
||||
local image=$1 out digest
|
||||
if ! command -v docker >/dev/null 2>&1; then
|
||||
echo "Error: docker is required to inspect $image" >&2
|
||||
exit 1
|
||||
fi
|
||||
out=$(docker buildx imagetools inspect "$image" 2>/dev/null \
|
||||
|| docker manifest inspect "$image" 2>/dev/null \
|
||||
|| true)
|
||||
if [[ -z "$out" ]]; then
|
||||
echo "Error: cannot inspect $image" >&2
|
||||
exit 1
|
||||
fi
|
||||
digest=$(printf '%s\n' "$out" | awk '/^Digest:/ {print $2; exit}')
|
||||
if [[ -z "$digest" ]]; then
|
||||
digest=$(python3 -c 'import json,sys
|
||||
try:
|
||||
d=json.load(sys.stdin)
|
||||
except Exception:
|
||||
sys.exit(0)
|
||||
print(d.get("digest") or "")' <<<"$out")
|
||||
fi
|
||||
if [[ -z "$digest" ]]; then
|
||||
echo "Error: inspect of $image had no digest" >&2
|
||||
exit 1
|
||||
fi
|
||||
printf '%s' "$digest"
|
||||
}
|
||||
|
||||
case "$venue" in
|
||||
ci)
|
||||
"$wait_ci" --sha "$sha" --root "$root" --timeout "$timeout_sec"
|
||||
if [[ ! -x "$version_sh" ]]; then
|
||||
echo "Error: version.sh not found: $version_sh" >&2
|
||||
exit 2
|
||||
fi
|
||||
if [[ -z "$registry" || -z "$repository" ]]; then
|
||||
echo "Error: DOCKER_REGISTRY and DOCKER_REPOSITORY are required to inspect the CI image" >&2
|
||||
exit 2
|
||||
fi
|
||||
tag=$(docker_tag_for_sha)
|
||||
image="${registry}/${repository}:${tag}"
|
||||
digest=$(inspect_image "$image")
|
||||
echo "ARTIFACT=$image"
|
||||
echo "DIGEST=$digest"
|
||||
echo "SHA=$sha"
|
||||
echo "VENUE=ci"
|
||||
echo "TAG=$tag"
|
||||
;;
|
||||
local)
|
||||
head=$(git rev-parse HEAD)
|
||||
if [[ "$head" != "$sha" ]]; then
|
||||
echo "Error: local obtain requires HEAD=$sha (HEAD is $head)" >&2
|
||||
exit 2
|
||||
fi
|
||||
if [[ ! -f "$root/makefile.builder" ]]; then
|
||||
echo "Error: no makefile.builder" >&2
|
||||
exit 2
|
||||
fi
|
||||
if make -s -C "$root" -f makefile.builder -n docker >/dev/null 2>&1; then
|
||||
make -C "$root" -f makefile.builder docker
|
||||
if [[ -n "${IMAGE_TAG:-}" ]]; then
|
||||
tag=$IMAGE_TAG
|
||||
elif [[ -x "$version_sh" ]]; then
|
||||
tag=$("$version_sh" --docker)
|
||||
else
|
||||
echo "Error: cannot derive IMAGE_TAG" >&2
|
||||
exit 2
|
||||
fi
|
||||
name=$(make -s -C "$root" -f makefile.builder print-PROJECT_NAME 2>/dev/null || basename "$root")
|
||||
image="${name}:${tag}"
|
||||
if [[ -n "$registry" && -n "$repository" ]]; then
|
||||
image="${registry}/${repository}:${tag}"
|
||||
fi
|
||||
echo "ARTIFACT=$image"
|
||||
echo "DIGEST=local"
|
||||
echo "SHA=$sha"
|
||||
echo "VENUE=local"
|
||||
echo "TAG=$tag"
|
||||
elif make -s -C "$root" -f makefile.builder -n deb >/dev/null 2>&1; then
|
||||
make -C "$root" -f makefile.builder deb
|
||||
echo "ARTIFACT=deb"
|
||||
echo "SHA=$sha"
|
||||
echo "VENUE=local"
|
||||
else
|
||||
echo "Error: local venue has no docker or deb target" >&2
|
||||
exit 2
|
||||
fi
|
||||
;;
|
||||
*)
|
||||
echo "Error: BUILD_VENUE must be local or ci (got ${venue})" >&2
|
||||
exit 2
|
||||
;;
|
||||
esac
|
||||
Reference in New Issue
Block a user