jenkinsci / jenkinsfile-runner-github-actions

Jenkins single-shot pipeline execution in a GitHub Action POC
https://github.com/features/actions
Apache License 2.0
200 stars 53 forks source link
github-actions jenkins jenkins-pipeline jenkinsfile jenkinsfile-container

GitHub Actions POC for Jenkins Single-shot master

Docker GitHubActions

This is a POC how to run Jenkinsfiles inside GitHub Actions - GitHub's built-in CI/CD using embedded Jenkins Single-shot masters.

image

image

Any GitHub project with a Jenkinsfilecan use those actions to execute its defined workflow inside a Docker container run by GitHub that spawns up a new Jenkins master, executes the tests and exits.

The commit that triggered the GitHub Action is automatically mapped to /github/workspace in the Jenkins Docker container. Test results are reported back to the corresponding pull requests.

image

image

Available GitHub Action

The POC comes with one action:

jenkinsfile-runner-prepackaged

Uses the official Jenkinsfile-Runner and prepackages Jenkins 2.138.2 and Maven 3.5.2 with it. There is also a Dockerfile available you could refer to in your workflow if you do not like to refer to the source.

How to use the action

Here is an example GitHub Action workflow that shows how to use the action:

on: push
name: Jenkins single-shot master
jobs:
  jenkinsfile-runner-prepackaged:
    runs-on: ubuntu-latest
    steps:
    - uses: actions/checkout@master
    - name: jenkinsfile-runner-prepackaged
      uses: jenkinsci/jenkinsfile-runner-github-actions/jenkinsfile-runner-prepackaged@master
      env:
        GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

An example Jenkinsfile that was tested with this

#!groovy
import groovy.json.JsonOutput

node {
    // pull request or feature branch
    if  (env.GITHUB_REF != 'refs/heads/master') {
        checkoutSource()
        build()
        unitTest()
    } // master branch / production
    else {
        checkoutSource()
        build()
        allTests()
        createRelease("${env.GITHUB_ACTION}-${env.GITHUB_SHA}")
    }
}

def createRelease(name) {
  stage ('createRelease') {
        def payload = JsonOutput.toJson(["tag_name": "v-${name}", "name": "GitHub Action triggered release: ${name}", "body": "This release has been created with the help of a Jenkins single-shot master running inside of a GitHub Action. For more details visit https://github.com/jonico/jenkinsfile-runner-github-actions"])
        def apiUrl = "https://api.github.com/repos/${env.GITHUB_REPOSITORY}/releases"
        mysh("curl -s --output /dev/null -H \"Authorization: Token ${env.GITHUB_TOKEN}\" -H \"Accept: application/json\" -H \"Content-type: application/json\" -X POST -d '${payload}' ${apiUrl}")
    }
}

// prevent output of secrets and a globbing patterns by Jenkins
def mysh(cmd) {
    sh('#!/bin/sh -e\n' + cmd)
}

def checkoutSource() {
  stage ('checkoutSource') {
    // as the commit that triggered that Jenkins action is already mapped to /github/workspace, we just copy that to the workspace
    copyFilesToWorkSpace()
  }
}

def copyFilesToWorkSpace() {
  mysh "cp -r /github/workspace/* $WORKSPACE"
}

def build () {
    stage ('Build') {
      mvn 'clean install -DskipTests=true -Dmaven.javadoc.skip=true -Dcheckstyle.skip=true -B -V'
    }
}

def unitTest() {
    stage ('Unit tests') {
      mvn 'test -B -Dmaven.javadoc.skip=true -Dcheckstyle.skip=true'
    }
}

def allTests() {
    stage ('All tests') {
      // don't skip anything
      mvn 'test -B'
    }
}

def mvn(args) {
    sh "mvn ${args} -Dmaven.repo.local=/github/workspace/.m2"
}

There are some things to point out with this example:

image

Local Trouble-shooting / customize the packaged Jenkins and plugins

Jenkinsfile-Runner Prepackaged

docker pull jonico/jenkinsfile-runner-prepackaged

or if you like to build the Docker image from scratch


git clone https://github.com/jenkinsci/jenkinsfile-runner-github-actions.git

cd jenkinsfile-runner-github-actions/jenkinsfile-runner-prepackaged

docker build -t jenkinsci/jenkinsfile-runner-prepackaged .

Then, cd to your git repo that contains your Jenkinsfile and mount it to /github/workspace while running the docker container

cd <your-repo>

docker run --rm -it -v $(pwd):/github/workspace  jenkinsci/jenkinsfile-runner-prepackaged

If you are using environmental variables in your Jenkinsfile, you would have to specify them using the "-e" command line option for docker:

docker run --rm -it -v $(pwd):/github/workspace -e GITHUB_REPOSITORY=jenkinsci/reading-time-app -e GITUB_GITHUB_REF=refs/heads/create-releases -e GITHUB_ACTION=jenkinsfile-runner-prepackaged -e GITHUB_SHA=mysha-3 -e GITHUB_TOKEN=<redacted> jenkinsci/jenkinsfile-runner-prepackaged

In case you like to modify the Docker base image that defines which version of Jenkins and which plugins are included, you find the Dockerfile here.

Current Limitations / TODOs

This is just a POC, in order to productize this, you would probably