ブランチのプレビューを別々に保つ

GitBeginner
オンラインで実践に進む

はじめに

Cedar & Common は、地域の交流イベントを計画しています。公式プログラムはすでに公開されており、候補となる 2 つのプランには、それぞれ独立したプレビューが必要です。Jenkins は両方のブランチをビルドできますが、現在の Pipeline は同じ場所に公開してしまいます。ビルドが成功するだけでは、両方の案を利用できる状態には保てません。

この実習では、ブランチを確認し、その衝突を観察してから、それぞれの Jenkinsfile を変更し、利用できる 2 つのプレビューを公開します。その後、一方の集合時刻を変更し、もう一方のプランを維持したまま、そのプレビューだけが更新されることを確認します。

前提知識は、基本的なターミナル入力とパス、Jenkins のページ操作、短い Declarative Pipeline を見て理解できることです。Git のブランチ、コミット、プッシュ、インデックス作成、および新しく使う Pipeline の設定については、使う前に説明します。リポジトリ、Java のビルドプログラム、公開処理、Jenkins プラグインは準備済みです。インストールや Web サイトの作成は行いません。これは 1 台の VM 上のローカルな練習用ソースサービスとプレビューサービスであり、GitHub や本番のデプロイ基盤ではありません。所要時間は著者による見積もりで、初心者による実測値ではありません。

プランとそのブランチのビルドを確認する

このステップでは、通常のプログラムと候補のソースを確認してから、ブランチのジョブを検出し、共有プレビューの衝突を観察します。Preview Desk から始めてください。

Open the official program を選びます。Common Ground Day と 09:30 を確認します。Explore this plan を選び、3 つのアクティビティとルートのイラストを確認してください。Download the activities で実際の CSV を、Read visitor notes で案内の全文を確認します。ブラウザーの Back 操作で概要ページに戻り、もう一度 Back でデスクに戻ります。Read the courtyard notes も開き、Courtyard Stories を確認してください。作業中は、この既存の 2 つのプログラムを常に利用できる状態に保つ必要があります。

Source に切り替えます。このターミナルは Git の作業コピーです。編集できるファイルは、その時点で選択している 1 つのブランチに属します。ブランチとは、名前を付けたソース履歴の流れです。ブランチを切り替えると、作業ファイルはそのブランチのバージョンに変わります。もう一方のブランチは変わりません。コミットとは、リポジトリの内容を記録したバージョンで、ハッシュで識別されます。この識別子によって、Jenkins のビルドとそのソースを結び付けます。

ターミナルは /home/labex/project/community-site で開きます。pwd は現在のディレクトリを表示します。git --no-pager branch --list はローカルブランチを一覧表示し、選択中のブランチに * を付けます。--no-pager は結果をターミナルに直接表示するための指定です。このオプションがない場合、Git は対話型のビューアーを開くことがあります。シェルのプロンプトではなく (END) が表示されたら、q を押してビューアーを終了します。次を実行してください。

pwd
git --no-pager branch --list

一覧には main、courtyard-notes、garden-plan、river-plan が含まれています。初期状態では garden-plan が選択されています。誤ってディレクトリを移動した場合は、続ける前に cd /home/labex/project/community-site で戻ってください。

cat は、ファイルを変更せずに内容を表示します。event.properties には、タイトル、集合の詳細、アクティビティの設定が、1 行につき 1 つの key=value 形式で保存されています。この小さなデータファイルを読みます。

cat event.properties

Garden Gathering、集合時刻 10:00、集合場所 Glasshouse gate が記載されています。meeting_time の行は、用意されたビルドプログラムが使うデータです。このプログラムは、ページ、CSV、案内をまとめて生成します。

git switch は、この作業コピーのブランチを選択します。もう一方の候補と比較してから、元に戻ります。

git switch river-plan
cat event.properties
git switch garden-plan

もう一方のプランは Riverside Picnic で、14:00 に River steps で集合します。これらは実際に異なるソースファイルであり、1 つのページに別のブランチ名のバッジを付けているだけではありません。

編集できる範囲は、候補ブランチの Jenkinsfile と、後で依頼される meeting_time の変更(event.properties 内)です。テンプレート、ルート画像、ビルドプログラム、公開処理は変更しないでください。準備済みの Jenkins プロジェクトやブランチジョブの編集、削除、名前変更、再作成は禁止です。Git と Jenkins のすべての履歴、保存されたすべてのプレビューアーカイブ、main と courtyard-notes のブランチ、公式プログラム、中庭のプレビューを維持してください。この演習では Docker や管理者コマンドは必要ありません。

