This directory contains custom GitHub Actions for the gh-aw project. These actions are used internally by compiled workflows to provide functionality such as MCP server file management.
Each action follows a standard structure:
actions/{action-name}/
├── action.yml # Action metadata and configuration
├── index.js # Bundled action code (generated, committed)
├── src/ # Source files
│ └── index.js # Main action source
└── README.md # Action-specific documentation
Copies workflow script files to the agent environment. This action embeds all necessary JavaScript files used across all workflow jobs and copies them to a specified destination directory.
Installs the gh-aw CLI extension for a specific version. Supports both release tags and commit SHAs that resolve to releases.
Processes noop safe output - a fallback output type that logs messages for transparency without taking any GitHub API actions.
Minimizes (hides) a comment using the GraphQL API.
Closes a GitHub issue.
Closes a GitHub pull request.
Closes a GitHub discussion.
Actions are built using the Go-based build system that reuses the bundler and script registry infrastructure from the workflow compiler.
The build process:
- Reads source files from
actions/{action-name}/src/ - Identifies and embeds required JavaScript dependencies from
pkg/workflow/js/ - Uses the same bundler infrastructure as workflow compilation
- Bundles everything into
actions/{action-name}/index.js - Validates
action.ymlfiles
# Build all actions (generates index.js files)
make actions-build
# or
gh aw actions-build
# Validate action.yml files
make actions-validate
# or
gh aw actions-validate
# Clean generated files
# Clean generated files
make actions-clean
# or
gh aw actions-cleanThe build system uses:
- Bundler Infrastructure: Same JavaScript bundler used for workflow compilation (
pkg/workflow/bundler.go) - Script Registry: Centralized registry for managing JavaScript sources (
pkg/workflow/script_registry.go) - Embedded Sources: All JavaScript files from
pkg/workflow/js/viaGetJavaScriptSources()
You can automatically generate action scaffolding from existing JavaScript modules in pkg/workflow/js/:
# Generate action.yml and README.md for selected JavaScript modules
make generate-action-metadata
# or
go run ./internal/tools/generate-action-metadata generateThis tool will:
- Parse JavaScript files to extract inputs (from
core.getInput()) and outputs (fromcore.setOutput()) - Extract descriptions from JSDoc comments
- Generate
action.ymlwith proper structure - Generate
README.mdwith usage examples - Copy source files to
actions/{action-name}/src/index.js
After generation, you need to:
- Review and refine the generated
action.ymlandREADME.md - Update the dependency mapping in
pkg/cli/actions_build_command.go - Run
make actions-buildto bundle dependencies
-
Create the directory structure:
mkdir -p actions/{action-name}/src -
Create action.yml: Define the action metadata, inputs, outputs, and runtime configuration.
name: 'Action Name' description: 'Action description' author: 'GitHub Next' inputs: input-name: description: 'Input description' required: false default: 'default-value' outputs: output-name: description: 'Output description' runs: using: 'node20' main: 'index.js'
-
Create source file (src/index.js): Write the action logic using
@actions/coreand@actions/github:const core = require('@actions/core'); async function run() { try { const input = core.getInput('input-name'); core.info(`Processing: ${input}`); // Action logic here core.setOutput('output-name', 'result'); } catch (error) { core.setFailed(`Action failed: ${error.message}`); } } run();
-
Update dependency mapping: Add the action to the dependency map in
pkg/cli/actions_build_command.goto specify which JavaScript files frompkg/workflow/js/should be embedded. -
Build and test:
make actions-build make actions-validate
-
Create README.md: Document the action's purpose, usage, inputs, outputs, and examples.
- Runtime: Actions must use Node.js 20 (
using: 'node20') - Dependencies: Use
@actions/coreand@actions/githubfor GitHub Actions integration - Error Handling: Always wrap main logic in try-catch and use
core.setFailed()for errors - Logging: Use
core.info(),core.warning(), andcore.error()for output - Outputs: Set outputs using
core.setOutput(name, value)
The build system supports embedding JavaScript files from pkg/workflow/js/ into actions. To use this:
-
Define a
FILESconstant in your source file:const FILES = { // This will be populated by the build script };
-
Add the files to the dependency map in
scripts/build-actions.js -
The build script will replace the empty
FILESobject with the actual file contents -
Use the embedded files in your action:
for (const [filename, content] of Object.entries(FILES)) { fs.writeFileSync(path.join(destination, filename), content, 'utf8'); }
This directory supports two types of actions:
Actions with all logic in src/index.js without additional source files.
Actions that use multiple source files in the src/ directory. The build system will bundle them together.
The build system validates:
- ✅
action.ymlexists and contains required fields - ✅
action.ymlusesnode20runtime - ✅ Source files exist in
src/directory - ✅ Required dependencies are available
- ✅
action.yml- Action metadata - ✅
index.js- Bundled action code (generated but committed) - ✅
src/- Source files - ✅
README.md- Documentation
- ❌
node_modules/- Dependencies (if any) - ❌
*.tmp- Temporary files - ❌
.build/- Build artifacts
Note: The bundled index.js files are committed to the repository because GitHub Actions requires the complete action code to be present when the action is used. This is standard practice for JavaScript actions.
Test actions locally by:
- Creating a test workflow in
.github/workflows/ - Using the action with a local path:
- uses: ./actions/setup with: destination: /tmp/test
- Running the workflow on GitHub Actions
Ensure the dependency files exist in pkg/workflow/js/ and are listed correctly in the dependency map.
Check that:
- All required inputs are provided
- The bundled
index.jsis up to date (runmake actions-build) - The action has necessary permissions
Ensure action.yml includes all required fields:
namedescriptionrunswithusing: 'node20'andmain: 'index.js'