|
| 1 | +#!/bin/bash |
| 2 | +set -eu |
| 3 | + |
| 4 | +## |
| 5 | +# Triggers a GitHub Actions workflow via workflow_dispatch, locates the |
| 6 | +# resulting run, and streams its output until completion. |
| 7 | +# |
| 8 | +# Requires these environment variables: |
| 9 | +# GITHUB_TOKEN – PAT or GitHub App token with Actions scope |
| 10 | +# GITHUB_REPO – owner/repo (e.g. cloudfoundry/kind-deployment) |
| 11 | +# WORKFLOW_FILE – workflow filename (e.g. kind-smoke.yaml) |
| 12 | +# WORKFLOW_REF – git ref to run against (default: main) |
| 13 | +# WORKFLOW_INPUTS – JSON object of workflow inputs (default: {}) |
| 14 | +## |
| 15 | + |
| 16 | +export GH_TOKEN="${GITHUB_TOKEN}" |
| 17 | + |
| 18 | +TEAM_NAME="${BUILD_TEAM_NAME:-unknown-team}" |
| 19 | +PIPELINE_NAME="${BUILD_PIPELINE_NAME:-unknown-pipeline}" |
| 20 | +JOB_NAME="${BUILD_JOB_NAME:-unknown-job}" |
| 21 | +BUILD_NAME="${BUILD_NAME:-unknown-build}" |
| 22 | +TRIGGER_SOURCE="${TEAM_NAME}/${PIPELINE_NAME}/${JOB_NAME}/${BUILD_NAME}" |
| 23 | +TRIGGER_ID=$(printf 'cfd-%s-%s-%s-%s-%s' \ |
| 24 | + "${TEAM_NAME}" "${PIPELINE_NAME}" "${JOB_NAME}" "${BUILD_NAME}" "$(date -u +%s)" \ |
| 25 | + | tr '/:@ ' '-' \ |
| 26 | + | tr -cd '[:alnum:]._-') |
| 27 | + |
| 28 | +if [ -z "${TRIGGER_ID}" ]; then |
| 29 | + TRIGGER_ID="cfd-$(date -u +%s)" |
| 30 | +fi |
| 31 | + |
| 32 | +DISPATCH_TS=$(date -u +"%Y-%m-%dT%H:%M:%SZ") |
| 33 | +ACTOR_LOGIN=$(gh api user --jq '.login') |
| 34 | + |
| 35 | +INPUTS_JSON=$(printf '%s' "${WORKFLOW_INPUTS}" \ |
| 36 | + | jq -ce 'if type == "object" then . else error("WORKFLOW_INPUTS must be a JSON object") end') |
| 37 | + |
| 38 | +# ── snapshot the latest existing run ID so we can find our new one ── |
| 39 | +BEFORE_ID=$(gh run list \ |
| 40 | + --repo "${GITHUB_REPO}" \ |
| 41 | + --workflow "${WORKFLOW_FILE}" \ |
| 42 | + --event workflow_dispatch \ |
| 43 | + --limit 1 \ |
| 44 | + --json databaseId \ |
| 45 | + --jq '.[0].databaseId // 0' 2>/dev/null || echo "0") |
| 46 | + |
| 47 | +# ── dispatch the workflow ─────────────────────────────────────────── |
| 48 | +echo "Dispatching ${WORKFLOW_FILE} on ${GITHUB_REPO}@${WORKFLOW_REF}..." |
| 49 | +echo "Trigger ID: ${TRIGGER_ID}" |
| 50 | +echo "Trigger source: ${TRIGGER_SOURCE}" |
| 51 | +echo "Workflow actor: ${ACTOR_LOGIN}" |
| 52 | +echo "${INPUTS_JSON}" \ |
| 53 | + | jq --arg ref "${WORKFLOW_REF}" '{ref: $ref, inputs: .}' \ |
| 54 | + | gh api --method POST \ |
| 55 | + "/repos/${GITHUB_REPO}/actions/workflows/${WORKFLOW_FILE}/dispatches" \ |
| 56 | + --input - |
| 57 | + |
| 58 | +# ── locate the newly created run ──────────────────────────────────── |
| 59 | +echo "Locating workflow run (previous latest ID: ${BEFORE_ID})..." |
| 60 | +RUN_ID="" |
| 61 | +attempt=0 |
| 62 | +while [ "${attempt}" -lt 60 ]; do |
| 63 | + RUN_ID=$(gh api \ |
| 64 | + "/repos/${GITHUB_REPO}/actions/workflows/${WORKFLOW_FILE}/runs?event=workflow_dispatch&branch=${WORKFLOW_REF}&per_page=20" \ |
| 65 | + 2>/dev/null \ |
| 66 | + | jq -r \ |
| 67 | + --argjson before_id "${BEFORE_ID}" \ |
| 68 | + --arg dispatch_ts "${DISPATCH_TS}" \ |
| 69 | + --arg actor_login "${ACTOR_LOGIN}" \ |
| 70 | + '.workflow_runs |
| 71 | + | map( |
| 72 | + select( |
| 73 | + (.id > $before_id) |
| 74 | + and (.created_at >= $dispatch_ts) |
| 75 | + and (.actor.login == $actor_login) |
| 76 | + ) |
| 77 | + ) |
| 78 | + | .[0].id // empty' || true) |
| 79 | + |
| 80 | + if [ -n "${RUN_ID}" ]; then |
| 81 | + break |
| 82 | + fi |
| 83 | + attempt=$((attempt + 1)) |
| 84 | + sleep 10 |
| 85 | +done |
| 86 | + |
| 87 | +if [ -z "${RUN_ID}" ]; then |
| 88 | + echo "ERROR: Dispatched run not found after 10 minutes." |
| 89 | + echo "Expected trigger_id=${TRIGGER_ID}" |
| 90 | + echo "Expected actor=${ACTOR_LOGIN}" |
| 91 | + echo "Workflow=${WORKFLOW_FILE} ref=${WORKFLOW_REF}" |
| 92 | + exit 1 |
| 93 | +fi |
| 94 | + |
| 95 | +# ── watch the run until completion ────────────────────────────────── |
| 96 | +echo "Watching: https://github.com/${GITHUB_REPO}/actions/runs/${RUN_ID}" |
| 97 | +gh run watch "${RUN_ID}" --repo "${GITHUB_REPO}" --exit-status |
0 commit comments