mcpField
M
messages

messages

github.com/github開発5.5k53 回インストール今日更新
リポジトリ

messages について

safe-output メッセージシステムに型を追加するための開発ガイドです。コントリビューター向けに、スキーマ、Go パーサー、JavaScript モジュール、テスト、バンドル、ドキュメントの更新手順を示します。

主な機能

  1. 01JSON Schema と Go 構造体の更新
  2. 02メッセージ設定の解析
  3. 03JavaScript メッセージモジュールの作成
  4. 04テストとエクスポートの追加
  5. 05埋め込みスクリプトの登録と文書更新

活用シーン

  1. 01カスタマイズ可能な safe-output メッセージの追加
  2. 02Go と JavaScript 間でのメッセージ型の連携
  3. 03新しいメッセージ実装の検証とバンドル

インストール

コマンドをコピーしてターミナルで実行します。

$npx skills add https://github.com/github/gh-aw --skill messages

インストール後、Claude Code で/messagesを入力して読み込まれたか確認します。

詳細

新しいメッセージタイプの追加ガイド

このガイドでは、安全な出力メッセージシステムに新しいメッセージタイプを追加し、フロントマター、コンパイラーでの解析、JavaScript、バンドルで利用できるようにする方法を説明します。

概要

メッセージシステムを使うと、ワークフローの作成者は安全な出力メッセージをカスタマイズできます。メッセージの流れ:

  1. フロントマター(YAML)→ 2. JSON Schema → 3. Go コンパイラー → 4. JavaScript モジュール → 5. バンドラー

Step 1: JSON Schema を更新する

pkg/parser/schemas/main_workflow_schema.json の messages オブジェクトに新しいメッセージフィールドを追加します:

{
  "messages": {
    "properties": {
      "my-new-message": {
        "type": "string",
        "description": "Description of when this message is used. Available placeholders: {placeholder1}, {placeholder2}.",
        "examples": [
          "Example message with {placeholder1}"
        ]
      }
    }
  }
}

重要なポイント:

  • YAML フィールド名には kebab-case を使用します(例:my-new-message)
  • 説明には使用可能なすべてのプレースホルダーを記載します
  • 参考になる例を用意します
  • 変更後に make build を実行します(スキーマはバイナリに埋め込まれます)

Step 2: Go 構造体を更新する

pkg/workflow/compiler.go の SafeOutputMessagesConfig に新しいフィールドを追加します:

type SafeOutputMessagesConfig struct {
	// ... existing fields ...
	MyNewMessage string `yaml:"my-new-message,omitempty" json:"myNewMessage,omitempty"` // Description of the message
}

重要なポイント:

  • Go のフィールド名には CamelCase を使用します
  • YAML タグには kebab-case を使用します(フロントマターと一致させます)
  • JSON タグには camelCase を使用します(JavaScript で使用します)
  • 両方のタグに omitempty を追加します

Step 3: Go パーサーを更新する

必要に応じて、pkg/workflow/safe_outputs.go のパーサーを更新します:

func parseMessagesConfig(messagesMap map[string]any) *SafeOutputMessagesConfig {
	config := &SafeOutputMessagesConfig{}
	// ... existing parsing ...
	
	if myNewMessage, ok := messagesMap["my-new-message"].(string); ok {
		config.MyNewMessage = myNewMessage
	}
	
	return config
}

注: パーサーはほとんどのフィールドでリフレクションを使用するため、単純な文字列フィールドの場合、この手順は不要なことがあります。

Step 4: JavaScript メッセージモジュールを作成する

新しいファイル pkg/workflow/js/messages_my_new.cjs を作成します:

// @ts-check
/// <reference types="@actions/github-script" />

/**
 * My New Message Module
 *
 * This module provides the my-new-message generation
 * for [describe when it's used].
 */

const { getMessages, renderTemplate, toSnakeCase } = require("./messages_core.cjs");

/**
 * @typedef {Object} MyNewMessageContext
 * @property {string} placeholder1 - Description of placeholder1
 * @property {string} placeholder2 - Description of placeholder2
 */

/**
 * Get the my-new-message, using custom template if configured.
 * @param {MyNewMessageContext} ctx - Context for message generation
 * @returns {string} The generated message
 */
function getMyNewMessage(ctx) {
  const messages = getMessages();

  // Create context with both camelCase and snake_case keys
  const templateContext = toSnakeCase(ctx);

  // Default message template
  const defaultMessage = "Default message with {placeholder1} and {placeholder2}";

  // Use custom message if configured
  return messages?.myNewMessage
    ? renderTemplate(messages.myNewMessage, templateContext)
    : renderTemplate(defaultMessage, templateContext);
}

module.exports = {
  getMyNewMessage,
};

重要なポイント:

  • ファイル名:messages_<category>.cjs(サブフォルダーではなくフラットな構成)
  • 共通ユーティリティは ./messages_core.cjs からインポートします
  • 型定義には JSDoc を使用します
  • 適切なデフォルトメッセージを用意します
  • カスタムテンプレートとデフォルトテンプレートの両方に対応します

Step 5: テストを追加する

pkg/workflow/js/messages_my_new.test.cjs を作成します:

import { describe, it, expect, beforeEach, vi } from "vitest";

// Mock core global
const mockCore = {
  warning: vi.fn(),
};
global.core = mockCore;

