Github Actions: From Scratch to Azure Deployment
Tags: azure, github, actions, workflows
Published: 2020-10-21 17:37:23


# **Github Actions Training**

  

# **Introduction**

**GitHub** is a development platform that enables you to host and review code, manage projects, and build software alongside 50 million developers. It provides some important DevOps features that organizations of all sizes need for their software projects. Be it planning of features, fixing bugs, or collaborating on changes, GitHub is the place where developers gather to make things.

In the October of 2018, Github was added to the Microsoft stack and has served to increase enterprise use of GitHub alongside other Microsoft's developer tools and services.

**Github Actions** are a relatively new feature to Github. It enables you to build, test, package and deploy your code, right from your repository. It is a task automation system fully baked into GitHub. It came out of beta and reached general availability in November 2019. In any organization, Github Action can significantly scale down the amount of work and time required to build and maintain software projects.

**Github Flow**: is a workflow that simplifies the way changes are made to a software project. It is branch based. We start off with the Master. When there is need to add a feature, we branch off into a parallel feature branch to add the changes. This is not to disrupt the master. When done, we create a Pull Request for team members review. If approved, it is merged with the Master branch.

Github Actions can massively improve an organization’s Github flow and SDLC.

# **Setting Up Github Action**

Github Actions are YAML files located at the “**_.github/workflows_**” of your Github repository, that describes actions or tasks to be taken on your code based off an event.

There are two ways of setting up Github Actions in your repo, and we shall consider both:

1. From the Actions Tab

2. Manually Adding a **.github/workflows** folder

## **Method 1: Automatic Process**

**From the Actions Tab:**

 - Create a new Github repo, or use an existing one without Github
   Actions yet.
 - Navigate to the **Actions** tab.
 - Locate the “**_Simple Workflow_**” Github Action and click on the
   **_Set up this workflow_** button.
 - This would open the Simple Workflow. Click on Commit.
 - You now have this Github Action in your .github/workflows directory.

## **Example 1:**

  ```yaml
# 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.
```
  

## **Field Dymystification**

The file is called an Action File. It is a YAML file that specifies the triggers, runners, steps and other details needed to run a job. Lets consider the terms you can find in the above Action file.

 - **Name**: _Optional_ - The name of the workflow as it will appear in the Actions tab of the GitHub repository. It is a label.
 - **On**: Specifies the event that automatically triggers the workflow file. This example uses the **_push_** and **_pull_request_** events on the **_Master branch_**, so that the jobs run every time someone pushes a change to that branch.
 - **_Jobs_**: This Groups together all the jobs that run in the **_CI_** workflow file.
 - **Runs-on**: Configures the job to run on a runner. A runner is a VM that has the Github Actions Application runner installed. Here an
   **_Ubuntu Linux_** runner is specified. This means that the job will execute on a fresh virtual machine hosted by GitHub. A runner can be Github hosted or self hosted.
 - **Steps**: Steps represent a sequence of tasks that will be executed sequentially as part of the job. Each line nested under this section is a separate action.
 - **Uses**: The uses keyword tells the job to retrieve **_v2_** of the community action named **_actions/checkout@v2_**. This is an action that checks out your repository and downloads it to the runner, allowing you to run actions against your code.
 - **Run**: The **_run_** keyword tells the job to execute a command on the runner. In this case, it uses the runner’s shell to echo texts.

A job contains steps with actions, run commands or api calls that is triggered when a workflow runs.

Steps run actions or commands on the same runner, meaning they can share data.

You can target any event and activity type on a repo with the syntax:
  
  ```yaml
 On: 
<event_type>:
   Activity type: [activity1, activity2, …]
```
The full list of all activities can be found at developer.github.com/v3

You can also schedule a workflow to run at a given UTC time:

```yaml
On: 
  Schedule:
   - cron: ‘*/15 * * *’
```

This will trigger a run on the last commit on the default branch.

## **Method 2: Manual Process**

The manual way of adding a Github Action to Github is to add a **‘.Github/workflow’** folder to your new or existing Github repo. Here you’ll create your Action Files.

Github will automatically pick up these action files and run them when the specified even and activity occurs.

## **Example 2**

In the .github/workflows folder, create an action file. Name it ‘Greet.yml’. In the file enter the following.

```yaml
# your-repo-name/.github/workflows/greet.yml
name: Second Example 
on: 
Push: [ master ]                                                  
jobs:                         
  greet-job:                           
    name: Say hi                           
    runs-on: ubuntu-latest                           
    steps:                           
      - name: Print a greeting                             
        run: echo Hi from our first workflow!   
     
      - name: Show ASCII greeting                             
        uses: mscoutermarsh/ascii-art-action@master   
        with:                               
          text: 'HELLO!'
```
This workflow is triggered whenever there is a push event. Lets commit this file to the master and observe the run at the Action tab.