ここで、どちらの候補が 10:00 に始まり、どちらが 14:00 に始まるかを確認してください。候補のプレビューは、まだ公開されていません。

次に、Jenkins 標準のブランチ検出を実行し、成功したビルドと実際の公開結果を比較します。Jenkins に切り替え、Dashboard から community-previews を開きます。

準備済みのこの親ジョブは、Multibranch Pipeline です。Git リポジトリをスキャンして Jenkinsfile を含むブランチを探し、それぞれに子の Pipeline ジョブを作成します。ソースには、この練習環境内の小さな読み取り専用 Git サービスを使います。作業コピーに準備された origin は、後でプッシュしてソース変更を公開する先のリポジトリです。外部アカウントや認証情報は必要ありません。

Jenkins のページの読み込みが完了するまで待ち、Scan Multibranch Pipeline Now を選びます。Scan Multibranch Pipeline Log を開き、Finished: SUCCESS を待ちます。スキャンは garden-plan と river-plan を検出します。main と courtyard-notes には Jenkinsfile がないため、候補のジョブにはなりません。パンくずリストの community-previews で戻ります。両方の子ビルドが完了するまで待ちます。

garden-plan、その番号付きビルド、Console Output の順に開きます。出力には、Garden Gathering、10:00、チェックアウトしたソースリビジョンが示されているはずです。community-previews で戻り、river-plan を開いて、その番号付きビルドのコンソールを確認します。Riverside Picnic、14:00、そのソースリビジョンが示されているはずです。両方とも SUCCESS で終わる必要があります。この準備済み環境では、チェックアウトが成功する前に Git ツールの Using Default メッセージが出ることがあります。チェックアウトの完了は、実際のリビジョンと最終結果を読んで判断してください。

Source に切り替えます。用意された Pipeline を読みます。

cat Jenkinsfile

options { skipDefaultCheckout() } は、Declarative Pipeline による暗黙のソースチェックアウトを無効にし、明示された Check out this branch ステージで行うようにします。checkout scm は、この Jenkinsfile を提供した特定のブランチリビジョンを使います。固定ブランチのチェックアウトに置き換えないでください。

用意された Build preview ステージは、チェックアウトしたソースから実際の来場者用ファイルを生成します。Archive preview は preview.zip を Jenkins に保存し、その後 Publish preview が同じバイト内容をローカルのデスクに送ります。最後の post ブロックでは、deleteDir() でそのビルドのワークスペースを消去します。これらのステージとクリーンアップを維持してください。

environment ブロックは各ステージに値を提供します。現在、両方のブランチに同じ設定があります。

PREVIEW_KEY = 'shared'

PREVIEW_KEY はデスクの公開先アドレスを選択します。リテラル文字列 'shared' は、ソースのチェックアウトが異なっていても、両方のビルドを 1 つの場所に送ってしまいます。Preview Desk に戻って再読み込みします。shared という候補カードが 1 枚あり、最後に公開したブランチが表示されています。その Open preview リンクを選び、タイトルを、成功した 2 つのソースビルドと比較してください。この 1 つのアドレスでは、独立した 2 つのプレビューを共有できません。

ブラウザーの Back 操作でデスクに戻ります。公式プログラムと中庭の案内は、引き続き利用できる必要があります。ブランチのジョブが別々でも、公開結果が自動的に別々になるわけではないことを観察できました。

ブランチごとに独立したプレビューを用意する

このステップでは、各ブランチの Jenkinsfile を変更して公開し、独立した両方のプレビューをビルドします。Source の /home/labex/project/community-site から始めてください。

Jenkins は、Multibranch のビルドに env.BRANCH_NAME を提供します。これは garden-plan などの現在のブランチ名です。共有の値を、この Jenkins 標準のブランチ識別情報に置き換えます。

PREVIEW_KEY = "${env.BRANCH_NAME}"

Groovy の二重引用符では、${...} に変数の値を埋め込めます。この式を一重引用符で囲むと、その文字がそのまま保持されてしまいます。この演習のブランチ名は、プレビューのアドレスに適した、単純な小文字とハイフンで構成されています。これは、任意のブランチ名を安全な形式に変換する一般的なルールではありません。

まず garden の候補を選びます。git status --short は、未コミットの変更を簡潔に表示します。M は変更済みファイルを意味し、何も表示されなければ作業コピーに未コミットの変更はありません。nano は、指定したファイルを開くターミナル用エディターです。保存して終了するまで、このターミナルを使います。

