From 11ecfa6e725bd146c4f2042526c2f572c1382413 Mon Sep 17 00:00:00 2001
From: Jialiang Liang <109499885+RyanL1997@users.noreply.github.com>
Date: Thu, 14 Dec 2023 18:01:40 -0800
Subject: [PATCH] [Backport 2.x] Refactor Cypress workflow (#1299)

* [CI/CD] Refactor Cypress workflow

Signed-off-by: Ryan Liang <jiallian@amazon.com>

* Remove duplicate group

Signed-off-by: Ryan Liang <jiallian@amazon.com>

* Enable cypress workflow

Signed-off-by: Ryan Liang <jiallian@amazon.com>

* Rename the title of each job

Signed-off-by: Ryan Liang <jiallian@amazon.com>

* Correct the path to event analytics test

Signed-off-by: Ryan Liang <jiallian@amazon.com>

---------

Signed-off-by: Ryan Liang <jiallian@amazon.com>
---
 .../app_analytics.spec.js}                    |   4 +-
 .../datasources.spec.js}                      |   0
 .../event_analytics.spec.js}                  |   6 +-
 .../integrations.spec.js}                     |   4 +-
 .../metrics_analytics.spec.js}                |   6 +-
 .../notebooks.spec.js}                        |   4 +-
 .../panels.spec.ts}                           |   4 +-
 .../trace_analytics_dashboard.spec.js}        |   4 +-
 .../trace_analytics_services.spec.js}         |   4 +-
 .../trace_analytics_traces.spec.js}           |   2 +-
 .../workflows/integration-tests-workflow.yml  | 173 ++++++++++++++++++
 11 files changed, 192 insertions(+), 19 deletions(-)
 rename .cypress/integration/{7_app_analytics.spec.js => app_analytics_test/app_analytics.spec.js} (99%)
 rename .cypress/integration/{10_datasources.spec.js => datasources_test/datasources.spec.js} (100%)
 rename .cypress/integration/{1_event_analytics.spec.js => event_analytics_test/event_analytics.spec.js} (99%)
 rename .cypress/integration/{9_integrations.spec.js => integrations_test/integrations.spec.js} (98%)
 rename .cypress/integration/{8_metrics_analytics.spec.js => metrics_analytics_test/metrics_analytics.spec.js} (98%)
 rename .cypress/integration/{2_notebooks.spec.js => notebooks_test/notebooks.spec.js} (99%)
 rename .cypress/integration/{3_panels.spec.ts => panels_test/panels.spec.ts} (99%)
 rename .cypress/integration/{4_trace_analytics_dashboard.spec.js => trace_analytics_test/trace_analytics_dashboard.spec.js} (99%)
 rename .cypress/integration/{5_trace_analytics_services.spec.js => trace_analytics_test/trace_analytics_services.spec.js} (99%)
 rename .cypress/integration/{6_trace_analytics_traces.spec.js => trace_analytics_test/trace_analytics_traces.spec.js} (98%)
 create mode 100644 .github/workflows/integration-tests-workflow.yml

diff --git a/.cypress/integration/7_app_analytics.spec.js b/.cypress/integration/app_analytics_test/app_analytics.spec.js
similarity index 99%
rename from .cypress/integration/7_app_analytics.spec.js
rename to .cypress/integration/app_analytics_test/app_analytics.spec.js
index 1e50d76aac..b875d4f3b5 100644
--- a/.cypress/integration/7_app_analytics.spec.js
+++ b/.cypress/integration/app_analytics_test/app_analytics.spec.js
@@ -4,7 +4,7 @@
  */
 
 /// <reference types="cypress" />
-import { suppressResizeObserverIssue } from '../utils/constants';
+import { suppressResizeObserverIssue } from '../../utils/constants';
 
 import {
   delay,
@@ -33,7 +33,7 @@ import {
   newName,
   TYPING_DELAY,
   timeoutDelay
-} from '../utils/app_constants';
+} from '../../utils/app_constants';
 
 suppressResizeObserverIssue();//needs to be in file once
 
