Skip to content

Commit

Permalink
Create github issue on distribution build job failure (#2448)
Browse files Browse the repository at this point in the history
Signed-off-by: Rishabh Singh <[email protected]>

Signed-off-by: Rishabh Singh <[email protected]>
  • Loading branch information
rishabh6788 authored Aug 16, 2022
1 parent 6c7af95 commit 0720e05
Show file tree
Hide file tree
Showing 8 changed files with 210 additions and 9 deletions.
28 changes: 19 additions & 9 deletions jenkins/opensearch/distribution-build.jenkinsfile
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,11 @@ pipeline {
description: 'Publish the status of this build job or not.',
defaultValue: true
)
booleanParam(
name: 'CREATE_GITHUB_ISSUE',
description: 'To create a github issue for failing component or not.',
defaultValue: true
)
}
stages {
stage('detect docker image + args') {
Expand Down Expand Up @@ -265,7 +270,7 @@ pipeline {
}
}
post {
always {
always {
script {
lib.jenkins.Messages.new(this).add(
"${STAGE_NAME}",
Expand Down Expand Up @@ -443,7 +448,7 @@ pipeline {
script {
lib.jenkins.Messages.new(this).add(
"${STAGE_NAME}",
lib.jenkins.Messages.new(this).get(["${STAGE_NAME}"]) +
lib.jenkins.Messages.new(this).get(["${STAGE_NAME}"]) +
"\n${env.ARTIFACT_URL_ARM64_TAR_INTEG_TEST_RESULT}" +
"\n${env.ARTIFACT_URL_ARM64_TAR_BWC_TEST_RESULT}"
)
Expand Down Expand Up @@ -538,7 +543,7 @@ pipeline {

postCleanup()
}
}
}
}
}
}
Expand All @@ -565,7 +570,7 @@ pipeline {
stage('docker build') {
when {
beforeAgent true
expression {
expression {
params.BUILD_DOCKER != 'do_not_build_docker'
}
}
Expand All @@ -581,7 +586,7 @@ pipeline {
script {
echo "env.ARTIFACT_URL_X64_TAR: ${env.ARTIFACT_URL_X64_TAR}"
echo "env.ARTIFACT_URL_ARM64_TAR: ${env.ARTIFACT_URL_ARM64_TAR}"

buildDockerImage(
inputManifest: "manifests/${INPUT_MANIFEST}",
buildNumber: "${BUILD_NUMBER}",
Expand All @@ -597,11 +602,11 @@ pipeline {
success {
node(AGENT_X64) {
script {
if (params.PUBLISH_NOTIFICATION) {
if (params.PUBLISH_NOTIFICATION) {
def stashed = lib.jenkins.Messages.new(this).get([
'build-and-test-x64-tar',
'build-and-test-x64-tar',
'assemble-archive-and-test-linux-x64-rpm',
'build-and-test-arm64-tar',
'build-and-test-arm64-tar',
'assemble-archive-and-test-linux-arm64-rpm'
])

Expand All @@ -621,14 +626,19 @@ pipeline {
failure {
node(AGENT_X64) {
script {
if (params.PUBLISH_NOTIFICATION) {
if (params.PUBLISH_NOTIFICATION) {
publishNotification(
icon: ':warning:',
message: buildFailureMessage(),
credentialsId: 'jenkins-build-notice-webhook',
manifest: "${INPUT_MANIFEST}"
)
}
if (params.CREATE_GITHUB_ISSUE) {
createGithubIssue(
message: buildFailureMessage()
)
}

postCleanup()
}
Expand Down
25 changes: 25 additions & 0 deletions tests/jenkins/TestCreateGithubIssue.groovy
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
package jenkins.tests

import jenkins.tests.BuildPipelineTest
import org.junit.*

class TestCreateGithubIssue extends BuildPipelineTest {
@Override
@Before
void setUp() {
this.registerLibTester(new CreateGithubIssueLibTester(["Error building OpenSearch, retry with: ./build.sh manifests/2.2.0/opensearch-2.2.0.yml --component OpenSearch --snapshot"]))
super.setUp()
}

@Test
public void testCreateGithubIssue() {
helper.addShMock("gh issue list --repo https://github.com/opensearch-project/OpenSearch.git -S \"[AUTOCUT] OS Distribution Build Failed for OpenSearch-2.0.0 in:title\" --label autocut",'',0)
super.testPipeline("tests/jenkins/jobs/CreateGithubIssue_Jenkinsfile")
}

@Test
public void testExistingGithubIssue() {
super.testPipeline("tests/jenkins/jobs/CreateGithubIssueExisting_Jenkinsfile")
}

}
18 changes: 18 additions & 0 deletions tests/jenkins/jobs/CreateGithubIssueExisting_Jenkinsfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
pipeline {
agent none
stages {
stage('notify') {
steps {
script {
try {
createGithubIssue(
message: ["Error building OpenSearch, retry with: ./build.sh manifests/2.2.0/opensearch-2.2.0.yml --component OpenSearch --snapshot"]
)
}catch (Exception e) {
echo 'Exception occurred: ' + e.toString()
}
}
}
}
}
}
13 changes: 13 additions & 0 deletions tests/jenkins/jobs/CreateGithubIssueExisting_Jenkinsfile.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
CreateGithubIssueExisting_Jenkinsfile.run()
CreateGithubIssueExisting_Jenkinsfile.pipeline(groovy.lang.Closure)
CreateGithubIssueExisting_Jenkinsfile.echo(Executing on agent [label:none])
CreateGithubIssueExisting_Jenkinsfile.stage(notify, groovy.lang.Closure)
CreateGithubIssueExisting_Jenkinsfile.script(groovy.lang.Closure)
CreateGithubIssueExisting_Jenkinsfile.createGithubIssue({message=[Error building OpenSearch, retry with: ./build.sh manifests/2.2.0/opensearch-2.2.0.yml --component OpenSearch --snapshot]})
createGithubIssue.readYaml({file=manifests/2.0.0/opensearch-2.0.0.yml})
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] OS Distribution Build Failed for OpenSearch-2.0.0 in:title" --label autocut, returnStdout=true})
createGithubIssue.sh({script=gh label list --repo https://github.com/opensearch-project/OpenSearch.git -S v2.0.0, returnStdout=true})
createGithubIssue.println(Issue already exists in the repository, skipping.)
createGithubIssue.sleep({time=3, unit=SECONDS})
18 changes: 18 additions & 0 deletions tests/jenkins/jobs/CreateGithubIssue_Jenkinsfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
pipeline {
agent none
stages {
stage('notify') {
steps {
script {
try {
createGithubIssue(
message: ["Error building OpenSearch, retry with: ./build.sh manifests/2.2.0/opensearch-2.2.0.yml --component OpenSearch --snapshot"]
)
}catch (Exception e) {
echo 'Exception occurred: ' + e.toString()
}
}
}
}
}
}
15 changes: 15 additions & 0 deletions tests/jenkins/jobs/CreateGithubIssue_Jenkinsfile.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
CreateGithubIssue_Jenkinsfile.run()
CreateGithubIssue_Jenkinsfile.pipeline(groovy.lang.Closure)
CreateGithubIssue_Jenkinsfile.echo(Executing on agent [label:none])
CreateGithubIssue_Jenkinsfile.stage(notify, groovy.lang.Closure)
CreateGithubIssue_Jenkinsfile.script(groovy.lang.Closure)
CreateGithubIssue_Jenkinsfile.createGithubIssue({message=[Error building OpenSearch, retry with: ./build.sh manifests/2.2.0/opensearch-2.2.0.yml --component OpenSearch --snapshot]})
createGithubIssue.readYaml({file=manifests/2.0.0/opensearch-2.0.0.yml})
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] OS Distribution Build Failed for OpenSearch-2.0.0 in:title" --label autocut, returnStdout=true})
createGithubIssue.sh({script=gh label list --repo https://github.com/opensearch-project/OpenSearch.git -S v2.0.0, returnStdout=true})
createGithubIssue.sh({script=gh issue create --title "[AUTOCUT] OS Distribution Build Failed for OpenSearch-2.0.0" --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.
Please see build log at www.example.com/jobs/test/123/consoleFull" --label "autocut,v2.0.0" --repo https://github.com/opensearch-project/OpenSearch.git, returnStdout=true})
createGithubIssue.sleep({time=3, unit=SECONDS})
35 changes: 35 additions & 0 deletions tests/jenkins/lib-testers/CreateGithubIssueLibTester.groovy
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
import static org.hamcrest.CoreMatchers.notNullValue
import static org.hamcrest.CoreMatchers.nullValue
import static org.hamcrest.MatcherAssert.assertThat

class CreateGithubIssueLibTester extends LibFunctionTester{
private List<String> message

public CreateGithubIssueLibTester(message){
this.message = message
}

@Override
String libFunctionName() {
return 'createGithubIssue'
}

@Override
void parameterInvariantsAssertions(Object call) {
assertThat(call.args.message.first(), notNullValue())
}

@Override
boolean expectedParametersMatcher(Object call) {
//return false
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/')
binding.setVariable('INPUT_MANIFEST', '2.0.0/opensearch-2.0.0.yml')
}
}
67 changes: 67 additions & 0 deletions vars/createGithubIssue.groovy
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
def call(Map args = [:]){
def failureMessages = args.message
List<String> failedComponents = []

if (failureMessages.size() == 1 && failureMessages[0] == "Build failed") {
println("No component failed, skip creating github issue.")
}
else {
for(message in failureMessages.unique()){
java.util.regex.Matcher match = (message =~ /(?<=\bcomponent\s).*/)
String matched = match[0]
println(matched.split(" ")[0].trim())
failedComponents.add(matched.split(" ")[0].trim())
}

def yamlFile = readYaml(file: "manifests/${INPUT_MANIFEST}")
def currentVersion = yamlFile.build.version

for(component in yamlFile.components){
if (failedComponents.contains(component.name)) {
println("Component ${component.name} failed, creating github issue")
compIndex = failedComponents.indexOf(component.name)
create_issue(component.name, component.repository, currentVersion, failureMessages[compIndex])
sleep(time:3,unit:"SECONDS")
}
}
}
}

def create_issue(component, url, currentVersion, failedMessage){
def versionLabel = "v${currentVersion}"
def label = "autocut"

def message = """***Received Error***: **${failedMessage}**.
The distribution build for ${component} has failed.
Please see build log at ${BUILD_URL}consoleFull""".stripIndent()


try {
withCredentials([usernamePassword(credentialsId: 'jenkins-github-bot-token', passwordVariable: 'GITHUB_TOKEN', usernameVariable: 'GITHUB_USER')]) {
def issues = sh (
script: "gh issue list --repo ${url} -S \"[AUTOCUT] OS Distribution Build Failed for ${component}-${currentVersion} in:title\" --label ${label}",
returnStdout: true
)

def hasLabel = sh (
script: "gh label list --repo ${url} -S ${versionLabel}",
returnStdout: true
)

if (hasLabel){
label = "\"autocut,${versionLabel}\""
}

if (issues){
println("Issue already exists in the repository, skipping.")
} else {
sh (
script: "gh issue create --title \"[AUTOCUT] OS Distribution Build Failed for ${component}-${currentVersion}\" --body \"${message}\" --label ${label} --repo ${url}",
returnStdout: true
)
}
}
} catch (Exception ex) {
println(ex.getMessage())
}
}

0 comments on commit 0720e05

Please sign in to comment.