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…

Newsletter

Get the weekly list of safe new skills, and the ones we pulled.