git switch garden-plan
git status --short
nano Jenkinsfile

nano は、このターミナルで指定したファイルを編集します。矢印キーで PREVIEW_KEY の行に移動してください。Home で行頭に移動し、Ctrl+K を 1 回押して、その 1 行を切り取ります。上記の置き換え行を、字下げも含めてすべて入力し、Enter を押して、次の RECEIVER_URL の行と分けてください。追加の行を切り取らないでください。Ctrl+O で保存し、Enter で Jenkinsfile を確定して、Ctrl+X で終了します。ここでの Ctrl は、macOS でも Control キーを押したまま操作することを意味します。

Git の履歴に記録する前に、編集内容を確認します。git diff は作業ファイルとコミット済みのバージョンを比較します。先ほどと同じく、--no-pager はターミナルに直接表示する指定です。-- はオプションとファイルパスを区切ります。次を実行してください。

git --no-pager diff -- Jenkinsfile

差分には、古い PREVIEW_KEY の行の削除と、新しい行の追加だけが表示されるはずです。先頭の - と + は、削除と追加を示す記号で、ファイルに入力する文字ではありません。意図しない変更が含まれていたら、nano Jenkinsfile を開き直し、修正して保存・終了し、再確認してください。ファイルが見つからないというエラーが出た場合は、pwd を実行し、上記の作業ディレクトリに戻ります。

コミット(commit)は、ステージしたソース変更を選択中のブランチに記録します。git add はこのファイルをステージし、git commit -m は指定したメッセージとともに記録します。git push origin garden-plan は、そのブランチを準備済みの origin リポジトリに公開し、Jenkins が新しいコミットを検出できるようにします。これらのコミット用コマンドでは、二重引用符で複数語のメッセージを 1 つの引数にまとめています。これらのコマンドが変更するのはソース履歴であり、公開中のプレビューを直接変更するわけではありません。

git add Jenkinsfile
git commit -m "Give the garden plan its own preview"
git push origin garden-plan

次に、もう一方の候補に同じ設定を適用します。

git switch river-plan
git status --short
nano Jenkinsfile

同じ nano 操作と、二重引用符を含む正確な式を使い、PREVIEW_KEY の行だけを置き換えます。保存して終了します。このブランチを確認し、コミットしてプッシュします。

git --no-pager diff -- Jenkinsfile
git add Jenkinsfile
git commit -m "Give the river plan its own preview"
git push origin river-plan

未コミットの変更があるため Git がブランチの切り替えを拒否した場合は、まず git status --short を実行し、現在のブランチの差分を確認してください。切り替える前に、意図した編集を完了するか修正します。ファイルの変更を破棄したり、リポジトリをリセットしたりしないでください。意図した変更をすでにコミットした後で、git commit がコミットするものがないと表示した場合は、git --no-pager log -1 --oneline を確認して、ブランチのプッシュに進みます。-1 は表示を 1 コミットに制限し、--oneline は短い識別子とメッセージを表示します。

Jenkins に切り替え、パンくずリストで community-previews に戻り、もう一度 Scan Multibranch Pipeline Now を選びます。このローカルの演習には Webhook がないため、ソースをプッシュするだけではスキャンは要求されません。スキャンと、両方の新しい子ビルドが正常に完了するまで待ちます。各コンソールには、それぞれのブランチのプレビューキーが表示される必要があります。ビルドで Groovy の構文エラーが出た場合は、Source でその Jenkinsfile の引用符と波括弧を修正し、そのブランチで修正をコミットしてプッシュし、再スキャンしてください。ソースの代わりに、自動生成された子ジョブを編集してはいけません。

Preview Desk に切り替えて再読み込みします。garden-plan と river-plan のカードが、別々に表示される必要があります。以前の共有カードは、先ほど観察した結果として残っている場合があります。各候補の Open preview リンクを開き、正しいタイトル、集合時刻、3 つのアクティビティ、ルート画像、CSV、来場者向けの案内を確認してください。プランを確認した後は、ブラウザーの Back 操作でその概要ページに戻り、もう一度 Back でデスクに戻ってから、もう一方のカードを開きます。2 つのプレビューのアドレスは異なり、同時に利用できる必要があります。

garden-plan と river-plan の独立したカードを表示する Preview Desk

それぞれのタイトルと元の集合時刻の上に、garden-plan と river-plan のキーがあることを確認してください。残された shared カードは、以前の衝突を示しています。どちらの独立したプレビューの代わりにもなりません。

