a first look at github actions
githubactionscicdworkflowsGitHub Actions can be used to automate, customize, and execute software development workflows from within a GitHub repository. You can discover, create, and share actions to perform CI/CD jobs and combine actions in a customized workflow.
Create an Action #
We will create a boilerplate workflow to help you get started with Actions.
mkdir -p ajcwebdev-actions/.github/workflows
cd ajcwebdev-actions
touch .github/workflows/hello.yml
echo '.DS_Store' > .gitignore
on
controls when the workflow will run. push
and pull_request
events trigger the workflow but only for the main branch. workflow_dispatch
allows you to run this workflow manually from the Actions tab.
name: CI
on:
push:
branches: [ main ]
pull_request:
branches: [ main ]
workflow_dispatch:
A workflow run is made up of one or more jobs
that can run sequentially or in parallel. Our workflow contains a single job called build
that is running on ubuntu-latest
.
jobs:
build:
runs-on: ubuntu-latest
steps
represent a sequence of tasks that will be executed as part of the job. uses
checks-out your repository under $GITHUB_WORKSPACE
, so your job can access it. run
will run a single command (echo "Hello from GitHub Actions"
) which will print Hello from GitHub Actions
using the runner's shell.
steps:
- uses: actions/checkout@v2
- name: Run a one-line script
run: echo "Hello from GitHub Actions"
The action will then run a multi-line script to print a series of messages containing common environment variables such as the repository name and job status.
- name: Run a multi-line script
run: |
echo "Job was triggered by a $ event."
echo "Job is now running on a $ server hosted on GitHub."
echo "The branch name is $."
echo "The repository name is $."
echo "Job status is $."
Here is the complete GitHub Action.
# .github/workflows/hello.yml
name: CI
on:
push:
branches: [ main ]
pull_request:
branches: [ main ]
workflow_dispatch:
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- name: Run a one-line script
run: echo "Hello from GitHub Actions"
- name: Run a multi-line script
run: |
echo "Job was triggered by a $ event."
echo "Job is now running on a $ server hosted on GitHub."
echo "The branch name is $."
echo "The repository name is $."
echo "Job status is $."
Push your project to a GitHub repository #
Initialize the repository, add all changes to the staging area, and commit all staged changes.
git init
git add .
git commit -m "Action Jackson"
Create a new blank repository #
You can create a blank repository by visiting repo.new or using the gh repo create
command with the GitHub CLI. Enter the following command to create a new repository, set the remote name from the current directory, and push the project to the newly created repository.
gh repo create ajcwebdev-actions \
--public \
--source=. \
--description="An Example GitHub Action Project" \
--remote=upstream \
--push
If you created a repository from the GitHub website instead of the CLI then you will need to set the remote and push the project with the following commands.
git remote add origin https://github.com/ajcwebdev/ajcwebdev-actions.git
git push -u origin main
Go to the actions tab on your GitHub repository to see your action.
Click your action to see the specific workflow.
Click "build" to see more details.
Click "Set up job" for more info.
Current runner version: '2.285.1'
Operating System
Ubuntu
20.04.3
LTS
Virtual Environment
Environment: ubuntu-20.04
Version: 20211219.1
Included Software: https://github.com/actions/virtual-environments/blob/ubuntu20/20211219.1/images/linux/Ubuntu2004-README.md
Image Release: https://github.com/actions/virtual-environments/releases/tag/ubuntu20%2F20211219.1
Virtual Environment Provisioner
1.0.0.0-main-20211214-1
GITHUB_TOKEN Permissions
Actions: write
Checks: write
Contents: write
Deployments: write
Discussions: write
Issues: write
Metadata: read
Packages: write
Pages: write
PullRequests: write
RepositoryProjects: write
SecurityEvents: write
Statuses: write
Secret source: Actions
Prepare workflow directory
Prepare all required actions
Getting action download info
Download action repository 'actions/checkout@v2' (SHA:ec3a7ce113134d7a93b817d10a8272cb61118579)
Click "Run actions/checkout@v2" for more info.
Syncing repository: ajcwebdev/ajcwebdev-actions
Getting Git version info
Deleting the contents of '/home/runner/work/ajcwebdev-actions/ajcwebdev-actions'
Initializing the repository
Disabling automatic garbage collection
Setting up auth
Fetching the repository
Determining the checkout info
Checking out the ref
/usr/bin/git log -1 --format='%H'
'14b8a71b0852e18cd03880acad4cf4558b3bd0bd'
Create JavaScript Action #
Our action will print "Hello World" in the logs or "Hello [who-to-greet]" if you provide a custom name. Initialize a package.json
file with npm
.
npm init -y
Add Actions Toolkit Packages #
This guide uses the GitHub Actions Toolkit Node.js module, actions/toolkit
, to speed up development. The actions toolkit is a collection of Node.js packages for building JavaScript actions with more consistency. Install the actions toolkit core
and github
packages.
npm i @actions/core @actions/github
The toolkit @actions/core
package provides an interface to the workflow commands, input and output variables, exit statuses, and debug messages. The toolkit also offers a @actions/github
package that returns an authenticated Octokit REST client and access to GitHub Actions contexts.
Create Action Metadata File #
Docker and JavaScript actions require a metadata file containing data that defines the inputs, outputs and main entrypoint for the action. Create a file called action.yml
for our action.
touch action.yml
The metadata filename must be either action.yml
or action.yaml
. This file defines the who-to-greet
input and time
output. It also tells the action runner how to start running this JavaScript action.
# action.yml
name: 'Hello World'
description: 'Greet someone and record the time for posterity'
inputs:
who-to-greet:
description: 'Who to greet'
required: true
default: 'World'
outputs:
time:
description: 'The time at which the greeting commenced'
runs:
using: 'node12'
main: 'index.js'
Create JavaScript Action File #
Create a file called index.js
for the JavaScript code.
touch index.js
index.js
will contain the JavaScript code to interact with our action metadata.
// index.js
const core = require('@actions/core')
const github = require('@actions/github')
try {
const nameToGreet = core.getInput('who-to-greet')
console.log(`Hello ${nameToGreet}!`)
const time = (new Date()).toTimeString()
core.setOutput("time", time)
const payload = JSON.stringify(github.context.payload, undefined, 2)
console.log(`The event payload: ${payload}`)
} catch (error) {
core.setFailed(error.message)
}
getInput
uses the who-to-greet
input defined in the action metadata file and initializes the value to a variable called nameToGreet
. The variable is then logged to the console. setOutput
uses the JavaScript Date()
constructor to create a Date
object and sets it as an output variable that actions running later in a job can use.
GitHub Actions provide context information that can be accessed with the github
package. Our action prints the webhook event payload to the log. github.context.payload
gets the JSON webhook payload for the event that triggered the workflow and logs it to the console. If an error is thrown in the above index.js
example, core.setFailed(error.message);
uses the actions toolkit @actions/core
package to log a message and set a failing exit code.
Commit and Tag JavaScript Action #
GitHub downloads each action run in a workflow during runtime and executes it as a complete package of code before you can use workflow commands like run
to interact with the runner machine. This means you must include any package dependencies required to run the JavaScript code. For this example that includes the toolkit core
and github
packages.
It's best practice to also add a version tag for releases of your action.
git add .
git commit -m "JavaScript Action"
git tag -a -m "First JavaScript action release" v0.1
git push --follow-tags
Test JavaScript Action with a Workflow #
touch .github/workflows/javascript.yml
Update the uses
line with your username and the name of your public repository.
# .github/workflows/javascript.yml
on: [push]
jobs:
hello_world_job:
runs-on: ubuntu-latest
name: A job to say hello to ajcwebdev
steps:
- name: Hello world action step
id: hello
uses: ajcwebdev/ajcwebdev-actions@v0.1
with:
who-to-greet: 'ajcwebdev'
- name: Get the output time
run: echo "The time was $"
When this workflow is triggered, the runner will download the ajcwebdev-actions
action from your public repository and then execute it.