change-management について
ServiceNow の変更管理を扱うスキルです。インフラ変更の申請、承認、タスク、状態遷移を説明し、関連する MCP ツールとワークフローの例も示します。
主な機能
- 01標準・通常・緊急変更の区分
- 02変更申請とタスクの作成
- 03影響を受ける CI の関連付け
- 04承認状況とスケジュール競合の確認
- 05変更状態の管理
活用シーン
- 01サーバーパッチ変更の計画
- 02変更への実施タスクと CI の追加
- 03承認状況の追跡と状態の更新
MCP 対応
変更の作成・検索、状態更新、CAB のスケジュールに使う MCP ツールと、ワークフロー例を記載しています。
インストール
コマンドをコピーしてターミナルで実行します。
$
npx skills add https:/ / github.com/ serac-labs/ serac --skill change-managementインストール後、Claude Code で/change-managementを入力して読み込まれたか確認します。
詳細
ServiceNow の変更管理
変更管理では、標準化されたプロセスと承認を通じて、IT インフラストラクチャへの変更を確実に管理します。
変更タイプ
| タイプ | 承認 | リスク | 例 |
|---|---|---|---|
| 標準 | 事前承認 | 低 | パスワードリセットテンプレート |
| 通常 | CAB 承認 | 中 | サーバーパッチ適用 |
| 緊急 | 実装後の承認 | 高 | 本番環境の障害対応 |
変更リクエストの構造
Change Request: CHG0010001
├── Risk Assessment
│ ├── Impact: Medium
│ ├── Risk: Low
│ └── Conflict Status: Clear
├── Schedule
│ ├── Planned Start: 2024-03-15 22:00
│ └── Planned End: 2024-03-15 23:00
├── Approvals
│ ├── Manager Approval: Approved
│ └── CAB Approval: Pending
├── Change Tasks
│ ├── Task 1: Backup current config
│ ├── Task 2: Apply patches
│ └── Task 3: Verify functionality
└── Affected CIs
├── PROD-WEB-001
└── PROD-DB-001
変更の作成
通常の変更(ES5)
// Create normal change request
var change = new GlideRecord("change_request")
change.initialize()
// Basic info
change.setValue("short_description", "Apply security patches to web servers")
change.setValue("description", "Monthly security patch deployment for production web tier")
change.setValue("type", "normal") // normal, standard, emergency
// Classification
change.setValue("category", "Software")
change.setValue("priority", 3)
// Risk assessment
change.setValue("risk", "low") // high, moderate, low
change.setValue("impact", 2) // 1-High, 2-Medium, 3-Low
// Schedule
var startDate = new GlideDateTime()
startDate.addDaysLocalTime(7)
startDate.setValue("2024-03-15 22:00:00")
change.setValue("start_date", startDate)
var endDate = new GlideDateTime(startDate)
endDate.addSeconds(3600) // 1 hour
change.setValue("end_date", endDate)
// Assignment
change.setValue("assignment_group", getGroupSysId("Change Management"))
change.setValue("assigned_to", getOnCallUser())
// Implementation plan
change.setValue(
"implementation_plan",
"1. Take backup of current configuration\\n" +
"2. Stop web services\\n" +
"3. Apply security patches\\n" +
"4. Restart services\\n" +
"5. Verify functionality",
)
change.setValue(
"backout_plan",
"1. Stop web services\\n" + "2. Restore from backup\\n" + "3. Restart services\\n" + "4. Verify rollback successful",
)
change.setValue(
"test_plan",
"1. Check web server response\\n" + "2. Verify all pages load\\n" + "3. Run automated health checks",
)
var changeSysId = change.insert()
緊急の変更(ES5)
// Create emergency change
var emergencyChange = new GlideRecord("change_request")
emergencyChange.initialize()
emergencyChange.setValue("short_description", "Emergency: Fix production database connection leak")
emergencyChange.setValue("type", "emergency")
emergencyChange.setValue("priority", 1)
emergencyChange.setValue("risk", "high")
emergencyChange.setValue("impact", 1)
// Emergency justification
emergencyChange.setValue(
"justification",
"Production database connections exhausted causing service outage. " + "Immediate fix required to restore service.",
)
// Immediate start
emergencyChange.setValue("start_date", new GlideDateTime())
var endDate = new GlideDateTime()
endDate.addSeconds(7200) // 2 hours
emergencyChange.setValue("end_date", endDate)
emergencyChange.insert()
// Emergency changes bypass normal CAB
gs.eventQueue("change.emergency.created", emergencyChange)
標準の変更(ES5)
// Create from standard change template
function createStandardChange(templateName, variables) {
// Find template
var template = new GlideRecord("std_change_producer")
template.addQuery("name", templateName)
template.query()
if (!template.next()) {
gs.error("Standard change template not found: " + templateName)
return null
}
// Create change from template
var change = new GlideRecord("change_request")
change.initialize()
// Copy template values
change.setValue("short_description", template.getValue("short_description"))
change.setValue("description", template.getValue("description"))
change.setValue("type", "standard")
change.setValue("std_change_producer", template.getUniqueValue())
// Apply variables
for (var key in variables) {
if (variables.hasOwnProperty(key) && change.isValidField(key)) {
change.setValue(key, variables[key])
}
}
return change.insert()
}
// Usage
createStandardChange("Password Reset", {
requested_by: userSysId,
cmdb_ci: applicationSysId,
})
変更タスク
変更タスクの作成(ES5)
// Add tasks to change
function addChangeTask(changeSysId, taskConfig) {
var task = new GlideRecord("change_task")
task.initialize()
task.setValue("change_request", changeSysId)
task.setValue("short_description", taskConfig.description)
task.setValue("order", taskConfig.order)
task.setValue("assignment_group", taskConfig.group)
task.setValue("planned_start_date", taskConfig.start)
task.setValue("planned_end_date", taskConfig.end)
return task.insert()
}
// Create implementation tasks
var tasks = [
{ description: "Pre-implementation backup", order: 100, group: "Database Team" },
{ description: "Apply patches", order: 200, group: "Server Team" },
{ description: "Verify functionality", order: 300, group: "QA Team" },
{ description: "Update documentation", order: 400, group: "Change Management" },
]
for (var i = 0; i < tasks.length; i++) {
addChangeTask(changeSysId, tasks[i])
}
影響を受ける CI
CI を変更にリンクする(ES5)
// Add affected CIs
function addAffectedCI(changeSysId, ciSysId) {
var task = new GlideRecord("task_ci")
task.initialize()
task.setValue("task", changeSysId)
task.setValue("ci_item", ciSysId)
return task.insert()
}
// Add all affected servers
var servers = ["server1_sys_id", "server2_sys_id", "db_sys_id"]
for (var i = 0; i < servers.length; i++) {
addAffectedCI(changeSysId, servers[i])
}
承認
承認状況の確認(ES5)
// Get approval status
function getApprovalStatus(changeSysId) {
var approvals = []
var approval = new GlideRecord("sysapproval_approver")
approval.addQuery("sysapproval", changeSysId)
approval.query()
while (approval.next()) {
approvals.push({
approver: approval.approver.getDisplayValue(),
state: approval.state.getDisplayValue(),
comments: approval.getValue("comments"),
sys_updated_on: approval.getValue("sys_updated_on"),
})
}
return approvals
}
承認のリクエスト(ES5)
// Add approval request
function requestApproval(changeSysId, approverSysId) {
var approval = new GlideRecord("sysapproval_approver")
approval.initialize()
approval.setValue("sysapproval", changeSysId)
approval.setValue("approver", approverSysId)
approval.setValue("state", "requested")
return approval.insert()
}
変更の競合検出
競合の確認(ES5)
// Check for scheduling conflicts
function checkChangeConflicts(changeSysId) {
var change = new GlideRecord("change_request")
if (!change.get(changeSysId)) return []
var conflicts = []
var startDate = change.getValue("start_date")
var endDate = change.getValue("end_date")
// Find overlapping changes on same CIs
var affected = new GlideAggregate("task_ci")
affected.addQuery("task", changeSysId)
affected.groupBy("ci_item")
affected.query()
while (affected.next()) {
var ciSysId = affected.ci_item.toString()
// Find other changes affecting this CI
var otherChanges = new GlideRecord("change_request")
otherChanges.addQuery("sys_id", "!=", changeSysId)
otherChanges.addQuery("state", "NOT IN", "closed,cancelled")
otherChanges.addQuery("start_date", "<=", endDate)
otherChanges.addQuery("end_date", ">=", startDate)
// Join to task_ci
otherChanges.addJoinQuery("task_ci", "sys_id", "task").addCondition("ci_item", ciSysId)
otherChanges.query()
while (otherChanges.next()) {
conflicts.push({
change: otherChanges.getValue("number"),
ci: ciSysId,
start: otherChanges.getValue("start_date"),
end: otherChanges.getValue("end_date"),
})
}
}
return conflicts
}
状態遷移
変更状態
| 状態 | 次の状態 | 条件 |
|---|---|---|
| 新規 | 評価 | 送信済み |
| 評価 | 承認、キャンセル | 評価完了 |
| 承認 | スケジュール済み、キャンセル | 承認完了 |
| スケジュール済み | 実装、キャンセル | メンテナンス時間内 |
| 実装 | レビュー、キャンセル | タスク完了 |
| レビュー | クローズ | PIR 完了 |
| クローズ | - | 最終状態 |
変更の遷移(ES5)
// Move change to next state
function transitionChange(changeSysId, newState, notes) {
var change = new GlideRecord("change_request")
if (!change.get(changeSysId)) {
gs.error("Change not found: " + changeSysId)
return false
}
// Validate transition
var currentState = change.getValue("state")
var validTransitions = {
"-5": ["-4", "4"], // New -> Assess or Cancelled
"-4": ["-3", "4"], // Assess -> Authorize or Cancelled
"-3": ["-2", "4"], // Authorize -> Scheduled or Cancelled
"-2": ["-1", "4"], // Scheduled -> Implement or Cancelled
"-1": ["0", "4"], // Implement -> Review or Cancelled
0: ["3"], // Review -> Closed
}
if (!validTransitions[currentState] || validTransitions[currentState].indexOf(newState) === -1) {
gs.error("Invalid state transition: " + currentState + " -> " + newState)
return false
}
change.setValue("state", newState)
if (notes) {
change.work_notes = notes
}
change.update()
return true
}
MCP ツール統合
利用可能な変更ツール
| ツール | 目的 |
|---|---|
snow_change_manage (action='create') | 変更を作成 |
snow_change_manage (action='create_task') | タスクを追加 |
snow_change_query (action='get') | 詳細を取得 |
snow_change_manage (action='update_state') | 状態を遷移 |
snow_change_query (action='search') | 変更を検索 |
snow_change_manage (action='schedule_cab') | CAB をスケジュール |
ワークフローの例
// 1. Create change (scheduling happens later via action: "update_state" -> "scheduled")
var changeId = await snow_change_manage({
action: "create",
short_description: "Database upgrade",
type: "normal",
risk: "medium",
})
// 2. Add tasks
await snow_change_manage({
action: "create_task",
sys_id: changeId,
short_description: "Backup database",
})
// 3. Check conflicts: search for overlapping open changes in the same window
// (see checkChangeConflicts above for per-CI conflict detection)
var conflicts = await snow_change_query({
action: "search",
query: "stateNOT INclosed,cancelled^start_date<=2024-03-21 02:00:00^end_date>=2024-03-20 22:00:00",
})
// 4. Submit for approval
await snow_change_manage({
action: "update_state",
sys_id: changeId,
state: "assess",
})
ベストプラクティス
- ドキュメントの完成 - 実装、ロールバック、テスト計画
- リスク評価 - リスクと影響度を正確に評価
- CI のリンク - 影響を受けるすべての CI を添付
- 適切なスケジュール設定 - メンテナンス時間内に実施
- タスクの分割 - 明確な実装手順
- 承認チェーン - 必要な承認をすべて取得
- 競合チェック - 変更の重複がないことを確認
- PIR - 教訓を得るための実装後レビュー
コメント
Markdown 対応