Jenkins で、各ブランチの最新の成功ビルドの状態ページを開き、Build Artifacts から preview.zip をダウンロードします。それぞれの ZIP を別々の新しいフォルダーに展開し、index.html を開きます。7 つのファイルはすべて同じフォルダーに置いてください。ページと添付ファイルはローカルでも使える必要があります。テキストの添付ファイルは、再度ダウンロードされずに直接開く場合があります。build.json は、実際のソースブランチとコミットを示します。これらの完全なプレビューが成果物です。ビルドの緑色の表示が 2 つあるだけでは不十分です。

一方のプランを更新し、もう一方を維持する

このステップでは、garden の集合時刻を変更し、もう一度スキャンして、そのブランチのプレビューだけを更新します。Jenkins から始め、最新の成功した river-plan のビルド番号を控えてください。比較のため、そのプレビューを開いたままにします。

Source に切り替えます。garden ブランチを選び、小さなデータファイルを編集します。

git switch garden-plan
git status --short
nano event.properties

meeting_time の行全体だけを、meeting_time=10:00 から次の内容に変更します。

meeting_time=10:30

Pipeline の行で使ったのと同じ操作で、矢印キー、Home、1 回の Ctrl+K、置き換えのテキスト、Enter を使います。Ctrl+O、Enter で保存し、Ctrl+X で終了してください。ビルドプログラムは、この 1 つの値を読んで、ページ、CSV、案内の内容を一致させます。生成された来場者用ファイルは編集しません。

このソース更新を確認し、公開します。

git --no-pager diff -- event.properties
git add event.properties
git commit -m "Move the garden meeting to 10:30"
git push origin garden-plan

差分では、この集合時刻だけが変更されるはずです。そうでなければ、コミット前にファイルを修正してください。river ブランチにはソース変更を加えません。

Jenkins に切り替え、community-previews に戻り、Scan Multibranch Pipeline Now を選びます。インデックス作成の後、garden ジョブは変更されたリビジョンで新しいビルドを実行するはずです。変更のない river ブランチは、控えたビルド番号を維持するはずです。garden のビルドが SUCCESS で完了するまで待ちます。Console Output を開き、新しいコミットと 10:30 をソース変更に照らし合わせてください。

スキャンが変更なしと表示し、garden のプレビューが古いままの場合は、Source に戻ります。git status --short と git --no-pager log -1 --oneline を確認し、意図した変更が garden-plan でコミットされたことを確かめ、そのブランチをプッシュしてから再スキャンします。origin に届いていないローカルのファイル編集やコミットは、まだ Jenkins が検出できるソースではありません。ビルドが失敗した場合はコンソールを読み、示されたソースのエラーを別のコミットとプッシュで修正します。VM のリセットや、用意されたビルドプログラムの置き換えは行わないでください。

Preview Desk に切り替えて再読み込みします。garden-plan を開きます。Garden Gathering の集合時刻が 10:30 になっている必要があります。Explore this plan、ダウンロードしたアクティビティの CSV、来場者向けの案内の全文を確認してください。集合時刻がすべて一致している必要があります。river-plan を開きます。Riverside Picnic は、引き続き 14:00 に集合し、元のアクティビティと利用可能な添付ファイルを維持している必要があります。その build.json は、以前のソースコミットと Jenkins 標準のビルド番号を維持している必要があります。この最後の更新中に、変更のない子ジョブを再実行してはいけません。

Jenkins に戻り、最新の garden の preview.zip をダウンロードします。別の新しいフォルダーに展開し、ローカルのページ、画像、CSV、案内をもう一度確認します。新しい garden のコミットを示している必要があります。先ほどダウンロードした river のパックは、引き続き独立して使えるはずです。

最後に Preview Desk に戻り、Open the official program と Read the courtyard notes を開き、両方のプログラムが欠けることなく維持されていることを確認します。元のブランチ履歴とビルド履歴を残してください。さらにソースを編集した場合は、完了をチェックする前に、コミット、プッシュを行い、対応する Jenkins ビルドを完了させます。2 つの公開中のプレビューと、一方の更新でもう一方が上書きも再ビルドもされなかった証拠が得られました。

まとめ

Jenkins 標準の Multibranch 検出と、各 Jenkinsfile に対応するソースリビジョンを使い、Jenkins のブランチ識別情報によって公開先を分けました。両方のプランは、それぞれ独立したアドレスで、利用できるページ、画像、添付ファイルを持つようになりました。その後の garden のコミットは、自分のプレビューだけを更新し、river のビルド、公式プログラム、中庭のプレビューは維持されました。