Understanding GitHub Actions to Automate Workflows (With Examples)

By Sruthy

By Sruthy

Sruthy, with her 10+ years of experience, is a dynamic professional who seamlessly blends her creative soul with technical prowess. With a Technical Degree in Graphics Design and Communications and a Bachelor’s Degree in Electronics and Communication, she brings a unique combination of artistic flair…

Learn about our editorial policies.
Updated April 1, 2025
Edited by Kamila

Edited by Kamila

Kamila is an AI-based technical expert, author, and trainer with a Master’s degree in CRM. She has over 15 years of work experience in several top-notch IT companies. She has published more than 500 articles on various Software Testing Related Topics, Programming Languages, AI Concepts,…

Learn about our editorial policies.

Automate your software workflow with GitHub Actions and boost development efficiency. Also, learn how to build, test & deploy code directly from your GitHub repository to save your time effectively:

This article illustrates the efficiency of GitHub Actions in streamlining CI/CD processes directly within the GitHub platform, making external integrations redundant.

GitHub Actions is an inbuilt CI/CD platform that allows you to automate, build, test, and deploy applications.

Learn to Use GitHub Actions: Step-by-Step Guide

Github Actions Featured Image

What are GitHub Actions

GitHub Actions are typically event-driven, meaning you can run a series of commands after an event. For example, when someone creates a pull request or a GitHub issue.

Below is the GitHub Actions Workflow process, which we will see in action through a few examples.

GitHub Actions

Workflows are triggered automatically when an event occurs. A workflow contains a job. The job then includes and uses steps to control the order in which actions are run. Each job will run on a runner, which is a virtual machine or even inside a container.

Here is a simple video on GitHub Actions:

GitHub Actions provides support for Linux, Windows, and MacOS virtual machines. These runners can be self-hosted in your data centers or on the cloud.

In this article, we will look at specific examples using self-hosted runners.

Key Components of GitHub Actions

Workflows: Workflows comprise one or more jobs and can be scheduled or triggered by an event. Many pre-defined workflow templates are available in GitHub Marketplace, which will be a good starting point.

GitHub workflows are written in YAML. The workflow refers to the .yml (YAML) file and is placed in .github/workflows directory

The GitHub repository can have multiple workflows. One for Build only and the other for the Deploy process.

Events: An activity that triggers a workflow. For example, activity can be when a user pushes a commit to a repository or when the pull request is created.

Example: Using a single event

# Workflow is triggered when code is pushed to any branch in a repository

on: push

Example: Using multiple events

# Workflow is triggered on push or pull request events

on: [push, pull_request]

Example: Using a particular branch (feature)

on:
# Workflow trigger on push or pull request, only for the feature branch
push:
branches:
– feature
pull_request:
branches:
– feature

Job: A job is a series of steps that is executed on the runner as shown in the above diagram

Step: A step is an individual task that can run commands in a job. A step can be either an action or a script.

Actions: Actions are commands that are added as steps in a job. One can create your own actions, or use actions that are created by the GitHub community. We will see how to use an action in a workflow and include it as a step.

Further Reading => Managing GitHub Repository – A Complete Study

GitHub Hosted Runners

GitHub offers hosted runners as virtual machines with Linux, Windows, and MacOS operating systems, which are used to run the workflows

Available GitHub-hosted runner types as described in https://docs.github.com/en/actions/using-github-hosted-runners/about-github-hosted-runners are:

GitHub hosted runners

In the GitHub Actions workflow (YAML file) we will reference the above hosted runner as

runs-on: windows-2016

GitHub Self-Hosted Runner

You can host your runners and customize the environment used to run jobs in your GitHub Actions workflows. Self-hosted runners can be on-premise physical machines, virtual machines, or on the cloud. This self-hosted runner offers better control over the hardware, OS, and software tools to be used.

We will add self-hosted runners at the repository level, which is for a single repository. It can also be applied at an Organization level for multiple repositories or at Enterprise level for multiple organizations.

Once configured the runner machine connects to GitHub. 

