【UiPath】CI/CD環境の構築その２（Jenkins編）

# 1. はじめに

* 前回の記事 [UiPath CI/CD環境の構築（Jenkins編）その１](https://qiita.com/MasahiroHarada1105/items/fd549a56f60689bbe6d9) では、UiPathのCI/CD環境をJenkins上に構築してジョブを手動で実行するところまで書きました。
* 本記事では、GitHubのリポジトリの特定のブランチにファイルがプッシュされたことをトリガーとしてJenkinsのジョブを実行させたいと思います。

https://qiita.com/MasahiroHarada1105/items/fd549a56f60689bbe6d9

# 2. ブランチにファイルがプッシュされたことをトリガーとしてジョブが実行されると何がうれしいのか

* 開発者の方にブランチにプッシュする前にテストを実行してもらうようルールを定めていても強制力がなくルールが形骸化することも多いかと思います。
* CI/CDの仕組みを取り入れることで、開発者がブランチにプッシュするとJenkinsがテストプロジェクトのビルドからOrchestratorへのパブリッシュ、テストケースの実行まで行ってくれるのでテストケースの実行忘れを防ぐことができます。

# 3. ブランチにファイルがプッシュされたことを検知する方法

JenkinsがGitHubのリポジトリにファイルがプッシュされたことを検知する方法はいろいろありますが、本記事では下記2種類の方法について記載します。
* SCMポーリング
* Generic Webhook Trigger

以降個別に設定手順を説明します（前回の記事同様フリースタイル・プロジェクトをベースとしています。パイプラインをご利用の場合は適時読み替えてください）。

## 3-1. SCMポーリング

Jenkinsが定期的にGitHub等のSCM（Source Code Management）のリポジトリに差分がないかを確認しに行く方法になります。起動スケジュールはcron方式で記述します。

### 設定

プロジェクト -> 設定 -> ビルド・トリガにある「SCMをポーリング」にチェックを入れます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3322296/5512bdad-6370-fa4a-f37a-145d55dd3246.png)
スケジュールにポーリング間隔をcron方式で記述します。
書式：```分 時 日 月 曜日```

| 設定例 | 意味 |
|:-|:-|
| H/15 * * * *        | 15分毎に実行 |
| H(0-29)/10 * * * *  | 0 ～ 29分の間のみ10分間隔で実行 |
| 45 9-16/2 * * 1-5   | 平日9時45分から15時45分まで、2時間に1回45分に実行 |
| H H(8-15)/2 * * 1-5 | 平日8時から16時までの2時間に1回に実行 |
| H H 1,15 1-11 *     | 12月を除く毎月1日と15日に各1回に実行 |

```* * * * *``` とすると毎分ポーリングが実行されてしまいSCMに負荷をかけてしまうことになります。必要以上に間隔を狭めないよう設定してください。

以上で設定は終わりです。

## 3-2. Generic Webhook Trigger

GitHub側でイベント（例：リポジトリにコードがプッシュされた）が発生したタイミングでJenkinsのWebhookを呼び出す仕組みです。この方式ではGitHubに対する変更通知を即時に受け取ることができます。

https://plugins.jenkins.io/generic-webhook-trigger/

### 設定
#### 3-2-1. Jenkinsの設定

Generic Webhook Trigger Pluginをインストールします。インストールがされていない場合は、Jenkinsの管理 -> Pluginsからインストールしてください。
インストールが完了したらジョブの設定を開いて、「Generic Webhook Trigger」にチェックを入れます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3322296/27a5219a-6033-8cce-ff25-f9fb7f0b9325.png)
**Post content parameters** セクションにパラメータを追加します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3322296/a5f95f98-c8b5-62d2-1654-c00cedadc236.png)

| 項目 | 内容 |
|:-|:-|
| Name of variable | payload （任意の名前を設定ください） |
| Expression | $.payload[0] |

:::note info
本当はブランチ名のみ変数に格納したかったのですが、Expressionに ```$.ref``` と指定しても想定通りに動作させることができませんでした。そのため本記事ではpayload全体を変数に格納してフィルターをかけています。
:::

**Token** を設定します。任意の値を指定することができます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3322296/c3965d65-dc51-036e-d53d-8826fcc9239b.png)
**Optional filter** にトリガーする条件を記載します。今回は、featureブランチにコードがプッシュされたときのみビルドを実行するようにします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3322296/fa74fcbc-6242-a4c7-25c5-0b3267099ae9.png)

Expression にフィルター条件となる正規表現、Text に評価する値または変数を記載します。
| 項目 | 内容 |
|:-|:-|
| Expression | .\*"ref":"refs\\/heads\\/feature\*.\* |
| Text       | $payload                              |

:::note info
GitHub以外のSCMではpayloadの内容が異なる可能性があります。Expressionに指定する正規表現は利用するSCMに応じて変更ください。
:::

#### 3-2-2. GitHubの設定

リポジトリのメニューSettings -> Webhooksを選択して「Add webhook」をクリックします。認証を求められるのでパスワードを入力して進みます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3322296/e94b6af2-1215-6765-cc06-ae099242f0bf.png)
Webhookの設定をします。必要な情報を入力したら「Add webhook」をクリックして登録します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3322296/6c721219-acdc-5981-1101-aece7ab94e41.png)

こちらが設定内容です。
| 項目 | 値 |
|:-|:-|
| Payload URL | 下記参照 |
| Content type | application/x-www-form-urlencoded |
| Which events would you like to trigger this webhook? | Just the push event. |
| Active | チェック |

