Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[CERTTF-457] feat: Github action for retrieving data from multi-device jobs #434

Merged
merged 12 commits into from
Feb 4, 2025
82 changes: 82 additions & 0 deletions .github/actions/poll-multi/action.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
name: Poll a multi-device job for child job data
inputs:
job-id:
description: The job ID of the parent multi-device job
type: string
required: true
sentinel-phase:
description: >
The phase that all child jobs must reach before this action terminates
type: string
required: false
default: complete
outputs:
jobs:
description: >
A JSON string containing an array of objects with machine IPs
and child job IDs
value: ${{ steps.data.outputs.jobs }}
runs:
using: composite
steps:
- name: Install prerequisites
shell: bash
run: |
echo "::group::Install prerequisites"
sudo snap install testflinger-cli
sudo snap install jq
echo "::endgroup::"

- name: Retrieve multi-device job data
id: data
shell: bash
env:
JOB_ID: ${{ inputs.job-id }}
run: |
echo "::group::Wait for parent job ${{ env.JOB_ID }} to complete"
while true; do
STATUS=$(testflinger status $JOB_ID)
echo "Parent job status: $STATUS"
[ "$STATUS" == "complete" ] && echo "Parent job $JOB_ID complete -> allocation complete" && break
sleep 10
done
echo "::endgroup::"
echo "::group::Retrieve IDs of children jobs"
RESULTS=$(testflinger results $JOB_ID)
if ! jq -e '.provision_status == 0' <<< "$RESULTS" >/dev/null; then
echo "::error::The provision phase of the parent job $JOB_ID failed"
exit 1
fi
JOB_IDS=$(jq -r '.provision_output' <<< "$RESULTS" | sed -n 's/^.*Created job \(.*\)$/\1/p')
echo "$JOB_IDS" > JOB_IDS_FILE
echo "::notice::" $JOB_IDS
echo "::endgroup::"
echo "::group::Retrieve IPs of reserved devices"
IPS=$(for JOB_ID in $JOB_IDS; do testflinger results $JOB_ID | jq -r '.device_info.device_ip'; done)
echo "::notice::" $IPS
echo "::endgroup::"
echo "::group::Construct output"
JSON=$(paste -d ' ' <(echo "$JOB_IDS") <(echo "$IPS") | jq -Rnc '[inputs | split(" ") | {"device-ip": .[1], "id": .[0]}]')
echo "Output: $JSON"
echo "jobs=$JSON" >> $GITHUB_OUTPUT
echo "::endgroup::"

- name: Hold until all child jobs reach the ${{ inputs.sentinel-phase }} phase
shell: bash
env:
SENTINEL_PHASE: ${{ inputs.sentinel-phase }}
run: |
echo "::group::Wait for child jobs to reach the $SENTINEL_PHASE phase"
JOB_IDS=$(cat JOB_IDS_FILE)
while true; do
REMAINING_JOB_IDS=
for JOB_ID in $JOB_IDS; do
JOB_STATUS=$(testflinger status $JOB_ID)
echo "Job $JOB_ID is in the $JOB_STATUS phase"
[[ "$JOB_STATUS" != "$SENTINEL_PHASE" ]] && REMAINING_JOB_IDS="$REMAINING_JOB_IDS $JOB_ID"
done
JOB_IDS="$REMAINING_JOB_IDS"
[ -z "$JOB_IDS" ] && break
echo "Waiting for $(echo $JOB_IDS | wc -w) child jobs to reach the $SENTINEL_PHASE phase"
sleep 60
done