How to Build a Custom GitHub Action in JavaScript
When a shell step gets too gnarly, a JavaScript action gives you typed inputs, outputs, and the full actions toolkit.
Define action.yml with runs: node20 and main, then use @actions/core in your script to read inputs and write outputs.
Steps
- Create action.yml declaring inputs, outputs, and a node20 runs block.
- Install @actions/core and write index.js that reads inputs and sets outputs.
- Bundle dependencies with ncc so dist/index.js is self-contained.
- Reference the action by path with uses: ./ in a test workflow.
Workflow
action.yml + index.js
# action.yml
name: 'Greet'
inputs:
who:
required: true
outputs:
message:
description: 'greeting'
runs:
using: 'node20'
main: 'dist/index.js'
# index.js
const core = require('@actions/core');
const who = core.getInput('who');
core.setOutput('message', `Hello ${who}`);
# usage
# - uses: ./
# with: { who: world }Notes
- Commit the bundled dist/ output, since the runner does not run npm install for the action.
- Latchkey managed runners run these custom-action jobs cheaper and self-heal mid-run.
Related guides
How to Build a Docker-Based GitHub ActionPackage a custom GitHub Action as a Docker container with action.yml using runs: docker, pass inputs as args,…
How to Build a Composite Action With Inputs and Outputs in GitHub ActionsBundle several shell and action steps into one reusable composite GitHub Action that accepts inputs and surfa…