describe("getMyNewMessage", () => {
  beforeEach(() => {
    vi.clearAllMocks();
    delete process.env.GH_AW_SAFE_OUTPUT_MESSAGES;
  });

  it("should return default message when no custom message configured", async () => {
    const { getMyNewMessage } = await import("./messages_my_new.cjs");

    const result = getMyNewMessage({
      placeholder1: "value1",
      placeholder2: "value2",
    });

    expect(result).toBe("Default message with value1 and value2");
  });

  it("should use custom message when configured", async () => {
    process.env.GH_AW_SAFE_OUTPUT_MESSAGES = JSON.stringify({
      myNewMessage: "Custom: {placeholder1}",
    });

    const { getMyNewMessage } = await import("./messages_my_new.cjs");

    const result = getMyNewMessage({
      placeholder1: "test",
      placeholder2: "ignored",
    });

    expect(result).toContain("Custom: test");
  });
});

make test-js を実行してテストします。

Step 6: コアモジュールの TypeDef を更新する

pkg/workflow/js/messages_core.cjs の SafeOutputMessages typedef に新しいプロパティを追加します:

/**
 * @typedef {Object} SafeOutputMessages
 * @property {string} [footer] - Custom footer message template
 * // ... existing properties ...
 * @property {string} [myNewMessage] - Custom my-new-message template
 */

さらに、getMessages() 関数の戻り値オブジェクトも更新します:

return {
  footer: rawMessages.footer,
  // ... existing fields ...
  myNewMessage: rawMessages.myNewMessage,
};

Step 7: バレルファイルを更新する

pkg/workflow/js/messages.cjs に再エクスポートを追加します:

// Re-export my new messages
const { getMyNewMessage } = require("./messages_my_new.cjs");

module.exports = {
  // ... existing exports ...
  getMyNewMessage,
};

Step 8: Go の埋め込みに登録する

pkg/workflow/js.go に追加します:

//go:embed js/messages_my_new.cjs
var messagesMyNewScript string

GetJavaScriptSources() に追加します:

func GetJavaScriptSources() map[string]string {
	return map[string]string{
		// ... existing entries ...
		"messages_my_new.cjs": messagesMyNewScript,
	}
}

Step 9: 呼び出し元のスクリプトで使用する

必要なスクリプトでは、対象のモジュールから直接インポートします:

const { getMyNewMessage } = require("./messages_my_new.cjs");

// Use the message
const message = getMyNewMessage({
  placeholder1: actualValue1,
  placeholder2: actualValue2,
});

Step 10: ドキュメントを更新する

scratchpad/safe-output-messages.md を更新します:

  1. 「Message Categories」セクションに新しいメッセージを追加する
  2. プレースホルダーと使い方を記載する
  3. 例を追加する

Message Module Architecture の表を更新します:

| Module | Purpose | Exported Functions |
|--------|---------|-------------------|
| `messages_my_new.cjs` | My new message description | `getMyNewMessage` |

検証チェックリスト

コミットする前に、次の項目を確認してください:

  • pkg/parser/schemas/main_workflow_schema.json の JSON Schema を更新した
  • pkg/workflow/compiler.go の Go 構造体を更新した
  • 必要に応じて、pkg/workflow/safe_outputs.go の Go パーサーが新しいフィールドを処理するようにした
  • JavaScript モジュールを作成した:pkg/workflow/js/messages_my_new.cjs
  • テストを作成した:pkg/workflow/js/messages_my_new.test.cjs
  • messages_core.cjs の TypeDef を更新した
  • バレルファイルを更新した:messages.cjs
  • js.go に Go の埋め込みディレクティブを追加した
  • GetJavaScriptSources() のマップに追加した
  • 呼び出し元のスクリプトを更新し、必要最小限のインポートを使用するようにした
  • scratchpad/safe-output-messages.md のドキュメントを更新した
  • テストが成功する:make test-js
  • ビルドが成功する:make build
  • Lint が成功する:make lint

ファイルの概要

ファイル目的必要な変更
pkg/parser/schemas/main_workflow_schema.jsonJSON Schemaフィールド定義を追加
pkg/workflow/compiler.goGo 構造体構造体フィールドを追加
pkg/workflow/safe_outputs.goパーサー必要に応じて解析ロジックを追加
pkg/workflow/js/messages_my_new.cjsJavaScript モジュール新しいファイルを作成
pkg/workflow/js/messages_my_new.test.cjsテスト新しいファイルを作成
pkg/workflow/js/messages_core.cjsコアユーティリティtypedef を更新
pkg/workflow/js/messages.cjsバレルファイル再エクスポートを追加
pkg/workflow/js.goGo の埋め込みembed ディレクティブを追加
scratchpad/safe-output-messages.mdドキュメント新しいメッセージを記載

例:close-older-discussion メッセージの追加

このメッセージタイプは、次の手順で追加されました。

  1. スキーマ:プレースホルダー {new_discussion_number}、{new_discussion_url}、{workflow_name}、{run_url} を含む close-older-discussion フィールドを追加
  2. Go 構造体:CloseOlderDiscussion string フィールドを追加
  3. JavaScript:getCloseOlderDiscussionMessage() を含む messages_close_discussion.cjs を作成
  4. テスト:対応するテストファイルを追加
  5. バンドラー:GetJavaScriptSources() に登録
  6. コンシューマー:直接インポートして close_older_discussions.cjs で使用

実装例については、これらのファイルを参照してください。

コメント