github-script
Use for authoring or reviewing uses: actions/github-script@v9 workflow steps.
with.script runs as an async function body; use await import(...) for module imports.
Defaults
- Pin
actions/github-script@v9
- Runtime is Node 24
- Self-hosted runner minimum is
v2.327.1
- Prefer
github.rest.* endpoint methods; use github.request(...) for raw requests.
- For multi-token / cross-org / GitHub App scenarios,
build extra clients with the injected
getOctokit(token, opts?) factory;
do not redeclare it with const/let.
- Prefer ESM modules (
.mjs or .js with // @ts-check); avoid CommonJS (require, module.exports).
require('@actions/github') no longer works in v9 — @actions/github v9 is ESM-only.
- If authoring helpers in TypeScript, compile to
.mjs/.js and import the built file in workflow steps.
Fast workflow
- Define step
id if downstream steps need outputs.
- Prefer
context and context.payload for event data already provided.
- Pass only missing values through
env.
- Keep inline script tiny; delegate logic to external ESM file.
- Read env values via
process.env inside module only when needed.
- Use
github.rest.*, github.graphql, or github.request.
- Return value only when output needed.
- Configure retries for flaky API calls.
ESM-first architecture
- Inline
script should usually do one thing: import + call exported function.
- Put reusable logic in
scripts/*.mjs modules.
- Share logic across workflows via one core module + small entry modules.
- Typecheck modules locally (enable
checkJs in tsconfig.json or add // @ts-check for JS).
- For
.ts source files, keep runtime imports pointed at compiled JS outputs.
See references/external-files.md for patterns.
Reading order
Security rules
- Never inline
${{ ... }} expressions directly inside script.
- Expressions are evaluated before script; direct interpolation can cause
injection or invalid JavaScript.
- If value exists in
context, use it there; do not mirror into env.
- Use
env boundary and parse/validate in script.
See references/security.md for patterns.
Script arguments available in script body
github: authenticated Octokit client with pagination plugins
octokit: alias for github
getOctokit(token, opts?): factory for additional authenticated clients
(multi-token, GitHub App, cross-org).
Cannot be redeclared with const/let — it is an injected function parameter.
context: workflow run context
core, glob, io, exec
- wrapped
require plus escape hatch __original_require__ (legacy; prefer ESM import).
Note: require('@actions/github') fails in v9 because @actions/github v9 is ESM-only.
If you need source-level API details, inspect the action repo: https://github.com/actions/github-script
(for example action.yml, types/async-function.d.ts, src/main.ts).
This action (upstream model)
with.script is the body of an async function. These values are pre-defined (no
import needed):
Output model
- Function return value becomes
steps.<id>.outputs.result
- Default result encoding is JSON
- Use
result-encoding: string for raw string output
Retry model
- Enable retries with
retries: <n>
- Default retry-exempt status codes:
400,401,403,404,422
- Override with
retry-exempt-status-codes
See references/inputs-outputs-retries.md for details.
Token model
- Default token is the action's
github-token input default (typically workflow token, repo-scoped)
- Use
github-token with PAT secret for cross-repo or broader scopes
In this reference
Scope note
Upstream repository currently does not accept general contributions.
Security fixes and major breakage fixes still maintained.
1---2name: github-script3description: Writes secure actions/github-script workflow steps. Use when GitHub Actions needs inline JavaScript with GitHub API/context.4license: MIT5---67# github-script89Use for authoring or reviewing `uses: actions/github-script@v9` workflow steps.1011`with.script` runs as an async function body; use `await import(...)` for module imports.1213## Defaults1415- Pin `actions/github-script@v9`16- Runtime is Node 2417- Self-hosted runner minimum is `v2.327.1`18- Prefer `github.rest.*` endpoint methods; use `github.request(...)` for raw requests.19- For multi-token / cross-org / GitHub App scenarios,20 build extra clients with the injected `getOctokit(token, opts?)` factory;21 do not redeclare it with `const`/`let`.22- Prefer ESM modules (`.mjs` or `.js` with `// @ts-check`); avoid CommonJS (`require`, `module.exports`).23 `require('@actions/github')` no longer works in v9 — `@actions/github` v9 is ESM-only.24- If authoring helpers in TypeScript, compile to `.mjs`/`.js` and import the built file in workflow steps.2526## Fast workflow27281. Define step `id` if downstream steps need outputs.292. Prefer `context` and `context.payload` for event data already provided.303. Pass only missing values through `env`.314. Keep inline script tiny; delegate logic to external ESM file.325. Read env values via `process.env` inside module only when needed.336. Use `github.rest.*`, `github.graphql`, or `github.request`.347. Return value only when output needed.358. Configure retries for flaky API calls.3637## ESM-first architecture3839- Inline `script` should usually do one thing: `import` + call exported function.40- Put reusable logic in `scripts/*.mjs` modules.41- Share logic across workflows via one core module + small entry modules.42- Typecheck modules locally (enable `checkJs` in `tsconfig.json` or add `// @ts-check` for JS).43- For `.ts` source files, keep runtime imports pointed at compiled JS outputs.4445See `references/external-files.md` for patterns.4647## Reading order4849| Task | Read |50| -------------------- | ------------------------------------------------------------------------------------------------------ |51| Write new step | [`SKILL.md`], [`references/external-files.md`], [`references/examples.md`], [`references/security.md`] |52| Review existing step | [`SKILL.md`], [`references/security.md`], [`references/inputs-outputs-retries.md`] |53| Migrate old workflow | [`SKILL.md`], [`references/runtime-and-migrations.md`] |5455## Security rules5657- Never inline `${{ ... }}` expressions directly inside `script`.58- Expressions are evaluated before script; direct interpolation can cause59 injection or invalid JavaScript.60- If value exists in `context`, use it there; do not mirror into `env`.61- Use `env` boundary and parse/validate in script.6263See [`references/security.md`] for patterns.6465## Script arguments available in script body6667- `github`: authenticated Octokit client with pagination plugins68- `octokit`: alias for `github`69- `getOctokit(token, opts?)`: factory for additional authenticated clients70 (multi-token, GitHub App, cross-org).71 Cannot be redeclared with `const`/`let` — it is an injected function parameter.72- `context`: workflow run context73- `core`, `glob`, `io`, `exec`74- wrapped `require` plus escape hatch `__original_require__` (legacy; prefer ESM `import`).75 Note: `require('@actions/github')` fails in v9 because `@actions/github` v9 is ESM-only.7677If you need source-level API details, inspect the action repo: `https://github.com/actions/github-script`78(for example `action.yml`, `types/async-function.d.ts`, `src/main.ts`).7980### This action (upstream model)8182`with.script` is the body of an async function. These values are pre-defined (no83import needed):8485- `github`: pre-authenticated [octokit/rest.js][rest.js] client86- `context`: workflow [run context][context]87- `core`: [@actions/core]88- `glob`: [@actions/glob]89- `io`: [@actions/io]90- `exec`: [@actions/exec]91- `getOctokit`: factory function from [@actions/github];92 inherits the same plugins (retry, request-log, proxy)93- `require`: wrapped Node require (cwd-relative + local npm packages);94 use `__original_require__` for unwrapped require9596## Output model9798- Function return value becomes `steps.<id>.outputs.result`99- Default result encoding is JSON100- Use `result-encoding: string` for raw string output101102## Retry model103104- Enable retries with `retries: <n>`105- Default retry-exempt status codes: `400,401,403,404,422`106- Override with `retry-exempt-status-codes`107108See `references/inputs-outputs-retries.md` for details.109110## Token model111112- Default token is the action's `github-token` input default (typically workflow token, repo-scoped)113- Use `github-token` with PAT secret for cross-repo or broader scopes114115## In this reference116117| File | Purpose |118| ---------------------------------------- | --------------------------------------------- |119| [`references/security.md`] | injection avoidance and env-boundary patterns |120| [`references/inputs-outputs-retries.md`] | inputs, outputs, retry semantics |121| [`references/runtime-and-migrations.md`] | v5-v9 changes and upgrade checks |122| [`references/external-files.md`] | external ESM architecture, reuse, typecheck |123| [`references/examples.md`] | minimal templates for common tasks |124125## Scope note126127Upstream repository currently does not accept general contributions.\128Security fixes and major breakage fixes still maintained.129130[`SKILL.md`]: ./SKILL.md131[`references/security.md`]: ./references/security.md132[`references/inputs-outputs-retries.md`]: ./references/inputs-outputs-retries.md133[`references/runtime-and-migrations.md`]: ./references/runtime-and-migrations.md134[`references/external-files.md`]: ./references/external-files.md135[`references/examples.md`]: ./references/examples.md136[@actions/github]: https://github.com/actions/toolkit/tree/main/packages/github137[@actions/core]: https://github.com/actions/toolkit/tree/main/packages/core138[@actions/glob]: https://github.com/actions/toolkit/tree/main/packages/glob139[@actions/io]: https://github.com/actions/toolkit/tree/main/packages/io140[@actions/exec]: https://github.com/actions/toolkit/tree/main/packages/exec141[context]: https://github.com/actions/toolkit/blob/main/packages/github/src/context.ts142[rest.js]: https://octokit.github.io/rest.js/