-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add test orchestrator script to trigger remote workflow runner outsid…
…e functional test repo for cypress tests Issue details - opensearch-project/OpenSearch-Dashboards#5392 Signed-off-by: manasvinibs <[email protected]>
- Loading branch information
1 parent
652537e
commit 11a4668
Showing
2 changed files
with
239 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,36 @@ | ||
name: Trigger Remote Cypress Workflow | ||
|
||
on: | ||
workflow_dispatch: | ||
inputs: | ||
repo: | ||
description: 'Name of the repository in {owner}/{repository} format' | ||
required: true | ||
workflow_name: | ||
description: 'Name of the Github workflow yml file in the component repository' | ||
required: true | ||
os_url: | ||
description: 'Release artifact of OpenSearch' | ||
required: true | ||
osd_url: | ||
description: 'Release artifact of OpenSearch Dashboards' | ||
required: true | ||
branch_ref: | ||
description: 'Test branch name or commit reference id' | ||
required: true | ||
|
||
jobs: | ||
trigger-cypress: | ||
runs-on: ubuntu-latest | ||
name: Remote Cypress Tests | ||
|
||
steps: | ||
- name: Checkout code | ||
uses: actions/checkout@v2 | ||
|
||
- name: Run Bash Script | ||
env: | ||
GITHUB_SECRET_TOKEN: ${{ secrets.GITHUB_TOKEN }} | ||
run: | | ||
./remoteCypress.sh -r "${{ github.event.inputs.repo }}" -w "${{ github.event.inputs.workflow_name }}" -o "${{ github.event.inputs.os_url }}" -d "${{ github.event.inputs.osd_url }}" -b "${{ github.event.inputs.branch_ref }}" | ||
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,203 @@ | ||
#!/bin/bash | ||
|
||
set -e | ||
|
||
function usage() { | ||
echo "" | ||
echo "This script triggers GitHub workflow runners within the component repository which runs Cypress integration tests on a remote OpenSearch/Dashboards cluster." | ||
echo "--------------------------------------------------------------------------" | ||
echo "Usage: $0 [args]" | ||
echo "Required arguments:" | ||
echo -e "-r REMOTE_REPO\t, Name of the repository in {owner}/{repository} format" | ||
echo -e "-w GITHUB_WORKFLOW_NAME\t, Name of the GitHub workflow file name with .yml extension that contain jobs that run Cypress tests in the component repository. For example, main.yaml" | ||
echo -e "-o OS_URL\t, Release artifact of the OpenSearch" | ||
echo -e "-d OSD_URL\t, Release artifact of the OpenSearch Dashboards" | ||
echo -e "-b BRANCH_REF\t Test Branch name or commit reference id" | ||
echo -e "-i BUILD_ID\t Release-specific build id for reference" | ||
echo "--------------------------------------------------------------------------" | ||
} | ||
|
||
# Initialize variables to empty strings | ||
REMOTE_REPO="" | ||
WORKFLOW_NAME="" | ||
OS_URL="" | ||
OSD_URL="" | ||
BRANCH_REF="" | ||
BUILD_ID="" | ||
|
||
# Parse command-line arguments | ||
while getopts ":h:r:w:o:d:b:i:" opt; do | ||
case $opt in | ||
h) | ||
usage | ||
exit 1 | ||
;; | ||
r) | ||
REMOTE_REPO="$OPTARG" | ||
;; | ||
w) | ||
WORKFLOW_NAME="$OPTARG" | ||
;; | ||
o) | ||
OS_URL="$OPTARG" | ||
;; | ||
d) | ||
OSD_URL="$OPTARG" | ||
;; | ||
b) | ||
BRANCH_REF="$OPTARG" | ||
;; | ||
i) | ||
BUILD_ID="$OPTARG" | ||
;; | ||
\?) | ||
echo "Invalid option: -$OPTARG" >&2 | ||
exit 1 | ||
;; | ||
:) | ||
echo "Option -$OPTARG requires an argument." >&2 | ||
exit 1 | ||
;; | ||
esac | ||
done | ||
|
||
# Check if required arguments are provided | ||
if [[ -z "$REMOTE_REPO" || -z "$WORKFLOW_NAME" || -z "$OS_URL" || -z "$OSD_URL" || -z "$BRANCH_REF" ]]; then | ||
echo "Error: Missing required arguments. See usage below." | ||
usage | ||
exit 1 | ||
fi | ||
|
||
# Accessing the secret as an environment variable using Github actions while invoking this script | ||
GITHUB_TOKEN=$GITHUB_SECRET_TOKEN | ||
# This is to uniquely identify each execution workflow. This ID has to be appended to the workflow_run | ||
# name in the component repository yaml file for polling purpose. | ||
UNIQUE_WORKFLOW_ID=$(uuidgen) | ||
echo "Unique Execution ID: $UNIQUE_WORKFLOW_ID" | ||
API_URL="https://api.github.com/repos/$REMOTE_REPO/actions/workflows/$WORKFLOW_NAME/dispatches" | ||
PAYLOAD="{\"ref\": \"$BRANCH_REF\",\"inputs\":{\"build_id\":\"$BUILD_ID\", \"OS_URL\":\"$OS_URL\", \"OSD_URL\":\"$OSD_URL\", \"UNIQUE_ID\":\"$UNIQUE_WORKFLOW_ID\"}}" | ||
|
||
# Maximum number of retries for triggering the remote runner | ||
MAX_RETRIES=3 | ||
|
||
# Trigger the remote GitHub workflow using curl and the PAT token | ||
trigger_remote_workflow() { | ||
curl -L -X POST -H "Authorization: Bearer $GITHUB_TOKEN" \ | ||
-H "Accept: application/vnd.github.v3+json" \ | ||
-H "X-GitHub-Api-Version: 2022-11-28" \ | ||
-w "%{http_code}" \ | ||
"$API_URL" -d "$PAYLOAD" | ||
} | ||
|
||
echo "Triggering the remote GitHub workflow for Cypress tests in the repository: $REMOTE_REPO" | ||
|
||
# Attempt to trigger the remote workflow with retries | ||
for ((i = 1; i <= MAX_RETRIES; i++)); do | ||
echo "Attempting to trigger the remote workflow (Attempt $i)" | ||
status_code=$(trigger_remote_workflow) | ||
echo "status_code: $status_code" | ||
|
||
if [[ $status_code -ge 200 && $status_code -lt 300 ]]; then | ||
echo "Remote workflow triggered successfully." | ||
break | ||
else | ||
echo "Failed to trigger the remote workflow. Retrying..." | ||
sleep 10 # Adds a delay between retries | ||
fi | ||
|
||
if [ $i -eq $MAX_RETRIES ]; then | ||
echo "Maximum number of retries reached. Exiting." | ||
exit 1 | ||
fi | ||
done | ||
|
||
# Function to check the status of the remote workflow by constantly polling the workflow-run | ||
check_remote_workflow_status() { | ||
local run_id | ||
local status | ||
local conclusion | ||
local run_details | ||
local workflow_runs | ||
local matching_workflow | ||
local polling_run_id_retries=1 | ||
local polling_workflow_completion_retries=1 | ||
local max_polling_run_id_retries=5 # Keep polling for the first 5 minutes to fetch the workflow run id till the workflow gets generated | ||
local max_polling_workflow_completion_retries=12 # Set the polling window period to be 1 hour | ||
|
||
# Check if a matching workflow object was found | ||
while [ -z "$matching_workflow" ] && [ $polling_run_id_retries -le $max_polling_run_id_retries ]; do | ||
echo "Querying for the workflow run id..." | ||
sleep 60 # Wait for 1 minute before polling for the workflow run_id till it gets created | ||
|
||
# Make a GET request to the GitHub API to get the list of workflow runs | ||
workflow_runs=$(curl -s -H "Authorization: Bearer $GITHUB_TOKEN" \ | ||
-H "Accept: application/vnd.github.v3+json" \ | ||
-H "X-GitHub-Api-Version: 2022-11-28" \ | ||
"https://api.github.com/repos/$REMOTE_REPO/actions/workflows/$WORKFLOW_NAME/runs") | ||
|
||
# Extract the JSON object whose "name" field contains the string with a unique id of the workflow | ||
matching_workflow=$(echo "$workflow_runs" | jq --arg unique_id "$UNIQUE_WORKFLOW_ID" '.workflow_runs[] | select(.name | contains($unique_id))') | ||
((polling_run_id_retries++)) | ||
|
||
done | ||
echo "matching_workflow: $matching_workflow" | ||
|
||
if [ -n "$matching_workflow" ]; then | ||
# Extract the "jobs_url" and "run_id" values from the matching object | ||
jobs_url=$(echo "$matching_workflow" | jq -r '.jobs_url') | ||
run_id=$(echo "$matching_workflow" | jq -r '.id') | ||
echo "Jobs URL: $jobs_url" | ||
echo "Run Id: $run_id" | ||
|
||
# Poll the status until the workflow is completed | ||
while [ $polling_workflow_completion_retries -le $max_polling_workflow_completion_retries ]; do | ||
echo "Checking the workflow run API status, attempt: $polling_workflow_completion_retries" | ||
|
||
run_details=$(curl -L -H "Authorization: Bearer $GITHUB_TOKEN" \ | ||
-H "Accept: application/vnd.github.v3+json" \ | ||
-H "X-GitHub-Api-Version: 2022-11-28" \ | ||
"https://api.github.com/repos/$REMOTE_REPO/actions/runs/$run_id") | ||
echo "Workflow run details: $run_details" | ||
|
||
# Extract status and conclusion from the run details | ||
status=$(echo "$run_details" | jq -r ".status") | ||
conclusion=$(echo "$run_details" | jq -r ".conclusion") | ||
|
||
# Check if the status indicates that the workflow is complete | ||
if [[ "$status" == "completed" ]]; then | ||
echo "Workflow completed with status: $status" | ||
|
||
# Check if it was successful | ||
if [[ $conclusion == "success" ]]; then | ||
echo "Remote workflow completed successfully." | ||
return 0 # Success | ||
elif [[ $conclusion == "failure" ]]; then | ||
echo "Remote workflow completed with errors. Conclusion: $conclusion" | ||
|
||
# Parse the workflow to find any failures in the test | ||
failures=$(echo "$run_details" | jq -r '.jobs[] | select(.conclusion == "failure") | .name') | ||
echo "Test failures: $failures" | ||
|
||
return 1 # Failure | ||
else | ||
echo "Remote workflow completed with unexpected conclusion. Conclusion: $conclusion" | ||
return 1 # Failure | ||
fi | ||
else | ||
echo "Remote workflow is still running. Waiting..." | ||
sleep 300 # Wait for 5 minutes before checking again | ||
((polling_workflow_completion_retries++)) | ||
fi | ||
done | ||
else | ||
echo "No matching workflow run object found even after retries. Exiting..." | ||
fi | ||
|
||
echo "Remote workflow didn't complete within the specified time." | ||
return 1 # Failure | ||
} | ||
|
||
# Check the status of the remote workflow | ||
check_remote_workflow_status | ||
|
||
exit 0 |