# 画面設計書 60-スクリプトコンソール

## 概要

本ドキュメントは、Groovyスクリプトを実行するスクリプトコンソール画面の設計仕様を定義するものである。

### 本画面の処理概要

スクリプトコンソール画面は、Jenkins管理者がGroovyスクリプトをサーバー上で直接実行できるインタラクティブなコンソールを提供する画面である。

**業務上の目的・背景**：Jenkinsの高度な管理作業や、通常のUIでは提供されていない操作を行う必要がある場合、スクリプトコンソールは強力なツールとなる。プラグインの一覧取得、設定の一括変更、データのマイグレーション、デバッグ情報の収集など、様々な管理タスクをGroovyスクリプトで自動化できる。ただし、この機能はJenkinsの内部APIに直接アクセスできるため、誤った操作はシステムに重大な影響を与える可能性があり、管理者権限を持つユーザーのみがアクセスできる。

**画面へのアクセス方法**：Jenkins管理画面から「Script Console」リンクをクリック、または直接`/script`にアクセスする。ノードのスクリプトコンソールは`/computer/{ノード名}/script`でアクセス可能。

**主要な操作・処理内容**：
1. Groovyスクリプトの入力
2. スクリプトの実行
3. 実行結果の表示
4. 結果のコピー

**画面遷移**：
- 遷移元：Jenkins管理画面（ManageJenkinsAction）、ノード詳細画面
- 遷移先：なし（同一画面で結果表示）

**権限による表示制御**：`Jenkins.ADMINISTER`権限を持つユーザーのみアクセス可能。この機能は非常に強力なため、最高レベルの権限が必要。

## 関連機能

| 機能No | 機能名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 44 | Groovyコンソール | 主機能 | Groovyスクリプトの実行 |
| 1 | Jenkins本体 | 補助機能 | Jenkinsオブジェクトへのアクセス |

## 画面種別

操作（コンソール）

## URL/ルーティング

- URL: `/script` (マスター)、`/computer/{ノード名}/script` (ノード)
- テンプレート: `core/src/main/resources/jenkins/model/Jenkins/_script.jelly`
- 共通テンプレート: `core/src/main/resources/lib/hudson/scriptConsole.jelly`
- POSTアクション: `/script`

## 入出力項目

| 項目名 | 項目ID | 入力/出力 | 型 | 必須 | 説明 |
|--------|--------|----------|-----|------|------|
| スクリプト | script | 入力 | String | 必須 | 実行するGroovyスクリプト |
| 実行結果 | output | 出力 | String | - | スクリプトの実行結果 |

## 表示項目

| 項目名 | 表示条件 | 説明 |
|--------|----------|------|
| タイトル | 常時 | "Script Console" |
| 説明文 | 常時 | スクリプトコンソールの概要説明 |
| スクリプト入力エリア | 常時 | Groovyスクリプト入力用テキストエリア |
| Runボタン | 常時 | スクリプト実行ボタン |
| Result | 実行後 | 実行結果セクション |
| コピーボタン | 実行後 | 結果をクリップボードにコピー |
| 結果表示 | 実行後 | スクリプトの出力 |
| オフラインメッセージ | ノードオフライン時 | 実行不可のメッセージ |
| サンプルスクリプト | 常時 | 実行例として表示されるサンプルコード |

## イベント仕様

### 1-ページ読み込み

ページ読み込み時にフォームを表示。前回のスクリプトがリクエストパラメータに含まれていれば復元。

処理フロー：
1. 権限チェック（`Jenkins.ADMINISTER`）
2. チャネルの接続状態を確認
3. スクリプト入力フォームを表示

### 2-スクリプト実行

「Run」ボタン押下時に`doScript()`が呼び出される。

処理フロー：
1. `Jenkins.ADMINISTER`権限の確認
2. スクリプトの監査ログ記録（`ScriptListener.fireScriptExecution()`）
3. `RemotingDiagnostics.executeGroovy()`でスクリプト実行
4. 出力の監査ログ記録（`ScriptListener.fireScriptOutput()`）
5. 結果を画面に表示

### 3-結果コピー

コピーボタン押下時に結果をクリップボードにコピー。

処理フロー：
1. `l:copyButton`コンポーネントによるJavaScript実行
2. 結果テキストをクリップボードにコピー

## データベース更新仕様

### 操作別データベース影響一覧

スクリプトコンソール自体はデータを更新しないが、実行されるスクリプトの内容によっては任意のデータ更新が可能。

| 操作（イベント） | 対象テーブル | 操作種別 | 概要 |
|----------------|-------------|---------|------|
| スクリプト実行 | スクリプト依存 | スクリプト依存 | 実行されるスクリプトによる |

## メッセージ仕様

| メッセージID | 種別 | メッセージ内容 | 表示条件 |
|-------------|------|--------------|----------|
| scriptConsole | 情報 | Script Console | 画面タイトル |
| description | 情報 | スクリプトコンソールの説明 | ページ説明 |
| description2 | 情報 | 追加の説明文 | ページ説明 |
| Run | 情報 | Run | ボタンラベル |
| Result | 情報 | Result | 結果セクションタイトル |
| successfullyCopied | 成功 | Successfully copied | コピー成功時 |
| clickToCopy | 情報 | Click to copy | ツールチップ |
| impossibleOffline | 警告 | Cannot execute scripts on offline nodes | ノードオフライン時 |

## 例外処理

