From dd3511f699c7e91dd530cf3972b4725beb02145b Mon Sep 17 00:00:00 2001 From: manasvinibs Date: Sat, 6 Jan 2024 00:25:08 +0000 Subject: [PATCH] Add remote cypress orchestrator integration with intestest script Signed-off-by: manasvinibs --- .github/workflows/remote-cypress-workflow.yml | 14 ++- integtest.sh | 73 +++++++++++++- poll_remote_workflow.sh | 28 +++--- remoteCypress.sh | 98 +++++++++---------- remote_cypress_manifest.json | 31 ++++++ 5 files changed, 175 insertions(+), 69 deletions(-) create mode 100644 remote_cypress_manifest.json diff --git a/.github/workflows/remote-cypress-workflow.yml b/.github/workflows/remote-cypress-workflow.yml index 9e75fdef9..e03ef376d 100644 --- a/.github/workflows/remote-cypress-workflow.yml +++ b/.github/workflows/remote-cypress-workflow.yml @@ -1,6 +1,8 @@ name: Trigger Remote Cypress Workflow on: + push: + branches: [ '**' ] workflow_dispatch: inputs: repo: @@ -27,10 +29,14 @@ jobs: steps: - name: Checkout code uses: actions/checkout@v2 - - - name: Run Bash Script + + - name: Set env variable 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 }}" + run: echo "Setting github secret token to an env variable for remoteCypress script to access the token" + - name: Run Remote Cypress Orchestrator Script + if: github.event_name == 'workflow_dispatch' + run: | + echo "Executing remoteCypress script for workflow_dispatch event" + ./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 }}" \ No newline at end of file diff --git a/integtest.sh b/integtest.sh index cd97c1da7..9eaf26186 100644 --- a/integtest.sh +++ b/integtest.sh @@ -102,17 +102,84 @@ echo -e "Test Files List:" echo $TEST_FILES | tr ',' '\n' echo "BROWSER_PATH: $BROWSER_PATH" +# Array to store remote cypress workflow background processes IDs when run in parallel +declare -a all_process_pids + +run_remote_cypress() { + local repo="$1" + local workflow_name="$2" + local os_url="$3" + local osd_url="$4" + local branch_ref="$5" + + # Call the remoteCypress.sh script with the required arguments + source remoteCypress.sh -r "$repo" -w "$workflow_name" -o "$os_url" -d "$osd_url" -b "$branch_ref" & + bg_process_pid=$! + echo "PID for the repo $repo is : $bg_process_pid" + all_process_pids+=($bg_process_pid) +} + +# Read inputs from the manifest file using jq +REMOTE_MANIFEST_FILE="remote_cypress_manifest.json" + +# Parse the JSON file using jq and iterate over the components array +components=$(jq -c '.components[]' "$REMOTE_MANIFEST_FILE") +release_version=$(jq -r '.build.version' "$REMOTE_MANIFEST_FILE") +echo "Components: $components" +echo "Release version: $release_version" + +for component in $components; do + echo "Processing for the component: $component" + + repo=$(echo "$component" | jq -r '.["repository"]') + workflow_name=$(echo "$component" | jq -r '.["workflow-name"]') + os_url=$(echo "$component" | jq -r '.["opensearch"]') + osd_url=$(echo "$component" | jq -r '.["opensearch-dashboards"]') + branch_ref=$(echo "$component" | jq -r '.["ref"]') + + # Set default values if the opensearch and opensearch-dashboards are not set in the manifest + os_url=${os_url:-https://artifacts.opensearch.org/releases/bundle/opensearch/$release_version/opensearch-$release_version-linux-x64.tar.gz} + osd_url=${osd_url:-https://artifacts.opensearch.org/releases/bundle/opensearch-dashboards/$release_version/opensearch-dashboards-$release_version-linux-x64.tar.gz} + + echo "repo: $repo" + echo "workflow_name: $workflow_name" + echo "os_url: $os_url" + echo "osd_url: $osd_url" + echo "branch_ref: $branch_ref" + + # Call the function for each component + run_remote_cypress "$repo" "$workflow_name" "$os_url" "$osd_url" "$branch_ref" +done + +# Wait for all processes to finish +wait "${all_process_pids[@]}" + +log_directory="/tmp/logfiles" + +# Read log files in tmp folder and put the output to CI +find "$log_directory" -type f -name "*.txt" | while IFS= read -r log_file; do + if [ -f "$log_file" ]; then + echo "Log content for file: $log_file" + cat "$log_file" + else + echo "Log file not found: $log_file" + fi +done + +# Delete the temporary log files and folder after writing to CI +rm -rf "$log_directory" + ## WARNING: THIS LOGIC NEEDS TO BE THE LAST IN THIS FILE! ## # Cypress returns back the test failure count in the error code # The CI outputs the error code as test failure count. # # We need to ensure the cypress tests are the last execute process to # the error code gets passed to the CI. -if [ $SECURITY_ENABLED = "true" ] -then + +if [ $SECURITY_ENABLED = "true" ]; then echo "run security enabled tests" yarn cypress:run-with-security --browser "$BROWSER_PATH" --spec "$TEST_FILES" else echo "run security disabled tests" yarn cypress:run-without-security --browser "$BROWSER_PATH" --spec "$TEST_FILES" -fi \ No newline at end of file +fi diff --git a/poll_remote_workflow.sh b/poll_remote_workflow.sh index e3d575d23..fdf78a950 100644 --- a/poll_remote_workflow.sh +++ b/poll_remote_workflow.sh @@ -1,10 +1,13 @@ #!/bin/bash +set -e + # 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" +exitcode=2 # Function to check the status of the remote github workflow by constantly polling the workflow-run check_remote_workflow_status() { @@ -52,12 +55,13 @@ check_remote_workflow_status() { -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") + echo "Workflow run status: $status" + # Check if the status indicates that the workflow is complete if [[ "$status" == "completed" ]]; then echo "Workflow completed with status: $status" @@ -65,7 +69,8 @@ check_remote_workflow_status() { # Check if it was successful if [[ $conclusion == "success" ]]; then echo "Remote workflow completed successfully." - return 0 # Success + exitcode=0 # Success + break; elif [[ $conclusion == "failure" ]]; then echo "Remote workflow completed with errors. Conclusion: $conclusion" @@ -75,13 +80,15 @@ check_remote_workflow_status() { "$jobs_url") # Parse the workflow to find any failures in the test - failures=$(echo "$run_details" | jq -r '.jobs[] | select(.conclusion == "failure") | .name') + failures=$(echo "$job_details" | jq -r '.jobs[] | select(.conclusion == "failure") | .name') echo "Test failures: $failures" - return 1 # Failure + exitcode=1 # Failure + break; else echo "Remote workflow completed with unexpected conclusion. Conclusion: $conclusion" - return 1 # Failure + exitcode=1 # Failure + break; fi else echo "Remote workflow is still running. Waiting..." @@ -91,13 +98,12 @@ check_remote_workflow_status() { done else echo "No matching workflow run object found even after retries. Exiting..." - return 1 # Failure + exitcode=1 # Failure fi - echo "Remote workflow didn't complete within the specified time." - return 1 # Failure + if [ "$exitcode" -eq 2 ]; then + echo "Remote workflow didn't complete within the specified time." + fi } check_remote_workflow_status - -exit 0 \ No newline at end of file diff --git a/remoteCypress.sh b/remoteCypress.sh index a2de652af..1a8831d03 100755 --- a/remoteCypress.sh +++ b/remoteCypress.sh @@ -53,61 +53,57 @@ while getopts ":h:r:w:o:d:b:i:" opt; do 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 +log_directory="/tmp/logfiles/${REPO}" +mkdir -p "$log_directory" +log_file="$log_directory/logfile.txt" -# 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" +# Check if required arguments are provided +if [[ -n "$REPO" && -n "$WORKFLOW_NAME" && -n "$OS_URL" && -n "$OSD_URL" && -n "$BRANCH_REF" ]]; then + # 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\"}}" -# 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" + # 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" + } - 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 + echo "Triggering the remote GitHub workflow for Cypress tests in the repository: $REPO" - if [ $i -eq $MAX_RETRIES ]; then - echo "Maximum number of retries reached. Exiting." - exit 1 - fi -done + 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." + + source poll_remote_workflow.sh "$REPO" "$UNIQUE_WORKFLOW_ID" "$API_URL" > "$log_file" 2>&1 + echo "Return code: $exitcode" -# Check the status of the remote workflow -source ./poll_remote_workflow.sh "$REPO" "$UNIQUE_WORKFLOW_ID" "$API_URL" -echo "Return code: $?" + if [ "$exitcode" -eq 0 ]; then + echo "Remote workflow for the repo $REPO completed successfully. EXIT CODE 0 " >> "$log_file" + elif [ "$exitcode" -eq 1 ]; then + echo "Remote workflow for the repo $REPO completed with errors. EXIT CODE 1 " >> "$log_file" + else + echo "Remote workflow for the repo $REPO did not complete within the specified time. EXIT CODE 2 " >> "$log_file" + fi -exit 0 + else + echo "Failed to trigger the remote workflow. Exiting." + echo "Failed to trigger the remote workflow for repo $REPO : EXIT CODE 1 " >> "$log_file" + fi +else + echo "Error: Missing required arguments. See usage below." + usage + echo "Remote workflow for the repo $REPO did not start due to missing arguments. EXIT CODE 1 " >> "$log_file" +fi diff --git a/remote_cypress_manifest.json b/remote_cypress_manifest.json new file mode 100644 index 000000000..cb445ab5a --- /dev/null +++ b/remote_cypress_manifest.json @@ -0,0 +1,31 @@ +{ + "schema-version": "1.0", + "build": { + "name": "OpenSearch Dashboards Functional Test", + "version": "3.0.0" + }, + "ci": { + "image": { + } + }, + "components": [ + { + "name": "OpenSearch-Dashboards", + "repository": "opensearch-project/OpenSearch-Dashboards", + "workflow-name": "", + "ref": "", + "opensearch": "https://artifacts.opensearch.org/releases/bundle/opensearch/3.0.0/opensearch-3.0.0-linux-x64.tar.gz", + "opensearch-dashboards": "https://artifacts.opensearch.org/releases/bundle/opensearch-dashboards/3.0.0/opensearch-dashboards-3.0.0-linux-x64.tar.gz", + "integ-test": { + "test-configs": [ + "with-security", + "without-security" + ], + "additional-cluster-configs": { + "vis_builder.enabled": true, + "data_source.enabled": true + } + } + } + ] +} \ No newline at end of file