Skip to content
Back to skills

Messages

ASecurity

Add new safe-output message types and wire validation/rendering.

  • 5,344 stars
  • 0 votes
  • 0 copies
  • 4 views
  • Added September 2, 2026
ai-agentsjavascriptgojavagitdocumentation

Security analysis

A100/100

Scanned October 3, 2026

npx -y skills add github/gh-aw --skill messages --agent claude-code

Installs into .claude/skills of the current project.

Are you the author of Messages?

Add the live security badge to your README. It updates with every re-scan.

Security grade badge for Messages
[![Security: A — Skills Directory](https://www.skillsdirectory.com/api/skills/github-messages-gh-aw/badge)](https://www.skillsdirectory.com/skills/github-messages-gh-aw)

More formats (shields.io, HTML) on the badges page. Keep it an A: scan every change in CI with Pro.

Download with Pro
SKILL.md
---
name: messages
description: Add new safe-output message types and wire validation/rendering.
---


# Adding 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:

1. **Frontmatter** (YAML)
2. **JSON Schema**
3. **Go Compiler**
4. **JavaScript module** under `pkg/workflow/js/` or `actions/setup/js/`
5. **Action/workflow bundle generation** via `make actions-build` or 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:

```json
{
	"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-case` for the YAML field name (for example `my-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/safe_outputs_config_types.go`:

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

**Key points:**
- Use `CamelCase` for Go field names
- Use `kebab-case` for YAML tags
- Use `camelCase` for JSON tags
- Add `omitempty` to both tags

## Step 3: Wire the field in the parser

Add the field to `parseMessagesConfig` in `pkg/workflow/safe_outputs_messages_config.go`. Each field is mapped explicitly; simple string fields use `extractStringFromMap`:

```go
config.MyNewMessage = extractStringFromMap(messagesMap, "my-new-message", nil)
```

## Step 4: Create the JavaScript message module

Create the new module in the current shared JS location, typically `pkg/workflow/js/`:

```javascript
// @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.cjs` for 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`:

```javascript
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

```javascript
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.cjs` and `messages.cjs` updated 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 workflow
- `pkg/workflow/js/messages_core.cjs` - shared safe-output message helpers
- `pkg/workflow/js/messages.cjs` - message exports
- `pkg/parser/schemas/main_workflow_schema.json` - schema source of truth

Update the Message Module Architecture table:
```markdown
| 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/`.

Attribution

Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.

Comments

Loading comments…