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 19, 2023
1 parent 76ec82d commit 52fc760
Show file tree
Hide file tree
Showing 3 changed files with 242 additions and 0 deletions.
26 changes: 26 additions & 0 deletions .github/workflows/remote-cypress-workflow.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
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: Run Bash Script
env:
GITHUB_SECRET_TOKEN: ${{ secrets.REMOTE_GITHUB_PAT }}
run: |
./remoteCypress.sh -r "manasvinibs/OpenSearch-Dashboards" -w "remote_cypress_workflow.yml" -o "tes_OS_URL" -d "test_OSD_URL" -b "POC"
103 changes: 103 additions & 0 deletions poll_remote_workflow.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
#!/bin/bash

# Accessing the secret as an environment variable using GitHub actions while invoking this script
GITHUB_TOKEN=$GITHUB_SECRET_TOKEN
REPO="$1"
UNIQUE_WORKFLOW_ID="$2"
API_URL="$3"

# Function to check the status of the remote github 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" \
"$API_URL/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/$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"

job_details=$(curl -L -H "Authorization: Bearer $GITHUB_TOKEN" \
-H "Accept: application/vnd.github.v3+json" \
-H "X-GitHub-Api-Version: 2022-11-28" \
"$jobs_url")

# 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..."
return 1 # Failure
fi

echo "Remote workflow didn't complete within the specified time."
return 1 # Failure
}

check_remote_workflow_status

exit 0
113 changes: 113 additions & 0 deletions remoteCypress.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,113 @@
#!/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 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)
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 "$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"
# For now we are using Github action API to trigger github workflows in plugins component
# ToDo: We can explore other test runners such as Jenkins to integrate with.
API_URL="https://api.github.com/repos/$REPO/actions/workflows/$WORKFLOW_NAME"
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/dispatches" -d "$PAYLOAD"
}

echo "Triggering the remote GitHub workflow for Cypress tests in the repository: $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


# Check the status of the remote workflow
source ./poll_remote_workflow.sh "$REPO" "$UNIQUE_WORKFLOW_ID" "$API_URL"
echo "Return code: $?"

exit 0

0 comments on commit 52fc760

Please sign in to comment.