Skip to main content

GitHub Actions

This page provides introduction to github actions.

Overview

GitHub action is github integrated tool, allowing automation. It is triggered by events in github such as pull_request, push etc.

Core Concepts

  • Actions: Actions are the smallest portable building block of a workflow and can be combined as step to create a job.
  • Events: Events are activity which can trigger a workflow run. For e.g. pull_request, push etc. Events can also be configured to listen to external events using webhooks.
  • Runner: A Runner is a machine with github action runner application is installed. Runners can be host on github or self-hosted.
  • Job: Job is made up of multiple steps and runs in an instance of virtual environment.
  • Step: A Step is set of tasks that can be executed by a job. Step can run commands or actions.
  • Workflow: Workflow is automated process that is made up of multiple jobs and can be triggered by an event. Workflows are defined in .github/workflows directory using yaml file.

Hello GitHub Action Demo

Click here to view the repository.

Let's start by creating an empty github repo.

On your local create a folder for project repo as below:

mkdir hello-github-action && cd hello-github-action

Create script.sh in root directoy with below content:

#!/bin/sh
echo "Hello GitHub Actions!!!"

Create github action under folder .github/workflows/print-github-actions.yaml

name: Print Action

on:
push:
branches:
- main

jobs:
build:
runs-on: ubuntu-latest

steps:
- name: Checkout code
uses: actions/checkout@v3

- name: Run a Script
run: sh script.sh

Check in the changes to github repo

git add .
git commit -m "first commit"
git branch -M main
git remote add origin https://github.com/vchoudhari45/hello-github-action.git
git push -u origin main

After you check in the changes, a github Actions workflow will automatically start. You can monitor its progress under the Actions tab in the repository.

github-action-1.svg

Handling Secrets

Sensitive data such as password, credentials, tokens or certificates can be stored as github secrets. You can define your secrets either at org, repository, or environment level.

Secret Github Action Demo

Click here to view the repository.

Let's start by creating an empty github repo.

On your local create a folder for project repo as below:

mkdir github-action-secret && cd github-action-secret

Create github action under folder .github/workflows/main.yaml

name: Getting Secret within Actions

on:
push:
branches:
- main

jobs:
get-repo-secret:
runs-on: ubuntu-latest
steps:
- name: Retrieve Secret
env:
repo_secret: ${{ secret.MY_SECRET }}
run: |
if [[ $repo_secret == "repo secret" ]]; then
echo "Sucessfully got repo secret value: $repo_secret"
fi

get-env-secret:
environment: dev
runs-on: ubuntu-latest
steps:
- name: Retrieve Secret
env:
env_secret: ${{ secret.MY_SECRET }}
run: |
if [[ $env_secret == "env secret" ]]; then
echo "Sucessfully got repo secret value: $env_secret"
fi

Check in the changes to github repo

git add .
git commit -m "first commit"
git branch -M main
git remote add origin https://github.com/vchoudhari45/github-action-secret.git
git push -u origin main

Once repo is created add repo secret and env secret as below:

github-action-2.svg

After creating the secrets, make a small change to the README.md file to trigger a GitHub Actions workflow. If the workflow completes successfully and shows the expected output, your secret export setup is working correctly.

github-action-3.svg

Handling Dependencies

By default all the jobs run in parallel at the same time, but you can use "needs" keyword to define a dependency. If dependency fails, all the remaining jobs will be skipped.

Here’s an example of how to define a dependency:

jobs:
setup:
runs-on: ubuntu-latest
steps:
- run: ./setup_server.sh

build:
needs: setup # this add setup step as pre-requisite for build step
runs-on: ubuntu-latest
steps:
- run: ./build_server.sh

Reusing Workflows

Let's first define the reusable workflow called workflow-A

name: workflow-A

on:
workflow_call # this makes workflow callable from other workflow
inputs:
my_input_value:
description: 'An optional input with a default value'
required: false
default: 'Default value'


jobs:
setup:
name: Print Hello Reusable Workflow
runs-on: ubuntu-latest
steps:
- name: Echo Reusable Message
run: echo "Input value is: ${{ inputs.my_input_value }}"

Now, let's call reusable workflow from caller workflow as below:

jobs:
# example of calling workflow-A with default value
call-workflow:
uses: org/repo-name/.github/workflows/workflow-A.yaml@v1

# example of calling workflow-A with abc
call-workflow-passing-data:
uses: org/repo-name/.github/workflows/workflow-B.yaml@v1
with:
my_input_value: abc

Defining Environment

Here’s an example of how to define environment:

jobs:
deployment:
runs-on: ubuntu-latest
environment: prod # defining environment
steps:
- name: deploy
# ... deployment specific steps.

Defining Environment Variables

Here's an example of how to define environment variables:

env:
# defining a variable at global level
GLOBALENV: Available for all jobs in this workflow

jobs:
sample-job-1:
runs-on: ubuntu-latest
env:
# defining a variable at job level
JOBENV: Available for all jobs in this workflow
steps:
- name: step-1
run: echo "${GLOBALENV}"

- name: step-2
run: echo "${JOBENV}"

sample-job-2:
runs-on: ubuntu-latest
steps:
run: echo "${GLOBALENV}"