:::note info
**Payload URLについて**
```http(s)://[JENKINS_HOST]/generic-webhook-trigger/invoke?token=[TOKEN]``` の形式で設定します。
例：https://your_jenkins_domain.com/generic-webhook-trigger/invoke?token=123456
:::

以上で設定は終わりです。

# 4. どちらの方法を使うとよいのか

可能であればGeneric Webhook TriggerのようなGitHubからの通知を受け取りジョブを実行する方式を採用したいところですが、CI/CDを構築しているネットワーク環境によっては、Jenkinsが外部からのWebhook通知を受け取れない場合もあるかと思います。そのような場合は、SCMポーリングでジョブをトリガすることになるかと思います。

# 5. ジョブを組んでみる

今回はfeatureブランチにファイルがプッシュされたことをトリガーとしてOrchestratorでテストケースを実行するジョブを組んでみます。

長いですがジョブの全体は以下となります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3322296/2416bd13-8808-3c12-aadd-59dbb4ce6d0b.png)

以下のパートは前回の記事 [UiPath CI/CD環境の構築（Jenkins編）その１](https://qiita.com/MasahiroHarada1105/items/fd549a56f60689bbe6d9) と同じ設定となりますので適時参照ください。
* General
* ソースコード管理
* ビルド環境

前回と異なる箇所は、ビルド・トリガに「SCMをポーリング」、ビルド後の処理に「UiPathのテストを実行」タスクを指定しているところです。

:::note
プロジェクト中にパブリッシュ可能として設定されているテストケースが一つも存在しない状態で「UiPathのテストを実行」タスクを実行すると下記エラーのためジョブの実行に失敗します。下記エラーでジョブが失敗する場合は、Studioでテストケースをパブリッシュ可能に変更してください。
```
A testing project should contain at least one entry point.
```
:::

:::note warn
UiPath Plugin バージョン ```3.0``` で、JUnit Plugin バージョン ```1217.v4297208a_a_b_ce``` またはそれ以上のバージョンを使用している場合、「UiPathのテストを実行」タスクを実行すると下記エラーのためジョブの実行に失敗します。
```
java.lang.AbstractMethodError: Receiver class com.uipath.uipathpackage.UiPathTest does not define or inherit an implementation of the resolved method 'abstract boolean isKeepProperties()' of interface hudson.tasks.junit.JUnitTask.
```
上記エラーを解消するには、JUnit Pluginのバージョン ```1214.va_2f9db_3e6de0``` 以降にダウングレードしていただく必要があります。
:::

「UiPathのテストを実行」タスクの設定項目は以下となります。タスクのみでテストプロジェクトのビルドからOrchestratorへのパブリッシュ、フォルダへのデプロイ及びテストケースの実行まで行ってくれます。
<table>
  <thead>
    <tr>
      <th>項目</th>
      <th>値</th>
    </tr>
  </thead>
  <tr>
    <td>ターゲット</td>
    <td>テストプロジェクトを実行</td>
  </tr>
  <tr>
    <td>プロジェクトのパス</td>
    <td>project.json</td>
  </tr>
  <tr>
    <td>Orchestratorのアドレス</td>
    <td>https://cloud.uipath.com/</td>
  </tr>
  <tr>
    <td>Orchestratorテナント</td>
    <td>DefaultTenant</td>
  </tr>
  <tr>
    <td>Orchestratorのフォルダー</td>
    <td>Shared</td>
  </tr>
  <tr>
    <td>認証</td>
    <td>外部アプリケーションを使用してCloud Orchestratorに認証</td>
  </tr>
  <tr>
    <td>Identity Url</td>
    <td>入力なし</td>
  </tr>
  <tr>
    <td>Account Name</td>
    <td>
      <code>https://cloud.uipath.com/[アカウント名]/[テナント名]</code><br />
      上記URLの[アカウント名]を入力
    </td>
  </tr>
  <tr>
    <td>Application Id</td>
    <td>Orchestrator外部アプリケーションの登録で取得したアプリID</td>
  </tr>
  <tr>
    <td>Application Secret</td>
    <td>Jenkinsに登録したCredentialの説明が表示されているはずなのでそのままでOK</td>
  </tr>
  <tr>
    <td>Application Scope(s)</td>
    <td>Orchestrator外部アプリケーションの登録で設定したスコープの一覧</td>
  </tr>
</table>

# 6. ジョブを実行してみよう

ジョブを作成したので、いよいよジョブを実行してみましょう。
ソースコード管理で指定したブランチにファイルをプッシュすることでジョブが実行されます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3322296/a942de84-44c1-b8d1-3f33-83ff5f837955.png)

ジョブが実行されると、Orchestrator上にテストプロジェクトがパブリッシュ、デプロイされテストケースが実行されます。テストの実行が完了すると、Jenkinsに以下のようにテストの実行結果が表示されるようになります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3322296/2aefc0b3-6bd1-07d2-b2be-78097ebeb0e0.png)
テストケース毎の実行結果も確認することができます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3322296/196e0b04-c420-7bf8-a859-87e9d7a6e7e6.png)

# 7. おわりに
* 特定のブランチへのプッシュをトリガーとしてテストケースを実行させることができました。
* 検証環境ではfeatureブランチ等の開発用ブランチへのプッシュ時にテストケースを自動で実行させるようにしておき、本番環境へのプロジェクトのパブリッシュ、デプロイは手動でJenkinsのジョブを実行するなど環境に応じてジョブの手動、自動実行を使い分けていただければと思います。
* 次回は応用編としてJenkins UiPathプラグインで提供されていない機能をCI/CDに組み込む方法を紹介していますので是非ご覧ください。

https://qiita.com/MasahiroHarada1105/items/0d3eb734794f6c4651d7