messages
Instruções para adicionar novos tipos de mensagem ao sistema de mensagens de saída segura
npx skills add https://github.com/github/gh-aw --skill messagesAdding New Message Types Guide
Use this guide to add a new safe-output message type so it works in the current gh-aw pipeline: frontmatter → schema → Go compiler → JavaScript modules → action/workflow build output.
Overview
The messages system lets workflow authors customize safe-output messages. The current architecture does not rely on the old pkg/workflow/js.go embedding registry for runtime shipping.
Current flow:
- Frontmatter (YAML)
- JSON Schema
- Go Compiler
- JavaScript module under
pkg/workflow/js/oractions/setup/js/ - Action/workflow bundle generation via
make actions-buildor the relevant workflow build path
Step 1: Update JSON Schema
Add the new message field to pkg/parser/schemas/main_workflow_schema.json in the messages object:
{
"messages": {
"properties": {
"my-new-message": {
"type": "string",
"description": "Description of when this message is used. Available placeholders: {placeholder1}, {placeholder2}.",
"examples": [
"Example message with {placeholder1}"
]
}
}
}
}
Key points:
- Use
kebab-casefor the YAML field name (for examplemy-new-message) - Document placeholders in the description
- Provide helpful examples
- Rebuild the schema-backed binary or run the relevant compile checks after changes
Step 2: Update Go Struct
Add the field to SafeOutputMessagesConfig in pkg/workflow/compiler.go:
type SafeOutputMessagesConfig struct {
// ... existing fields ...
MyNewMessage string `yaml:"my-new-message,omitempty" json:"myNewMessage,omitempty"`
}
Key points:
- Use
CamelCasefor Go field names - Use
kebab-casefor YAML tags - Use
camelCasefor JSON tags - Add
omitemptyto both tags
Step 3: Update the parser if needed
If the message needs custom parsing logic, update the workflow parser in pkg/workflow/safe_outputs.go or the relevant config block. Most simple string fields will be wired automatically by the existing reflection-based parser.
Step 4: Create the JavaScript message module
Create the new module in the current shared JS location, typically pkg/workflow/js/:
// @ts-check
/// <reference types="@actions/github-script" />
const { getMessages, renderTemplate, toSnakeCase } = require("./messages_core.cjs");
/**
* @typedef {Object} MyNewMessageContext
* @property {string} placeholder1 - Description of placeholder1
* @property {string} placeholder2 - Description of placeholder2
*/
function getMyNewMessage(ctx) {
const messages = getMessages();
const templateContext = toSnakeCase(ctx);
const defaultMessage = "Default message with {placeholder1} and {placeholder2}";
return messages?.myNewMessage
? renderTemplate(messages.myNewMessage, templateContext)
: renderTemplate(defaultMessage, templateContext);
}
module.exports = {
getMyNewMessage,
};
Key points:
- File naming:
messages_<category>.cjs - Reuse
./messages_core.cjsfor shared helpers - Use JSDoc for types and default behavior
- Keep the default message sensible and deterministic
Step 5: Add tests
Create a matching test file, for example pkg/workflow/js/messages_my_new.test.cjs:
import { describe, it, expect, beforeEach, vi } from "vitest";
const mockCore = { warning: vi.fn() };
global.core = mockCore;
describe("getMyNewMessage", () => {
beforeEach(() => {
vi.clearAllMocks();
delete process.env.GH_AW_SAFE_OUTPUT_MESSAGES;
});
it("returns the default message when no custom template is 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("uses the custom template 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");
});
});
Run the relevant tests with make test-js or the targeted Vitest file.
Step 6: Update the core JS type metadata and exports
Update the SafeOutputMessages typedef and the return object in pkg/workflow/js/messages_core.cjs, and re-export the message helper from pkg/workflow/js/messages.cjs.
Step 7: Wire it into the real build path
Do not add any new //go:embed entries to pkg/workflow/js.go for a normal message module. The current system packages JavaScript through the action-generation/build path.
Instead:
- keep the JS module in
pkg/workflow/js/or the relevant action folder, - update the action dependency map or action source if needed,
- rebuild the action bundle with
make actions-build.
Step 8: Use the message in consumer scripts
const { getMyNewMessage } = require("./messages_my_new.cjs");
const message = getMyNewMessage({
placeholder1: actualValue1,
placeholder2: actualValue2,
});
Step 9: Update documentation
Document the new message in the repo’s relevant safe-output docs, and keep the examples aligned with the current action-based JavaScript build flow.
Verification Checklist
Before committing a message change:
- Frontmatter and schema updated
- Go config/struct updated if needed
- JS module created under the correct source tree
- Tests added and passing
-
messages_core.cjsandmessages.cjsupdated if relevant - Generated action/build output refreshed when required
- No stale embedding instructions are introduced for the current action-based JS build flow
References
actions/README.md- current action-generation/build workflowpkg/workflow/js/messages_core.cjs- shared safe-output message helperspkg/workflow/js/messages.cjs- message exportspkg/parser/schemas/main_workflow_schema.json- schema source of truth
Update the Message Module Architecture table:
| Module | Purpose | Exported Functions |
|--------|---------|-------------------|
| `messages_my_new.cjs` | My new message description | `getMyNewMessage` |
Notes
For current gh-aw work, keep message modules aligned with the action-generation flow instead of the historical Go-embed pattern. If you need an example, review the existing safe-output modules under pkg/workflow/js/ and the generated action files under actions/.