Supported self-hosted runners are mentioned in Supported architectures and operating systems for self-hosted runners

Adding a self-hosted runner to a repository

To add self-hosted runners to a single repository, follow the below steps:

On the main page of the repository.

  1. Click  Settings.
  2. In the left sidebar, click Runners under Actions.
  3. Under “Runners”, click on the Add Runner button.
  4. Select the operating system (Windows) and architecture (X64) for the self-hosted runner machine.
Adding a self-hosted runner to a repository4
Adding a self-hosted runner

Open the PowerShell window on your Windows machine and run the commands as shown.

PS D:\actions-runner> [Net.ServicePointManager]:: SecurityProtocol = [Net.SecurityProtocolType]::Tls12

PS D:\actions-runner> Invoke-WebRequest -Uri https://github.com/actions/runner/releases/download/v2.278.0/actions-runner-win-x64-2.278.0.zip -OutFile actions-runner-win-x64-2.278.0.zip

PS D:\actions-runner> dir

Directory: D:\actions-runner

actions-runner

PS D:\actions-runner> Add-Type -AssemblyName System.IO.Compression.FileSystem ; [System.IO.Compression.ZipFile]::Extract

ToDirectory(“$PWD/actions-runner-win-x64-2.278.0.zip”, “$PWD”)

PS D:\actions-runner> dir

Directory: D:\actions-runner

PS D actions-runner

PS D:\actions-runner> ./config.cmd –url https://github.com/vniranjan1972/HW-Maven-Repo –token AETIUMKYPSD6SLEEB4OYSZTA2272W

Self-hosted runner registration

# Authentication

Radical SymbolConnected to GitHub

# Runner Registration

Enter the name of the runner: [press Enter for L-0310] AG-VN-Runner

This runner will have the following labels: ‘self-hosted’, ‘Windows’, ‘X64’

Enter any additional labels (ex. label-1,label-2): [press Enter to skip]

Radical SymbolRunner successfully added

Radical SymbolRunner connection is good

# Runner settings

Enter name of work folder: [press Enter for _work]

Radical SymbolSettings Saved.

Would you like to run the runner as a service? (Y/N) [press Enter for N]

Note: As an admin before starting the runner please set the execution policy in the PowerShell window

Set-ExecutionPolicy RemoteSigned

Set Execution policy
Admin windows

The self-hosted runner is now added successfully.

Self-hosted runner added successfully

# For each job use the below YAML in your workflow file
runs-on: self-hosted

Creating the First GitHub Actions Workflow

Example 1: From your repository on GitHub, create a new file in the .github/workflows directory named hello-world.yml

Creating first GitHub Actions

Copy the following YAML contents into the hello-world.yml file

name: hello-world
on: push
jobs:
  firstjob:
     runs-on: self-hosted
     steps:
         - name: Printing my name
           run: echo "Hi Niranjan, Welcome to GitHub Actions"

Understanding the above workflow in order

  • Name of the workflow as it will appear in the Actions tab (This is defined by name field)
  • Trigger the workflow based on the push event (This is defined by on field)
  • The above workflow contains only one job with the name of firstjob.
  • The job runs on a self-hosted runner and not an inbuilt hosted runner (This is defined by the runs-on field)
  • The job contains only one step by the name Printing my name and executes an echo command only

Commit the changes to the main branch.

Commit the changes to main branch

Go to the Actions tab and click on the workflow to view the result of the run.

click on the workflow
Go to Actions tab and click on the workflow2

So next time when a change is made to the code and pushed to the repo the workflow will be triggered.

Example 2: Print the GitHub repository name, workspace directory, and other default environment variables

Also, refer to the Default environment variables

name: hello-world
on: push

