🎀

Jenkins ジョブを GitHub Actions 上で動かせるようになりました

2022/05/21に公開

概要

Jenkins を GitHub Actions 上で動かすアクションを作りました。
まだ動かない機能もあると思いますが Jenkins から GitHub Actions へ移行する際の選択肢になるといいのかなと思っています。

作ったアクション

https://github.com/snow-actions/setup-jenkins

設計

CI を移行する際に何が大変かというと異なる言語で書かれた設定ファイルの移植です。
なのでそもそも移植をしなくて済むように Jenkins そのものを Docker Compose で構築して GitHub Actions ランナー上で走らせています。

覚えることを増やさないように独自の機能はほとんど入れていませんので Jenkins の知識があれば大体のことはできるのではないかと思います。

セットアップウィザードをスキップするため認証機能はオフになっています。

操作は Jenkins CLI で行うのが楽です。
Remote Access API も使えますが認証がないので Crumb の発行が必要です。

使い方

既存ジョブ

既存ジョブがある場合は $JENKINS_HOME/jobs/*/config.xml をコピーしリポジトリにコミットしておきます。

.github/workflows/jenkins.yml
steps:
  - uses: actions/checkout@v3
  - uses: snow-actions/setup-jenkins@v1.0.0
  - run: wget $JENKINS_URL/jnlpJars/jenkins-cli.jar
  - run: java -jar jenkins-cli.jar -webSocket install-plugin http_request -deploy
  - run: java -jar jenkins-cli.jar -webSocket create-job job-1 < path/to/config.xml
  - run: java -jar jenkins-cli.jar -webSocket build job-1 -f -v -p param_1=p1

Credentials 等が必要な場合は後述する JCasC や Remote Access API で設定できます。

Jenkins Configuration as Code (JCasC)

https://www.jenkins.io/projects/jcasc/

従来の Jenkins は GUI で設定を行い JENKINS_HOME 配下に設定ファイルが保存されてきました。(前項で使用した config.xml もこれです)
これらの設定を人が読みやすいコードで管理する (as Code) ためのプラグインです。

JCasC で管理する場合はリポジトリに jenkins.yaml をコミットしておき、そのディレクトリへのパスを jenkins_home に指定します。
拡張子は .yaml であることに注意してください。

jenkins_home/jenkins.yaml
jobs:
  - script: |
      pipelineJob('job-2') {
        definition {
          cpsScm {
            scm {
              git {
                remote {
                  url('https://github.com/jenkinsci/job-dsl-plugin.git')
                }
                branch('*/master')
              }
            }
            lightweight()
          }
        }
      }
.github/workflows/jenkins.yml
steps:
  - uses: actions/checkout@v3
  - uses: snow-actions/setup-jenkins@v1.0.0
    with:
      jenkins_home: ./jenkins_home
  - run: java -jar jenkins-cli.jar -webSocket build job-2 -f -v

Jenkins コンテナにアクセス

Docker Compose で起動している Jenkins コンテナにもアクセスできます。
COMPOSE_FILE 環境変数が設定されるようになっているのでそのまま docker compose コマンドが使用できます。
コンテナ名は jenkins です。

環境変数を取得したりミドルウェアをインストールしたり。

.github/workflows/jenkins.yml
steps:
  - uses: snow-actions/setup-jenkins@v1.0.0
  - run: docker compose exec jenkins printenv
  - run: docker compose exec -u root jenkins apt-get update
  - run: docker compose exec -u root jenkins apt-get install -y awscli

Credentials

GitHub Actions では秘匿情報は Secrets に保存します。
一度ファイルに出力して env_file に指定することで Docker Compose の env_file 経由でコンテナへ環境変数を渡せます。
その環境変数を jenkins.yaml で使用することができます。

.github/workflows/jenkins.yml
steps:
  - uses: actions/checkout@v3
  - run: echo "PAT=${{ secrets.PAT }}" >> .env
  - uses: snow-actions/setup-jenkins@v1.0.0
    with:
      jenkins_home: ./jenkins_home
      env_file: .env
  - run: java -jar jenkins-cli.jar -webSocket build job-3 -f -v
