Skip to main content

Creating JavaScript Actions

1. Creating Node.js Action

Property Value Description
name "My Node.js Action" Name of the action as it appears in the UI
description "A simple Node.js action example" Short description of what the action does
inputs { greeting: { required: true, default: "Hello" } } Input parameters the action accepts
outputs { message: { value: "${{ steps.my-step.outputs.message }}" } } Outputs that the action exposes
runs { using: "node16", main: "dist/index.js" } How the action is executed

Example: Node.js Action Structure

const core = require('@actions/core');
const github = require('@actions/github');

async function run() {
  const greeting = core.getInput('greeting');
  const message = `${greeting}, World!`;
  
  core.setOutput('message', message);
}

run().catch(error => core.setFailed(error.message));

Example: Action Manifest (action.yml)

name: 'My Node.js Action'
description: 'A simple Node.js action example'
inputs:
  greeting:
    required: true
    default: 'Hello'
outputs:
  message:
    description: 'The generated message'
runs:
  using: node16
  main: dist/index.js
Note: Ensure that your action is built and transpiled to dist/index.js before publishing.

2. Defining Action Entry Point

Property Value Description
main src/main.js Entry point for the JavaScript action
uses actions/javascript@v1 Reference to the JavaScript action in the workflow

Example: Defining Action Entry Point

const { getInput, setOutput } = require('@actions/core');

const input = getInput('input');
setOutput('output', `Processed: ${input}`);

3. Using Actions Toolkit

The Actions Toolkit is a JavaScript library that simplifies building GitHub Actions. It provides utilities for handling inputs, outputs, logging, and interacting with the GitHub Actions runtime.

Feature Description Usage
core Core utilities for input/output, logging, and environment handling. const core = require('@actions/core');
github GitHub REST API client for interacting with GitHub. const github = require('@actions/github');
io Utilities for file system operations. const io = require('@actions/io');

Example: Reading Inputs

const core = require('@actions/core');

try {
  const name = core.getInput('name');
  core.setOutput('greeting', `Hello, ${name}!`);
} catch (error) {
  core.setFailed(error.message);
}

Example: Setting Outputs

const core = require('@actions/core');

core.setOutput('result', 'success');
core.setOutput('timestamp', new Date().toISOString());

Example: Logging Messages

const core = require('@actions/core');

core.info('This is an info message');
core.warning('This is a warning');
core.error('This is an error');

Example: Using GitHub API

const { GitHub, getOctokitOptions } = require('@actions/github');
const core = require('@actions/core');

async function run() {
  const token = core.getInput('token');
  const octokit = new GitHub(token);
  
  const { data } = await octokit.rest.repos.get({
    owner: 'octocat',
    repo: 'Hello-World'
  });
  
  core.setOutput('repo-name', data.name);
}

run().catch(error => core.setFailed(error.message));

4. Getting Action Inputs

Input Description Type Required
name The name of the input parameter string Yes
description A description of the input parameter string No
required Whether the input parameter is required boolean No
default The default value if the input is not provided string No
options A list of valid values for the input parameter array No

Example: Using Inputs in a JavaScript Action

const core = require('@actions/core');

const input = core.getInput('my-input');
console.log(`Input value: ${input}`);

5. Setting Action Outputs

Property Description Example
name Name of the output result
value Value to set as output ${{ steps.step1.outputs.result }}

Example: Setting an Output in JavaScript Action

const core = require('@actions/core');

// Set output value
core.setOutput('result', 'success');

// Access output in workflow
// result: ${{ steps.myaction.outputs.result }}
Note: Outputs are available to subsequent steps in the same job.

6. Setting Failed Status

Property Description Values
core.setFailed() Sets the action's status to failed string

Example: Setting Failed Status

import { core } from '@actions/core';

try {
  // Some operation that might fail
  const result = performOperation();
  if (!result) {
    core.setFailed('Operation failed');
  }
} catch (error) {
  core.setFailed(error.message);
}

7. Logging Messages

Example: Using console.log in a JavaScript Action

const core = require('@actions/core');

function run() {
  console.log("This is a debug message");
  core.info("This is an info message");
  core.warning("This is a warning message");
  core.error("This is an error message");
}

run();
Method Description Usage
core.info() Logs an info-level message core.info("Processing file...")
core.warning() Logs a warning-level message core.warning("File not found")
core.error() Logs an error-level message core.error("Failed to process")
Note: Messages logged with console.log are visible in the logs but not as structured messages. Use core.info, core.warning, and core.error for better visibility in the GitHub Actions UI.

Example: Logging with context

const core = require('@actions/core');

const fileName = 'data.json';
const fileSize = 1024;

core.info(`Processing file: ${fileName}`);
core.info(`File size: ${fileSize} bytes`);

if (fileSize > 512) {
  core.warning(`File ${fileName} is larger than 512 bytes`);
}

8. Grouping Logs

GitHub Actions allows you to group related log output using the group and endgroup commands. This helps organize logs for better readability, especially in complex workflows.

