mirror of
https://github.com/ggml-org/llama.cpp.git
synced 2026-09-07 21:41:08 +02:00
2092353c8b
This commit contains a suggestion for handling container images which are currently not semver tagged, they only have build numbers in there tags. The proposed solution here is to first add a check to make sure that there are container images built for the build number of the release and if not fail the build. The container images are build nightly but they can be triggered manually as well. If the the container images check passes then the make-release workflow will re-tag the images with the semver.
171 lines
7.0 KiB
Bash
Executable File
171 lines
7.0 KiB
Bash
Executable File
#!/bin/bash
|
|
# Run all pre-release checks and determine the release version.
|
|
#
|
|
# Usage: make-release-checks.sh [--dry-run]
|
|
# --dry-run: warn on failures instead of aborting
|
|
#
|
|
# Env (when running in GitHub Actions):
|
|
# GH_TOKEN, GITHUB_REPOSITORY, GITHUB_OUTPUT
|
|
# RELEASE_BRANCH: when set, HEAD must belong to origin/RELEASE_BRANCH and must
|
|
# not be older than 3 days from the branch HEAD (skipped when unset)
|
|
set -euo pipefail
|
|
|
|
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
REPO_ROOT="$(cd "$SCRIPT_DIR/.." && pwd)"
|
|
|
|
DRY_RUN=false
|
|
CHECKS_PASSED=true
|
|
for arg in "$@"; do
|
|
case "$arg" in
|
|
--dry-run) DRY_RUN=true ;;
|
|
*) echo "Unknown argument: $arg"; exit 1 ;;
|
|
esac
|
|
done
|
|
|
|
MAJOR=$(grep "set(LLAMA_VERSION_MAJOR" "$REPO_ROOT/CMakeLists.txt" | grep -oP '\d+')
|
|
MINOR=$(grep "set(LLAMA_VERSION_MINOR" "$REPO_ROOT/CMakeLists.txt" | grep -oP '\d+')
|
|
PATCH=$(grep "set(LLAMA_VERSION_PATCH" "$REPO_ROOT/CMakeLists.txt" | grep -oP '\d+')
|
|
VERSION="v${MAJOR}.${MINOR}.${PATCH}"
|
|
echo "Determined version: ${VERSION}"
|
|
if [[ -n "${GITHUB_OUTPUT:-}" ]]; then
|
|
echo "version=${VERSION}" >> "$GITHUB_OUTPUT"
|
|
fi
|
|
|
|
SHA=$(git rev-parse HEAD)
|
|
|
|
echo "Checking that commit ${SHA} belongs to the release branch..."
|
|
if [[ -z "${RELEASE_BRANCH:-}" ]]; then
|
|
echo "Warning: RELEASE_BRANCH not set - skipping commit check (local run)"
|
|
else
|
|
TIP="origin/${RELEASE_BRANCH}"
|
|
COMMIT_ERR=""
|
|
if ! git rev-parse --verify "${TIP}" >/dev/null 2>&1; then
|
|
COMMIT_ERR="branch ${RELEASE_BRANCH} not found on remote"
|
|
elif ! git merge-base --is-ancestor "${SHA}" "${TIP}"; then
|
|
COMMIT_ERR="commit ${SHA} is not part of branch ${RELEASE_BRANCH}"
|
|
else
|
|
COMMIT_TS=$(git show -s --format=%ct "${SHA}")
|
|
TIP_TS=$(git show -s --format=%ct "${TIP}")
|
|
AGE_DAYS=$(( (TIP_TS - COMMIT_TS) / 86400 ))
|
|
if (( TIP_TS - COMMIT_TS > 3 * 86400 )); then
|
|
COMMIT_ERR="commit ${SHA} is ${AGE_DAYS} day(s) older than the HEAD of ${RELEASE_BRANCH} (max: 3)"
|
|
fi
|
|
fi
|
|
if [[ -n "${COMMIT_ERR}" ]]; then
|
|
if [[ "$DRY_RUN" == "true" ]]; then
|
|
echo "Warning: ${COMMIT_ERR} (dry run, continuing)."
|
|
CHECKS_PASSED=false
|
|
else
|
|
echo "Error: ${COMMIT_ERR}"
|
|
exit 1
|
|
fi
|
|
else
|
|
echo "Commit ${SHA} is on branch ${RELEASE_BRANCH} and within 3 days of its HEAD - OK"
|
|
fi
|
|
fi
|
|
|
|
echo "Checking that tag ${VERSION} does not already exist..."
|
|
if git ls-remote --tags origin "${VERSION}" | grep -q "${VERSION}"; then
|
|
echo "Error: tag ${VERSION} already exists on remote"
|
|
exit 1
|
|
fi
|
|
echo "Tag ${VERSION} does not exist on remote - OK"
|
|
|
|
echo "Checking release.yml status for commit ${SHA}..."
|
|
if [[ -z "${GITHUB_REPOSITORY:-}" ]]; then
|
|
echo "Warning: GITHUB_REPOSITORY not set - skipping CI check (local run)"
|
|
else
|
|
RUNS=$(gh api "repos/${GITHUB_REPOSITORY}/actions/workflows/release.yml/runs?per_page=100" \
|
|
--jq "[.workflow_runs[] | select(.head_sha == \"${SHA}\" and .conclusion == \"success\")] | length")
|
|
if [[ "$RUNS" -eq 0 ]]; then
|
|
if [[ "$DRY_RUN" == "true" ]]; then
|
|
echo "Warning: no successful release.yml run found for HEAD (${SHA}) (dry run, continuing)."
|
|
CHECKS_PASSED=false
|
|
else
|
|
echo "Error: no successful release.yml run found for HEAD (${SHA})"
|
|
echo "The nightly build must complete successfully before making a release."
|
|
exit 1
|
|
fi
|
|
else
|
|
echo "Found successful release.yml run for HEAD."
|
|
fi
|
|
fi
|
|
|
|
MAJOR=$(grep "set(GGML_VERSION_MAJOR" "$REPO_ROOT/ggml/CMakeLists.txt" | grep -oP '\d+')
|
|
MINOR=$(grep "set(GGML_VERSION_MINOR" "$REPO_ROOT/ggml/CMakeLists.txt" | grep -oP '\d+')
|
|
PATCH=$(grep "set(GGML_VERSION_PATCH" "$REPO_ROOT/ggml/CMakeLists.txt" | grep -oP '\d+')
|
|
GGML_VERSION="v${MAJOR}.${MINOR}.${PATCH}"
|
|
echo "Local ggml version: ${GGML_VERSION}"
|
|
|
|
if ! git clone --depth 1 --branch "${GGML_VERSION}" https://github.com/ggml-org/ggml.git upstream-ggml 2>/dev/null; then
|
|
echo "Warning: tag ${GGML_VERSION} not found in upstream ggml - skipping comparison"
|
|
else
|
|
echo "Comparing local ggml/ src and include with upstream ${GGML_VERSION}..."
|
|
DIFF=$(diff -rq "$REPO_ROOT/ggml/src" upstream-ggml/src 2>&1 || true)
|
|
DIFF+=$(diff -rq "$REPO_ROOT/ggml/include" upstream-ggml/include 2>&1 || true)
|
|
DIFF+=$(diff "$REPO_ROOT/ggml/CMakeLists.txt" upstream-ggml/CMakeLists.txt 2>&1 || true)
|
|
rm -rf upstream-ggml
|
|
if [[ -n "$DIFF" ]]; then
|
|
echo "local ggml/ differs from upstream ${GGML_VERSION}:"
|
|
echo "$DIFF"
|
|
if [[ "$DRY_RUN" == "true" ]]; then
|
|
echo "Warning: would abort release due to ggml mismatch (dry run, continuing)."
|
|
CHECKS_PASSED=false
|
|
else
|
|
echo "Error: ggml must match upstream before making a release."
|
|
exit 1
|
|
fi
|
|
else
|
|
echo "local ggml/ matches upstream ${GGML_VERSION}"
|
|
fi
|
|
fi
|
|
|
|
echo "Checking container images for commit ${SHA}..."
|
|
NIGHTLY_TAG="$(git tag --points-at "${SHA}" | grep -E '(^|-)b[0-9]+(-[0-9a-f]{7})?$' | head -n 1 || true)"
|
|
if [[ -z "${NIGHTLY_TAG}" ]]; then
|
|
echo "Warning: no nightly tag points at ${SHA} - skipping container image check"
|
|
elif [[ -z "${GITHUB_REPOSITORY:-}" ]]; then
|
|
echo "Warning: GITHUB_REPOSITORY not set - skipping container image check (local run)"
|
|
else
|
|
CONTAINER_REPO="${GITHUB_REPOSITORY,,}" # lower-case owner/repo for ghcr.io
|
|
GHCR_TOKEN="$(curl -fsSL \
|
|
"https://ghcr.io/token?scope=repository:${CONTAINER_REPO}:pull&service=ghcr.io" \
|
|
| grep -oP '"token"\s*:\s*"\K[^"]+')"
|
|
|
|
VARIANTS=("" "-cuda" "-cuda13" "-vulkan" "-rocm" "-intel" "-musa" "-openvino")
|
|
TYPES=("full" "light" "server")
|
|
CONTAINER_ERR=""
|
|
for type in "${TYPES[@]}"; do
|
|
for variant in "${VARIANTS[@]}"; do
|
|
tag="${type}${variant}-${NIGHTLY_TAG}"
|
|
STATUS="$(curl -s -o /dev/null -w "%{http_code}" \
|
|
-H "Authorization: Bearer ${GHCR_TOKEN}" \
|
|
-H "Accept: application/vnd.oci.image.index.v1+json,application/vnd.docker.distribution.manifest.list.v2+json" \
|
|
"https://ghcr.io/v2/${CONTAINER_REPO}/manifests/${tag}")"
|
|
if [[ "${STATUS}" == "200" ]]; then
|
|
echo " ${tag} - OK"
|
|
else
|
|
echo " ${tag} - MISSING"
|
|
CONTAINER_ERR+=" ${tag}"
|
|
fi
|
|
done
|
|
done
|
|
|
|
if [[ -n "${CONTAINER_ERR}" ]]; then
|
|
if [[ "$DRY_RUN" == "true" ]]; then
|
|
echo "Warning: missing container images for ${NIGHTLY_TAG}:${CONTAINER_ERR} (dry run, continuing)."
|
|
CHECKS_PASSED=false
|
|
else
|
|
echo "Error: missing container images for ${NIGHTLY_TAG}:${CONTAINER_ERR}"
|
|
echo "The Docker workflow must complete successfully before making a release."
|
|
exit 1
|
|
fi
|
|
else
|
|
echo "All container images found for ${NIGHTLY_TAG} - OK"
|
|
fi
|
|
fi
|
|
|
|
if [[ -n "${GITHUB_OUTPUT:-}" ]]; then
|
|
echo "checks_passed=${CHECKS_PASSED}" >> "$GITHUB_OUTPUT"
|
|
fi
|