From e6deb1897c9d5f53c95c2c3ab4442ced12523b7f Mon Sep 17 00:00:00 2001 From: manasvinibs Date: Mon, 6 Nov 2023 04:05:34 +0000 Subject: [PATCH] [POC] Add ability to trigger remote workflow runner outside functional test repo Signed-off-by: manasvinibs --- .../test-remote-cypress-workflow.yml | 26 +++ remoteCypress.sh | 181 ++++++++++++++++++ 2 files changed, 207 insertions(+) create mode 100644 .github/workflows/test-remote-cypress-workflow.yml create mode 100755 remoteCypress.sh diff --git a/.github/workflows/test-remote-cypress-workflow.yml b/.github/workflows/test-remote-cypress-workflow.yml new file mode 100644 index 000000000..a6137867c --- /dev/null +++ b/.github/workflows/test-remote-cypress-workflow.yml @@ -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 + env: + REMOTE_GITHUB_PAT: ${{secrets.REMOTE_GITHUB_PAT}} + + steps: + - name: Checkout code + uses: actions/checkout@v2 + + - name: Run Bash Script + run: | + ./remoteCypress.sh + diff --git a/remoteCypress.sh b/remoteCypress.sh new file mode 100755 index 000000000..6cde721e6 --- /dev/null +++ b/remoteCypress.sh @@ -0,0 +1,181 @@ +#!/bin/bash + +# The below params values are taken as an input param +REMOTE_REPO="manasvinibs/OpenSearch-Dashboards" # This is for POC, will be updated to read from manifest file. +WORKFLOW_NAME="remote_cypress_workflow.yml" +GITHUB_TOKEN="$REMOTE_GITHUB_PAT" +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" +BRANCH_NAME="POC" +PAYLOAD="{\"ref\": \"$BRANCH_NAME\",\"inputs\":{\"build_id\":\"$UNIQUE_WORKFLOW_ID\"}}" # Build id is the unique id generated for each execution. + + +function usage() { + echo "" + echo "This script is used to trigger github workflow runners which runs cypress integration tests for plugins installed on a remote OpenSearch/Dashboards cluster outside functional test repository." + echo "--------------------------------------------------------------------------" + echo "Usage: $0 [args]" + echo "" + echo "Required arguments:" + echo -e "-b REMOTE_REPO\t, " + echo -e "-p GITHUB_WORKFLOW_NAME\t, defaults to 9200 or 5601 depends on OpenSearch or Dashboards, can be changed to any port for the cluster location." + echo -e "-s OS_URL\t, defaults to true. Specify the OpenSearch/Dashboards have security enabled or not." + echo -e "-c OSD_URL\t, no defaults, effective when SECURITY_ENABLED=true." + echo -e "-r ref\t commit reference has id or branch name." + echo "--------------------------------------------------------------------------" +} + +# Parse command-line arguments +while getopts "h:r:w:a:b:r:" opt; do + case $opt in + h) + usage + exit 1 + ;; + r) + REMOTE_REPO="$OPTARG" + ;; + w) + WORKFLOW_NAME="$OPTARG" + ;; + a) + OS_URL="$OPTARG" + ;; + b) + OSD_URL="$OPTARG" + ;; + c) + BRANCH_NAME="$OPTARG" + ;; + \?) + echo "Invalid option: -$OPTARG" >&2 + exit 1 + ;; + :) + echo "Option -$OPTARG requires an argument." >&2 + exit 1 + ;; + esac +done + +# Maximum number of retries for triggering 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 remote GitHub workflow for Cypress tests in repository: $REMOTE_REPO" + +# Attempt to trigger the remote workflow with retries +for ((i = 1; i <= MAX_RETRIES; i++)); do + echo "Attempting to trigger 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 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 first 5 minutes to fetch workflow run id till 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 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" + + echo "Checking the workflow run API status, attempt: $polling_workflow_completion_retries" + + # Poll the status until the workflow is completed + while [ $polling_workflow_completion_retries -le $max_polling_workflow_completion_retries ]; do + 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 + else + 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 + 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