# **CI**

CI stands for Continuous Integration, and is the idea that as different members of the team work on code on different git branches, the code is merged to a single working branch which is then built and tested with automated workflows before merging to the production ready Master branch. This helps to constantly make sure everyone's code is working properly together and is well-tested.

From the point of view of CI, the main goal of GitHub Actions and Workflows is to build and test our software every time something changes. This way we can spot bugs and correct things as soon as the errors come up.

## **CI Demo: A NodeJS CI pipeline**

Create a **_CI.yaml_** file in your **_.github/workflows_** folder.

Paste the following into it:

```yaml
name: Node Continuous Integration

on:
  Push:
    branches: [ master ]

  pull_request:
    branches: [ master ]


jobs:
  test_pull_request:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v2
      - uses: actions/setup-node@v1
        with:
          node-version: 12
      - run: npm ci
      - run: npm test
      - run: npm run build`
```

## **Branch Protection**

Define branch protection rules to ensure builds pass before it can be merged to master.

To set up branch protection:

 - Go to **setting**
 - Click on **branches**
 - Under **Branch Protection Rules** click on **Add Rule**
 - Check “***Require status checks to pass before merging***” and other
   additional rules you want.
 - Click on **create**.

Now test your rule by intentionally breaking your code such that build fails.

# **CD**

CD stands for Continuous Deployment (or Delivery). Continuous Deployment takes things a step further and takes the automation to the deployment level. Where with the CI process, you automate the testing and the building, Continuous Deployment will automate the process of deploying the project to a desired environment.

## **CICD Demo: A NodeJS CICD Pipeline**

 - Clone this repo for a Sample NodeJS app
   [https://github.com/udujoel/nodejs_sample.git ]
 - Create a **_.github/workflows_** folder
 - Add a **_cicd.yaml_** file
 - Copy the workflow details below into it and Commit.

```yaml
# File: .github/workflows/cicd.yml

on:
  push:
    branches:
      - master

env:
  AZURE_WEBAPP_NAME: app_name_here   # set this to your application's name
  AZURE_WEBAPP_PACKAGE_PATH: '.'      
  NODE_VERSION: '10.x'                

jobs:
  build-and-deploy:
    name: Build and Deploy
    runs-on: ubuntu-latest
    steps:
    - uses: actions/checkout@master
    - name: Use Node.js ${{ env.NODE_VERSION }}
      uses: actions/setup-node@v1
      with:
        node-version: ${{ env.NODE_VERSION }}
    - name: npm install, build, and test
      run: |
        # Build and test the project, then
        # deploy to Azure Web App.
        npm install
        npm run build --if-present
        npm run test --if-present
    - name: 'Deploy to Azure WebApp'
      uses: azure/webapps-deploy@v2
      with: 
        app-name: ${{ env.AZURE_WEBAPP_NAME }}
        publish-profile: ${{ secrets.AZURE_WEBAPP_PUBLISH_PROFILE }}
        package: ${{ env.AZURE_WEBAPP_PACKAGE_PATH }}
```

Checking the Actions page, you’ll see our deploy is failing. We’ll fix that next. Now we need to understand how to setup Secrets and how to use it for Job authentication.

## **Secrets and Authentication**

You can use encrypted secrets, variables and tokens in your workflow to protect your repo and store sensitive info.

 - You can set them by visiting your Github repo settings tab,
 - click on ‘**_Secrets’_**.
 - Click on ‘**_New Secret_**’ to add a new one.
 - Set the name and value
 - Click on ‘**_add secret_**’ to save the addition.

To make use of a added secret:

```yaml
Steps:
  With:
Super_secret_input: ${{ secret.SECRET_NAME }}
```

To set these secrets as environment variable:

```yaml
Steps:
  env:
Super_secret_input: ${{ secret.SECRET_NAME }}
```

### Now to fix our workflow:

 - Create an **Azure App Service**
 - Download, open and copy the App service's **Publish Profile.**
 - Add a repo secret, with title "***AZURE_WEBAPP_PUBLISH_PROFILE***" and
   paste the **Publish Profile**.
 - Update the ***CICD.yaml*** file in `.github/workflows` with the App name.

Commit this file to trigger a CICD process. Open the Actions tab to observe the build and deploy.

When done.

View the changes on the site address: `[your-app-name].azurewebsites.net`



*Thanks for your time!*