本記事は連載「ServiceNow標準機能だけで作るPull型自動化連携」の第7回です。
第6回では、結果登録APIで自動化の結果を記録し、成功なら次の作業へ進め、失敗なら人の担当グループへ引き継ぐところまで作りました。
今回は、Business Ruleを1本だけ追加して、SCTASKの進捗をRITMのActivityに表示し、依頼者が「今どうなっているのか」を確認できるようにします。
この回で作るもの
ここまでの仕組みでは、自動化の状態はSCTASKの State × Assigned to で表されています。しかし依頼者が普段見るのはRITMで、SCTASKの変化は直接見えません。
そこで、SCTASKの状態が変わったときに、RITMの Additional comments に進捗を1行ずつ書き込みます。
| SCTASKの変化 | RITMのActivityに表示される内容 |
|---|---|
Open + autoengine1 → In Progress + autoengine1(確保) |
[Automation] Task claimed and queued. |
autoengine1 → autoengine1running(実行開始) |
[Automation] Execution started. |
| → Closed Complete(正常完了) | [Automation] Execution completed successfully. |
状態管理用のカスタムフィールドは、ここでも追加しません。既存のStateとAssigned toの変化を読み取って、表示するだけです。
1. 役割分担
結果の記録と進捗の表示は、次のように分けています。
| 情報 | 記録先 | 担当 | 読み手 |
|---|---|---|---|
| 進捗(確保・実行開始・完了) | RITMの Additional comments | 本記事のBusiness Rule | 依頼者 |
| 結果の詳細 | SCTASKの Work Notes | 結果登録API(第6回) | 運用者 |
| 結果の表示用テキスト | RITMの execution_result_display
|
結果登録API(第6回) | 依頼者 |
| 結果の履歴(機械処理用) | RITMの execution_result_json
|
結果登録API(第6回) | 後続の自動化処理 |
Business Ruleは進捗の通知だけを担当します。結果の中身や失敗の詳細は転記しません。
2. Business Ruleを作成する
System Definition > Business Rules を開き、New を選択します。
| フィールド | 設定値 |
|---|---|
| Name | SCTASK Activity to RITM |
| Table | Catalog Task [sc_task] |
| Active | true |
| Advanced | true |
| When | after |
| Order | 100 |
| Insert | false |
| Update | true |
| Delete | false |
2.1 実行条件
StateかAssigned toのどちらかが変わったときだけ動かします。Advanced Conditionを使う場合は、次を指定します。
current.state.changes() || current.assigned_to.changes()
それ以外の更新(Work Notesの追記など)では、RITMにコメントを追加しません。
2.2 なぜ after なのか
SCTASKの更新が確定した後に、別のレコード(RITM)を更新するためです。SCTASK自身の値を書き換えるわけではないので、before にする必要はありません。
3. Business Rule Script
Script欄に、次のコードを設定します。
IN_PROGRESS_STATE と CLOSED_COMPLETE_STATE は、対象インスタンスの sc_task.state の内部値に合わせてください。特に CLOSED_COMPLETE_STATE は、第6回の結果登録APIと同じ値にする必要があります。
(function executeRule(current, previous) {
'use strict';
var IN_PROGRESS_STATE = '2';
var CLOSED_COMPLETE_STATE = '3';
var WAITING_ASSIGNEE = 'autoengine1';
var RUNNING_ASSIGNEE = 'autoengine1running';
if (current.request_item.nil()) {
return;
}
var ritm = current.request_item.getRefRecord();
if (!ritm || !ritm.isValidRecord()) {
return;
}
if (!ritm.comments.canWrite()) {
gs.warn(
'SCTASK Activity to RITM: comments cannot be updated for ' +
ritm.getValue('number')
);
return;
}
var currentAssignee = getAssignedToUserName(current);
var previousAssignee = getAssignedToUserName(previous);
var message = '';
// Open + autoengine1 -> In Progress + autoengine1
if (current.state.changesTo(IN_PROGRESS_STATE) &&
currentAssignee === WAITING_ASSIGNEE) {
message = [
'[Automation] Task claimed and queued.',
'Task: ' + current.getValue('number')
].join('\n');
}
// In Progress + autoengine1 -> In Progress + autoengine1running
if (current.assigned_to.changes() &&
previousAssignee === WAITING_ASSIGNEE &&
currentAssignee === RUNNING_ASSIGNEE) {
message = [
'[Automation] Execution started.',
'Task: ' + current.getValue('number')
].join('\n');
}
// In Progress -> Closed Complete
if (current.state.changesTo(CLOSED_COMPLETE_STATE)) {
message = [
'[Automation] Execution completed successfully.',
'Task: ' + current.getValue('number')
].join('\n');
}
if (!message) {
return;
}
ritm.comments = message;
ritm.update();
function getAssignedToUserName(record) {
if (!record || !record.isValidRecord() ||
record.getElement('assigned_to').nil()) {
return '';
}
var user = record.getElement('assigned_to').getRefRecord();
return user && user.isValidRecord()
? user.getValue('user_name') || ''
: '';
}
})(current, previous);
3.1 コードのポイント
状態の変化を「前後の組み合わせ」で判定する
changesTo() と previous の値を使い、第2回で決めた状態遷移のどこを通ったかを判定しています。
| 判定 | 条件 |
|---|---|
| 確保 | Stateが In Progress に変わり、担当が autoengine1
|
| 実行開始 | 担当が autoengine1 から autoengine1running に変わった |
| 正常完了 | Stateが Closed Complete に変わった |
ユーザーはsys_idではなく user_name で比べる
第5回のAPIと同じく、インスタンスに依存しない名前で判定します。
書き込めない場合は何もしない
RITMの comments に書き込む権限がなければ、更新せずにSystem Logへ警告を出します。Business Ruleのエラーで、SCTASKの更新そのものが妨げられることはありません。
RITMに紐づかないSCTASKは対象外
request_item が空のSCTASKでは、何もしません。
3.2 失敗時はコメントを出さない
結果登録APIがFAILEDを受け取ると、SCTASKは In Progress のまま、failure_assignment_group へ引き継がれ、Assigned toは空欄になります。
- Stateは In Progress のまま変わらない → 「確保」の条件に当てはまらない
- 担当は
autoengine1runningから空欄に変わる → 「実行開始」の条件に当てはまらない - Closed Complete にはならない → 「正常完了」の条件に当てはまらない
そのため、失敗時にはBusiness Ruleからコメントは出ません。失敗の詳細は、運用者向けのWork Notesと、結果登録APIが更新する execution_result_display で扱います。
comments(Additional comments)は依頼者に表示されます。内部情報や機密情報を含めないでください。
3.3 人が担当する作業では動かない
人が担当するSCTASKは、Assigned toが autoengine1 系ではないため、「確保」と「実行開始」のコメントは出ません。
一方、「正常完了」の判定は担当者を見ていないため、人が担当するSCTASKをClosed Completeにした場合も [Automation] Execution completed successfully. が出ます。自動化の作業だけに絞りたい場合は、完了判定にも担当者の条件を追加してください。
4. 複数の自動化エンジンを使う場合
第3回で紹介したように、作業3を自動化エンジン2(autoengine2)に担当させる場合、このサンプルのままでは「確保」と「実行開始」のコメントが出ません。WAITING_ASSIGNEE と RUNNING_ASSIGNEE を autoengine1 固定で比べているためです。
複数のエンジンに対応するには、たとえば次のように、名前の規則で判定する方法があります。
function isWaitingAssignee(userName) {
return /^autoengine[0-9]+$/i.test(userName);
}
function isRunningAssignee(userName) {
return /^autoengine[0-9]+running$/i.test(userName);
}
この場合は、第5回のAPIの isAllowedAutomationUser() も同じ規則に合わせてください。
5. 表示内容
RITMのActivityには、次のように表示されます。
確保したとき
[Automation] Task claimed and queued.
Task: SCTASK0010006
実行を開始したとき
[Automation] Execution started.
Task: SCTASK0010006
正常に完了したとき
[Automation] Execution completed successfully.
Task: SCTASK0010006
Execution Planで複数の作業がある場合は、SCTASKごとにこの3行が順に並びます。依頼者は、RITMの画面だけで、どの作業まで進んだかを追えます。
6. 動作確認
第4〜6回で作ったAPIを順に呼び、RITMのActivityを確認します。
6.1 確保
-
Open + autoengine1のSCTASKを用意する - Table APIでStateを2に更新する(第4回)
- RITMのActivityに
Task claimed and queued.が追加される
6.2 実行開始
- SCTASKが
In Progress + autoengine1であることを確認する - 第5回のAPIで、Assigned toを
autoengine1runningに変更する - RITMのActivityに
Execution started.が追加される
6.3 正常完了
- 第6回の結果登録APIへSUCCESSを送る
- SCTASKがClosed Completeになる
- RITMのActivityに
Execution completed successfully.が追加される
6.4 チェックリスト
-
Business Ruleが
sc_taskの after update で動く - 確保・実行開始・正常完了で、それぞれ1件ずつコメントが追加される
- Work Notesの追記など、StateやAssigned toに関係しない更新ではコメントが追加されない
- FAILEDの結果登録では、コメントが追加されない
- RITMに紐づかないSCTASKでは、何もしない
-
CLOSED_COMPLETE_STATEが結果登録APIと同じ値になっている
次回予告
次回は、第4〜6回の処理を1本にまとめたE2Eテストスクリプトで、依頼から完了までを通しで動かします。取得 → 確保 → 詳細取得 → 実行開始 → 実行 → 結果登録の流れと、各段階で確認するポイントを紹介します。
連載記事
- 第1回 なぜ今ServiceNow標準機能だけで作る自動化連携なのか
- 第2回 全体アーキテクチャと設計方針
- 第3回 Catalog Item・Variable Set・Execution Planの準備
- 第4回 Table APIで実行待ちタスクを取得・確保する
- 第5回 Scripted REST APIでタスク詳細取得と実行開始
- 第6回 Scripted REST APIで結果を登録する
- 第7回 Business Ruleで依頼者に進捗を見せる
- 第8回 E2Eテストスクリプトで通しで動かす
- 第9回 本番化に向けた検討ポイント
※ 本記事の内容は個人の見解であり、所属する組織の公式な見解ではありません。