| 例外種別 | 発生条件 | 処理内容 |
|----------|----------|----------|
| 権限不足 | ADMINISTER権限がない | アクセス拒否 |
| ノードオフライン | 対象ノードが接続されていない | 「impossibleOffline」メッセージを表示 |
| スクリプトエラー | Groovyスクリプトで例外発生 | スタックトレースを結果に表示 |

## 備考

- スクリプトはJenkinsのサーバープロセス内で実行される
- `out`変数を使って出力を記述（`PrintWriter`）
- 実行結果は`Result: {戻り値}`の形式で表示される
- 例外発生時はスタックトレースが表示される
- スクリプト実行は`ScriptListener`で監査ログに記録される
- `RemotingDiagnostics.executeGroovy()`で実行され、リモートノードでも動作可能
- CodeMirrorエディタによるGroovyシンタックスハイライトが有効
- サンプルスクリプト: `println(Jenkins.instance.pluginManager.plugins)`

---

## コードリーディングガイド

本画面を理解するために参照すべきファイルと、推奨する読み解き順序を以下に示す。

### 推奨読解順序

#### Step 1: データ構造を理解する

まず、スクリプト実行の仕組みを理解することが重要。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | RemotingDiagnostics.java | `core/src/main/java/hudson/util/RemotingDiagnostics.java` | スクリプト実行のコアロジック |
| 1-2 | ScriptListener.java | `core/src/main/java/jenkins/util/ScriptListener.java` | 監査ログの記録 |

**読解のコツ**: `executeGroovy()`がどのように`GroovyShell`を使ってスクリプトを評価するかを把握する。

#### Step 2: エントリーポイントを理解する

処理の起点となるファイル・関数を特定。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | _script.jelly | `core/src/main/resources/jenkins/model/Jenkins/_script.jelly` | マスター用エントリー |
| 2-2 | scriptConsole.jelly | `core/src/main/resources/lib/hudson/scriptConsole.jelly` | 共通テンプレート |

**主要処理フロー**:
1. **31行目（_script.jelly）**: `t:scriptConsole`タグでコンソールを表示
2. **39行目（scriptConsole.jelly）**: `permission="${app.ADMINISTER}"`で権限チェック
3. **49行目（scriptConsole.jelly）**: `it.channel`でチャネル状態を確認
4. **59-64行目（scriptConsole.jelly）**: スクリプト入力フォーム
5. **67-73行目（scriptConsole.jelly）**: 結果表示

#### Step 3: バックエンド処理を理解する

スクリプト実行のサーバーサイド処理。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | RemotingDiagnostics.java | `core/src/main/java/hudson/util/RemotingDiagnostics.java` | `executeGroovy()`メソッド（121-128行目） |
| 3-2 | RemotingDiagnostics.java | `core/src/main/java/hudson/util/RemotingDiagnostics.java` | `Script`内部クラス（130-175行目） |

**主要処理フロー**:
- **122-123行目**: 相関IDとコンテキストの生成
- **124行目**: `ScriptListener.fireScriptExecution()`で監査ログ
- **125行目**: `channel.call(new Script(script))`でスクリプト実行
- **126行目**: `ScriptListener.fireScriptOutput()`で出力の監査ログ
- **148-154行目**: `CompilerConfiguration`とインポートの設定
- **159-165行目**: スクリプト評価と結果のフォーマット

### プログラム呼び出し階層図

```
/script アクセス
    │
    └─ scriptConsole.jelly レンダリング
           │
           ├─ 権限チェック (ADMINISTER)
           │
           ├─ it.channel 確認
           │      ├─ null: オフラインメッセージ
           │      └─ 存在: フォーム表示
           │
           └─ "Run" クリック → /script POST
                  │
                  └─ doScript()
                         │
                         ├─ ScriptListener.fireScriptExecution()
                         │
                         ├─ RemotingDiagnostics.executeGroovy()
                         │      │
                         │      └─ Script.call()
                         │             ├─ GroovyShell作成
                         │             ├─ インポート設定
                         │             ├─ shell.evaluate(script)
                         │             └─ 結果フォーマット
                         │
                         └─ ScriptListener.fireScriptOutput()
```

### データフロー図

```
[入力]                      [処理]                           [出力]

Groovyスクリプト ──────▶ ┌─────────────────────────┐
                          │ RemotingDiagnostics    │
                          │                         │
                          │ 1. 監査ログ記録         │
                          │ 2. GroovyShell作成      │
                          │ 3. インポート設定       │
                          │ 4. shell.evaluate()     │
                          │ 5. 結果フォーマット     │
                          │ 6. 出力監査ログ         │
                          │                         │
                          └─────────────────────────┘
                                   │
                                   ▼
                          ┌─────────────────────────┐
                          │ 結果表示                │
                          │ - 戻り値: Result: xxx   │
                          │ - 例外: スタックトレース│
                          └─────────────────────────┘
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| _script.jelly | `core/src/main/resources/jenkins/model/Jenkins/_script.jelly` | テンプレート | マスター用エントリー |
| scriptConsole.jelly | `core/src/main/resources/lib/hudson/scriptConsole.jelly` | テンプレート | 共通テンプレート |
| RemotingDiagnostics.java | `core/src/main/java/hudson/util/RemotingDiagnostics.java` | ソース | スクリプト実行 |
| ScriptListener.java | `core/src/main/java/jenkins/util/ScriptListener.java` | ソース | 監査ログ |
| groovy.js | CodeMirror | JavaScript | シンタックスハイライト |