jobs:
  firstjob:
     runs-on: self-hosted
     steps:
         - name: Printing my name
           run: echo "Hi Niranjan, Welcome to GitHub Actions"
         - name: Print GitHub Repository
           run:  echo $env:GITHUB_REPOSITORY
         - name: Print GitHub Workspace
           run:  echo $env:GITHUB_WORKSPACE
         - name: Print GitHub Workflow Name
           run:  echo $env:GITHUB_WORKFLOW
         - name: Print GitHub Workflow Initiator
           run:  echo $env:GITHUB_ACTOR
         - name: Print GitHub Runner Name
             run:  echo $env:RUNNER_NAME
         - name: Print GitHub Runner OS
           run:  echo $env:RUNNER_OS
Example2

GitHub Marketplace

In a typical DevSecOps flow we will need to perform SCM checkout wherein a copy of the source code repository is downloaded onto your build machine where the runner is running and then build is performed e.g., maven build, code analysis using SonarQube, unit testing, pushing the build artifact files to a binary repository manager like Nexus or Artifactory and then deploy to tomcat etc.

GitHub Marketplace allows us to find specific apps/actions for use across the entire DevSecOps flow (CI/CD/CT) as described above.

GitHub Marketplace can be browsed @ https://github.com/marketplace

GitHub Marketplace

One can think of this as similar to Jenkins plugins. Let’s see how to make use of these apps or actions in our workflow.

Java Maven Example – Build and Deployment Workflow

Example 1: Below is the workflow showing a Maven Build

In the Actions tab click on New Workflow and enter the contents of the YML file

name: CI and CD with Maven
on:
  push:
      branches: [ master ]
 jobs:
  build:
    runs-on: self-hosted
    steps:
      - uses: actions/checkout@v2
      - name: Build with Maven
         run: mvn clean install

Go to the Actions Tab and click on the job to view the log.

Java Maven Example
In the workflow there is a line which mentions the below under steps   – uses: actions/[email protected]This action checks-out your GitHub repository to the GitHub Workspace in the runner machine  so that you can run various actions against the code. This is usually the first step in any DevSecOps flow.
Checkout V3

More such actions or apps can be found in the GitHub marketplace and reused in the workflow. We will look at many more such actions or apps and use them in our workflow for different activities as part of automating the DevSecOps flow. Examples of using the same in your workflow steps can be found in the marketplace as shown below.

Example 2: Extend the above example to perform Deploy steps to Tomcat

name: CI and CD with Maven
on:
  push:
    branches: [ master ]
jobs:
  Maven_Build_Deploy:
        runs-on: self-hosted
 steps:
    - uses: actions/checkout@v3
  
  - name: Build with Maven
      run: mvn clean install
    - name: Deploy to Tomcat
       run: copy ${env:GITHUB_WORKSPACE}\target\HelloWorld-Maven.war E:\apache-tomcat-7.0.65\apache-tomcat-7.0.65\webapps\

Go to the Actions Tab and click on the job to view the log.

Go to the Actions Tab and click on the job to view the log

Example 3: Extend the above example to upload an artifact to GitHub

From the marketplace view on the right select the Upload a Build Artifact.

Example 3
Go to the Actions Tab and click on the job to view the log2

Copy and paste the snippet below the ‘mvn clean install’ command

