Running A Javascript Github Action

Pavol Kutaj
4 min readFeb 13, 2021

The aim of this tutorial🔍 is to offer both a hello-world and a real-world example of a successfully set up and executed JavaScript Github Action.

1. Prerequisites

1.1. Setup a Project (github repo, npm init)

  • create a new repo
  • clone locally
  • run npm init -y to initialize a node project by creating a package.json
Wrote to C:\Users\Admin\Documents\workspace\SNOW\hello-world-javascript-action\package.json:{
"name": "hello-world-javascript-action",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"repository": {
"type": "git",
"url": "git+https://github.com/pkutaj/hello-world-javascript-action.git"
},
"keywords": [],
"author": "",
"license": "ISC",
"bugs": {
"url": "https://github.com/pkutaj/hello-world-javascript-action/issues"
},
"homepage": "https://github.com/pkutaj/hello-world-javascript-action#readme"
}

1.2. Add NPM Github Actions Toolkit Packages

  • use npm to install 2 required packages from the toolkit
  • @actions/core → interface to the workflow commands, input, output variables, exit statuses, debug messages
  • @actions/github → returns an authenticated Octokit REST client; provides access to Github Actions contexts
  • to install, run
  • run npm install @actions/core
  • run npm install @actions/github
â–¶ npm install @actions/core
npm notice created a lockfile as package-lock.json. You should commit this file.
npm WARN hello-world-javascript-action@1.0.0 No description
+ @actions/core@1.2.6
added 1 package and audited 1 package in 0.742s
found 0 vulnerabilities
~\Documents\workspace\SNOW\hello-world-javascript-action  master ≢ +4 ~0 -0 ! ⚡ ⨯
â–¶ npm install @actions/github
npm WARN hello-world-javascript-action@1.0.0 No description
+ @actions/github@4.0.0
added 21 packages from 56 contributors and audited 22 packages in 4.408s
found 0 vulnerabilities

2. Action Metadata

Docker and JavaScript actions require a metadata file. The metadata filename must be either action.yml or action.yaml. The data in the metadata file defines the inputs, outputs, and main entry point for your action.

  1. Name: Action Name
  2. Description: Action’s description
  3. Runs: using: What application are you using to execute the code
  4. Runs: main: The actual file containing the action code (what is being executed)
  • There are other optional fields as well, as illustrated in the Hello World AMF

2.1. Hello-World AMF

  • this is from the exemplary GitHub’s action metadata file that
  • defines input: who-to-greet
  • defines output: time
  • tells the action runner hot to start running this actions
name: 'Hello World'
description: 'Greet someone and record the time'
inputs:
who-to-greet: # id of input
description: 'Who to greet'
required: true
default: 'World'
outputs:
time: # id of output
description: 'The time we greeted you'
runs:
using: 'node12'
main: 'index.js'

2.2. Real-World AMF

  • This is the bare bones essential with the 4 required fields
name: 'Publish to Zendesk'
description: 'Publish Markdown to Zendesk'
runs:
using: 'node12'
main: 'publish.js'

3. Action

  • Action == Code to be executed by a SQL runner that is in a separate file or a repo

3.1. Hello-World Action

  • create index.js as defined in the metadata and populate with your code, for example with
const core = require('@actions/core');
const github = require('@actions/github');
try {
// `who-to-greet` input defined in action metadata file
const nameToGreet = core.getInput('who-to-greet');
console.log(`Hello ${nameToGreet}!`);
const time = (new Date()).toTimeString();
core.setOutput("time", time);
// Get the JSON webhook payload for the event that triggered the workflow
const payload = JSON.stringify(github.context.payload, undefined, 2)
console.log(`The event payload: ${payload}`);
} catch (error) {
core.setFailed(error.message);
}

3.2. Real-World Action

4. Workflow

  • required
  • it has to be in a location
repo\.github\workflows\main.yaml
  • if you are not running a shared public action it must include a public action called Checkout
  • the uses key points to a repository where action.yml is located

4.1. Hello-World Workflow

on: [push]jobs:
hello_world_job:
runs-on: ubuntu-latest
name: A job to say hello
steps:
- name: Checkout
uses: actions/checkout@v2
- name: Hello world action step
id: hello
uses: ./
with:
who-to-greet: 'Mr Paul'
# Use the output from the `hello` step
- name: Get the output time
run: echo "The time was $"

4.2. Real-World Workflow

on: [push]jobs:
publish_to_zendesk:
runs-on: ubuntu-latest
name: Publish to Zendesk
steps:
- name: Checkout
uses: actions/checkout@v2
- name: Publish
id: publish
uses: ./
- name: Commit
run: |
date > generated.txt
git config user.name github-actions
git config user.email github-actions@github.com
git add .
git commit -m "generated"
git push

5. Commit && Push

  • During the runtime of a workflow, github downloads each action used there
  • Actions are executed as s complete packages of code before commands like run can be used
  • It follows, that any package dependencies must be included
  • Shared prerequisites are core and github npm packages checked in the action repo

6. Summary: required items to be commited

  1. action.yml
  2. index.js any code to be executed
  3. node_modules
  4. package.json
  5. package-lock.json
  • README.md being optional

7. Tests

7.1. Hello-World verification

8. sources

--

--

Pavol Kutaj

Today I Learnt | Infrastructure Support Engineer at snowplow.io with a passion for cloud infrastructure/terraform/python/docs. More at https://pavol.kutaj.com