We're no longer maintaining and actively developing triggear.
Triggear is a service that integrates GitHub with Jenkins pipelines. It provides ways of registering Jenkins pipelines for specific events in GitHub and reporting job statuses and details back to GitHub. If you ever thought about running Jenkins jobs without entering Jenkins and remembering about all the jobs that you need to run - Triggear is the guy you were looking for.
It should not be confused with GitHub plugins/service integration with Jenkins as Triggear can do much more for you.
The example usage flow is following:
- Jenkins pipeline sends registration request to Triggear, specifying what type of events in some repository should trigger it
- Triggear saves registration in Mongo DB
- At this point if event specified in registration request occurs in repository, Triggear will automatically trigger job that registered
- After build is done, Triggear reports its status to GitHub - usually to commit/PR that triggered the job
Triggear now have submodule of triggear_pipeline located in
src/com/futuresimple
. So be sure to clone with submodules:
git clone --recursive git@github.com:futuresimple/triggear.git
For overview of Triggear features please read 6. Workflows section
- Building Triggear
- Running tests
- Running Triggear as a service
- Setup in Jenkins
- Setup in GitHub
- Workflows
Feel free to propose any new sections of docs by creating an issue. ###1. Building Triggear To build triggear:
- manually
You need to have Python 3.6.3 installed with pip. Then you download dependencies with:
pip install -r requirements.txt
- with docker
docker build --tag triggear .
Note: docker build runs all the unittests by default
- with docker-compose
docker-compose build
Note: docker-compose build runs all the unittests by default ###2. Running tests
- manually
PYTHONPATH=[PATH_TO_TRIGGEAR] py.test .
- with docker
Included in build phase
- with docker-compose
Included in build phase
###3. Running Triggear as a service
To run Triggear you need to have running Jenkins instance and
GitHub repository (or many repositories). Then you need to
prepare creds.yml
file like in example
providing:
- Jenkins URL
- Jenkins user ID (will be used to trigger builds)
- Jenkins API token for this user
- GitHub token for your GitHub bot (needs write access to repositories)
- Triggear token that will be used to authorize pipeline/github calls
There are couple of ways of running Triggear providing creds.yml
- manually In this case you need to have running mongo DB on localhost
CREDS_PATH=[PATH_TO_CREDS_YML] CONFIG_PATH=config.yml python3 app/main.py
- with docker
In this case creds.yml
needs to be in <triggear-path>/configs
and
mongo DB needs to be running on localhost
docker run doc python app/main.py
- with docker-compose
In this case creds.yml
needs to be in <triggear-path>/configs
docker-compose up
This is of course easiest and preferred version of running Triggear not taking into consideration deploy to Kubernetes option. ###4. Setup in Jenkins
Provided that you have running Triggear instance, we need to setup it as a shared library in Jenkins, to let pipelines use registration and status methods. To do it:
-
Add
TRIGGEAR_URL
and global Jenkins variable. Its value should be something like `https://TRIGGEAR_URL/" -
Add Triggear repository as Shared Library in Jenkins. By doing so pipelines will get access to
vars
directory and will be able to use register and status update functions -
Add secret text with name
triggear_token
and value of triggear_token field from yourcreds.yml
Alternatively you can simply add triggear_pipeline
as submodule in your shared library src/com
to make it available for you pipelines.
Note: Workflows section of docs assumes that you called Triggear
shared library as simply as Triggear
###5. Setup in GitHub
Note: this setup needs to be done in all repositories that are supposed to trigger Jenkins jobs
-
Add GitHub bot (the one that has API token used in
creds.yml
) to repository collaborators with write permissions -
Add webhook to repository:
- Set Payload URL to
https://TRIGGEAR_URL/github
- Set Content type to
application/json
- Set secret to value of your
triggear_token
- Select individual hook elements: Issue comment, Pull request, Push, Create
- Set Payload URL to
-
Save - at this point test payload should be sent to Triggear and response 200 should be returned to GitHub (can be seen in the bottom of webhook configuration where logs are)
At this point events from GitHub will be sent to Triggear. ###6. Workflows
This section will describe possible user scenarios that Triggear can execute.
Note: for all trigger types Triggear uses value of rerun_time_limit
set in ./config.yml
. It is meant to throttle builds, not to run
some job 30 times in 1 minute just because someone furiously
pushes TYPO fixes to your repo. This limit can be modified manually.
Case #1 You want your pipeline to be run on every push to repository X
To solve that you want your pipeline to use Triggear
var triggearRegister
:
// Assuming you called this shared library "Triggear" in Jenkins
// Ommit this line if you add Triggear as shared library implicitly
@Library(['Triggear']) _
import com.futuresimple.triggear.Request
import com.futuresimple.triggear.TriggearClient
import com.futuresimple.triggear.GitHubRepository
import org.jenkinsci.plugins.workflow.libs.Library
TriggearClient triggear = new TriggearClient(this, new GitHubRepository('triggear'))
triggear.register(Request
.forPushes()
.build())
Now you need to run your job once to call register properly. From then on every time someone pushes something to X this job will be triggered.
Case #2 You want your pipeline to be run on every push to repository X and get branch and commit SHA of this push (e.g. you want to run unittests job for every push)
To solve that you want your pipeline to use Triggear
method registerForPushes
:
// Assuming you called this shared library "Triggear" in Jenkins
// Ommit this line if you add Triggear as shared library implicitly
@Library(['Triggear']) _
import com.futuresimple.triggear.Request
import com.futuresimple.triggear.TriggearClient
TriggearClient triggear = new TriggearClient(this, new GitHubRepository('triggear'))
triggear.register(Request
.forPushes()
.addBranchAsParameter()
.addShaAsParameter()
.build())
Now you need to run your job once to call register properly. From
then on every time someone pushes something to X this job will
be triggered with branch
and sha
parameters. __Remember that
your pipeline needs to accept branch
and sha
parameters,
otherwise execution will fail.
In both cases once your job is done, commit status in GitHub will be set based on it's results:
You can see, that job name is set as status context. When you click on Details link you will be redirected to your job build URL.
Case #3 You want your pipeline to be run on every push to repository X only if something changed in directory 'X/Y' or file 'Z'
To do it, you will need to pass changeRestrictions parameter to registerForPushes method:
// Assuming you called this shared library "Triggear" in Jenkins
// Ommit this line if you add Triggear as shared library implicitly
@Library(['Triggear']) _
import com.futuresimple.triggear.Request
import com.futuresimple.triggear.TriggearClient
TriggearClient triggear = new TriggearClient(this, new GitHubRepository('X'))
triggear.register(Request.forPushes()
.addChangeRestriction('X/Y')
.addChangeRestriction('Z')
.addBranchAsParameter()
.addShaAsParameter()
.build())
Please note, that it works in a way, that Triggear checks if any files paths changed/added/removed in current push starts with strings mentioned in changeRestrictions parameter. If so - job will be triggered. If not - nothing happens, message is logged in Triggear.
Case #1 You want your job to be run, when label Y is set on PR in repository X
To solve that you want your pipeline to use Triggear
var triggearRegister
:
// Assuming you called this shared library "Triggear" in Jenkins
// Ommit this line if you add Triggear as shared library implicitly
@Library(['Triggear']) _
import com.futuresimple.triggear.Request
import com.futuresimple.triggear.TriggearClient
triggering_label = 'Y'
TriggearClient triggear = new TriggearClient(this, new GitHubRepository('X'))
Request registrationRequest = Request.forLabels()
.addLabel(triggering_label)
.build()
triggear.register(registrationRequest)
Now run you pipeline once to make register call. From then on you can set label Y on your PR in X repository it will trigger your pipeline.
Case #2 You want your job to be run, when label Y is set on PR in repository X and get branch and current SHA of this PR (e.g. you want to deploy this branch to some environment)
To solve that you want your pipeline to use Triggear
var triggearRegister
:
// Assuming you called this shared library "Triggear" in Jenkins
// Ommit this line if you add Triggear as shared library implicitly
@Library(['Triggear']) _
import com.futuresimple.triggear.Request
import com.futuresimple.triggear.TriggearClient
triggering_label = 'Y'
TriggearClient triggear = new TriggearClient(this, new GitHubRepository('X'))
Request registrationRequest = Request.forLabels()
.addLabel(triggering_label)
.addBranchAsParameter()
.addShaAsParameter()
.build()
triggear.register(registrationRequest)
Now run you pipeline once to make register call. From then on
you can set label Y on your PR in X repository it will trigger
your pipeline setting branch
and sha
as parameters.
Remember that your job needs to accept such parameters.
In both cases once the job is done it will create or update PR status with your job results:
As you can see job name is again used as context. Details link will redirect users from GitHub to your pipeline build.
Case #1 You want to run job registered for label Y on every push to the PR labeled with Y (e.g. redeploy code on every PR sync)
At first you need to register your job for label Y in repo X:
// Assuming you called this shared library "Triggear" in Jenkins
// Ommit this line if you add Triggear as shared library implicitly
@Library(['Triggear']) _
import com.futuresimple.triggear.Request
import com.futuresimple.triggear.TriggearClient
triggering_label = 'Y'
TriggearClient triggear = new TriggearClient(this, new GitHubRepository('X'))
Request registrationRequest = Request.forLabels()
.addLabel(triggering_label)
.build()
triggear.register(registrationRequest)
Then, you'll need a special label in your GitHub repo. It's name
should be triggear-label-sync
.
Set label Y and triggear-label-sync
on one of your PRs.
From then on every push to this PRs branch will trigger your job.
Removing triggear-label-sync
label will stop this behaviour.
Case #1 You want to run job on every PR opened in repo X.
Also you would like for it to be rerun if anything is pushed
to that PR (so called synchronize
events):
At first you need to register your job for PR opened events in repo X:
// Assuming you called this shared library "Triggear" in Jenkins
// Ommit this line if you add Triggear as shared library implicitly
@Library(['Triggear']) _
import com.futuresimple.triggear.Request
import com.futuresimple.triggear.TriggearClient
TriggearClient triggear = new TriggearClient(this, new FSTechRepo('PipelinesExamples'))
triggear.register(Request.forPrOpened()
.build())
Then, you'll need a special label in your GitHub repo. It's name
should be triggear-pr-sync
. If that label is present triggear will
set in on PR automatically. It will cause all synchronize events
to re-run the job.
Case #1 You labeled PR with label Y which triggered some jobs and reported status back to PR. Commit status is set to fail, as your job failed and you know that it is not related to code. You want to rerun it without having to push something to PR.
To do this simply open GitHub PR and write comment:
triggear-label-sync
By doing so following behaviour will start:
- Triggear will look on your PR and check it's labels
- Triggear will run the job that failed giving it
branch
andsha
parameters according to what you specified in PR/comment, wheresha
is latest commit in this PR - Once the job is done Triggear will update commit status according to job results
Voila - no pushes/labels caused full rerun of jobs registered with context of specified SHA.
Case #1 Some event (push/labeled) triggered your job and it produced an artifact in Jenkins available at some URL. You want to make this URL visible as one of commits statuses, not to dig through Jenkins UI. Common use case for us at Base is that we want link to unittest report to be visible directly in GitHub without digging through Jenkins build UI
So let's assume that unittests report is stored at $BUILD_URL/report
.
Your job is registered for pushes and gets SHA from Triggear
and you want this report to be visible in GitHub for every commit.
To do so - in your Pipeline, once it's done call triggearStatus
var:
import com.futuresimple.triggear.CommitStatus
// this is the case when your job handles sha as param
triggear.addCommitStatus(sha,
currentBuild.result == "SUCCESS" ? CommitState.SUCCESS : CommitState.FAILURE,
"Custom status console logs link",
"Console logs",
"${BUILD_URL}console"
)
By doing so, every commit will have new custom status once the job is done:
Of course this status will only be visible after job is done so there won't be any pending state visible in GH for it at any time.
Case #1 You want your job to create a comment on PR/commit with some details that are too long to be presented as commit statuses
So the common case for us at Base is that we won't to present some information about build that are simply too long for statuses in GH (remember: it has content length limit). It can be info about binary size, build time or anything non-status-like.
To do so, use triggearComment
var at some point in your
pipeline:
// this is the case when your job handles sha as param
triggear.addComment(sha, 'Important build details as commit comment')
By doing so you will see the following results:
Of course one pipeline can create multiple comments.
Case #1 You want your job to run at the time when someone pushes a new tag to repository. At Base we use that to create app's with given tag for reference
To do so you need to register your job for tagged
events in repo X:
// Assuming you called this shared library "Triggear" in Jenkins
@Library(['Triggear']) _
import com.futuresimple.triggear.Request
import com.futuresimple.triggear.TriggearClient
TriggearClient triggear = new TriggearClient(this, new FSTechRepo('PipelinesExamples'))
triggear.register(Request.forTags()
.addTagAsParameter()
.addBranchAsParameter()
.addShaAsParameter()
.build())
By running your job once, you'll enable functionality of running your job every time new tag is pushed to origin. Your job will receive tag name and branch/sha of tagged commit as parameters, so make sure that it accepts them and can handle such params.
Case #1 You want to run specific job by writing comment on you PR, not having to enter Jenkins
This is rather uncommon case but maybe you remember your job name and it's parameters, but you don't want to enter Jenkins UI and you want to run it with PR comment?
So in PR type following comment:
Triggear run jobDir/jobName param1=value1 param2=value2
If your job has no params simply remove params specification from that line. Once the job is executed you will get a PR comment with it's status and URL to it.