Diffinery

codician/diffinerypublic

Open-source, agent-first GitHub and GitHub Actions alternative that runs on your own Cloudflare account: git hosting, pull requests, code review and drop-in GitHub Actions YAML on Workers, Durable Objects, R2 and Containers.

51 lines · 2.3 KB · executableRaw History
1#!/usr/bin/env bash
2# Waits for every Diffinery Actions run on a commit (including runs that other runs
3# start, like workflow_run followers) and prints each run and job. Prints the logs of
4# failed jobs and exits non-zero if any run did not succeed.
5#
6# Usage: DIFFINERY=https://diffinery.com TOKEN=... diffinery-wait-runs.sh owner/repo sha [minutes]
7set -euo pipefail
8repo=$1 sha=$2 minutes=${3:-60}
9api() { curl -fsS --retry 3 "$DIFFINERY/api/v3/repos/$repo$1" -H "Authorization: Bearer $TOKEN"; }
10
11deadline=$(( $(date +%s) + minutes * 60 ))
12settled=0
13while :; do
14 runs=$(api "/actions/runs?head_sha=$sha&per_page=100")
15 total=$(jq '.workflow_runs | length' <<<"$runs")
16 pending=$(jq '[.workflow_runs[] | select(.status != "completed")] | length' <<<"$runs")
17 if [ "$total" -gt 0 ] && [ "$pending" = 0 ]; then
18 # Finished runs can start followers (workflow_run), so make sure nothing new appears.
19 settled=$((settled + 1))
20 [ "$settled" -ge 3 ] && break
21 else
22 settled=0
23 fi
24 if [ "$(date +%s)" -ge "$deadline" ]; then
25 echo "::error::Diffinery runs for $sha were not finished after $minutes minutes"
26 jq -r '.workflow_runs[] | " \(.name) [\(.event)]: \(.status)"' <<<"$runs"
27 exit 1
28 fi
29 sleep 15
30done
31
32failed=0
33for id in $(jq -r '.workflow_runs[].id' <<<"$runs"); do
34 run=$(api "/actions/runs/$id")
35 jq -r '"\(.name) [\(.event)]: \(.conclusion)\(try " in \((.updated_at | fromdateiso8601) - (.created_at | fromdateiso8601))s" catch "") \(.html_url)"' <<<"$run"
36 jobs=$(api "/actions/runs/$id/jobs")
37 # Each job's time, and its steps that took over 20 seconds, to see where a sync spends it.
38 jq -r 'def secs: try ((.completed_at | fromdateiso8601) - (.started_at | fromdateiso8601)) catch null;
39 .jobs[] | " \(.name): \(.conclusion)\(if .failure then " - " + (.failure.message // "") else "" end)\(if secs then " (\(secs)s)" else "" end)",
40 (.steps[]? | select((secs // 0) > 20) | " \(secs)s \(.name)")' <<<"$jobs"
41 if [ "$(jq -r .conclusion <<<"$run")" != success ]; then
42 failed=1
43 for job in $(jq -r '.jobs[] | select(.conclusion == "failure" or .conclusion == "timed_out") | .id' <<<"$jobs"); do
44 echo "::group::Last log lines of job $job"
45 api "/actions/jobs/$job/logs" | tail -n 120
46 echo "::endgroup::"
47 done
48 fi
49done
50[ "$failed" = 0 ] && echo "every Diffinery run on $sha succeeded"
51exit "$failed"