Repository: opensearch-project/opensearch-build

Issue:
Add bwctest.sh in OpenSearch and one plugin
- [x] OpenSearch Core - https://github.com/opensearch-project/OpenSearch/pull/1150
- [x] Anomaly Detection Plugin - https://github.com/opensearch-project/anomaly-detection/pull/189


Discussion:

Resolving patch:
diff --git a/bundle-workflow/src/paths/script_finder.py b/bundle-workflow/src/paths/script_finder.py
--- a/bundle-workflow/src/paths/script_finder.py
+++ b/bundle-workflow/src/paths/script_finder.py
@@ -85,3 +85,16 @@ def find_install_script(cls, component_name):
         ]
 
         return cls.__find_script("install.sh", paths)
+
+    @classmethod
+    def find_bwc_test_script(cls, component_name, git_dir):
+        paths = [
+            os.path.realpath(os.path.join(git_dir, "bwctest.sh")),
+            os.path.realpath(os.path.join(git_dir, "scripts/bwctest.sh")),
+            os.path.realpath(
+                os.path.join(cls.component_scripts_path, component_name, "bwctest.sh")
+            ),
+            os.path.realpath(os.path.join(cls.default_scripts_path, "bwctest.sh")),
+        ]
+
+        return cls.__find_script("bwctest.sh", paths)


Test patch:
diff --git a/bundle-workflow/jenkins_workflow/test/Jenkinsfile b/bundle-workflow/jenkins_workflow/test/Jenkinsfile
--- a/bundle-workflow/jenkins_workflow/test/Jenkinsfile
+++ b/bundle-workflow/jenkins_workflow/test/Jenkinsfile
@@ -36,7 +36,7 @@ pipeline {
                                     ),
                                     string(
                                             defaultValue: '',
-                                            name: 'test_suite_type',
+                                            name: 'test_suite',
                                             trim: true
                                     ),
                             ])