Command Description Usage
::group::<name> Starts a new log group with the specified name ::group::Build Logs
::endgroup:: Ends the current log group ::endgroup::

Example: Grouping Logs in a Workflow

name: Log Grouping Example
on: [push]

jobs:
  build:
    runs-on: ubuntu-latest
    steps:
      - name: Setup Node.js
        uses: actions/checkout@v4

      - name: Grouped Build Logs
        run: |
          echo "::group::Installing Dependencies"
          npm install
          echo "::endgroup::"

          echo "::group::Running Tests"
          npm test
          echo "::endgroup::"
Note: Log groups are only visible in the GitHub Actions UI and do not affect the actual execution of the workflow.

9. Masking Values

When working with secrets or sensitive data in GitHub Actions, it's important to mask values to prevent them from being exposed in logs or outputs. GitHub Actions provides built-in masking capabilities to help secure sensitive information.

Property Description Usage
log mask Masks sensitive values in logs to prevent exposure Use echo "::add-mask::<secret_value>"

Example: Masking a Secret Value

echo "::add-mask::my-sensitive-token"
echo "Using token: my-sensitive-token"
Note: The mask is applied to the log output, so any sensitive values will be replaced with *** in logs.
Warning: Masking only affects logs and does not prevent sensitive data from being used in workflows or stored in environment variables.

10. Using GitHub API

Method Endpoint Description Notes
GET /repos/{owner}/{repo}/issues Retrieve issues from a repository Supports pagination and filtering
POST /repos/{owner}/{repo}/issues Create a new issue Requires repo scope
PATCH /repos/{owner}/{repo}/issues/{issue_number} Update an existing issue Can update title, body, labels, etc.
GET /repos/{owner}/{repo}/contents/{path} Retrieve file contents Supports base64 decoding of content
PUT /repos/{owner}/{repo}/contents/{path} Create or update a file Requires repo scope and branch name

Example: Create a new issue using GitHub API

const { Octokit } = require("@octokit/rest");
const octokit = new Octokit({ auth: process.env.GITHUB_TOKEN });

async function createIssue() {
  const response = await octokit.rest.issues.create({
    owner: "octocat",
    repo: "Hello-World",
    title: "Found a bug",
    body: "I'm having a problem with this."
  });

  console.log("Issue created: " + response.data.html_url);
}

createIssue();
Note: The GITHUB_TOKEN is automatically provided in GitHub Actions workflows and has appropriate permissions for the repository.
Warning: Be cautious with token permissions. Only grant the minimum required scopes to avoid security risks.

11. Compiling TypeScript

Option Values Notes
main.ts export async function run() { ... } Entry point for the action
tsconfig.json { "compilerOptions": { "target": "ES2019", "module": "commonjs" } } Configuration for TypeScript compilation
package.json { "scripts": { "build": "tsc" } } Build script to compile TypeScript

Example: Compiling TypeScript Action

import { getInput, setOutput } from '@actions/core';

export async function run() {
  const input = getInput('input');
  setOutput('output', `Processed: ${input}`);
}

run().catch((err) => {
  console.error(err);
});
Note: Ensure node_modules is included in the action's distribution package for runtime dependencies.
Warning: Avoid using async/await in the main function if not properly handling errors.

12. Handling Async Operations

Operation Description Example
async/await Use async/await for handling asynchronous operations in JavaScript actions
async function run() {
  const result = await someAsyncFunction();
  console.log(result);
}
Promise Handle asynchronous operations using Promise syntax
someAsyncFunction().then(result => {
  console.log(result);
}).catch(error => {
  console.error(error);
});

Example: Using async/await in a GitHub Action

const core = require('@actions/core');
const github = require('@actions/github');

async function run() {
  try {
    const token = core.getInput('token');
    const octokit = new github.GitHub(token);

    const { data: issues } = await octokit.issues.listForRepo({
      owner: 'owner',
      repo: 'repo',
      state: 'open'
    });

    core.setOutput('issue-count', issues.length);
  } catch (error) {
    core.setFailed(error.message);
  }
}

run();
Note: When writing JavaScript actions, always handle async operations properly to avoid hanging or incomplete workflows.

13. Publishing to Marketplace

Field Description Required Example
name Action name displayed in the Marketplace Yes My JavaScript Action
description Short description of the action's purpose Yes A simple action to greet users
icon URL to an icon image (16x16px) No https://example.com/icon.png
categories Array of categories for Marketplace search No ["utility", "notification"]
tags Array of tags for Marketplace search No ["greeting", "hello"]

Example: Publishing to Marketplace

name: My JavaScript Action
description: A simple action to greet users
icon: https://example.com/icon.png
categories:
  - utility
  - notification
tags:
  - greeting
  - hello
Note: The action must be published to a public repository to appear in the Marketplace.
Warning: Ensure all metadata fields are properly formatted to avoid Marketplace validation errors.

Was this article helpful?