/ .github / utils / wait_for_workflows.sh
wait_for_workflows.sh
 1  #!/bin/bash
 2  # wait_for_workflows.sh - Wait for tag-triggered workflows to complete
 3  #
 4  # Usage: ./wait_for_workflows.sh <tag> <workflow_name1> [workflow_name2] ...
 5  # Requires: GH_TOKEN and GITHUB_REPOSITORY environment variables
 6  #
 7  # Example:
 8  #   ./wait_for_workflows.sh v2.19.0 "Project release on PyPi" "Docker image release"
 9  #
10  # This script is used in the release.yml workflow to wait for the workflows triggered by a specific release tag to
11  # successfully complete.
12  
13  
14  # With the default values, we wait for 20 minutes
15  MAX_ATTEMPTS="${MAX_ATTEMPTS:-40}"
16  SLEEP_SECONDS="${SLEEP_SECONDS:-30}"
17  
18  set -euo pipefail
19  
20  if [[ -z "${GH_TOKEN:-}" ]] || [[ -z "${GITHUB_REPOSITORY:-}" ]]; then
21      echo "❌ GH_TOKEN and GITHUB_REPOSITORY must be set"
22      exit 1
23  fi
24  
25  TAG="$1"
26  shift
27  WORKFLOWS=("$@")
28  
29  
30  # Get commit SHA from tag
31  TAG_SHA=$(git rev-list -n 1 "${TAG}" 2>/dev/null) || {
32      echo "❌ Tag ${TAG} not found"
33      exit 1
34  }
35  
36  echo "Tag ${TAG} (commit: ${TAG_SHA:0:7})"
37  echo ""
38  
39  wait_for_workflow() {
40      local name="$1"
41      echo "⏳ Waiting for: $name"
42  
43      for ((i=1; i<=MAX_ATTEMPTS; i++)); do
44          jq_filter="[.workflow_runs[] | select(.head_sha == \"${TAG_SHA}\" and .name == \"${name}\")]
45              | sort_by(.created_at) | last"
46  
47          result=$(gh api "repos/${GITHUB_REPOSITORY}/actions/runs" \
48              --jq "$jq_filter" 2>/dev/null || echo "")
49  
50          if [[ -z "$result" ]]; then
51              echo "   Attempt $i/$MAX_ATTEMPTS: not started yet..."
52              sleep $SLEEP_SECONDS
53              continue
54          fi
55  
56          status=$(echo "$result" | jq -r '.status')
57          conclusion=$(echo "$result" | jq -r '.conclusion')
58  
59          if [[ "$status" == "completed" ]]; then
60              if [[ "$conclusion" == "success" ]]; then
61                  echo "✅ $name completed"
62                  return 0
63              else
64                  echo "❌ $name failed: $conclusion"
65                  return 1
66              fi
67          fi
68  
69          echo "   Attempt $i/$MAX_ATTEMPTS: $status..."
70          sleep $SLEEP_SECONDS
71      done
72  
73      echo "❌ $name: timeout after $((MAX_ATTEMPTS * SLEEP_SECONDS / 60)) minutes"
74      return 1
75  }
76  
77  for workflow in "${WORKFLOWS[@]}"; do
78      wait_for_workflow "$workflow" || exit 1
79  done
80  
81  echo ""
82  echo "✅ All workflows completed"