We had to deploy a remote Jenkins instance. By default, pods running in OpenShift are configured under the default security context which means ssh’ing as an Administrator to perform adminstrative functions is out of the question. As such, we have spun up a virtual server on IBM Cloud and ran Jenkins as a docker image within it.
The procedure is a such:
-
Deploy a Centos 7.9 VSI on BM Cloud. Any server will do, so as long as Docker can be downloaded and installed.
-
Installed Docker on the VM. Steps given here.
- Note: It would be ideal to make an image out of this server to be used in the future. This way, we don’t need to install Docker all the time.
- Note: Depending on the OS of the server you deployed, the steps required to install and run docker will likely be different. Consult the relevant documentation in such case.
-
Run docker command to run Jenkins. The command is as such:
- docker run --name jenkins -d -p 8080:8080 -p 50000:50000 --restart=on-failure -v jenkins_home:/var/jenkins_home jenkins/jenkins:lts-jdk11
-
Execute into the running jenkins container as root to install the python enviroment needed to execute the actual jenkins job later. (NOTE: It would be ideal to make our own Jenkins image with these preinstalled defaults in the future. Save this image to our own registry to be used downstream with minimal fuss.)
- docker exec -u 0 -it jenkins /bin/bash #start an interactive shell in the container as root
- apt-get update
- apt-get install python3
- apt-get install python3-pip
- apt-get install python3-venv
- cd var/jenkins_home/ #location where the build job expects the virtual enviroment
- python3 -m venv jenkins-env #setup virtual enviroment
- chown -R jenkins:jenkins jenkins-env/ #change owner from root to jenkins so it can be used in every build job
-
Configure the job within Jenkins (NOTE: The user which executes the jenkins pipelines/scripts is the jenkins user by default. We made a targeted vritualenv for this user and dynamically installed the required dependencies on that env. This is performed by the Jenkins job (in the event the PR added a new library to the requirements.txt). This environment is used when the pipeline is triggered. Right now, we have a freestyle job. Future work includes making a Jenkinsfile pipeline out of this.)
- Do all the steps under "Configuring Pull Requests to Trigger a Jenkins Job/Pipeline"
- set enviroment variables. There are two options:
- use credential binding (secure) here.
- set simple enviroment variables (easy) 1)go to "Manage Jenkins">"Configure System">"Enviroment variables" 2)add (Name:JOB; Value:Dev_Pipeline) (Name:KEY; Value:an API Key you created within IBM Cloud) (Name:PROJECT; Value:The ID of your watson studio project)
- navigate to Dashboard>your_job_name>Configuration and copy paste the content of jenkins/utils/template_job.sh into Build Steps>Execute shell and save
- Do a test run by clicking Dashboard>your_job_name>Build Now . You can check the output by clicking on the number of the build in the menu
-
Install GitHub Pull Request Builder plugin
- Manage Jenkins > Manage Plugins > Available Tab and search for “Github pull request builder” > Checkbox for Install > Install without restart
-
Configure GitHub Pull Request Builder plugin
- Manage Jenkins > Configure System > GitHub Pull Request Builder
- Credentials > Add > Jenkins > Select Username with password for Kind
- Username: <YOUR_GITHUB_USERNAME>
- Password: <YOUR_GITHUB_TOKEN>
- Test Credentials > Check Test basic connection to GitHub > Connect to API
- If you don’t have a GitHub token, you can create one in GitHub: Settings > Developer settings > Personal access tokens > Tokens (classic) > Generate new token > Enter jenkins-token for Note > Select repo and admin:repo_hook for Select scopes > Keep your token (! important)
- Correct Output: Connected to https://api.github.com as null (null) login: <YOUR_GITHUB_USERNAME>
- Add a username in Admin list
- Save
-
Configure GitHub Repository Webhook
- Go to your GitHub Repository > Settings > Webhooks > Add webhook
- Enter or Select
- Payload URL: <YOUR_JENKINS_HOST>/ghprbhook/
- Content type: application/json
- Which events would you like to trigger this webhook?: Let me select individual events. > Pull requests
- Add webhook
-
Create a Jenkins job and Configure it
- New Item > Enter an item name > Freestyle project > OK
- Click the project > Configure
- Description: Project to build on pull request to GitHub
- Check GitHub project and Enter Project url <YOUR_GITHUB_REPO_URL>
- Source Code Management > Git
- Repository URL: <YOUR_GITHUB_REPO_URL>
- Credentials: Select the credential you created previously
- Advanced > Refspec: +refs/pull/*:refs/remotes/origin/pr/*
- Branches to build: ${sha1}
- Build Triggers
- Check GitHub Pull Request Builder
- Check Use github hooks for build triggering
-
Test
- Create a new branch (master)
- Add a file and commit
- Raise a PR
- Check Build History in Jenkins
-
Additional Steps
- Go to your GitHub Repository > Settings > Branches > Branch protection rules > Add rule
- Branch name pattern: master
- Check Require status checks to pass before merging > Check Require branches to be up to date before merging
- Go to your GitHub Repository > Settings > Branches > Branch protection rules > Add rule
-
Install Generic Webhook Trigger plugin
- Manage Jenkins > Manage Plugins > Available Tab and search for “Generic Webhook Trigger” > Checkbox for Install > Install without restart
-
Create a Jenkins job and Configure it
-
New Item > Enter an item name > Freestyle project > OK
-
Click the project > Configure
- Description: Project to build on push to GitHub
- Check GitHub project and Enter Project url <YOUR_GITHUB_REPO_URL>
- Source Code Management > Git
- Repository URL: <YOUR_GITHUB_REPO_URL>
- Credentials: Select the credential you created previously
- Branches to build: */master
- Build Triggers
- Check Generic Webhook Trigger
- Post content parameters > Add
- Name of variable: IF_MERGED, Expression: $.pull_request.merged, JSONPath
- Name of variable: BRANCH, Expression: $.pull_request.base.ref, JSONPath
- Token: jenkins-push
- Optional Filter
- Expression: (?=.*true)(?=.*pre-prod).*
- Text: $IF_MERGED $BRANCH
-
-
Configure GitHub Repository Webhook
- Go to your GitHub Repository > Settings > Webhooks > Add webhook
- Enter or Select
- Payload URL: <YOUR_JENKINS_HOST>/generic-webhook-trigger/invoke?token=jenkins-push
- Content type: application/json
- Which events would you like to trigger this webhook?: Let me select individual events. > Push, Pull requests
-
Test
- Create a new branch (master)
- Add a file and commit
- Raise a PR
- Check Build History in Jenkins
Please note a Slack Adminstrator should perform this. If you are not a workspace admin, contact your workspace admin(s) to perform this procedure for you.
Setting it up is quite simple. The main page is given here. Follow the link given in step 2.
Select the workspace as given in the top right of the screen. In the image above, the workspace is “IBM Sales”. Next, choose the channel as given in the “Choose a channel”. Note you should have administrative access to the workspace in question. Next, press “Add Jenkins CI Integration”
You will then be directed to a page containing a number of steps to follow along with documented usage instructions for this plugin. The procedure is relatively straightforward and should not be terribly complicated to configure. “Step 3” however is a little outdated. Perhaps an older Jenkins version was used. Recent versions resembles the following:
Please note the Workspace name may or may not coincide with the display name you see in Slack. For instance, consider the following:
The workspace display name is “IBM Data and AI” but the reference name is “ibm-analytics”. Errors will appear in the event the display name is used.
The channel id can be found as such:
Click on the channel. Navigate to the top of the screen where the channel name is visible. Click the dropdown as seen above.
The channel ID can be seen towards the bottom of the screen above. Not the best in terms of visibility but it will do. Use this value to populate the channel id text field in Jenkins.