Jenkins Pipelineを試す

dev

フリースタイルより柔軟に設定が可能と言われているPipelineを試してみた。
シェルをガツガツ書いていくには、フリースタイルでシェルを実行スタイルで行う方が簡単だった。
Pipelineからフリースタイルのジョブへパラメータを連携して呼ぶことも可能なので、うまく組み合わせていけば良さそう。
pipeline {} から始まるDeclarative方式とnode {} から始まる Script方式があるみたいだが、推奨されているpipelineを試した。

参考) https://leprofront.tech/index.php/jenkins-pipeline-concept/

Sponsored links

JenkinsのInstall

自分の端末に以下参考にしてインストールした
https://www.jenkins.io/doc/book/installing/linux/

  • localhost:8080でアクセス
  • recommended plugin を選択してセットアップ

設定

Androidのビルドが主なのでANDROID_HOMEの設定が必須 (ANDROID_SDK_ROOT)でも良いみたいだが。

Jenkinsの管理→ 設定 → 環境変数にチェック

  • キー: ANDROID_HOME
  • 値 : /home/hige/Android/Sdk

こんなディレクトリがあるAndroidのSDKルート

[email protected]:~cd /home/hige/Android/Sdk
[email protected]:~/Android/Sdk ls
build-tools  emulator  extras  fonts  licenses  patcher  platform-tools  platforms  skins  sources  system-images  tools

ビルドのパラメータ化

Pipelineに記載して一回ビルドすると「ビルドのパラメータ化」に反映されるっぽい。そうすると、「ビルド」が「パラメータ付きビルド」に変化する。
反映されない場合、どこかにエラーがあるっぽいので修正する。
以下のように, string, choice, booleanParam を試した。

pipeline {

    agent {
        // どのノードを使うか、このマシン本体=master
        label 'master'
    }

    // パラメータ付きビルドに必要な設定
    parameters {
        // branch 
        string(
            name: 'branch',
            defaultValue: 'master',
            description: 'ビルドするbranchを指定'
        )

        // gradle param
        choice(name: 'gradlew_param',
                choices: [
                'assembleDevelopDebug',
                'assembleProductionDebug',
                'assembleProductionRelease',
            ],
            description: 'ビルドするパラメタを指定'
        )

        // s3    
        booleanParam(
            name: 's3',
            defaultValue: true,
            description: 'S3にアップロード'
        )

    }

    stages {
        stage('checkout') {
            // 略 ...
        }

        stage('build') {
            // 略 ...
        }

    }

}

git リポジトリからチェックアウトする

Jenkins本体に設定したssh秘密鍵を使ってgitリポジトリにアクセスしてビルドするソースをcheckoutする

おすすめはcurrentBuild.displayNameにブランチ名を入れる。こうするとデフォルトではビルド番号だけしか表示されないが、branchも表示されるようになり、過去のビルド一覧からどのブランチをビルドしたかがわかりやすい。

// gitリポジトリ
def repository = "[email protected]:hogehoge/hugahuga.git"
// Jenkins本体に設定しているSSH鍵のID @see 認証情報 -> System -> グローバルドメイン -> jenkins (gitのssh)
def credential = "jenkins-ssh"

// ビルドしたブランチがわかるよう記載
currentBuild.displayName = "#{BUILD_NUMBER}, branch:{branch}"

pipeline {

    agent {
        label 'master'
    }

    // パラメータ付きビルドに必要な設定
    parameters {
        // branch 
        string(
            name: 'branch',
            defaultValue: 'master',
            description: 'ビルドするbranch'
        )
        // 略
  
  stages {
        stage('checkout') {
            steps {
                // gitコマンド
                git([
                    branch        : "${branch}",
                    credentialsId : credential,
                    url           : repository
                ])
            }
        }
        // 略
    }

branchだけでなく、tag, commitHashでcheckoutしたい

↑の例だとbranchしかできないみたいなので、以下のようにする

                // gitコマンド credentialとrepositoryだけ指定する
                git([
                    credentialsId : [credential-id],
                    url           : repository
                ])
                // branch, tag, commi-hashでもなんでもcheckoutできる。branch変数にはtag, hashが入る
                sh(script:"""
                    git checkout \(git rev-parse --verify origin/{branch})
                """)

submoduleをcheckoutする場合

git で単純にやっているとそのリポジトリのアクセス権が無いみたいだったので、
sshagentプラグインというのを使って以下のように書くとOK。元に使ったsshのcredentialと同じものを指定してsubmoduleもcheckoutできる。

sshagentプラグイン: https://plugins.jenkins.io/ssh-agent/

                // サブモジュールをupdate
                sshagent(credentials: [credential]) {
                    sh('GIT_SSH_COMMAND="ssh -oStrictHostKeyChecking=no" git submodule update --init --recursive')
                }

gradleのビルド

Androidをビルドしたいのでgradleのビルドコマンドを使う。
選択したパラメータを使ってビルドする。

stages {
                // 略

        stage('build') {
            steps {
                withGradle {
                    // gradleのビルドコマンド 引数のパラメタでビルドする
                    sh "./gradlew clean ${gradlew_param}"
                }
            }
        }

    }

他のプロジェクトを呼ぶ

共通処理を記載してモジュール化しているプロジェクトなどを呼びたい場合に使う。
stagesでメインの処理が終わった後、postで成功時にパラメータを引き渡して実行するようにした。
呼び出される側のプロジェクトはフリースタイルのプロジェクトで、パラメータを記載していないと受け取れない。ここでは、PARENT_WORKSPACEとPARENT_JOB_NAME
パラメータのチェック状態によって、実行するかしないかをscriptを使ってif文で判定している。params.xxx の形式で指定している。
条件判定にはwhenを使うこともできるが、postでは使うことができないらしい。。

Declarative pipeline when condition in post
As far as declarative pipelines go in Jenkins, I'm having trouble with the when keyword. I keep getting the error No such DSL method 'when' found among steps. ...
    stages {
        // 略
    }

    post {
        always{
            // workspaceのクリーンをするとgitの情報も消えてしまうので、いったんskip
            // cleanWs()
            echo 'build finished.'
        }
        success{
            echo 'build succeeded!'
            // 保存する成果物
            archiveArtifacts artifacts: 'app/build/outputs/apk/**/*.apk', followSymlinks: false
            echo 'posting artifact to aws s3...'

            script {
                // S3へのアップロード
                if (params.s3 == true) {
                    build(
                    job: "upload-s3",
                    parameters: [
                        string(name: "PARENT_WORKSPACE", value: "{WORKSPACE}"),
                        string(name: "PARENT_JOB_NAME",  value: "{JOB_NAME}")
                    ]
                    )
                } else {
                    echo 'upload s3 is skipped.'
                }
            }

        }
        failure{
            echo 'build failed.'
        }
    }

stagesの中でwhenを使う場合は以下のようにする。

whenの中では、parametersに指定した変数は params.ticket_no のようにparams.で参照するっぽい

pipeline {
    agent any

    // パラメータ付きビルドに必要な設定
    parameters {

        // s3    
        booleanParam(
            name: 's3',
            defaultValue: true,
            description: 'S3にアップロードする場合はチェック'
        )

        // ticket no
        string(
            name: 'ticket-no',
            defaultValue: '',
            description: 'チケットにS3のダウンロードリンクをポスト'
        )
    }

    stages {
        stage('Hello') {
            when {
                expression { 
                    params.s3 == true
                }
            }
            steps {
                echo 'checked!'
            }
        }

        stage('Hello2') {
            when {
                expression {
                    params.ticket_no != ''
                }
            }
            steps {
                echo 'ticket_no is assigned.'
            }
        }
    }
}

↑どうもstage1つにつき、whenひとつ、stepがひとつの制限があるみたい。複数書いていると以下のようなエラーになった。

WorkflowScript: 51: Multiple occurrences of the when section @ line 51, column 9.
           stage('Hello') {
           ^

WorkflowScript: 51: Multiple occurrences of the steps section @ line 51, column 9.
           stage('Hello') {
           ^

古いビルドを自動で消す

options に以下のような感じで記載する。いろいろオプションがあるみたいだが、以下の例では 直近100 個のビルドを保持する。

        options {
        // 古いビルドを消します 直近100件のビルドをkeep
        buildDiscarder(
            logRotator(
                numToKeepStr: '100'
            )
        )
    }
    // buildDiscarder#logRoratorのオプション
    // daysToKeepStr: history is only kept up to this days.
    // numToKeepStr: only this number of build logs are kept.
    // artifactDaysToKeepStr: artifacts are only kept up to this days.
    // artifactNumToKeepStr: only this number of builds have their artifacts kept.

Comments

タイトルとURLをコピーしました