diff --git a/.cypress/integration/10_datasources.spec.js b/.cypress/integration/datasources_test/datasources.spec.js
similarity index 100%
rename from .cypress/integration/10_datasources.spec.js
rename to .cypress/integration/datasources_test/datasources.spec.js
diff --git a/.cypress/integration/1_event_analytics.spec.js b/.cypress/integration/event_analytics_test/event_analytics.spec.js
similarity index 99%
rename from .cypress/integration/1_event_analytics.spec.js
rename to .cypress/integration/event_analytics_test/event_analytics.spec.js
index f25987f4fb..c018a00602 100644
--- a/.cypress/integration/1_event_analytics.spec.js
+++ b/.cypress/integration/event_analytics_test/event_analytics.spec.js
@@ -24,8 +24,8 @@ import {
   VIS_TYPE_VBAR,
   FIELD_HOST,
   FIELD_AGENT
-} from '../utils/event_analytics/constants';
-import { suppressResizeObserverIssue, COMMAND_TIMEOUT_LONG } from '../utils/constants';
+} from '../../utils/event_analytics/constants';
+import { suppressResizeObserverIssue, COMMAND_TIMEOUT_LONG } from '../../utils/constants';
 
 import {
   querySearch,
@@ -34,7 +34,7 @@ import {
   landOnEventVisualizations,
   landOnPanels,
   clearQuerySearchBoxText,
-} from '../utils/event_analytics/helpers';
+} from '../../utils/event_analytics/helpers';
 
 describe('Adding sample data and visualization', () => {
   it('Adds sample flights data for event analytics', () => {
diff --git a/.cypress/integration/9_integrations.spec.js b/.cypress/integration/integrations_test/integrations.spec.js
similarity index 98%
rename from .cypress/integration/9_integrations.spec.js
rename to .cypress/integration/integrations_test/integrations.spec.js
index 18a4c15ada..3ae5db17c6 100644
--- a/.cypress/integration/9_integrations.spec.js
+++ b/.cypress/integration/integrations_test/integrations.spec.js
@@ -7,7 +7,7 @@
 
 import {
   TEST_INTEGRATION_INSTANCE, TEST_SAMPLE_INSTANCE,
-} from '../utils/constants';
+} from '../../utils/constants';
 
 let testInstanceSuffix = (Math.random() + 1).toString(36).substring(7);
 let testInstance = `${TEST_INTEGRATION_INSTANCE}_${testInstanceSuffix}`;
@@ -66,7 +66,7 @@ describe('Basic sanity test for integrations plugin', () => {
     moveToAvailableNginxIntegration();
     cy.get('.euiFilterGroup').trigger('mouseover').click();
     cy.get('.euiFilterSelectItem').contains('visualization').click();
-    cy.get('.euiTableRow').should('have.length', 4);//Filters correctly to visualization types
+    cy.get('.euiTableRow').should('have.length', 6);//Filters correctly to visualization types
   })
 });
 
diff --git a/.cypress/integration/8_metrics_analytics.spec.js b/.cypress/integration/metrics_analytics_test/metrics_analytics.spec.js
similarity index 98%
rename from .cypress/integration/8_metrics_analytics.spec.js
rename to .cypress/integration/metrics_analytics_test/metrics_analytics.spec.js
index 255a354341..d7898ba5ad 100644
--- a/.cypress/integration/8_metrics_analytics.spec.js
+++ b/.cypress/integration/metrics_analytics_test/metrics_analytics.spec.js
@@ -11,9 +11,9 @@ import {
   PPL_METRICS_NAMES,
   VIS_TYPE_LINE,
   TESTING_PANEL,
-} from '../utils/metrics_constants';
-import { suppressResizeObserverIssue, COMMAND_TIMEOUT_LONG } from '../utils/constants';
-import { landOnPanels, clearQuerySearchBoxText } from '../utils/event_analytics/helpers';
+} from '../../utils/metrics_constants';
+import { suppressResizeObserverIssue, COMMAND_TIMEOUT_LONG } from '../../utils/constants';
+import { landOnPanels, clearQuerySearchBoxText } from '../../utils/event_analytics/helpers';
 
 describe('Metrics Analytics', () => {
   beforeEach(() => {
diff --git a/.cypress/integration/2_notebooks.spec.js b/.cypress/integration/notebooks_test/notebooks.spec.js
similarity index 99%
rename from .cypress/integration/2_notebooks.spec.js
rename to .cypress/integration/notebooks_test/notebooks.spec.js
index 46aab9b519..e23d706673 100644
--- a/.cypress/integration/2_notebooks.spec.js
+++ b/.cypress/integration/notebooks_test/notebooks.spec.js
@@ -15,9 +15,9 @@ import {
   NOTEBOOK_TEXT,
   OPENSEARCH_URL,
   COMMAND_TIMEOUT_LONG,
-} from '../utils/constants';
+} from '../../utils/constants';
 
-import { SAMPLE_PANEL } from '../utils/panel_constants';
+import { SAMPLE_PANEL } from '../../utils/panel_constants';
 
 import { skipOn } from '@cypress/skip-test';
 
diff --git a/.cypress/integration/3_panels.spec.ts b/.cypress/integration/panels_test/panels.spec.ts
similarity index 99%
rename from .cypress/integration/3_panels.spec.ts
rename to .cypress/integration/panels_test/panels.spec.ts
index 7096f5aa86..3750c2e02e 100644
--- a/.cypress/integration/3_panels.spec.ts
+++ b/.cypress/integration/panels_test/panels.spec.ts
@@ -5,7 +5,7 @@
 
 /// <reference types="cypress" />
 
-import { suppressResizeObserverIssue } from '../utils/constants';
+import { suppressResizeObserverIssue } from '../../utils/constants';
 import {
   delay,
   NEW_VISUALIZATION_NAME,
@@ -14,7 +14,7 @@ import {
   PPL_VISUALIZATIONS,
   PPL_VISUALIZATIONS_NAMES,
   TEST_PANEL,
-} from '../utils/panel_constants';
+} from '../../utils/panel_constants';
 
 describe('Panels testing with Sample Data', () => {
   suppressResizeObserverIssue();//needs to be in file once
diff --git a/.cypress/integration/4_trace_analytics_dashboard.spec.js b/.cypress/integration/trace_analytics_test/trace_analytics_dashboard.spec.js
similarity index 99%
rename from .cypress/integration/4_trace_analytics_dashboard.spec.js
rename to .cypress/integration/trace_analytics_test/trace_analytics_dashboard.spec.js
index be31f21833..5edf0d33a2 100644
--- a/.cypress/integration/4_trace_analytics_dashboard.spec.js
+++ b/.cypress/integration/trace_analytics_test/trace_analytics_dashboard.spec.js
@@ -5,8 +5,8 @@
 
 /// <reference types="cypress" />
 
-import { testDataSet, delay, setTimeFilter, jaegerTestDataSet } from '../utils/constants';
-import { suppressResizeObserverIssue } from '../utils/constants';
+import { testDataSet, delay, setTimeFilter, jaegerTestDataSet } from '../../utils/constants';
+import { suppressResizeObserverIssue } from '../../utils/constants';
 
 suppressResizeObserverIssue();//needs to be in file once
 
diff --git a/.cypress/integration/5_trace_analytics_services.spec.js b/.cypress/integration/trace_analytics_test/trace_analytics_services.spec.js
similarity index 99%
rename from .cypress/integration/5_trace_analytics_services.spec.js
rename to .cypress/integration/trace_analytics_test/trace_analytics_services.spec.js
index f09b92426c..1f278c2b34 100644
--- a/.cypress/integration/5_trace_analytics_services.spec.js
+++ b/.cypress/integration/trace_analytics_test/trace_analytics_services.spec.js
@@ -5,8 +5,8 @@
 
 /// <reference types="cypress" />
 
-import { delay, SERVICE_NAME, SERVICE_SPAN_ID, setTimeFilter, verify_traces_spans_data_grid_cols_exists, count_table_row, AUTH_SERVICE_SPAN_ID } from '../utils/constants';
-import { suppressResizeObserverIssue } from '../utils/constants';
+import { delay, SERVICE_NAME, SERVICE_SPAN_ID, setTimeFilter, verify_traces_spans_data_grid_cols_exists, count_table_row, AUTH_SERVICE_SPAN_ID } from '../../utils/constants';
+import { suppressResizeObserverIssue } from '../../utils/constants';
 
 suppressResizeObserverIssue();//needs to be in file once
 
diff --git a/.cypress/integration/6_trace_analytics_traces.spec.js b/.cypress/integration/trace_analytics_test/trace_analytics_traces.spec.js
similarity index 98%
rename from .cypress/integration/6_trace_analytics_traces.spec.js
rename to .cypress/integration/trace_analytics_test/trace_analytics_traces.spec.js
index 336f5b6ffe..843e6640ad 100644
--- a/.cypress/integration/6_trace_analytics_traces.spec.js
+++ b/.cypress/integration/trace_analytics_test/trace_analytics_traces.spec.js
@@ -5,7 +5,7 @@
 
 /// <reference types="cypress" />
 
-import { delay, setTimeFilter, SPAN_ID, TRACE_ID } from '../utils/constants';
+import { delay, setTimeFilter, SPAN_ID, TRACE_ID } from '../../utils/constants';
 
 describe('Testing traces table empty state', () => {
   beforeEach(() => {
diff --git a/.github/workflows/integration-tests-workflow.yml b/.github/workflows/integration-tests-workflow.yml
new file mode 100644
index 0000000000..b82200a93a
--- /dev/null
+++ b/.github/workflows/integration-tests-workflow.yml
@@ -0,0 +1,173 @@
+name: Dashboards observability plugin E2E test
+
+on: [pull_request, push]
+
+env:
+  PLUGIN_NAME: dashboards-observability
+  OPENSEARCH_DASHBOARDS_VERSION: '2.x'
+  OPENSEARCH_VERSION: '2.12.0'
+  OPENSEARCH_PLUGIN_VERSION: '2.12.0.0'
+
+jobs:
+  tests:
+    name: Run test group of ${{ matrix.testgroups }}
+    env:
+      # Prevents extra Cypress installation progress messages
+      CI: 1
+      # Avoid warnings like "tput: No value for $TERM and no -T specified"
+      TERM: xterm
+      WORKING_DIR: ${{ matrix.working_directory }}.
+
+    strategy:
+      fail-fast: false
+      matrix:
+        os: [ubuntu-latest]
+        java: [11]
+        testgroups: [
+          app_analytics_test,
+          datasources_test,
+          event_analytics_test,
+          integrations_test,
+          metrics_analytics_test,
+          notebooks_test,
+          panels_test,
+          trace_analytics_test
+        ]
+        include:
+          - os: ubuntu-latest
+            cypress_cache_folder: ~/.cache/Cypress
+    runs-on: ${{ matrix.os }}
+
+    steps:
+      - name: Set up Java 11
+        uses: actions/setup-java@v3
+        with:
+          distribution: 'corretto'
+          java-version: '11'
+
+      - name: Download observability artifact
+        uses: suisei-cn/actions-download-file@v1.4.0
+        with:
+          url: https://aws.oss.sonatype.org/service/local/artifact/maven/redirect?r=snapshots&g=org.opensearch.plugin&a=opensearch-observability&v=${{ env.OPENSEARCH_PLUGIN_VERSION }}-SNAPSHOT&p=zip
+          target: plugin-artifacts/
+          filename: observability.zip
+
+      - name: Download SQL artifact
+        uses: suisei-cn/actions-download-file@v1.4.0
+        with:
+          url: https://aws.oss.sonatype.org/service/local/artifact/maven/redirect?r=snapshots&g=org.opensearch.plugin&a=opensearch-sql-plugin&v=${{ env.OPENSEARCH_PLUGIN_VERSION }}-SNAPSHOT&p=zip
+          target: plugin-artifacts/
+          filename: sql.zip
+
+      - name: Download OpenSearch
+        uses: peternied/download-file@v2
+        with:
+          url: https://artifacts.opensearch.org/snapshots/core/opensearch/${{ env.OPENSEARCH_VERSION }}-SNAPSHOT/opensearch-min-${{ env.OPENSEARCH_VERSION }}-SNAPSHOT-linux-x64-latest.tar.gz
+
+      - name: Extract OpenSearch
+        run: |
+          tar -xzf opensearch-*.tar.gz
+          rm -f opensearch-*.tar.gz
+        shell: bash
+
+      - name: Install observability plugin
+        run: |
+          /bin/bash -c "yes | ./opensearch-${{ env.OPENSEARCH_VERSION }}-SNAPSHOT/bin/opensearch-plugin install file:$(pwd)/plugin-artifacts/observability.zip"
+        shell: bash
+
+      - name: Install SQL plugin
+        run: |
+          /bin/bash -c "yes | ./opensearch-${{ env.OPENSEARCH_VERSION }}-SNAPSHOT/bin/opensearch-plugin install file:$(pwd)/plugin-artifacts/sql.zip"
+        shell: bash
+
+      - name: Run OpenSearch
+        run: /bin/bash -c "./opensearch-${{ env.OPENSEARCH_VERSION }}-SNAPSHOT/bin/opensearch &"
+        shell: bash
+
+      - name: Checkout OpenSearch Dashboards
+        uses: actions/checkout@v2
+        with:
+          repository: opensearch-project/Opensearch-Dashboards
+          ref: ${{ env.OPENSEARCH_DASHBOARDS_VERSION }}
+          path: OpenSearch-Dashboards
+
+      - name: Checkout dashboards observability
+        uses: actions/checkout@v2
+        with:
+          path: OpenSearch-Dashboards/plugins/dashboards-observability
+
+      - name: Get node and yarn versions
+        working-directory: ${{ env.WORKING_DIR }}
+        id: versions_step
+        run: |
+          echo "::set-output name=node_version::$(cat ./OpenSearch-Dashboards/.nvmrc | cut -d"." -f1)"
+          echo "::set-output name=yarn_version::$(node -p "(require('./OpenSearch-Dashboards/package.json').engines.yarn).match(/[.0-9]+/)[0]")"
+
+      - name: Setup node
+        uses: actions/setup-node@v1
+        with:
+          node-version: ${{ steps.versions_step.outputs.node_version }}
+          registry-url: 'https://registry.npmjs.org'
+
+      - name: Install correct yarn version for OpenSearch Dashboards
+        run: |
+          npm uninstall -g yarn
+          echo "Installing yarn ${{ steps.versions_step.outputs.yarn_version }}"
+          npm i -g yarn@${{ steps.versions_step.outputs.yarn_version }}
+
+      - name: Bootstrap the plugin
+        run: |
+          cd OpenSearch-Dashboards/plugins/dashboards-observability
+          yarn osd bootstrap
+
+      - name: Run OpenSearch Dashboards server
+        run: |
+          cd OpenSearch-Dashboards
+          nohup yarn start --no-base-path --no-watch | tee dashboard.log &
+
+      - name : Check If OpenSearch Dashboards Is Ready
+        if: ${{ runner.os == 'Linux' }}
+        run: |
+          cd ./OpenSearch-Dashboards
+          if timeout 600 grep -q "bundles compiled successfully after" <(tail -n0 -f dashboard.log); then
+            echo "OpenSearch Dashboards compiled successfully."
+          else
+            echo "Timeout for 600 seconds reached. OpenSearch Dashboards did not finish compiling."
+            exit 1
+          fi
+
+      - name: Install Cypress
+        run: |
+          cd ./OpenSearch-Dashboards/plugins/dashboards-observability
+          npx cypress install
+        shell: bash
+
+      - name: Get Cypress version
+        id: cypress_version
+        run: |
+          cd ./OpenSearch-Dashboards/plugins/dashboards-observability
+          echo "::set-output name=cypress_version::$(cat ./package.json | jq '.dependencies.cypress' | tr -d '"')"
+
+      - name: Reset npm's script shell
+        if: ${{ matrix.os == 'windows-latest' }}
+        run: |
+          npm config delete script-shell
+
+      - name: Run Cypress tests for test group of ${{ matrix.testgroups }}
+        run: |
+          cd ./OpenSearch-Dashboards/plugins/dashboards-observability
+          yarn cypress:run --browser chrome --headless --spec '.cypress/integration/${{ matrix.testgroups }}/*'
+
+      - name: Capture failure screenshots
+        uses: actions/upload-artifact@v1
+        if: failure()
+        with:
+          name: cypress-screenshots-${{ matrix.os }}
+          path: OpenSearch-Dashboards/plugins/dashboards-observability/.cypress/screenshots
+
+      - name: Capture test video
+        uses: actions/upload-artifact@v1
+        if: always()
+        with:
+          name: cypress-videos-${{ matrix.os }}
+          path: OpenSearch-Dashboards/plugins/dashboards-observability/.cypress/videos
\ No newline at end of file