jenkins_home/jenkins.yaml
credentials:
  system:
    domainCredentials:
    - credentials:
      - usernamePassword:
          id: pat
          scope: GLOBAL
          username: "SnowCait"
          password: "${PAT}"
jenkins:
  globalNodeProperties:
  - envVars:
      env:
      - key: BRANCH
        value: main
jobs:
  - script: |
      pipelineJob('job-3') {
        definition {
          cps {
            script('''\
              pipeline {
                  agent any
                  stages {
                      stage('checkout') {
                          steps {
                              checkout scm: [
                                  $class: 'GitSCM',
                                  branches: [[ name: "${env.BRANCH}" ]],
                                  userRemoteConfigs: [
                                      [
                                          url: 'https://github.com/SnowCait/private-repository.git',
                                          credentialsId: 'pat'
                                      ]
                                  ]
                              ]
                          }
                      }
                  }
              }
            '''.stripIndent())
            sandbox()
          }
        }
      }

Jenkinsfile の Lint

Jenkins には Declarative Pipeline の Linter があります。

.github/workflows/jenkins.yml
steps:
  - uses: actions/checkout@v3
  - uses: snow-actions/setup-jenkins@v1.0.0
  - run: java -jar jenkins-cli.jar -webSocket declarative-linter < path/to/Jenkinsfile

Jenkins の機能

先にコードは紹介してしまいましたがジョブを実行するには Jenkins CLI や Remote Access API が使用できます。

Jenkins CLI

https://www.jenkins.io/doc/book/managing/cli/

ジョブの実行には Jenkins CLI が便利です。基本的にはこちらを使うのをおすすめします。
$JENKINS_URL/cli/ にアクセスすると詳しいドキュメントがあります。

立ち上げた Jenkins から Jenkins CLI クライアント (jenkins-cli.jar) をダウンロードします。
Jenkins の URL は JENKINS_URL 環境変数にセットされています。

.github/workflows/jenkins.yml
steps:
  - uses: actions/checkout@v3
  - uses: snow-actions/setup-jenkins@v1.0.0
    with:
      jenkins_home: jenkins_home
  - run: wget $JENKINS_URL/jnlpJars/jenkins-cli.jar
  - run: java -jar jenkins-cli.jar -webSocket help
  - run: java -jar jenkins-cli.jar -webSocket build job-1 -f -v -p param_1=p1

Remote Access API

https://www.jenkins.io/doc/book/using/remote-access-api/

認証がないので Crumb の発行が必要ですが REST API としてアクセスできます。

.github/workflows/jenkins.yml
steps:
  - uses: actions/checkout@v3
  - uses: snow-actions/setup-jenkins@v1.0.0
    with:
      jenkins_home: jenkins_home
  - run: |
      crumb=$(curl -s -c cookie $JENKINS_URL/crumbIssuer/api/json)
      echo "CRUMB_HEADER=$(echo $crumb | jq -r '.crumbRequestField'): $(echo $crumb | jq -r '.crumb')" >> $GITHUB_ENV
  - run: curl -X POST -H "$CRUMB_HEADER" -b cookie $JENKINS_URL/api/json | jq '.jobs'
  - run: curl -X POST -H "$CRUMB_HEADER" -b cookie $JENKINS_URL/job/job-1/build

実行速度

推奨プラグインのインストールを含めても1分以内で立ち上がるのでそこそこ現実的なのではないでしょうか。
プラグインを最小限にできるようになるともうちょっと速くなりそうです。

どこまで動く?

現時点で把握している動作しない(と思われる)機能としては Docker です。
これは Jenkins を Docker で立ち上げているため Docker in Docker (DinD) になってしまうことが原因です。
何かしら対応はできるのかもしれませんが、Docker で動いているものは GitHub Actions へ移植する難易度も低いと思うので対応優先度は低めです。

まだ最低限の確認しかしていないので他にも色々と動かないと思いますが追々対応していきます。
正直どこまで動くか分からないので試した方がいればここのコメントか Discussion にでも気軽に報告いただけると助かります。

感想

https://twitter.com/snow_cait/status/1525237290422849536

Discussion