Skip to content

Commit 306bf3c

Browse files
author
Jared Murrell
authored
Merge pull request #178 from github/primetheus/jenkins-samples
Jenkins pipeline samples
2 parents f1dfba6 + 4c31398 commit 306bf3c

File tree

4 files changed

+1074
-0
lines changed

4 files changed

+1074
-0
lines changed
Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
node {
2+
properties([
3+
[$class: 'BuildDiscarderProperty',
4+
strategy: [$class: 'LogRotator',
5+
artifactDaysToKeepStr: '',
6+
artifactNumToKeepStr: '',
7+
daysToKeepStr: '',
8+
numToKeepStr: '5']
9+
]
10+
])
11+
stage('Validate JIRA Issue') {
12+
//echo sh(returnStdout: true, script: 'env')
13+
// Get the issue number from the PR Title
14+
def prTitleJira = sh(
15+
script: "echo \${GITHUB_PR_TITLE}|awk {'print \$1'}",
16+
returnStdout: true)
17+
18+
// Get the issue number from the PR Body
19+
def prBodyJira = sh(
20+
script: "echo \${GITHUB_PR_BODY}|awk {'print \$1'}",
21+
returnStdout: true)
22+
23+
// Convert the discovered issue to a string
24+
def prIssue = prBodyJira.trim()
25+
26+
// Validate that the issue exists in JIRA
27+
def issue = jiraGetIssue (
28+
site: "JIRA",
29+
idOrKey: "${prIssue}")
30+
31+
// Validate the state of the ticket in JIRA
32+
def transitions = jiraGetIssueTransitions (
33+
site: "JIRA",
34+
idOrKey: "${prIssue}")
35+
36+
// Create a variable from the issue state
37+
def statusId = issue.data.fields.status.statusCategory.id.toString()
38+
def statusName = issue.data.fields.status.statusCategory.name.toString()
39+
40+
// Validate that it's in the state that we want... in this case, 4 = 'In Progress'
41+
if (statusId == '4') {
42+
setGitHubPullRequestStatus (
43+
context: "",
44+
message: "${prIssue} is in the correct status",
45+
state: "SUCCESS")
46+
} else {
47+
setGitHubPullRequestStatus (
48+
context: "",
49+
message: "${prIssue} is not properly prepared in JIRA. Please place it in the current sprint and begin working on it",
50+
state: "FAILURE")
51+
}
52+
}
53+
}
Lines changed: 108 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,108 @@
1+
## Jira issue validator
2+
In order to use this pipeline, you will need the following plugins:
3+
4+
- [Pipeline](https://plugins.jenkins.io/workflow-aggregator): This plugin allows us to store our `Jenkins` _jobs_ as code, and moves away from the common understanding of Jenkins `builds` to an `Agile` and `DevOps` model
5+
- [Pipeline: Declarative](https://plugins.jenkins.io/pipeline-model-definition): Provides the ability to write _declarative pipelines_ and add `Parallel Steps`, `Wait Conditions` and more
6+
- [Pipeline: Basic Steps](https://plugins.jenkins.io/workflow-basic-steps): Provides many of the most commonly used classes and functions used in _Pipelines_
7+
- [Pipeline: Job](https://plugins.jenkins.io/workflow-job): Allows us to define `Triggers` within our _Pipeline_
8+
- [Pipeline: Utility Steps](https://plugins.jenkins.io/pipeline-utility-steps): Provides us with the ability to read config files, zip archives and files on the filesystem
9+
- [GitHub Integration](https://plugins.jenkins.io/github-pullrequest): Provides the ability to customize pull request builds
10+
- [Pipeline: GitHub](https://plugins.jenkins.io/pipeline-github): Allows using GitHub steps within a _Jenkinsfile_
11+
- [GitHub](https://plugins.jenkins.io/github): Provides integration with GitHub
12+
- [Jira Pipeline Steps](https://plugins.jenkins.io/jira-steps): Allows using Jira steps within a _Jenkinsfile_
13+
- [Jira](https://plugins.jenkins.io/jira): Enables integration with Jira
14+
15+
### Configuring Jenkins
16+
17+
1. Log in to Jenkins and click _Manage Jenkins_
18+
2. Click _Configure System_
19+
3. In the **Jira Steps** section, provide the required information for connecting to your Jira server
20+
![jenkins-setup-jira](https://user-images.githubusercontent.com/865381/39254110-587316e2-4877-11e8-93f0-9050a7144ea2.png)
21+
4. In the **GitHub Pull Request Builder** section, fill out the connection information
22+
![jenkins-config-gh-pull-1](https://user-images.githubusercontent.com/865381/39254113-5d8fde58-4877-11e8-81f5-fb037ae06266.png)
23+
![jenkins-setup-gh-pull-2](https://user-images.githubusercontent.com/865381/39254114-5dacc112-4877-11e8-9a0b-f1a8643de7c0.png)
24+
25+
### Creating the pipeline
26+
1. Log in to Jenkins and click _New Item_
27+
2. Give it a name and select _Pipeline_ as the type
28+
![jira-github-validation](https://user-images.githubusercontent.com/865381/37780888-0e1d3c88-2dc6-11e8-8cd8-4b3efc55a1f1.png)
29+
3. Check the box to enable _GitHub Project_ and provide the URL for the repository
30+
![jenkins-github-pr-validation](https://user-images.githubusercontent.com/865381/37780961-31ee22bc-2dc6-11e8-88a3-9bec66621840.png)
31+
4. Check the box to trigger on _GitHub Pull Requests_
32+
4a. Choose _Hooks with Persisted Data_ as the **Trigger Mode*
33+
4b. Check the box to _Set status before build_
34+
4c. Add _Commit changed_ and _Pull Request Opened_ as the **Trigger Events**
35+
![jenkins-github-integration-pr-trigger](https://user-images.githubusercontent.com/865381/37780979-38469c84-2dc6-11e8-98b2-19c06b77fcf4.png)
36+
37+
38+
### Example pipeline
39+
This pipeline functions by taking the _issue ID_ from the pull request body, performing a lookup in Jira, then setting the status of the build in GitHub based on the _transition_ in Jira.
40+
41+
```groovy
42+
node {
43+
properties([
44+
[$class: 'BuildDiscarderProperty',
45+
strategy: [$class: 'LogRotator',
46+
artifactDaysToKeepStr: '',
47+
artifactNumToKeepStr: '',
48+
daysToKeepStr: '',
49+
numToKeepStr: '5']
50+
]
51+
])
52+
stage('Validate JIRA Issue') {
53+
//echo sh(returnStdout: true, script: 'env')
54+
// Get the issue number from the PR Title
55+
def prTitleJira = sh(
56+
script: "echo \${GITHUB_PR_TITLE}|awk {'print \$1'}",
57+
returnStdout: true)
58+
59+
// Get the issue number from the PR Body
60+
def prBodyJira = sh(
61+
script: "echo \${GITHUB_PR_BODY}|awk {'print \$1'}",
62+
returnStdout: true)
63+
64+
// Convert the discovered issue to a string
65+
def prIssue = prBodyJira.trim()
66+
67+
// Validate that the issue exists in JIRA
68+
def issue = jiraGetIssue (
69+
site: "JIRA",
70+
idOrKey: "${prIssue}")
71+
72+
// Validate the state of the ticket in JIRA
73+
def transitions = jiraGetIssueTransitions (
74+
site: "JIRA",
75+
idOrKey: "${prIssue}")
76+
77+
// Create a variable from the issue state
78+
def statusId = issue.data.fields.status.statusCategory.id.toString()
79+
def statusName = issue.data.fields.status.statusCategory.name.toString()
80+
81+
// Validate that it's in the state that we want
82+
if (statusId == '4') {
83+
setGitHubPullRequestStatus (
84+
context: "",
85+
message: "${prIssue} is in the correct status",
86+
state: "SUCCESS")
87+
} else {
88+
setGitHubPullRequestStatus (
89+
context: "",
90+
message: "${prIssue} is not properly prepared in JIRA. Please place it in the current sprint and begin working on it",
91+
state: "FAILURE")
92+
}
93+
}
94+
}
95+
```
96+
97+
### Visual status
98+
1. Create a new file with a commit message. The Jira plugin will automatically comment on the ticket if you use the `JIRA-[number] #comment <comment>` format
99+
![jenkins-jira-commit](https://user-images.githubusercontent.com/865381/37779241-544b8bc8-2dc2-11e8-8dd6-aaca12556ed0.png)
100+
101+
2. Create a new pull request, and be sure that `JIRA-[number]` is the first word in the _body_
102+
![jenkins-jira-pr-body](https://user-images.githubusercontent.com/865381/37779286-7056832c-2dc2-11e8-9cfb-82a931d40ca0.png)
103+
104+
#### Ticket is not _In Progress_
105+
![jenkins-jira-pr-check-fail](https://user-images.githubusercontent.com/865381/37779349-9480bfd8-2dc2-11e8-895a-38088692f071.png)
106+
107+
#### Ticket is _In Progress_
108+
![jenkins-jira-validator-pass](https://user-images.githubusercontent.com/865381/37779337-8f198138-2dc2-11e8-915f-a28130bc02ba.png)
Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
node {
2+
properties([
3+
[$class: 'BuildDiscarderProperty',
4+
strategy: [$class: 'LogRotator',
5+
artifactDaysToKeepStr: '',
6+
artifactNumToKeepStr: '',
7+
daysToKeepStr: '',
8+
numToKeepStr: '5']
9+
],
10+
pipelineTriggers([
11+
[$class: 'GenericTrigger',
12+
genericVariables: [
13+
[expressionType: 'JSONPath', key: 'repository', value: '$.repository'],
14+
[expressionType: 'JSONPath', key: 'organization', value: '$.organization'],
15+
[expressionType: 'JSONPath', key: 'sender', value: '$.sender'],
16+
[expressionType: 'JSONPath', key: 'ref_type', value: '$.ref_type'],
17+
[expressionType: 'JSONPath', key: 'master_branch', value: '$.master_branch'],
18+
[expressionType: 'JSONPath', key: 'branch_name', value: 'ref']
19+
],
20+
regexpFilterText: '',
21+
regexpFilterExpression: ''
22+
]
23+
])
24+
])
25+
// Define the payload to send to GitHub.
26+
// This is JSON
27+
def githubPayload = """{
28+
"required_status_checks": {
29+
"strict": true,
30+
"contexts": [
31+
"continuous-integration/jenkins/branch"
32+
]
33+
},
34+
"enforce_admins": true,
35+
"required_pull_request_reviews": {
36+
"dismissal_restrictions": {
37+
"users": [
38+
"hollywood",
39+
"primetheus"
40+
],
41+
"teams": [
42+
"test-team"
43+
]
44+
},
45+
"dismiss_stale_reviews": true,
46+
"require_code_owner_reviews": true
47+
},
48+
"restrictions": {
49+
"users": [
50+
"hollywood",
51+
"primetheus"
52+
],
53+
"teams": [
54+
"test-team"
55+
]
56+
}
57+
}"""
58+
59+
stage("Protect Master Branch") {
60+
if(env.branch_name && "${branch_name}" == "${master_branch}") {
61+
// The credentialsId should match yours, not this demonstration
62+
withCredentials([string(credentialsId: '1cf07897-ad01-4e59-9075-617ea40cf111', variable: 'githubToken')]) {
63+
httpRequest(
64+
contentType: 'APPLICATION_JSON',
65+
consoleLogResponseBody: true,
66+
customHeaders: [
67+
[maskValue: true, name: 'Authorization', value: "token ${githubToken}"],
68+
[name: 'Accept', value: 'application/vnd.github.loki-preview']],
69+
httpMode: 'PUT',
70+
ignoreSslErrors: true,
71+
requestBody: githubPayload,
72+
responseHandle: 'NONE',
73+
url: "${repository_url}/branches/${repository_default_branch}/protection")
74+
}
75+
} else {
76+
sh(name: "Skip", script: 'echo "Move along, nothing to see here"')
77+
}
78+
}
79+
}

0 commit comments

Comments
 (0)