diff --git a/build.gradle b/build.gradle index e08f82525..3a9d1f6dd 100644 --- a/build.gradle +++ b/build.gradle @@ -120,7 +120,7 @@ jacocoTestReport { } } -String version = '5.2.0' +String version = '5.3.0' task updateVersion { doLast { diff --git a/tests/jenkins/TestBuildFailureMessage.groovy b/tests/jenkins/TestBuildMessage.groovy similarity index 73% rename from tests/jenkins/TestBuildFailureMessage.groovy rename to tests/jenkins/TestBuildMessage.groovy index 9edee45c7..d5e4fd200 100644 --- a/tests/jenkins/TestBuildFailureMessage.groovy +++ b/tests/jenkins/TestBuildMessage.groovy @@ -11,12 +11,12 @@ package jenkins.tests import jenkins.tests.BuildPipelineTest import org.junit.* -class TestBuildFailureMessage extends BuildPipelineTest { +class TestBuildMessage extends BuildPipelineTest { @Before void setUp() { - this.registerLibTester(new BuildFailureMessageLibTester()) + this.registerLibTester(new BuildMessageLibTester('pass')) super.setUp() def currentBuild = binding.getVariable('currentBuild') binding.setVariable("currentBuild", currentBuild) @@ -24,6 +24,6 @@ class TestBuildFailureMessage extends BuildPipelineTest { @Test void testBuildFailureMsg() { - super.testPipeline("tests/jenkins/jobs/BuildFailureMessage_Jenkinsfile") + super.testPipeline("tests/jenkins/jobs/BuildMessage_Jenkinsfile") } } diff --git a/tests/jenkins/TestCloseBuildSuccessGithubIssue.groovy b/tests/jenkins/TestCloseBuildSuccessGithubIssue.groovy new file mode 100644 index 000000000..7debc9a6f --- /dev/null +++ b/tests/jenkins/TestCloseBuildSuccessGithubIssue.groovy @@ -0,0 +1,46 @@ +/* + * Copyright OpenSearch Contributors + * SPDX-License-Identifier: Apache-2.0 + * + * The OpenSearch Contributors require contributions made to + * this file be licensed under the Apache-2.0 license or a + * compatible open source license. + */ +package jenkins.tests + +import jenkins.tests.BuildPipelineTest +import org.junit.Before +import org.junit.Test +import static com.lesfurets.jenkins.unit.MethodCall.callArgsToString +import static org.hamcrest.CoreMatchers.hasItem +import static org.hamcrest.MatcherAssert.assertThat + +class TestCloseBuildSuccessGithubIssue extends BuildPipelineTest { + + @Override + @Before + void setUp() { + this.registerLibTester(new CloseBuildSuccessGithubIssueLibTester(['Build successful OpenSearch'])) + super.setUp() + } + + + @Test + public void testExistingGithubIssue() { + super.testPipeline('tests/jenkins/jobs/CloseBuildSuccessGithubIssue_Jenkinsfile') + assertThat(getCommands('sh', 'script'), hasItem("{script=gh issue list --repo https://github.com/opensearch-project/OpenSearch.git -S \"[AUTOCUT] Distribution Build Failed for OpenSearch-2.0.0 in:title\" --label autocut,v2.0.0 --json number --jq '.[0].number', returnStdout=true}")) + assertThat(getCommands('sh', 'script'), hasItem("{script=gh issue close bbb\nccc -R opensearch-project/OpenSearch --comment \"Closing the issue as the distribution build for OpenSearch has passed for version: **2.0.0**.\n Please see build log at www.example.com/jobs/test/123/consoleFull\", returnStdout=true}")) + } + + def getCommands(method, text) { + def shCommands = helper.callStack.findAll { call -> + call.methodName == method + }.collect { call -> + callArgsToString(call) + }.findAll { command -> + command.contains(text) + } + return shCommands + } + +} diff --git a/tests/jenkins/TestCloseGithubIssue.groovy b/tests/jenkins/TestCloseGithubIssue.groovy new file mode 100644 index 000000000..c182f2fb2 --- /dev/null +++ b/tests/jenkins/TestCloseGithubIssue.groovy @@ -0,0 +1,51 @@ +/* + * Copyright OpenSearch Contributors + * SPDX-License-Identifier: Apache-2.0 + * + * The OpenSearch Contributors require contributions made to + * this file be licensed under the Apache-2.0 license or a + * compatible open source license. + */ +package jenkins.tests + +import jenkins.tests.BuildPipelineTest +import org.junit.Before +import org.junit.Test +import static com.lesfurets.jenkins.unit.MethodCall.callArgsToString +import static org.hamcrest.CoreMatchers.hasItem +import static org.hamcrest.MatcherAssert.assertThat + +class TestCloseGithubIssue extends BuildPipelineTest { + + @Override + @Before + void setUp() { + super.setUp() + } + + + @Test + void testCloseExistingGithubIssue() { + this.registerLibTester(new CloseGithubIssueLibTester( + 'https://github.com/opensearch-project/opensearch-build', + 'Test GH issue title', + 'Test GH issue close comment', + 'label101', + )) + super.testPipeline('tests/jenkins/jobs/CloseGithubIssue_JenkinsFile') + assertThat(getCommands('sh', 'script'), hasItem("{script=gh issue list --repo https://github.com/opensearch-project/opensearch-build -S \"Test GH issue title in:title\" --label label101 --json number --jq '.[0].number', returnStdout=true}")) + assertThat(getCommands('sh', 'script'), hasItem("{script=gh issue close bbb\nccc -R opensearch-project/opensearch-build --comment \"Test GH issue close comment\", returnStdout=true}")) + } + + def getCommands(method, text) { + def shCommands = helper.callStack.findAll { call -> + call.methodName == method + }.collect { call -> + callArgsToString(call) + }.findAll { command -> + command.contains(text) + } + return shCommands + } + +} diff --git a/tests/jenkins/TestCreateBuildFailureGithubIssue.groovy b/tests/jenkins/TestCreateBuildFailureGithubIssue.groovy index fe1dfc0aa..d8023b3c8 100644 --- a/tests/jenkins/TestCreateBuildFailureGithubIssue.groovy +++ b/tests/jenkins/TestCreateBuildFailureGithubIssue.groovy @@ -34,7 +34,10 @@ class TestCreateBuildFailureGithubIssue extends BuildPipelineTest { @Test public void testExistingGithubIssue() { super.testPipeline('tests/jenkins/jobs/CreateBuildFailureGithubIssue_Jenkinsfile', 'tests/jenkins/jobs/CreateBuildFailureGithubExistingIssueCheck_Jenkinsfile') - assertThat(getCommands('println', ''), hasItem('Issue already exists in the repository, skipping.')) + assertThat(getCommands('println', ''), hasItem('Issue already exists, adding a comment.')) + assertThat(getCommands('sh', 'script'), hasItem("{script=gh issue list --repo https://github.com/opensearch-project/OpenSearch.git -S \"[AUTOCUT] Distribution Build Failed for OpenSearch-2.0.0 in:title\" --label autocut,v2.0.0, returnStdout=true}")) + assertThat(getCommands('sh', 'script'), hasItem("{script=gh issue list --repo https://github.com/opensearch-project/OpenSearch.git -S \"[AUTOCUT] Distribution Build Failed for OpenSearch-2.0.0 in:title\" --label autocut,v2.0.0 --json number --jq '.[0].number', returnStdout=true}")) + assertThat(getCommands('sh', 'script'), hasItem("{script=gh issue comment bbb\nccc --repo https://github.com/opensearch-project/OpenSearch.git --body \"***Received Error***: **Error building OpenSearch, retry with: ./build.sh manifests/2.2.0/opensearch-2.2.0.yml --component OpenSearch --snapshot**.\n The distribution build for OpenSearch has failed for version: 2.0.0.\n Please see build log at www.example.com/jobs/test/123/consoleFull\", returnStdout=true}")) } def getCommands(method, text) { diff --git a/tests/jenkins/TestCreateGithubIssue.groovy b/tests/jenkins/TestCreateGithubIssue.groovy index c271bc53a..eab71196e 100644 --- a/tests/jenkins/TestCreateGithubIssue.groovy +++ b/tests/jenkins/TestCreateGithubIssue.groovy @@ -41,11 +41,13 @@ class TestCreateGithubIssue extends BuildPipelineTest { this.registerLibTester(new CreateGithubIssueLibTester( 'https://github.com/opensearch-project/opensearch-build', 'Test GH issue title', - 'Test GH issue body' + 'Test GH issue body', )) super.testPipeline('tests/jenkins/jobs/CreateGithubIssueExisting_JenkinsFile') - assertThat(getCommands('println', ''), hasItem('Issue already exists in the repository, skipping.')) - assertThat(getCommands('sh', 'script'), hasItem('{script=gh issue list --repo https://github.com/opensearch-project/opensearch-build -S "Test GH issue title in:title" --label autocut, returnStdout=true}')) + assertThat(getCommands('println', ''), hasItem('Issue already exists, adding a comment.')) + assertThat(getCommands('sh', 'script'), hasItem("{script=gh issue list --repo https://github.com/opensearch-project/opensearch-build -S \"Test GH issue title in:title\" --label autocut, returnStdout=true}")) + assertThat(getCommands('sh', 'script'), hasItem("{script=gh issue list --repo https://github.com/opensearch-project/opensearch-build -S \"Test GH issue title in:title\" --label autocut --json number --jq '.[0].number', returnStdout=true}")) + assertThat(getCommands('sh', 'script'), hasItem("{script=gh issue comment bbb\nccc --repo https://github.com/opensearch-project/opensearch-build --body \"Test GH issue body\", returnStdout=true}")) } def getCommands(method, text) { diff --git a/tests/jenkins/jobs/BuildFailureMessage_Jenkinsfile b/tests/jenkins/jobs/BuildMessage_Jenkinsfile similarity index 92% rename from tests/jenkins/jobs/BuildFailureMessage_Jenkinsfile rename to tests/jenkins/jobs/BuildMessage_Jenkinsfile index fb5b2b8df..cd927551e 100644 --- a/tests/jenkins/jobs/BuildFailureMessage_Jenkinsfile +++ b/tests/jenkins/jobs/BuildMessage_Jenkinsfile @@ -14,7 +14,7 @@ pipeline { steps { script { try { - buildFailureMessage() + buildMessage(search: 'pass') currentBuild.result = 'SUCCESS' } catch (Exception err) { //https://github.com/jenkinsci/JenkinsPipelineUnit/issues/509 diff --git a/tests/jenkins/jobs/BuildMessage_Jenkinsfile.txt b/tests/jenkins/jobs/BuildMessage_Jenkinsfile.txt new file mode 100644 index 000000000..4a2ca6331 --- /dev/null +++ b/tests/jenkins/jobs/BuildMessage_Jenkinsfile.txt @@ -0,0 +1,6 @@ + BuildMessage_Jenkinsfile.run() + BuildMessage_Jenkinsfile.pipeline(groovy.lang.Closure) + BuildMessage_Jenkinsfile.echo(Executing on agent [label:none]) + BuildMessage_Jenkinsfile.stage(notify, groovy.lang.Closure) + BuildMessage_Jenkinsfile.script(groovy.lang.Closure) + BuildMessage_Jenkinsfile.buildMessage({search=pass}) diff --git a/tests/jenkins/jobs/CloseBuildSuccessGithubIssue_Jenkinsfile b/tests/jenkins/jobs/CloseBuildSuccessGithubIssue_Jenkinsfile new file mode 100644 index 000000000..2121c74ff --- /dev/null +++ b/tests/jenkins/jobs/CloseBuildSuccessGithubIssue_Jenkinsfile @@ -0,0 +1,24 @@ +/* + * Copyright OpenSearch Contributors + * SPDX-License-Identifier: Apache-2.0 + * + * The OpenSearch Contributors require contributions made to + * this file be licensed under the Apache-2.0 license or a + * compatible open source license. + */ + +pipeline { + agent none + stages { + stage('notify') { + steps { + script { + closeBuildSuccessGithubIssue( + message: ["Build successful OpenSearch"], + inputManifestPath: 'tests/data/opensearch-2.0.0.yml' + ) + } + } + } + } +} diff --git a/tests/jenkins/jobs/CloseBuildSuccessGithubIssue_Jenkinsfile.txt b/tests/jenkins/jobs/CloseBuildSuccessGithubIssue_Jenkinsfile.txt new file mode 100644 index 000000000..2fd7dcd83 --- /dev/null +++ b/tests/jenkins/jobs/CloseBuildSuccessGithubIssue_Jenkinsfile.txt @@ -0,0 +1,18 @@ + CloseBuildSuccessGithubIssue_Jenkinsfile.run() + CloseBuildSuccessGithubIssue_Jenkinsfile.pipeline(groovy.lang.Closure) + CloseBuildSuccessGithubIssue_Jenkinsfile.echo(Executing on agent [label:none]) + CloseBuildSuccessGithubIssue_Jenkinsfile.stage(notify, groovy.lang.Closure) + CloseBuildSuccessGithubIssue_Jenkinsfile.script(groovy.lang.Closure) + CloseBuildSuccessGithubIssue_Jenkinsfile.closeBuildSuccessGithubIssue({message=[Build successful OpenSearch], inputManifestPath=tests/data/opensearch-2.0.0.yml}) + closeBuildSuccessGithubIssue.legacySCM(groovy.lang.Closure) + closeBuildSuccessGithubIssue.library({identifier=jenkins@main, retriever=null}) + closeBuildSuccessGithubIssue.readYaml({file=tests/data/opensearch-2.0.0.yml}) + closeBuildSuccessGithubIssue.closeGithubIssue({repoUrl=https://github.com/opensearch-project/OpenSearch.git, issueTitle=[AUTOCUT] Distribution Build Failed for OpenSearch-2.0.0, closeComment=Closing the issue as the distribution build for OpenSearch has passed for version: **2.0.0**. + Please see build log at www.example.com/jobs/test/123/consoleFull, label=autocut,v2.0.0}) + closeGithubIssue.usernamePassword({credentialsId=jenkins-github-bot-token, passwordVariable=GITHUB_TOKEN, usernameVariable=GITHUB_USER}) + closeGithubIssue.withCredentials([[GITHUB_USER, GITHUB_TOKEN]], groovy.lang.Closure) + closeGithubIssue.sh({script=gh issue list --repo https://github.com/opensearch-project/OpenSearch.git -S "[AUTOCUT] Distribution Build Failed for OpenSearch-2.0.0 in:title" --label autocut,v2.0.0 --json number --jq '.[0].number', returnStdout=true}) + closeGithubIssue.sh({script=gh issue close bbb +ccc -R opensearch-project/OpenSearch --comment "Closing the issue as the distribution build for OpenSearch has passed for version: **2.0.0**. + Please see build log at www.example.com/jobs/test/123/consoleFull", returnStdout=true}) + closeBuildSuccessGithubIssue.sleep({time=3, unit=SECONDS}) diff --git a/tests/jenkins/jobs/CloseGithubIssue_JenkinsFile.txt b/tests/jenkins/jobs/CloseGithubIssue_JenkinsFile.txt new file mode 100644 index 000000000..acc8ef946 --- /dev/null +++ b/tests/jenkins/jobs/CloseGithubIssue_JenkinsFile.txt @@ -0,0 +1,11 @@ + CloseGithubIssue_JenkinsFile.run() + CloseGithubIssue_JenkinsFile.pipeline(groovy.lang.Closure) + CloseGithubIssue_JenkinsFile.echo(Executing on agent [label:none]) + CloseGithubIssue_JenkinsFile.stage(closeGithubIssue, groovy.lang.Closure) + CloseGithubIssue_JenkinsFile.script(groovy.lang.Closure) + CloseGithubIssue_JenkinsFile.closeGithubIssue({repoUrl=https://github.com/opensearch-project/opensearch-build, issueTitle=Test GH issue title, closeComment=Test GH issue close comment, label=label101}) + closeGithubIssue.usernamePassword({credentialsId=jenkins-github-bot-token, passwordVariable=GITHUB_TOKEN, usernameVariable=GITHUB_USER}) + closeGithubIssue.withCredentials([[GITHUB_USER, GITHUB_TOKEN]], groovy.lang.Closure) + closeGithubIssue.sh({script=gh issue list --repo https://github.com/opensearch-project/opensearch-build -S "Test GH issue title in:title" --label label101 --json number --jq '.[0].number', returnStdout=true}) + closeGithubIssue.sh({script=gh issue close bbb +ccc -R opensearch-project/opensearch-build --comment "Test GH issue close comment", returnStdout=true}) diff --git a/tests/jenkins/jobs/CloseGithubIssue_Jenkinsfile b/tests/jenkins/jobs/CloseGithubIssue_Jenkinsfile new file mode 100644 index 000000000..e8e313011 --- /dev/null +++ b/tests/jenkins/jobs/CloseGithubIssue_Jenkinsfile @@ -0,0 +1,26 @@ +/* + * Copyright OpenSearch Contributors + * SPDX-License-Identifier: Apache-2.0 + * + * The OpenSearch Contributors require contributions made to + * this file be licensed under the Apache-2.0 license or a + * compatible open source license. + */ + +pipeline { + agent none + stages { + stage('closeGithubIssue') { + steps { + script { + closeGithubIssue( + repoUrl: 'https://github.com/opensearch-project/opensearch-build', + issueTitle: 'Test GH issue title', + closeComment: 'Test GH issue close comment', + label: 'label101' + ) + } + } + } + } +} diff --git a/tests/jenkins/jobs/CreateBuildFailureGithubExistingIssueCheck_Jenkinsfile.txt b/tests/jenkins/jobs/CreateBuildFailureGithubExistingIssueCheck_Jenkinsfile.txt index e19c52fdd..c17ca14d4 100644 --- a/tests/jenkins/jobs/CreateBuildFailureGithubExistingIssueCheck_Jenkinsfile.txt +++ b/tests/jenkins/jobs/CreateBuildFailureGithubExistingIssueCheck_Jenkinsfile.txt @@ -13,5 +13,10 @@ createGithubIssue.usernamePassword({credentialsId=jenkins-github-bot-token, passwordVariable=GITHUB_TOKEN, usernameVariable=GITHUB_USER}) createGithubIssue.withCredentials([[GITHUB_USER, GITHUB_TOKEN]], groovy.lang.Closure) createGithubIssue.sh({script=gh issue list --repo https://github.com/opensearch-project/OpenSearch.git -S "[AUTOCUT] Distribution Build Failed for OpenSearch-2.0.0 in:title" --label autocut,v2.0.0, returnStdout=true}) - createGithubIssue.println(Issue already exists in the repository, skipping.) + createGithubIssue.println(Issue already exists, adding a comment.) + createGithubIssue.sh({script=gh issue list --repo https://github.com/opensearch-project/OpenSearch.git -S "[AUTOCUT] Distribution Build Failed for OpenSearch-2.0.0 in:title" --label autocut,v2.0.0 --json number --jq '.[0].number', returnStdout=true}) + createGithubIssue.sh({script=gh issue comment bbb +ccc --repo https://github.com/opensearch-project/OpenSearch.git --body "***Received Error***: **Error building OpenSearch, retry with: ./build.sh manifests/2.2.0/opensearch-2.2.0.yml --component OpenSearch --snapshot**. + The distribution build for OpenSearch has failed for version: 2.0.0. + Please see build log at www.example.com/jobs/test/123/consoleFull", returnStdout=true}) createBuildFailureGithubIssue.sleep({time=3, unit=SECONDS}) diff --git a/tests/jenkins/jobs/CreateGithubIssueExisting_JenkinsFile.txt b/tests/jenkins/jobs/CreateGithubIssueExisting_JenkinsFile.txt index 2589b67a6..4ca263dbe 100644 --- a/tests/jenkins/jobs/CreateGithubIssueExisting_JenkinsFile.txt +++ b/tests/jenkins/jobs/CreateGithubIssueExisting_JenkinsFile.txt @@ -7,4 +7,7 @@ createGithubIssue.usernamePassword({credentialsId=jenkins-github-bot-token, passwordVariable=GITHUB_TOKEN, usernameVariable=GITHUB_USER}) createGithubIssue.withCredentials([[GITHUB_USER, GITHUB_TOKEN]], groovy.lang.Closure) createGithubIssue.sh({script=gh issue list --repo https://github.com/opensearch-project/opensearch-build -S "Test GH issue title in:title" --label autocut, returnStdout=true}) - createGithubIssue.println(Issue already exists in the repository, skipping.) + createGithubIssue.println(Issue already exists, adding a comment.) + createGithubIssue.sh({script=gh issue list --repo https://github.com/opensearch-project/opensearch-build -S "Test GH issue title in:title" --label autocut --json number --jq '.[0].number', returnStdout=true}) + createGithubIssue.sh({script=gh issue comment bbb +ccc --repo https://github.com/opensearch-project/opensearch-build --body "Test GH issue body", returnStdout=true}) diff --git a/tests/jenkins/lib-testers/BuildFailureMessageLibTester.groovy b/tests/jenkins/lib-testers/BuildFailureMessageLibTester.groovy deleted file mode 100644 index 02a14117f..000000000 --- a/tests/jenkins/lib-testers/BuildFailureMessageLibTester.groovy +++ /dev/null @@ -1,31 +0,0 @@ -/* - * Copyright OpenSearch Contributors - * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - */ - -class BuildFailureMessageLibTester extends LibFunctionTester { - - - public BuildFailureMessageLibTester() {} - - - void parameterInvariantsAssertions(call) { - //N/A - } - - boolean expectedParametersMatcher(call) { - return true - } - - - String libFunctionName() { - return 'buildFailureMessage' - } - - void configure(helper, binding){ - } -} diff --git a/tests/jenkins/lib-testers/BuildMessageLibTester.groovy b/tests/jenkins/lib-testers/BuildMessageLibTester.groovy new file mode 100644 index 000000000..633590beb --- /dev/null +++ b/tests/jenkins/lib-testers/BuildMessageLibTester.groovy @@ -0,0 +1,36 @@ +/* + * Copyright OpenSearch Contributors + * SPDX-License-Identifier: Apache-2.0 + * + * The OpenSearch Contributors require contributions made to + * this file be licensed under the Apache-2.0 license or a + * compatible open source license. + */ +import static org.hamcrest.CoreMatchers.notNullValue +import static org.hamcrest.CoreMatchers.nullValue +import static org.hamcrest.MatcherAssert.assertThat + +class BuildMessageLibTester extends LibFunctionTester { + + private String search + + public BuildMessageLibTester(search) { + this.search = search + } + + + void parameterInvariantsAssertions(call) { + assertThat(call.args.search.first(), notNullValue()) + } + + boolean expectedParametersMatcher(call) { + return call.args.search.first().toString().equals(this.search) + } + + String libFunctionName() { + return 'buildMessage' + } + + void configure(helper, binding){ + } +} diff --git a/tests/jenkins/lib-testers/CloseBuildSuccessGithubIssueLibTester.groovy b/tests/jenkins/lib-testers/CloseBuildSuccessGithubIssueLibTester.groovy new file mode 100644 index 000000000..ce674905c --- /dev/null +++ b/tests/jenkins/lib-testers/CloseBuildSuccessGithubIssueLibTester.groovy @@ -0,0 +1,41 @@ +/* + * Copyright OpenSearch Contributors + * SPDX-License-Identifier: Apache-2.0 + * + * The OpenSearch Contributors require contributions made to + * this file be licensed under the Apache-2.0 license or a + * compatible open source license. + */ +import static org.hamcrest.CoreMatchers.notNullValue +import static org.hamcrest.CoreMatchers.nullValue +import static org.hamcrest.MatcherAssert.assertThat + +class CloseBuildSuccessGithubIssueLibTester extends LibFunctionTester{ + private List message + + public CloseBuildSuccessGithubIssueLibTester(message){ + this.message = message + } + + @Override + String libFunctionName() { + return 'closeBuildSuccessGithubIssue' + } + + @Override + void parameterInvariantsAssertions(Object call) { + assertThat(call.args.message.first(), notNullValue()) + } + + @Override + boolean expectedParametersMatcher(Object call) { + return call.args.message.first().equals(this.message) + } + + @Override + void configure(Object helper, Object binding) { + helper.registerAllowedMethod('withCredentials', [Map]) + helper.registerAllowedMethod('sleep', [Map]) + binding.setVariable('BUILD_URL', 'www.example.com/jobs/test/123/') + } +} diff --git a/tests/jenkins/lib-testers/CloseGithubIssueLibTester.groovy b/tests/jenkins/lib-testers/CloseGithubIssueLibTester.groovy new file mode 100644 index 000000000..9ef114e2c --- /dev/null +++ b/tests/jenkins/lib-testers/CloseGithubIssueLibTester.groovy @@ -0,0 +1,53 @@ +/* + * Copyright OpenSearch Contributors + * SPDX-License-Identifier: Apache-2.0 + * + * The OpenSearch Contributors require contributions made to + * this file be licensed under the Apache-2.0 license or a + * compatible open source license. + */ +import static org.hamcrest.CoreMatchers.notNullValue +import static org.hamcrest.CoreMatchers.nullValue +import static org.hamcrest.MatcherAssert.assertThat + +class CloseGithubIssueLibTester extends LibFunctionTester { + + private String repoUrl + private String issueTitle + private String closeComment + private String label + + public CloseGithubIssueLibTester(repoUrl, issueTitle, closeComment, label){ + this.repoUrl = repoUrl + this.issueTitle = issueTitle + this.closeComment = closeComment + this.label = label + } + + + @Override + String libFunctionName() { + return 'closeGithubIssue' + } + + @Override + void parameterInvariantsAssertions(Object call) { + assertThat(call.args.repoUrl.first(), notNullValue()) + assertThat(call.args.issueTitle.first(), notNullValue()) + assertThat(call.args.closeComment.first(), notNullValue()) + assertThat(call.args.label.first(), notNullValue()) + } + + @Override + boolean expectedParametersMatcher(Object call) { + return call.args.label.first().equals(this.label) + && call.args.repoUrl.first().equals(this.repoUrl) + && call.args.issueTitle.first().equals(this.issueTitle) + && call.args.closeComment.first().equals(this.closeComment) + } + + @Override + void configure(Object helper, Object binding) { + helper.registerAllowedMethod('withCredentials', [Map]) + } +} diff --git a/vars/buildFailureMessage.groovy b/vars/buildMessage.groovy similarity index 64% rename from vars/buildFailureMessage.groovy rename to vars/buildMessage.groovy index 2887f8697..2138ef906 100644 --- a/vars/buildFailureMessage.groovy +++ b/vars/buildMessage.groovy @@ -6,11 +6,20 @@ * this file be licensed under the Apache-2.0 license or a * compatible open source license. */ + /** Library to find a pattern in jenkins build log. + @param Map args = [:] args A map of the following parameters + @param args.search - Use 'pass' to get the components passed and 'fail' for components failed. + */ import com.cloudbees.groovy.cps.NonCPS import org.apache.commons.io.IOUtils @NonCPS -def call(){ - String ERROR_STRING = "Error building" +def call(Map args = [:]){ + String QUERY_STRING = '' + if (args.search == 'fail') { + QUERY_STRING = "Error building" + } else if (args.search == 'pass') { + QUERY_STRING = "Build successful" + } List message = [] Reader performance_log = currentBuild.getRawBuild().getLogReader() String logContent = IOUtils.toString(performance_log) @@ -19,7 +28,7 @@ def call(){ logContent.eachLine() { line -> line=line.replace("\"", "") //Gets the exact match for Error building - def java.util.regex.Matcher match = (line =~ /$ERROR_STRING.*/) + def java.util.regex.Matcher match = (line =~ /$QUERY_STRING.*/) if (match.find()) { line=match[0] message.add(line) diff --git a/vars/closeBuildSuccessGithubIssue.groovy b/vars/closeBuildSuccessGithubIssue.groovy new file mode 100644 index 000000000..228f04811 --- /dev/null +++ b/vars/closeBuildSuccessGithubIssue.groovy @@ -0,0 +1,42 @@ +/* + * Copyright OpenSearch Contributors + * SPDX-License-Identifier: Apache-2.0 + * + * The OpenSearch Contributors require contributions made to + * this file be licensed under the Apache-2.0 license or a + * compatible open source license. + */ + /** Library to close GitHub issue across opensearch-project repositories. + @param Map args = [:] args A map of the following parameters + @param args.message - message retrieved from buildMessage() method. + @param args.inputManifestPath - Path to input manifest. + */ +void call(Map args = [:]) { + lib = library(identifier: 'jenkins@main', retriever: legacySCM(scm)) + def passMessages = args.message + List passedComponents = [] + for (message in passMessages.unique()) { + java.util.regex.Matcher match = (message =~ /(?<=\bBuild successful\s).*/) + String matched = match[0] + println(matched.split(" ")[0].trim()) + passedComponents.add(matched.split(" ")[0].trim()) + } + + def yamlFile = readYaml(file: args.inputManifestPath) + def currentVersion = yamlFile.build.version + + for (component in yamlFile.components) { + if (passedComponents.contains(component.name)) { + println("Component ${component.name} passed, closing github issue") + ghIssueBody = """Closing the issue as the distribution build for ${component.name} has passed for version: **${currentVersion}**. + Please see build log at ${BUILD_URL}consoleFull""".stripIndent() + closeGithubIssue( + repoUrl: component.repository, + issueTitle: "[AUTOCUT] Distribution Build Failed for ${component.name}-${currentVersion}", + closeComment: ghIssueBody, + label: "autocut,v${currentVersion}" + ) + sleep(time:3, unit:'SECONDS') + } + } +} diff --git a/vars/closeGithubIssue.groovy b/vars/closeGithubIssue.groovy new file mode 100644 index 000000000..907bbe55e --- /dev/null +++ b/vars/closeGithubIssue.groovy @@ -0,0 +1,38 @@ +/* + * Copyright OpenSearch Contributors + * SPDX-License-Identifier: Apache-2.0 + * + * The OpenSearch Contributors require contributions made to + * this file be licensed under the Apache-2.0 license or a + * compatible open source license. + */ + +/** Library to close GitHub issue across opensearch-project repositories. + @param Map args = [:] args A map of the following parameters + @param args.repoUrl - GitHub repository URL to create issue + @param args.issueTitle - GitHub issue title + @param args.closeComment - GitHub issue leave a closing comment + @param args.label - GitHub issue label to be attached along with 'untriaged'. Defaults to autocut. + */ +void call(Map args = [:]) { + label = args.label ?: 'autocut' + try { + withCredentials([usernamePassword(credentialsId: 'jenkins-github-bot-token', passwordVariable: 'GITHUB_TOKEN', usernameVariable: 'GITHUB_USER')]) { + def issuesNumber = sh( + script: "gh issue list --repo ${args.repoUrl} -S \"${args.issueTitle} in:title\" --label ${label} --json number --jq '.[0].number'", + returnStdout: true + ).trim() + if (!issuesNumber.isEmpty()) { + def repoPath = args.repoUrl.replaceFirst("https://github.com/", "").replaceAll("\\.git\$", "") + sh( + script: "gh issue close ${issuesNumber} -R ${repoPath} --comment \"${args.closeComment}\"", + returnStdout: true + ) + } else { + println("No open distribution failure AUTOCUT issues to close for the repo ${args.repoUrl}") + } + } + } catch (Exception ex) { + error("Unable to close GitHub issue for ${args.repoUrl}", ex.getMessage()) + } +} \ No newline at end of file diff --git a/vars/createGithubIssue.groovy b/vars/createGithubIssue.groovy index 2134c357d..ccece247b 100644 --- a/vars/createGithubIssue.groovy +++ b/vars/createGithubIssue.groovy @@ -22,9 +22,16 @@ void call(Map args = [:]) { script: "gh issue list --repo ${args.repoUrl} -S \"${args.issueTitle} in:title\" --label ${label}", returnStdout: true ) - if (issues) { - println('Issue already exists in the repository, skipping.') + println('Issue already exists, adding a comment.') + def issuesNumber = sh( + script: "gh issue list --repo ${args.repoUrl} -S \"${args.issueTitle} in:title\" --label ${label} --json number --jq '.[0].number'", + returnStdout: true + ).trim() + sh( + script: "gh issue comment ${issuesNumber} --repo ${args.repoUrl} --body \"${args.issueBody}\"", + returnStdout: true + ) } else { sh(