- name: Upload a Build Artifact 
      uses: actions/[email protected]
      with:
           name: assets-for-upload
           path: target/*.war
           retention-days: 5

The advantage of uploading the build artifact to the GitHub repo is that it can be reused in another workflow.

advantage for uploading the build artifact to GitHub

Commit the changes. The workflow is run and the artifacts are uploaded.

Commit the changes

To view the artifacts uploaded click on the Summary on the left. Look at the Artifacts section and click on the assets for the download link.

click on the Summary
click on the Summary2

The Zip file contains the WAR file built.

Example 4: Code for downloading artifact to the runner machine

Add the below code from the marketplace for downloading the artifact to a directory in the runner machine. In this case, the WAR file which was uploaded in the previous step will be downloaded to a specific directory.

- name: Download the artifacts 
      uses: actions/[email protected]
      with:
           name: assets-for-upload
           # Destination path
           path: e:\temp\rel
Example4

Let’s now commit the code and watch the download.

commit the code and watch the download
commit the code and watch the download2

The downloaded artifact can be referenced in some other workflow for some other deployment.

Example 5: Create a release in GitHub repository

To create a release we will follow these steps

  • Archive the WAR file. Create a ZIP file containing the WAR file
  • Create a GitHub Release (https://github.com/actions/create-release)
  • Upload the asset to GitHub Release (https://github.com/actions/upload-release-asset)

The code for the above steps will be added from the marketplace. Add the code below the download artifact step.

- name: Archive the WAR file (Create ZIP  file for Release)
   uses: vimtor/action-zip@v1
    with:
             files: target/HelloWorld-Maven.war
             dest: Hw-Maven-Repo.zip
  - name: Create Github Release
     id: create-new-release
    uses: actions/create-release@v1
    env:
       GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} # This token is provided by Actions, you do not need to create your own token
     with:
            tag_name: v${{ github.run_number }}
            release_name: Release V${{ github.run_number }} 
  - name: Upload asset to Github Release
       uses: actions/upload-release-asset@v1
       env:
            GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} # This token is provided by Actions, you do not need to create your own token
       with:
            upload_url: ${{ steps.create-new-release.outputs.upload_url }} # This pulls from the CREATE RELEASE step above, referencing it's ID to get its outputs object, which include a `upload_url`. 
            asset_path: ${{ github.workspace }}/Hw-Maven-Repo.zip
            asset_name: Hw-Maven-Repo-v${{ github.run_number }}.zip
            asset_content_type: application/zip
Example5
Example5.0
Release V31

Angular Example – Build and Deployment Workflow

To run this example, ensure to install NodeJs and NPM on the runner machine. Angular CLI would also need to be installed.

Add the following code to the YML file in .github/workflows directory in the GitHub repository which contains the Angular Code

name: Angular Example
on: [push]
jobs:
  Angular_Build_Deploy_Tomcat:
    runs-on: angular-runner
    steps:
      - uses: actions/checkout@v2
      - name: Install dependencies
        run: npm install
      - name: Build App
         run: ng build --base-href=/angular/
      - name: Deploy to Tomcat 
        run: copy ${env:GITHUB_WORKSPACE}\dist\vnNewApp\*.*  E:\apache-tomcat-7.0.65\apache-tomcat-7.0.65\webapps\angular
Build and Deployment Workflow

Commit the YML file and view the workflow run.

Commit the YML file and view the workflow run.

Launch the application deployed to Tomcat using the URL http://localhost:8080/angular/

Launch the application deployed

Docker Example – Build and Deployment Workflow

In this section, we will look at an example of Docker build and push to Docker Hub and JFrog Artifactory private registry.

Example 1:

I have the sample WAR file built and stored in my Linux build server machine. The same path as shown below has Dockerfile as well, which is needed for Docker build.

Docker Example

Let’s look at the GitHub Actions Workflow for Docker build and push.

name: Docker Build and Push 
on:
  push:
    branches: [ master ]  
jobs:
  Docker_Build_Push:
    runs-on: self-hosted
    steps:
      - name: Login to Docker Hub
        uses: docker/login-action@v1
        with:
          username: ${{ secrets.DOCKERHUB_USERNAME }}
          password: ${{ secrets.DOCKERHUB_TOKEN }}

    - name: Docker image Build and Push to Docker Hub
       uses: docker/[email protected]
       with:
           # Path where code and Dockerfile is located 
           context: /home/ubuntu/example
           push: true
           tags: vniranjan1972/vnmaven:${{ github.run_number }}

In the above, I have used the Docker build and push action available in GitHub Marketplace. This action helps to build and push tags to Dockerhub.

In the last line associated with tags, I have specified ${{ github.run_number }}. This is the context that helps to access information about the workflow runs, runner environments, etc. More about how to use the contexts in the workflow can be found @ https://docs.github.com/en/actions/learn-github-actions/contexts#github-context

Docker Example 2

Commit the file and check the output and the image pushed to Dockerhub.

Commit the file and check the output and the image pushed to Dockerhub

The image is now available in Docker Hub with tag number 23.

Image is now available in Docker Hub

Example 2:

In this section, we will look at the Docker image build and push to JFrog Artifactory.

Here is the simple Dockerfile used and stored in my GitHub repository.

FROM vniranjan1972.jfrog.io/vn-docker-virtual/httpd
MAINTAINER V Niranjan
COPY index.html /var/www/html/

GitHub Actions Workflow

name: JFrog Artifactory Build and Push
on:
  push:
    branches: [ master ]  
jobs:
  Artifactory_Docker_Build_Push:
    runs-on: ubuntu-latest
    steps:
      - name: Checkout 
        uses: actions/checkout@v3
      
      
      - name: Login to JFrog   
        uses: docker/[email protected]
        with:
          registry: vniranjan1972.jfrog.io
          username: ${{ secrets.JFROG_USER }}
          password: ${{ secrets.JFROG_PASSWORD }}
      
      - name: Docker Image Build and push 
         uses: docker/[email protected]
        with:
          push: true
          tags: vniranjan1972.jfrog.io/vn-docker-virtual/vntomcatnew1:latest

In the above workflow, I am using a JFrog Artifactory Virtual repository called vn-docker-virtual which contains a remote repository for downloading dependencies and a local repository for uploading the docker image.

Commit the above workflow and on PUSH, the workflow triggers.

Commit the above workflow and on PUSH the workflow triggers

JFrog Artifactory local repository with the latest image uploaded.

JFrog Artifactory local repository

Further Reading => GitHub Advanced Security – A Complete Guide

GitHub Actions for GitHub Enterprise Server using Actions-sync

The actions from the GitHub marketplace or even GitHub.com are not normally available to use for workflows in the GitHub Enterprise Server (On-Prem version of GitHub). In such cases where users need to make use of GitHub Actions features, we need to MANUALLY sync the actions from GitHub.com.

We will look at the procedure to download specific actions and make them available to your GitHub Enterprise Server so that users can use the GitHub Actions feature.

To download the actions to be made available to your GitHub Enterprise Server, you should use the open-source utility from GitHub called as actions-sync. This will help to sync specific actions repositories from GitHub.com to your Enterprise server.

The latest version of actions-sync tool can be downloaded from https://github.com/actions/actions-sync/releases/

The workflow for achieving this using actions-sync would be as shown

GitHub Actions for GitHub Enterprise

EXAMPLE: The actions-sync command format (Linux)

The actions-sync command format


• In the above command for the parameter –repo-name if the repository is to be named differently in the enterprise server then use it as actions/checkout:dest_org/checkout
• For the PAT token, the scope of the repo and workflow should be included.
• Repolist file format, if used should be as follows. Add all actions as needed in the file.

actions/checkout:dest_org/checkout
actions/upload-artifact:dest_org/upload-artifact
In your GitHub Actions workflow, reference the action as
uses: dest_org/checkout

Billing for GitHub Actions

GitHub Actions is free for public repositories and self-hosted runners. For private repositories, it includes 2000 free build minutes every month. For other plans, you could pay as per the details given in the link https://docs.github.com/en/billing/managing-billing-for-github-actions/about-billing-for-github-actions

Recommended Reading => GitHub Projects – Review of New Beta Features

Conclusion

In this article, we have seen how GitHub Actions can be used for CI/CD and within GitHub itself, rather than using GitHub repos with any third-party integration.

We have also seen the concepts in GitHub Actions and how easy it is to set up custom pipelines or workflows using YAML files to perform Build, Create a Release, Upload artifacts to Release, and Deployment to Tomcat.

GitHub Actions are completely integrated into GitHub, and you need not launch any separate tool for the same. We can use this feature similarly to using other features of GitHub like Commits, Pull Requests, Wiki’s, Issues, etc.

In the next series of articles, I will focus on other integrations with Sonar, Artifactory, and Docker and also cover details on GitHub Actions Secrets & Environment variables, though I have covered some aspects of it in this article.

Was this helpful?

Thanks for your feedback!

READ MORE FROM THIS SERIES: