こんにちは。テクマトリックスの長久保です。
今回はInstallShieldを用いてJenkinsからインストーラーを作成する方法について紹介します。

前提

従来、インストーラー作成までを以下の方法で実施していたと仮定します。

  1. ソースコードを特定のフォルダーにチェックアウトする。
  2. ビルドバッチを実行し成果物を作成する。
  3. 作成した成果物をInstallShieldの「ソースコンピューターのフォルダー」に該当するフォルダーに移動する。
  4. GUIのInstallShield上から「ビルド」を行いインストーラーを作成する。
  5. 作成したインストーラーを成果物フォルダーに保存する。

今回はなるべくこの環境構成を変更することなく、Jenkinsを用いて自動化する方法について考えてみたいと思います。

環境

InstallShield2022 R2(バージョン28)
Jenkins2.375.3
OSWindows10 Pro

パイプライン

パイプラインの実行イメージは以下の様になります。

それぞれ順に先述の項目2-5に該当します。宣言型パイプラインの場合チェックアウトに関してはJenkins側で実施してくれるためパイプラインのステージとしては書いていません。
それぞれのステージで実施する内容を順に記載します。

ビルド

ビルドステージではソースコードをビルドします。
従来実行しているバッチコマンドをJenkinsのパイプラインから実行することになるのですが、その際にバッチ内のパスの指定が問題になることがあります。

Jenkinsのパイプライン上からバッチコマンドを実行する際のカレントディレクトリはJenkinsのワークスペースとなります。Jenkinsのワークスペースはジョブに応じて動的に生成されます。

Jenkinsのワークスペース例

また、Jenkinsのエージェントを用いて複数ノードで分散ビルドを行う場合はこのワークスペースがノードごとに作成されます。
これらのことを考慮し、バッチコマンドの内容の修正が必要になることがあります。

        stage('ビルド') {
            steps {
                bat 'build.bat'
            }
        }

ビルド成果物のコピー

ビルドステージの次はコマンドラインからInstallShieldを実行します。その下準備のためのステージです。

インストーラー作成用のビルド成果物のパスの指定方法について、InstallShieldのアプリケーションデータ > ファイルとフォルダーの「ソースコンピューターのフォルダー」や「ソースコンピューターのファイル」についてはismファイルに固定の設定として指定されているかと思います。

InstallShieldのアプリケーションデータ > ファイルとフォルダー


先述の通りJenkinsのワークスペースが動的に変更になるため、実行引数などでインストーラー作成用のビルド成果物のパスの指定ができればよいのですが、InstallShieldのユーザーマニュアルを確認する限り難しそうです。
また、コマンドライン実行時に指定するismファイルを切り替えることにより「ソースコンピューターのフォルダー」や「ソースコンピューターのファイル」の指定の切り替えも可能ですが、切り替えの組み合わせが複雑になりすぎてしまいます。
そのため、今回の例では既存のismファイルで設定しているフォルダー構成のままジョブが実行できるように、「ソースコンピューターのフォルダー」のパスに対してxcopyコマンドなどでビルド成果物をコピーします。
実行中のJenkinsのワークスペースのパスは%WORKSPACE%という環境変数で取得が可能です。

        stage('ビルド成果物のコピー') {
            steps {
                bat 'xcopy "%WORKSPACE%\\build artifact\\*" "C:\\forInstallShield" /E /I /Y'
            }
        }

InstallShieldの実行

Jenkinsのパイプラインで実行するためには、対話式でないコマンドラインでInstallShieldを実行する必要があります。
InstallShieldのユーザーマニュアルを参照しながらコマンドラインを作成しました。

ISCmdBld.exe -p "C:\InstallShield 2022 Projects\My Project Name-1.ism"
ISCmdBld.exe -i "C:\InstallShield 2022 Projects\MySetup.ini"

上記の様にISCmdBld.exeを実行することでインストーラーのビルドが実行できます。
実行方法についてはismファイルを参照する方法と、iniファイルを参照する方法があります。

ismファイルを参照する場合
実行時引数に様々なパラメーターを指定することができます。
ただし、ユーザーマニュアルのp.3644に「一部の ISCmdBld.exe コマンドライン パラメーターは特定のプロジェクト タイプにのみ適用します」とあります。プロジェクトタイプによっては利用できない実行時引数もありますので注意が必要です。

iniファイルを参照する場合
iniファイル内でismファイルやそれ以外の実行時パラメーターを指定することができます。
ただし、ユーザーマニュアルのp.1278に記載の内容を確認する限り、すべてのパラメーターが指定できるわけではない可能性があります。また、またismファイルを指定しての実行時引数の時と同様にプロジェクトタイプによっては指定できないパラメーターがある場合がありますので、こちらも同様に注意が必要です。

        stage('InstallShieldの実行') {
            steps {
                bat 'ISCmdBld.exe -p "C:\\InstallShield 2022 Projects\\My Project Name-1.ism"'
            }
        }

成果物の保存

成果物の保存についてはArtifactoryといった成果物リポジトリを利用したり、共有フォルダーに保存したりといった方法も考えられますが、今回はJenkinsに保存します。

Jenkinsに成果物を保存。ダウンロードも可能です。

Jenkinsに成果物を保存するとJenkins上からInstallShieldで作成したインストーラーをダウンロードできるようになります。ジョブの実行からインストーラーのダウンロードまでJenkins上で完結するため利便性は高いです。

Jenkinsに成果物を保存するにはarchiveArtifactsを利用します。
注意点としては、archiveArtifactsとして保存できる対象はJenkinsのワークスペース内に存在する必要があります。
Jenkinsのワークスペース外にあるファイルを絶対パスで指定した場合、以下のようにファイルが存在しないというエラーになります。

そのため、成果物として保存したいファイルをJenkinsのワークスペース内に一時的に保存し、archiveArtifactsを実行する必要があります。

        stage('成果物の保存') {
            steps {
                bat 'xcopy "C:\\InstallShield 2022 Projects\\My Project Name-1\\Media\\CD-ROM\\Disk Images\\Disk1" "%WORKSPACE%\\tmpArtifact" /E /I /Y'
                archiveArtifacts artifacts: 'tmpArtifact/**', fingerprint: true
            }
        }

ハマったこと

検証を行う際に文字コードにはまりました。

Jenkinsのジョブコンソール画面

Jenkinsの文字コードは ダッシュボード > Jenkinsの管理 > システム情報 > システムプロパティの「file.encoding」「sun.jnu.encoding」で確認できます。
一時的に文字コードを変更して検証したい場合は、 ダッシュボード > Jenkinsの管理 > スクリプトコンソールを利用するとよいです。
「System.setProperty(‘file.encoding’, ‘UTF-8’)」や「System.setProperty(‘sun.jnu.encoding’, ‘UTF-8’)」と実行すると文字コードを変更できます。


ただし、スクリプトコンソールで変更した内容はJenkinsを再起動すると消えてしまいます。設定を常に反映させたい場合は以下の記事を参考に「-Dfile.encoding=UTF-8 -Dsun.jnu.encoding=UTF-8」のJava引数を追加してください。

How to add Java arguments to Jenkins?

注意

プラグイン

[InstallShield Jenkins]で検索をすると次のページが表示されます。
Jenkins : InstallShield Plugin
しかしこちらのプラグインは現在plugins.jenkins.ioから配布されておりません。
理由はこちらのページを参照ください。
Deprecating non-Java plugins

同時実行数

今回の様にInstallShield利用時に特定のフォルダーを利用して実行する場合、Jenkinsでジョブを並行実行することはできません。そのため、ジョブの同時実行数を制限する必要があります。

エグゼキューターの数を制限する
エグゼキューターの数を制限することで、同時に実行されるジョブの数を制限することができます。
ダッシュボード > Jenkinsの管理 > ノードの管理 > master > 設定に画面遷移し、同時実行数を1に変更します。

Throttle Concurrent Builds プラグインを利用する
上記のエグゼキューターの数でも制限は可能ですが、複数ノードがある場合実現できないことがあります。
その場合Throttle Concurrent Buildsプラグインを利用します。
このプラグインを利用することで、特定のジョブやカテゴリ内のジョブの同時実行数を制限でき、複数ノードが存在する場合でも同時実行数を制限できます。

Build Blocker プラグインを利用する
Build Blockerプラグインを用いることでも、複数ノードが存在する場合でも同時実行数を制限できます。
ただし、こちらはジョブの「設定」によって設定するため、Jenkinsのジョブタイプによっては設定できないものもあります。フリースタイル・プロジェクトのビルドやパイプラインでは設定項目が表示されましたが、Multibranch Pipelineでは設定項目が表示されませんでした。

まとめ

Jenkinsというとビルドやテストの自動化という点で取り上げられることが多いですが、このようなインストーラーの作成の自動化にも活用できます。

もし「手動でインストーラーを毎回作成している」といった場合は、Jenkinsの導入を検討してみてはいかがでしょうか。

宣伝

興味は沸いたがノウハウが無いのでとっかかりが欲しい

CI/CD環境構築
「スモールスタートしたい」「ちょっと興味はあるんだけどうちの開発は少し特殊でネット上の情報も有益なものが無い」「やりたいことはなんとなくイメージはつくんだけど実現・実装方法について相談したい」など、環境構築についてお困りなことがある方は是非お問合せいただければと思います。

Jenkinsについて詳しく学習したい

Jenkinsについて体系的に学習をしたい方という方は、Jenkinsのトレーニングを受講をお勧めします
Jenkinsトレーニング
バックアップやユーザー管理、セキュリティ等、Jenkinsの管理者向けの「Jenkins 管理-基礎」、パイプライン初心者向けの「パイプライン基礎」、共有ライブラリといったパイプラインの発展的な内容を扱う「パイプライン中級」とレベル別に体系的に学習することができます。
各開発環境ごとに適したパイプラインは異なると思いますので、ぜひ体系的に知識を身に着けて、開発環境の改善に役立ててください。

By nagakubo

主にCI環境構築をメインで担当しています。 Certified CloudBees Jenkins Engineer (CCJE)