mirror of
https://github.com/OrcaSlicer/OrcaSlicer.git
synced 2026-10-12 18:31:18 +00:00
* Wait for the PR's Deps Cache in clang-tidy When deps/ Changes * Fail the clang-tidy Deps Wait When Listing Caches Keeps Failing * Wait for Deps Through ci_deps_cache.sh in clang-tidy Reuse the macOS deps wait for Linux: the job names, workflow and cache ref are passed in, and a new 'own' mode waits for the PR's own build when it changes deps/. A PR that keeps deps/ now waits for a running base build with the same deps, and warns when it falls back to older ones. The wait ends as soon as the deps job fails.
155 lines
5.9 KiB
Bash
155 lines
5.9 KiB
Bash
#!/usr/bin/env bash
|
|
# Lets a pull request's macOS deps build, or its clang-tidy job, wait for a
|
|
# build that saves the deps cache it needs, from a Linux job. `check` runs after
|
|
# a cache miss and names a queued or running push build of the base branch with
|
|
# the same deps/ and .github/ to wait for, unless the pull request changes either.
|
|
# `own` names the pull request's own build instead, for clang-tidy when the pull
|
|
# request changes deps/. `wait` waits until that build saves KEY under CACHE_REF,
|
|
# or its deps job fails. actions/cache then confirms the entry can be restored.
|
|
#
|
|
# Environment: GH_TOKEN, REPO, WORKFLOW_REF (or WORKFLOW, the build workflow's
|
|
# file name) and BASE_REF, plus HEAD_SHA for `own`, and KEY_INPUTS, WAIT_FOR,
|
|
# WAIT_SINCE, WAIT_MINUTES, KEY, CACHE_REF (default the base branch) and ARCH
|
|
# (or JOB, the matrix job's name) for `wait`.
|
|
# Writes key-inputs, wait-for and wait-since to $GITHUB_OUTPUT.
|
|
set -uo pipefail
|
|
|
|
workflow=${WORKFLOW_REF:-}
|
|
workflow=${workflow%%@*}
|
|
workflow=${WORKFLOW:-${workflow##*/}}
|
|
|
|
# Must match the job names in build_all.yml, build_check_cache.yml and build_deps.yml.
|
|
job=${JOB:-build_macos_arch (${ARCH:-})}
|
|
check_job_name="$job / Check Cache"
|
|
deps_job_name="$job / Build Deps / Build Deps"
|
|
|
|
out() { echo "$1" >> "${GITHUB_OUTPUT:-/dev/stdout}"; }
|
|
|
|
# The cache key depends on deps/ and on the workflows under .github/.
|
|
local_key_inputs() { echo "$(git rev-parse "$1:.github") $(git rev-parse "$1:deps")"; }
|
|
remote_key_inputs() {
|
|
gh api "repos/$REPO/git/trees/$1" < /dev/null \
|
|
--jq '[.tree[] | select(.path == ".github" or .path == "deps") | {key: .path, value: .sha}] | from_entries | "\(.[".github"]) \(.deps)"'
|
|
}
|
|
|
|
# Prints the id of a push build of the base branch that has not finished, is not
|
|
# one of the ids in $1, and has KEY_INPUTS.
|
|
matching_base_build() {
|
|
local status runs id sha
|
|
runs=$(for status in in_progress queued pending waiting requested; do
|
|
gh api -X GET "repos/$REPO/actions/workflows/$workflow/runs" \
|
|
-f branch="$BASE_REF" -f event=push -f status="$status" -f per_page=10 < /dev/null \
|
|
| jq -r '.workflow_runs[] | "\(.id) \(.head_sha)"'
|
|
done)
|
|
while read -r id sha; do
|
|
[ -n "$id" ] || continue
|
|
[[ " ${1:-} " == *" $id "* ]] && continue
|
|
if [ "$(remote_key_inputs "$sha")" = "$KEY_INPUTS" ]; then
|
|
echo "$id"
|
|
return
|
|
fi
|
|
done <<< "$runs"
|
|
}
|
|
|
|
check() {
|
|
KEY_INPUTS=$(local_key_inputs HEAD)
|
|
out "key-inputs=$KEY_INPUTS"
|
|
if [ "$KEY_INPUTS" != "$(local_key_inputs HEAD^1)" ]; then
|
|
echo "This pull request changes deps/ or .github/, so it builds its own deps."
|
|
return
|
|
fi
|
|
local id
|
|
id=$(matching_base_build)
|
|
if [ -n "$id" ]; then
|
|
echo "Build $id of $BASE_REF has the same deps/ and .github/. Waiting for its cache."
|
|
out "wait-for=$id"
|
|
out "wait-since=$(date +%s)"
|
|
else
|
|
echo "No build of $BASE_REF is building these deps."
|
|
fi
|
|
}
|
|
|
|
own() {
|
|
out "key-inputs=$(local_key_inputs HEAD)"
|
|
local id
|
|
# The build can be created a moment after this job.
|
|
for _ in 1 2 3 4 5; do
|
|
id=$(gh api -X GET "repos/$REPO/actions/workflows/$workflow/runs" \
|
|
-f head_sha="$HEAD_SHA" -f event=pull_request -f per_page=1 --jq '.workflow_runs[0].id // empty' < /dev/null)
|
|
[ -n "$id" ] && break
|
|
sleep 30
|
|
done
|
|
if [ -n "$id" ]; then
|
|
echo "Waiting for the deps cache of build $id of this pull request."
|
|
out "wait-for=$id"
|
|
out "wait-since=$(date +%s)"
|
|
else
|
|
echo "No build of this pull request is building its deps."
|
|
fi
|
|
}
|
|
|
|
key_saved() {
|
|
gh cache list -R "$REPO" --ref "${CACHE_REF:-refs/heads/$BASE_REF}" --key "$KEY" --json key < /dev/null \
|
|
| jq -e --arg key "$KEY" 'any(.[]; .key == $key)' > /dev/null
|
|
}
|
|
|
|
wait_for() {
|
|
# Counts the limit from the check, including time queued behind other waiting
|
|
# pull requests.
|
|
local id=$WAIT_FOR seen=$WAIT_FOR deadline=$((${WAIT_SINCE:-$(date +%s)} + WAIT_MINUTES * 60)) jobs job check warned=
|
|
while [ "$(date +%s)" -lt "$deadline" ]; do
|
|
if key_saved; then
|
|
echo "Found $KEY."
|
|
return
|
|
fi
|
|
jobs=$(gh api -X GET "repos/$REPO/actions/runs/$id/jobs" -f filter=latest -f per_page=100 < /dev/null)
|
|
job=$(jq -r --arg name "$deps_job_name" 'first(.jobs[] | select(.name == $name) | "\(.status) \(.conclusion)") // ""' <<< "$jobs")
|
|
case "$job" in
|
|
"completed success" | "completed skipped")
|
|
# The new entry can take a moment to be listed, and a skipped job means
|
|
# the build found the cache, possibly under the default branch.
|
|
for _ in 1 2 3; do
|
|
key_saved && { echo "Found $KEY."; return; }
|
|
sleep 20
|
|
done
|
|
echo "Build $id finished its deps without saving $KEY."
|
|
return ;;
|
|
"completed cancelled") ;;
|
|
completed*)
|
|
echo "The deps job of build $id did not succeed."
|
|
return ;;
|
|
# The deps job exists only once the build's cache check has succeeded.
|
|
"")
|
|
case "$(gh api "repos/$REPO/actions/runs/$id" --jq '"\(.status) \(.conclusion)"' < /dev/null)" in
|
|
"completed cancelled") ;;
|
|
completed*)
|
|
check=$(jq -r --arg name "$check_job_name" 'first(.jobs[] | select(.name == $name) | .conclusion) // ""' <<< "$jobs")
|
|
if [ -z "$warned" ] && { [ -z "$check" ] || [ "$check" = success ]; }; then
|
|
echo "::warning title=Deps wait::Build $id has no job named \"$deps_job_name\". If the build jobs were renamed, update scripts/ci_deps_cache.sh. This does not affect this pull request."
|
|
warned=1
|
|
fi ;;
|
|
*)
|
|
sleep 120
|
|
continue ;;
|
|
esac ;;
|
|
*)
|
|
sleep 120
|
|
continue ;;
|
|
esac
|
|
# Follows another unfinished build with the same key inputs, such as the
|
|
# push that replaced a cancelled one.
|
|
id=$(matching_base_build "$seen")
|
|
[ -n "$id" ] || break
|
|
seen="$seen $id"
|
|
echo "Following build $id of $BASE_REF."
|
|
done
|
|
echo "No build saved $KEY."
|
|
}
|
|
|
|
case "${1:-}" in
|
|
check) check ;;
|
|
own) own ;;
|
|
wait) wait_for ;;
|
|
*) echo "usage: $0 check|own|wait" >&2; exit 2 ;;
|
|
esac
|