- Pipeline: GitHub
- License
- Prerequisites
- Credentials
- Triggers
- Global Variables
- Auxiliary Classes
- Examples
The entry points for this plugin’s functionality are additional global variables, available to pipeline scripts when the plugin is enabled and the prerequisites are met.
MIT
-
Jenkins running Java 8 or higher.
-
Projects/jobs must be automatically created by the GitHub Organization folder/project type.
See: GitHub Branch Source Plugin
Currently all operations against GitHub will be performed using the builds GitHubSCMSource
credentials. These will typically be the Scan Credentials
you configured in your GitHub Organization.
However you can override this in a pipeline script by calling setCredentials(String userName, String password)
before any properties or methods are accessed/invoked on the pullRequest
global variable.
pullRequest.setCredentials('John.Smith', 'qwerty4321')
If you plan to use this plugin to add/modify/remove comments, labels, commit statuses etc. Please ensure that the required permissions are assigned to the token supplied in the credentials (Scan Credentials
or Manually
supplied).
This plugin adds the following pipeline triggers
- This trigger only works on Pull Requests, created by the GitHub Branch Source Plugin.
- Currently this trigger will only allow collaborators of the repository in question to trigger builds.
The Pull Request's job/build must have run at least once for the trigger to be registered. If an initial run never takes place then the trigger won't be registered and cannot pickup on any comments made.
This should not be an issue in practice, because a requirement of using this plugin is that your jobs are setup automatically by the GitHub Branch Source Plugin, which will trigger an initial build when it is notified of a new Pull Request.
This trigger would be of limited usefulness for people wishing to build public GitHub/Jenkins bots, using pipeline scripts. As there is no way to ensure that a Pull Request's Jenkinsfile
contains any triggers. Not to mention you would not want to trust just any Jenkinsfile
from a random Pull Request/non-collaborator.
This trigger is intended to be used inside enterprise organizations:
- Where all branches and forks just contain a token
Jenkinsfile
that delegates to the real pipeline script, using shared libraries. - Trust all their Pull Request authors.
commentPattern
(Required) - A Java style regular expression
properties([
pipelineTriggers([
issueCommentTrigger('.*test this please.*')
])
])
pipeline {
triggers {
issueCommentTrigger('.*test this please.*')
}
}
def triggerCause = currentBuild.rawBuild.getCause(
org.jenkinsci.plugins.pipeline.github.trigger.IssueCommentCause
)
if (triggerCause) {
echo("Build was started by ${triggerCause.userLogin}, who wrote: " +
"\"${triggerCause.comment}\", which matches the " +
"\"${triggerCause.triggerPattern}\" trigger pattern.")
} else {
echo('Build was not started by a trigger')
}
Coming soon!
Before you can use the pullRequest
global variable you must ensure you are actually in a Pull Request build job. The best way to do this is to check for the existence of the CHANGE_ID
environment variable.
node {
stage('Build') {
try {
echo 'Hello World'
} catch (err) {
// CHANGE_ID is set only for pull requests, so it is safe to access the pullRequest global variable
if (env.CHANGE_ID) {
pullRequest.addLabel('Build Failed')
}
throw err
}
}
}
pipeline {
agent any
stages {
stage('Build') {
steps {
echo 'Hello World'
}
}
}
post {
failure {
script {
// CHANGE_ID is set only for pull requests, so it is safe to access the pullRequest global variable
if (env.CHANGE_ID) {
pullRequest.addLabel('Build Failed')
}
}
}
}
}
Name | Type | Setter | Description |
---|---|---|---|
id | Integer |
false | |
state | String |
true | Valid values open or closed |
number | Integer |
false | |
url | String |
false | |
patchUrl | String |
false | |
diffUrl | String |
false | |
issueUrl | String |
false | |
title | String |
true | |
body | String |
true | |
locked | Boolean |
true | Accepts true , false or 'true' , 'false' |
milestone | Integer |
true | |
head | String |
false | Revision (SHA) of the head commit of this pull request |
headRef | String |
false | Name of the branch this pull request is created for |
base | String |
true | Name of the base branch in the current repository this pull request targets |
files | Iterable<CommitFile> |
false | |
assignees | List<String> |
true | Accepts a List<String> |
commits | Iterable<Commit> |
false | |
comments | Iterable<IssueComment> |
false | |
reviewComments | Iterable<ReviewComment> |
false | |
labels | Iterable<String> |
true | Accepts a List<String> |
statuses | List<CommitStatus> |
false | |
requestedReviewers | Iterable<String> |
false | |
updatedAt | Date |
false | |
createdAt | Date |
false | |
createdBy | String |
false | |
closedAt | Date |
false | |
closedBy | String |
false | |
mergedAt | Date |
false | |
mergedBy | String |
false | |
commitCount | Integer |
false | |
commentCount | Integer |
false | |
additions | Integer |
false | |
deletions | Integer |
false | |
changedFiles | Integer |
false | |
merged | Boolean |
false | |
mergeable | Boolean |
false | |
mergeCommitSha | String |
false | |
maintainerCanModify | Boolean |
true | Accepts true , false or 'true' , 'false' |
String merge([String commitTitle, String commitMessage, String sha, String mergeMethod])
Returns the merge's SHA/commit id.
CommitStatus createStatus(String status [, String context, String description, String targetUrl])
void addLabels(List labels)
void removeLabel(String label)
void addAssignees(List assignees)
void removeAssignees(List assignees)
ReviewComment reviewComment(String commitId, String path, int position, String body)
ReviewComment editReviewComment(long commentId, String body)
ReviewComment replyToReviewComment(long commentId, String body)
void deleteReviewComment(long commentId)
IssueComment comment(String body)
IssueComment editComment(long commentId, String body)
void deleteComment(long commentId)
void createReviewRequests(List reviewers)
void deleteReviewRequests(List reviewers)
void setCredentials(String userName, String password)
Name | Type | Setter | Description |
---|---|---|---|
id | String |
false | |
url | String |
false | |
status | String |
false | One of pending , success , failure or error |
context | String |
false | |
description | String |
false | |
targetUrl | String |
false | |
createdAt | Date |
false | |
updatedAt | Date |
false | |
creator | String |
false |
None.
Name | Type | Setter | Description |
---|---|---|---|
sha | String |
false | |
url | String |
false | |
author | String |
false | |
committer | String |
false | |
parents | List<String> |
false | List of parent commit SHA's |
message | String |
false | |
commentCount | Integer |
false | |
comments | Iterable<ReviewComment> |
false | |
additions | Integer |
false | |
deletions | Integer |
false | |
totalChanges | Integer |
false | |
files | List<CommitFile> |
false | List of files added, removed and or modified in this commit |
statuses | List<CommitStatus> |
false | List of statuses associated with this commit |
CommitStatus createStatus(String status [, String context, String description, String targetUrl])
ReviewComment comment(String body [, String path, Integer position])
Name | Type | Setter | Description |
---|---|---|---|
sha | String |
false | |
filename | String |
false | |
status | String |
false | One of |
patch | String |
false | |
additions | Integer |
false | |
deletions | Integer |
false | |
changes | Integer |
false | |
rawUrl | String |
false | |
blobUrl | String |
false |
None.
Name | Type | Setter | Description |
---|---|---|---|
id | Integer |
false | |
url | String |
false | |
user | String |
false | |
body | String |
true | |
createdAt | Date |
false | |
updatedAt | Date |
false |
void delete()
Name | Type | Setter | Description |
---|---|---|---|
id | Integer |
false | |
url | String |
false | |
user | String |
false | |
createdAt | Date |
false | |
updatedAt | Date |
false | |
commitId | String |
false | |
originalCommitId | Integer |
false | |
body | String |
true | |
path | String |
false | |
line | Integer |
false | |
position | Integer |
false | |
originalPosition | Integer |
false | |
diffHunk | String |
false |
void delete()
pullRequest.title = 'Updated title'
pullRequest.body = pullRequest.body + '\nEdited by Pipeline'
pullRequest.status = 'closed'
pullRequest.createStatus(status: 'success',
context: 'continuous-integration/jenkins/pr-merge/tests',
description: 'All tests are passing',
targetUrl: "${JOB_URL}/testResults")
if (pullRequest.locked) {
pullRequest.locked = false
}
if (pullRequest.mergeable) {
pullRequest.merge('merge commit message here')
}
// or
if (pullRequest.mergeable) {
pullRequest.merge(commitTile: 'Make it so..', commitMessage: 'TO BOLDLY GO WHERE NO MAN HAS GONE BEFORE...', mergeMethod: 'squash')
}
pullRequest.addLabel('Build Passing')
pullRequest.removeLabel('Build Passing')
pullRequest.labels = ['Bug', 'Feature']
pullRequest.addAssignee('Spock')
pullRequest.removeAssignee('McCoy')
pullRequest.assignees = ['Data', 'Scotty']
for (commitFile in pullRequest.files) {
echo "SHA: ${commitFile.sha} File Name: ${commitFile.filename} Status: ${commitFile.status}"
}
def comment = pullRequest.comment('This PR is highly illogical..')
pullRequest.editComment(comment.id, 'Live long and prosper.')
// or
comment.body = 'Live long and prosper.'
pullRequest.deleteComment(commentId)
// or
comment.delete()
def commitId = 'SHA of the commit containing the change/file you wish to review';
def path = 'src/main/java/Main.java'
def lineNumber = 5
def body = 'The review comment'
def comment = pullRequest.reviewComment(commitId, path, lineNumber, body)
pullRequest.editReviewComment(comment.id, 'Live long and prosper.')
// or
comment.body = 'Live long and prosper.'
pullRequest.deleteReviewComment(comment.id)
// or
comment.delete()
pullRequest.replyToReviewComment(comment.id, 'Khaaannnn!')
// or
comment.createReply('Khaaannnn!')
for (commit in pullRequest.commits) {
echo "SHA: ${commit.sha}, Committer: ${commit.committer}, Commit Message: ${commit.message}"
}
for (comment in pullRequest.comments) {
echo "Author: ${comment.user}, Comment: ${comment.body}"
}
for (reviewComment in pullRequest.reviewComments) {
echo "File: ${reviewComment.path}, Line: ${reviewComment.line}, Author: ${reviewComment.user}, Comment: ${reviewComment.body}"
}
for (commit in pullRequest.commits) {
for (status in commit.statuses) {
echo "Commit: ${commit.sha}, Status: ${status.status}, Context: ${status.context}, URL: ${status.targetUrl}"
}
}
for (commit in pullRequest.commits) {
commit.createStatus(status: 'pending')
}
for (status in pullRequest.statuses) {
echo "Commit: ${pullRequest.head}, Status: ${status.status}, Context: ${status.context}, URL: ${status.targetUrl}"
}
for (requestedReviewer in pullRequest.requestedReviewers) {
echo "${requestedReviewer} was requested to review this Pull Request"
}
pullRequest.createReviewRequests('Spock', 'McCoy')
pullRequest.deleteReviewRequests('McCoy')