Automated deployment and delivery pipelines increase software development process efficiency, increase team productivity, and enhance the ability to deliver software rapidly without compromising quality. GitHub Actions workflow features allow users to configure various deployment and delivery pipelines to support different technologies.
In this chapter, you learn about GitHub Actions workflows. We discuss the components that are important for configuring build and deployment pipelines.
GitHub Actions workflows are configured using preconfigured workflow templates or Marketplace actions, which you learn to work with in this chapter. This chapter also explains GitHub Action workflows’ structure and continuous integration capabilities by using a sample .NET Core application pipeline.
Using Preconfigured Workflow Templates
A GitHub Actions workflow is a YAML file that consists of automated process instructions. It is made of jobs, events, steps, actions, and runners. Steps are identified as the tasks executed by the job, which runs Actions and commands. One workflow can have one or multiple independent or dependent jobs. The workflow file needs a mechanism to configure automated triggers, and events automatically decide which activity triggers the workflow. A runner is a machine on which the GitHub Actions runner application is installed. Workflow jobs are executed using the runner provided in the workflow script.
Today, the information technology industry uses more tools and technologies than ever before. Hence, more hosting platforms are available in the market that can be integrated with deployment tools.
GitHub has multiple predefined workflow templates to create automated build and deployment processes. To find these workflow templates, go to the GitHub repository, and move to Actions. You can find continuous integration and deployment workflow templates on this page (see Figure 2-1).
Figure 2-1
Workflow templates
You see the deployment workflow templates for all the main cloud platforms, such as Azure, AWS, Google Cloud, and IBM Cloud. Clicking the “Set up this workflow” button opens a template workflow YAML file, which you can edit to fit your requirements (see Figure 2-2).
Figure 2-2
Workflow template YAML file
In addition to continuous deployment workflow templates, there are continuous integration workflow templates to build applications using different technologies, such as Ruby, Java, .NET, Python, and more. Like the deployment workflow template, integration workflow is also a YAML file consisting of basic build steps that you can edit according to your requirements.
The workflow template consists of all the basic sections required to set up a build pipeline or deployment pipeline.
Using Marketplace Actions to Create Workflows
A GitHub workflow is a collection of multiple components. Of all the components, an action is the smallest portable building block in the workflow. There are two types of GitHub Actions: publicly available actions (a.k.a. Marketplace actions) and self-defined actions. This section explains how to work with Marketplace actions.
You can access Marketplace actions from two places; one is from the workflow editor. Since you have already learned about the workflow template, let’s add an action from the workflow editor page (see Figure 2-3).
Figure 2-3
Marketplace actions
Select the action that needs to be added to the workflow. A YAML script is added to the workflow YAML file. For this example, let’s select Download a Build Artifact (see Figure 2-4).
Figure 2-4
Marketplace action YAML script
To install the Marketplace action in the workflow, copy the YAML script under the Installation section of the Marketplace action. Select the relevant action version before copying the YAML script. Paste the copied YAML action in the steps section of the workflow. Provide all the relevant details for the action.
Understanding the Structure of a Workflow
In this section, you learn about the structure of a workflow.
To set up a workflow, go to Actions in your repo. You see a “set up a workflow yourself” link to start the workflow creation process without using templates (see Figure 2-5).
Figure 2-5
Creating a workflow from scratch
A YAML file opens with a basic workflow configuration structure. You can follow the YAML file structure to build the workflow according to your needs.
Let’s discuss each section of the workflow. A manually created workflow template is set up as follows.
# This is a basic workflow to help you get started with Actions
name: CI
# Controls when the action will run. Triggers the workflow on push or pull request
# events but only for the master branch
on:
push:
branches: [ master ]
pull_request:
branches: [ master ]
# A workflow run is made up of one or more jobs that can run sequentially or in parallel
jobs:
# This workflow contains a single job called "build"
build:
# The type of runner that the job will run on
runs-on: ubuntu-latest
# Steps represent a sequence of tasks that will be executed as part of the job
steps:
# Checks-out your repository under $GITHUB_WORKSPACE, so your job can access it
- uses: actions/checkout@v2
# Runs a single command using the runners shell
- name: Run a one-line script
run: echo Hello, world!
# Runs a set of commands using the runners shell
- name: Run a multi-line script
run: |
echo Add other actions to build,
echo test, and deploy your project.
Workflow files should be saved in github/workflows in the repository root. You can define the exact triggering condition for each workflow. You can set up event triggers, schedule triggers, and manual triggers. A workflow_dispatch event should be activated in your workflow to enable a manual trigger, as shown next.
name: MyManualBuild
on: [workflow_dispatch]
This enables the Run workflow button (see Figure 2-6).
Figure 2-6
Run workflow manually
You learn about triggers in the next section. Another important component of GitHub Actions is the runner. A runner is a machine or container that executes the workflow. A runner is defined with a runs-on keyword. You can use two types of runners: GitHub-hosted runners or self-hosted runners. Setting up self-hosted runners is discussed in Chapter 6. Each job needs to specify a name and runner. The following specifies a runner hosted by the latest Ubuntu runner (machine).
jobs:
# This job name is mybuild
mybuild:
# Runner type that the job will run on
runs-on: ubuntu-latest
A job is another major part of a workflow. A workflow can have one or more jobs. By default, jobs run in parallel. Hence, if you need to run jobs one after another, dependency should be defined. For example, in the following workflow, the AppCenterDistribute job needs the Android job to complete before it can execute. Dependency is defined with the needs: DependingJobName syntax in each job scope.
jobs:
Android:
runs-on: macos-latest
steps:
- uses: actions/checkout@v1
# omitted steps for brevity
AppCenterDistibute:
runs-on: ubuntu-latest
needs: Android
steps:
All workflow steps and actions are defined in a workflow job. The following uses AppCenterDistribute job steps as an example. This example uses a secret in a step, which we discuss in Chapter 4.
AppCenterDistibute:
runs-on: ubuntu-latest
needs: Android
steps:
- uses: actions/download-artifact@v2
with:
name: my-artifact
- name: App Center
uses: wzieba/AppCenter-Github-Action@v1.0.0
with:
# App name followed by username
appName: Ch-DemoOrg/demoapp
# Upload token - you can get one from appcenter.ms/settings
So far, you have gained a basic understanding about a workflow’s YAML structure. Now, let’s discuss workflow runs.
Go to Actions in the GitHub repository. You find a list of the workflows run, as shown in Figure 2-7 (see the area labeled 2). (We assume that by now you have created at least one workflow, utilizing an available template or sample structure created when you selected the “Set up workflow yourself” option). You can also see run history information for the selected workflow, including run duration, commit, branch, and actor details (see the area labeled 3 in Figure 2-7). If you click one of the run history records listed, you move to a detailed view of the run.
Figure 2-7
Workflow runs
Click the workflow run history to navigate to the workflow details page (see Figure 2-8).
Figure 2-8
Workflow run details
You see the workflow name (see the area labeled 1). If you click “build” (your build job may have a different name based on your YAML), it navigates to the build logs, where you can find all the important details regarding the build (see Figure 2-9).
Figure 2-9
Log of workflow steps
You now have a basic understanding of a GitHub Actions workflow.
Setting up Continuous Integration Using GitHub Actions
Setting up continuous integration is a very important section of the pipelines. It enables teams to ensure that the submitted code is validated. The required important branches are protected, and the deployment happens as expected. In this section, you learn about triggers in GitHub Actions and how to control them in different conditions.
When configuring triggers, you need to identify the starting event, which explains the pipeline’s situation. Three main events trigger a GitHub Actions pipeline: pushing a commit to the repository, creating an issue, and creating a pull request.
An event is defined using on: syntax. As shown in the following example, a workflow triggers when it pushes changes to the master branch.
on:
push:
branches: [ master ]
Similarly, you can trigger both a push and a pull request targeting the master branch, as shown next.
on:
push:
branches: [ master ]
pull_request:
branches: [ master ]
You can use a scheduled event as a trigger using cron: syntax.
on:
schedule:
- cron: '0 * * * *'
Cron expressions allow you to define schedule triggers based on the following format.
A workflow can be triggered manually using a workflow_dispatch trigger. If required, you can define input values that are changeable in a workflow_dispatch trigger. The following example shows utilizing input in a workflow with a manual trigger.
name: myworkflow
on:
workflow_dispatch:
inputs:
name:
description: 'name of the person'
required: true
default: 'Chaminda'
country:
description: 'Country'
required: false
jobs:
greetuser:
runs-on: ubuntu-latest
steps:
- run: |
echo "Hi ${{ github.event.inputs.name }}!"
echo "- in ${{ github.event.inputs.country }}!"
There are multiple webhook events that you can use in GitHub Actions to trigger a workflow. When you press Ctrl+Space after On: in the GitHub Actions workflow editor, you get IntelliSense support to find all the events (see Figure 2-10).
Figure 2-10
Workflow triggers
This section looked at setting up two commonly used triggers and how to find the available triggers in a GitHub Actions workflow.
Building a .NET Core Web App with GitHub Actions
GitHub Actions supports many different technologies. In this lesson, you learn how to build a .NET Core app with GitHub Actions.
The prerequisites are a GitHub repo with .NET Core code.
As discussed, there are two options for creating a GitHub workflow. You can either create a workflow from scratch or use a template. This section uses a .NET Core workflow template to modify the YAML file according to requirements (see Figure 2-11).
Figure 2-11
.NET Core template
Let’s look at common GitHub Actions syntax by using a .NET Core workflow.
First, you name the workflow.
name: .NET Core
A workflow needs an event to start it. The events are defined with the triggers after the on: syntax. The following example has two events defined as a push and a pull request. If either the push or the pull request is made to the master branch, the workflow is triggered, as shown in the following syntax. You can set up triggers according to your needs and preferences.
on:
push:
branches: [ master ]
pull_request:
branches: [ master ]
A workflow has one or more jobs. All the steps are defined under the jobs executed in a runner (in other words, on a machine). A workflow job is defined with the jobs syntax. Under the jobs section, you need to define the runner machine and the steps to execute. Use the runs-on syntax with the runner machine YAML workflow label to define the runner machine. For example, you can use the “ubuntu-latest” workflow label. It uses a ubuntu-18.04 machine as the GitHub-hosted runner. In GitHub workflows, you can use GitHub-hosted runners or self-hosted runners. Self-hosted runners are discussed in Chapter 6.
runs-on: ubuntu-latest
Now we can define the build steps to build the .NET core project. Source code should be downloaded to the build machine or the runner as the first step before building the code. Therefore, the checkout action downloads the source. When we define the actions in the workflow, names can be given to actions, and those can be any meaningful name. The action should appear after the uses: syntax. Each action has a version, which is very important and should be used when defining a workflow; otherwise, failures may occur in the workflows due to version incompatibility.
steps:
- name: Checkout GitHub actions
uses: actions/checkout@v2
All the required components should be downloaded and installed before building the code. Therefore, the .NET Core framework is downloaded to the build machine with the following action. The .NET Core version is defined after the with: syntax, as shown next.
- name: Setup .NET Core
uses: actions/setup-dotnet@v1
with:
dotnet-version: 3.1.301
The next step is to set up the .NET Core project’s dependencies. The dotnet restore command can be run in the workflow for this purpose.
- name: Install dependencies
run: dotnet restore
Once all the dependencies are installed, the code can be built. The dotnet build command can be used with relevant parameters to do this.
After the build, test scripts are executed with the dotnet test command.
- name: Test
run: dotnet test --no-restore --verbosity normal
Now, the code is built and tested. You can prepare the source code to host. The dotnet publish command prepares all the required files to publish. The following command has two parameters: configuration and output directory.
Finally, you can upload published files as an artifact to the build pipeline. When you need to deploy files, they can be downloaded from the artifact’s location.
- name: Upload Artifacts
uses: actions/upload-artifact@v2
with:
name: my-artifact
path: "./dotnetcorewebapp"
The following is the full workflow code for a complete implementation of a .NET Core build pipeline.
This section looked at a complete workflow that builds a .NET Core project and uploads artifacts to GitHub.
Summary
This chapter explored using preconfigured templates to define GitHub Actions workflows and creating a workflow from scratch. It discussed workflow structure, including syntax and components. You explored the triggers that initiate a workflow and a sample workflow from a .NET Core application build.
The next chapter looks at using variables and secret variables.