Files
greptimedb/.github/scripts/find-previous-workflow-artifact.sh
2026-06-10 08:51:37 +00:00

185 lines
4.4 KiB
Bash
Executable File

#!/usr/bin/env bash
set -euo pipefail
usage() {
cat <<'EOF'
Find the most recent previous successful workflow run that has a non-expired artifact.
Usage:
find-previous-workflow-artifact.sh --workflow-path PATH --artifact-name NAME [options]
Options:
--repo OWNER/REPO GitHub repository. Defaults to GITHUB_REPOSITORY.
--current-run-id ID Current workflow run id to exclude. Defaults to GITHUB_RUN_ID.
--workflow-path PATH Workflow path, for example .github/workflows/nightly-jsonbench.yaml.
--artifact-name NAME Artifact name to find.
--status STATUS Workflow run status filter. Defaults to success.
--per-page N GitHub API page size. Defaults to 100.
--run-id-only Print only the run id. This is the default.
--artifact-id-only Print only the artifact id.
--json Print a JSON object with run_id and artifact_id.
--debug Print GitHub API requests and responses to stderr.
-h, --help Show this help.
The script uses gh CLI and jq. Provide GH_TOKEN or authenticate gh before running it.
EOF
}
repo="${GITHUB_REPOSITORY:-}"
current_run_id="${GITHUB_RUN_ID:-}"
workflow_path=""
artifact_name=""
status="success"
per_page="100"
output_format="run_id"
debug="false"
debug_log() {
if [[ "${debug}" == "true" ]]; then
printf '[debug] %s\n' "$*" >&2
fi
}
log_stderr_file() {
if [[ "${debug}" != "true" || ! -s "${err_file}" ]]; then
return
fi
while read -r line; do
debug_log "stderr: ${line}"
done < "${err_file}"
: > "${err_file}"
}
while [[ $# -gt 0 ]]; do
case "$1" in
--repo)
repo="$2"
shift 2
;;
--current-run-id)
current_run_id="$2"
shift 2
;;
--workflow-path)
workflow_path="$2"
shift 2
;;
--artifact-name)
artifact_name="$2"
shift 2
;;
--status)
status="$2"
shift 2
;;
--per-page)
per_page="$2"
shift 2
;;
--run-id-only)
output_format="run_id"
shift
;;
--artifact-id-only)
output_format="artifact_id"
shift
;;
--json)
output_format="json"
shift
;;
--debug)
debug="true"
shift
;;
-h | --help)
usage
exit 0
;;
*)
echo "Unknown argument: $1" >&2
usage >&2
exit 2
;;
esac
done
if [[ -z "${repo}" ]]; then
echo "--repo is required when GITHUB_REPOSITORY is not set." >&2
exit 2
fi
if [[ -z "${workflow_path}" ]]; then
echo "--workflow-path is required." >&2
exit 2
fi
if [[ -z "${artifact_name}" ]]; then
echo "--artifact-name is required." >&2
exit 2
fi
err_file=$(mktemp)
trap 'rm -f "${err_file}"' EXIT
debug_log "request: gh api --method GET repos/${repo}/actions/runs -f status=${status} -f per_page=${per_page} --paginate"
candidate_run_ids=$(
gh api --method GET "repos/${repo}/actions/runs" \
-f "status=${status}" \
-f "per_page=${per_page}" \
--paginate \
--jq ".workflow_runs[] | select(.path == \"${workflow_path}\") | .id" \
2> "${err_file}" || true
)
log_stderr_file
debug_log "response run ids: ${candidate_run_ids:-<none>}"
while read -r run_id; do
if [[ -z "${run_id}" || "${run_id}" == "${current_run_id}" ]]; then
debug_log "skip run id: ${run_id:-<empty>}"
continue
fi
debug_log "request: gh api repos/${repo}/actions/runs/${run_id}/artifacts"
artifacts_response=$(
gh api "repos/${repo}/actions/runs/${run_id}/artifacts" \
2> "${err_file}" || true
)
log_stderr_file
debug_log "response for run ${run_id}: ${artifacts_response}"
artifact_id=$(
printf '%s\n' "${artifacts_response}" \
| jq -r --arg name "${artifact_name}" '.artifacts[]? | select(.name == $name and (.expired | not)) | .id' \
| head -n 1 || true
)
debug_log "artifact id for run ${run_id}: ${artifact_id:-<none>}"
if [[ -z "${artifact_id}" ]]; then
continue
fi
case "${output_format}" in
run_id)
echo "${run_id}"
;;
artifact_id)
echo "${artifact_id}"
;;
json)
printf '{"run_id":"%s","artifact_id":"%s"}\n' "${run_id}" "${artifact_id}"
;;
esac
exit 0
done <<< "${candidate_run_ids}"
debug_log "no previous workflow run with artifact '${artifact_name}' found"
case "${output_format}" in
json)
printf '{"run_id":"","artifact_id":""}\n'
;;
esac