Observing workflow run status on Github
It is sometimes useful to get notified about the completion of a job executed on your CI service. When talking about manually triggered, long-running workflows, it could be easy to forget about them – when instead of waiting and watching the output log, you just start working on a different task.
GitHub doesn’t share an API that makes it possible to do this easily and efficiently. We are going to use an old-school technique called “short polling.” This fancy name means nothing more than just executing requests in an indefinite loop with a delay in between.
Repository workflow runs list request will be the core of our observer. Take a closer look at the documentation; using query parameters you can filter the results at this early stage. For example: list only workflows triggered by yourself with the actor parameter, specify event which triggered the run or specific branch.
We will just focus on the last run, whatever triggered it, and whoever did it.
|
1 2 3 4 5 6 7 8 9 10 11 12 13 |
GITHUB_TOKEN="$(gopass show github-token)" # stored in a password manager REPO="eclipsesource/tabris-js-hello-world" TEMP_FILE="temp.json" curl \ --silent \ --location \ --request GET \ --header 'Accept: application/vnd.github.everest-preview+json' \ --header 'Content-Type: application/json' \ --header "Authorization: token $GITHUB_TOKEN" \ --header 'cache-control: no-cache' \ "https://api.github.com/repos/${REPO}/actions/runs" > $TEMP_FILE |
JQ is a JSON parser with CLI, we will use it to extract the status of the last run. jqplay is a playground where you can test your queries. Ours will consist of:
– .workflow_runs – peek into the array with the list of runs
– sort_by( .created_at ) – order items by creation date
– .[-1] – select the last one from the list
– .status – extract status
Value of the status property can be one of: “queued”, “in_progress”, or “completed”. When it’s “completed,” it makes sense to check if it finished successfully. We need a value of the conclusion property. Can be one of the “success”, “failure”, “neutral”, “cancelled”, “skipped”, “timed_out”, or “action_required”.
|
1 2 |
STATUS=$(jq -r ".workflow_runs | .[-1] | .status" $TEMP_FILE) CONCLUSION=$(jq -r ".workflow_runs | .[-1] | .conclusion" $TEMP_FILE) |
Let’s wrap it in a loop, as we want to know when it finishes, not only what’s the current state.
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 |
#!/usr/bin/env bash # exit if any command exits with non-zero status set -e # token is stored in a password manager GITHUB_TOKEN="$(gopass show github-token)" REPO="$1" TEMP_FILE="temp.json" SLEEP_INTERVAL=30 echo "Checking conclusion of the last executed run in \"$REPO_OWNER/$REPO_NAME\" repository:" while true; do curl \ --silent \ --location \ --request GET \ --header 'Accept: application/vnd.github.everest-preview+json' \ --header 'Content-Type: application/json' \ --header "Authorization: token $GITHUB_TOKEN" \ --header 'cache-control: no-cache' \ "https://api.github.com/repos/${REPO}/actions/runs" > $TEMP_FILE STATUS=$(jq -r ".workflow_runs | sort_by( .created_at ) | .[-1] | .status" $TEMP_FILE) echo "Check suite state: ${STATUS}" if [ "$STATUS" = "completed" ]; then CONCLUSION=$(jq -r ".workflow_runs | sort_by( .created_at ) | .[-1] | .conclusion" $TEMP_FILE) echo "Check suite conclusion: ${CONCLUSION}" break; fi sleep $SLEEP_INTERVAL done rm $TEMP_FILE || true |
How does it look like in practice?
|
1 2 3 4 5 6 7 8 |
$ ./check_suite_state.sh eclipsesource/tabris-js-hello-world Checking conclusion of the last executed run in "eclipsesource/tabris-js-hello-world" repository: Check suite state: in_progress Check suite state: in_progress (...) Check suite state: in_progress Check suite state: completed Check suite conclusion: success |
Some services allow you to easily send push notifications to your mobile devices. You might want to use one to catch your attention. Or if it’s enough, then just play a system sound. Just choose an appropriate one – depending on the conclusion! ;)
|
1 2 3 4 5 6 |
# macOS only: if [ "$CONCLUSION" = "success" ]; then afplay /System/Library/Sounds/Glass.aiff else afplay /System/Library/Sounds/Basso.aiff fi |
Feedback is welcome!
Want to join the discussion?Feel free to contribute!



