Skip to content

Commit

Permalink
[POC] Add ability to trigger remote workflow runner outside functiona…
Browse files Browse the repository at this point in the history
…l test repo

Signed-off-by: manasvinibs <[email protected]>
  • Loading branch information
manasvinibs committed Dec 5, 2023
1 parent 76ec82d commit 38854f9
Show file tree
Hide file tree
Showing 2 changed files with 222 additions and 0 deletions.
35 changes: 35 additions & 0 deletions .github/workflows/test-remote-cypress-workflow.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
name: Trigger Remote Cypress Workflow

on:
workflow_dispatch:
inputs:
remote_workflow:
description: 'Trigger Remote Cypress Workflow'
required: false
push:
branches: [ '**' ]

jobs:
trigger-cypress:
runs-on: ubuntu-latest
name: Remote Cypress Tests

steps:
- name: Checkout code
uses: actions/checkout@v2

- name: GitHub App token
id: github_app_token
uses: tibdex/[email protected]
with:
app_id: ${{ secrets.APP_ID }}
private_key: ${{ secrets.APP_PRIVATE_KEY }}
# opensearch-trigger-bot installation ID
installation_id: 22958780

- name: Run Bash Script
env:
REMOTE_GITHUB_PAT: ${{ steps.github_app_token.outputs.token }}
run: |
./remoteCypress.sh -r "manasvinibs/OpenSearch-Dashboards" -w "remote_cypress_workflow.yml" -o "tes_OS_URL" -d "test_OSD_URL" -b "POC"
187 changes: 187 additions & 0 deletions remoteCypress.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,187 @@
#!/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 "--------------------------------------------------------------------------"
}

# 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

# Accessing the secret as an environment variable
GITHUB_TOKEN=$REMOTE_GITHUB_PAT
# This is to uniquely identify each execution workflow
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

0 comments on commit 38854f9

Please sign in to comment.