@@ -64,7 +64,7 @@ pipeline {
                 }
             }
             steps {
-                sh "./bundle-workflow/test.sh ${test_suite_type} --s3-bucket ${ARTIFACT_BUCKET_NAME} --opensearch-version ${opensearch_version} --build-id ${build_id} --architecture ${architecture} --test-run-id ${test_run_id}"
+                sh "./bundle-workflow/test.sh ${test_suite} --s3-bucket ${ARTIFACT_BUCKET_NAME} --opensearch-version ${opensearch_version} --build-id ${build_id} --architecture ${architecture} --test-run-id ${test_run_id}"
             }
             post() {
                 always {
diff --git a/bundle-workflow/jenkins_workflow/test/README.md b/bundle-workflow/jenkins_workflow/test/README.md
--- a/bundle-workflow/jenkins_workflow/test/README.md
+++ b/bundle-workflow/jenkins_workflow/test/README.md
@@ -12,4 +12,4 @@ This job runs integration/bwc tests for a bundle via `test.sh` in Jenkins.
 | build_id |  Unique identifier for a bundle build                         |
 | architecture | CPU Architecture of bundle                                |
 | test_run_id | Unique identifier for a test run                           |
-| test_suite_type | Run a specific test suite. [integ-test, bwc-test]      |
+| test_suite | Run a specific test suite. [integ-test, bwc-test]           |
diff --git a/bundle-workflow/src/run_bwc_test.py b/bundle-workflow/src/run_bwc_test.py
--- a/bundle-workflow/src/run_bwc_test.py
+++ b/bundle-workflow/src/run_bwc_test.py
@@ -6,23 +6,25 @@
 # compatible open source license.
 
 import logging
-import os
 import sys
 
 from manifests.bundle_manifest import BundleManifest
+from system import console
 from system.temporary_directory import TemporaryDirectory
+from system.working_directory import WorkingDirectory
 from test_workflow.bwc_test.bwc_test_suite import BwcTestSuite
 from test_workflow.test_args import TestArgs
 
 
 def main():
     args = TestArgs()
+    console.configure(level=args.logging_level)
     with TemporaryDirectory(keep=args.keep) as work_dir:
         logging.info("Switching to temporary work_dir: " + work_dir)
-        os.chdir(work_dir)
-        bundle_manifest = BundleManifest.from_s3(
-            args.s3_bucket, args.build_id, args.opensearch_version, args.architecture, work_dir)
-        BwcTestSuite(bundle_manifest, work_dir, args.component, args.keep).execute()
+        with WorkingDirectory(work_dir) as cur_dir:
+            bundle_manifest = BundleManifest.from_s3(
+                args.s3_bucket, args.build_id, args.opensearch_version, args.architecture, cur_dir)
+            BwcTestSuite(bundle_manifest, cur_dir, args.component, args.keep).execute()
 
 
 if __name__ == "__main__":
diff --git a/bundle-workflow/src/test_workflow/bwc_test/bwc_test_suite.py b/bundle-workflow/src/test_workflow/bwc_test/bwc_test_suite.py
--- a/bundle-workflow/src/test_workflow/bwc_test/bwc_test_suite.py
+++ b/bundle-workflow/src/test_workflow/bwc_test/bwc_test_suite.py
@@ -9,33 +9,38 @@
 
 import logging
 import os
-import subprocess
 
+from paths.script_finder import ScriptFinder
+from system.execute import execute
 from test_workflow.test_component import TestComponent
 
 
 class BwcTestSuite:
     manifest: str
+    work_dir: str
     component: str
     keep: bool
 
     def __init__(self, manifest, work_dir, component=None, keep=False):
         self.manifest = manifest
         self.work_dir = work_dir
+        self.script_finder = ScriptFinder()
         self.component = component
         self.keep = keep
 
-    def run_tests(self, work_dir):
-        bwc_script = "bwctest.sh"
-        run_bwctests = f"./{bwc_script}"
-        output = subprocess.check_output(run_bwctests, cwd=work_dir, shell=True)
-        return output
+    def run_tests(self, work_dir, component_name):
+        script = self.script_finder.find_bwc_test_script(
+            component_name, work_dir
+        )
+        cmd = f"{script}"
+        (status, stdout, stderr) = execute(cmd, work_dir, True, False)
+        return (status, stdout, stderr)
 
     def component_bwc_tests(self, component):
         test_component = TestComponent(component.repository, component.commit_id)
         test_component.checkout(os.path.join(self.work_dir, component.name))
         try:
-            console_output = self.run_tests(self.work_dir + "/" + component.name)
+            console_output = self.run_tests(self.work_dir + "/" + component.name, component.name)
             return console_output
         except:
             # TODO: Store and report test failures for {component}
diff --git a/bundle-workflow/tests/test_bwc_workflow/bwc_test/data/test_manifest.yaml b/bundle-workflow/tests/test_bwc_workflow/bwc_test/data/test_manifest.yaml
--- a/bundle-workflow/tests/test_bwc_workflow/bwc_test/data/test_manifest.yaml
+++ b/bundle-workflow/tests/test_bwc_workflow/bwc_test/data/test_manifest.yaml
@@ -9,36 +9,36 @@ components:
     location: https://artifacts.opensearch.org/builds/1.0.0/41d5ae25183d4e699e92debfbe3f83bd/bundle/opensearch-min-1.0.0-linux-x64.tar.gz
     name: OpenSearch
     ref: "1.0"
-    repository: https://github.com/saratvemulapalli/OpenSearch.git
+    repository: https://github.com/opensearch-project/OpenSearch.git
   - commit_id: 7fad9529358259de529763c1c923fd947817a3bd
     location: https://artifacts.opensearch.org/builds/1.0.0/41d5ae25183d4e699e92debfbe3f83bd/plugins/opensearch-job-scheduler-1.0.0.0.zip
     name: job-scheduler
-    ref: 1.0.0.0
+    ref: "1.0.0.0"
     repository: https://github.com/opensearch-project/job-scheduler.git
   - commit_id: 65bb94fb7d46a88b07b61622585ed701918b19c5
     location: https://artifacts.opensearch.org/builds/1.0.0/41d5ae25183d4e699e92debfbe3f83bd/plugins/opensearch-sql-1.0.0.0.zip
     name: sql
-    ref: 1.0.0.0
+    ref: "1.0.0.0"
     repository: https://github.com/opensearch-project/sql.git
   - commit_id: a14ccd49389ca41446acc3200e3e870cde15a68e
     location: https://artifacts.opensearch.org/builds/1.0.0/41d5ae25183d4e699e92debfbe3f83bd/plugins/opensearch-alerting-1.0.0.0.zip
     name: alerting
-    ref: 1.0.0.0
+    ref: "1.0.0.0"
     repository: https://github.com/opensearch-project/alerting.git
   - commit_id: 2e21d59749526baa8e4666168643c4594cdadf79
     location: https://artifacts.opensearch.org/builds/1.0.0/41d5ae25183d4e699e92debfbe3f83bd/plugins/opensearch-security-1.0.0.0.zip
     name: security
-    ref: 1.0.0.0
+    ref: "1.0.0.0"
     repository: https://github.com/opensearch-project/security.git
   - commit_id: 091fe9f6612cd7e85054918036587bcd3c67eab1
     location: https://artifacts.opensearch.org/builds/1.0.0/41d5ae25183d4e699e92debfbe3f83bd/plugins/opensearch-index-management-1.0.0.0.zip
     name: index-management
-    ref: 1.0.0.0
+    ref: "1.0.0.0"
     repository: https://github.com/opensearch-project/index-management.git
   - commit_id: 9b29a99b05f2c8cd9d54dc868994cab8460ff0db
     location: https://artifacts.opensearch.org/builds/1.0.0/41d5ae25183d4e699e92debfbe3f83bd/plugins/opensearch-knn-1.0.0.0.zip
     name: k-NN
-    ref: 1.0.0.0
+    ref: "1.0.0.0"
     repository: https://github.com/opensearch-project/k-NN.git
   - commit_id: 502c96e54fae1cec9fee1fafd77ad92fde9d2459
     location: https://artifacts.opensearch.org/builds/1.0.0/41d5ae25183d4e699e92debfbe3f83bd/plugins/opensearch-anomaly-detection-1.0.0.0.zip
@@ -48,16 +48,16 @@ components:
   - commit_id: bd31e80adf6d52c1b4662d0d2cc9b30d8ae14309
     location: https://artifacts.opensearch.org/builds/1.0.0/41d5ae25183d4e699e92debfbe3f83bd/plugins/opensearch-asynchronous-search-1.0.0.0.zip
     name: asynchronous-search
-    ref: main
+    ref: "main"
     repository: https://github.com/opensearch-project/asynchronous-search.git
   - commit_id: 72705e2dfcad760c5de7609891700aa11d767884
     location: https://artifacts.opensearch.org/builds/1.0.0/41d5ae25183d4e699e92debfbe3f83bd/plugins/opensearch-reports-scheduler-1.0.0.0.zip
     name: dashboards-reports
-    ref: 1.0.0.0
+    ref: "1.0.0.0"
     repository: https://github.com/opensearch-project/dashboards-reports.git
   - commit_id: fd745a77c19df4991254b495cf0ec3730c66534d
     location: https://artifacts.opensearch.org/builds/1.0.0/41d5ae25183d4e699e92debfbe3f83bd/plugins/opensearch-notebooks-1.0.0.0.zip
     name: dashboards-notebooks
-    ref: 1.0.0.0
+    ref: "1.0.0.0"
     repository: https://github.com/opensearch-project/dashboards-notebooks.git
 schema-version: '1.0'
\ No newline at end of file
diff --git a/bundle-workflow/tests/test_bwc_workflow/bwc_test/test_bwc_suite.py b/bundle-workflow/tests/test_bwc_workflow/bwc_test/test_bwc_suite.py
--- a/bundle-workflow/tests/test_bwc_workflow/bwc_test/test_bwc_suite.py
+++ b/bundle-workflow/tests/test_bwc_workflow/bwc_test/test_bwc_suite.py
@@ -5,7 +5,6 @@
 # compatible open source license.
 
 import os
-import subprocess
 import unittest
 from unittest.mock import MagicMock, call, patch
 
@@ -34,17 +33,15 @@ def test_execute(self):
         )
 
     def test_run_bwctest(self):
-        with self.assertRaises(subprocess.CalledProcessError) as process_ret:
-            self.bwc_test_suite.run_tests(".")
-        # 127 ret code == could not find the script to run the command
-        self.assertEqual(process_ret.exception.returncode, 127)
-        self.assertEqual(process_ret.exception.cmd, "./bwctest.sh")
+        response = self.bwc_test_suite.run_tests(".", self.manifest.components[1].name)
+        # could find the script but the script exited because `./gradlew` doesn't exist
+        self.assertTrue("default/bwctest.sh" in response[2])  # stderr
 
     @patch("test_workflow.bwc_test.bwc_test_suite.TestComponent")
     def test_component_bwctest(self, test_component_mock):
         component = self.manifest.components[1]
         self.bwc_test_suite.run_tests = MagicMock()
-        expected = [call("./" + self.manifest.components[1].name)]
+        expected = [call("./" + self.manifest.components[1].name, self.manifest.components[1].name)]
 
         self.bwc_test_suite.component_bwc_tests(component)
         test_component_mock.return_value.checkout.assert_called_with(