Introduction to GitHub Actions: Streamlining CI/CD Pipelines
Tags: github, beginners, programming, productivity
Published: 2023-08-23 11:30:00

## Introduction

The developer’s productivity should be utilized in writing code. But there are instances when they are involved in non-core or repetitive tasks. Automating repetitive tasks should be practiced to save developers time. By automating tasks, we can get better productivity from developers.

With the rise in Continous Integration/ Continous Deployment (CI/CD) pipeline. The process of automating tasks has become easier than ever. With CI, we can integrate code into a shared repository and run automated tests to detect early errors. At the same time, CD helps in automating the deployment process as per the changes made to code and environment variables. Its aim is to deliver rapid and reliable code.

GitHub has also introduced a CI/CD pipeline to automate tasks. It is called GitHub Actions. They aim to help developers to automate the software development lifecycle. So, today we are going to look into different aspects of GitHub Actions.

Let’s get started.

## GitHub Actions

GitHub Action was first announced in 2018 and made publicly available in 2019 as a CI/CD pipeline to automate various aspects of SDLC directly from the GitHub repository. The code defines for the automation is in a YAML file. It is a human-readable data-serialization language that can be used for writing configuration files.

![GitHub Actions](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/lkk1z0v5aiv5mm0p0t4z.png)

The trigger to run the GitHub Action can be pull, push, or any other external trigger. You can run GitHub actions to run build, test, or deploy websites.  

Let’s create a Github Action to understand it better.

## Creating GitHub Actions

Creating a GitHub action is easy. Go to your GitHub repository either on the GitHub webpage or the local repository. Create a `.github/workflow`s  directory in the root directory. In this created directory, you can create a YAML file with any name you want. The extension of the YAML file is `.yml`. So, the name of the file goes like `name.yml`.

**Basic Structure of the YAML file**

At the top, we need to provide the name of the action with `name` keyword in the YAML file.

```yaml
    name: GitHub Actions 
```

After that, we can add the trigger. The trigger can be a pull, push, or at any interval of time. For defining the trigger, we use the keyword `on`.

For GitHub-defined events such as pull, you can use the below syntax. You can also add multiple triggers too.

```yaml
    // single
    on: [push]
    
    // multiple
    on: [push, fork]
```

You can look [here](https://docs.github.com/en/github-ae@latest/actions/using-workflows/events-that-trigger-workflows) for all the events that can trigger the workflow.

For triggering at any interval, we can schedule keywords with a cron.

```yaml
    on:
      schedule:
        - cron: "0 */12 * * *"
```

The cron expression can be breakdown into the following:

- 0: The first field is for the minute. It indicates that it will run on the 0th minute of the hour.
- */12: It indicates the hour field. It will run every 12 hours. */12 will indicate that every 12 hours the job will run. While providing only 12 will result in running jobs at 12 AM and 12 PM. You can specify time in 24 hours too. For example 23 for 11 PM.
- "*”: It is the day of the run. Will run every day. 
- “*”: The next asterisk is for the month. It will run every month.
- “*”: The last asterisk defines the day of the week. It shows that it will run every day of the week. It takes the day of the week as a number. Sunday is the first day of the week with a value of 0. Separate different days of the week with commas such as `0,2,3`. 

Thus the simpler syntax be written as 

```yaml
    cron: "Minute Hour Day Month Day_of_Week"
```

Now, it’s time to add the actual function that runs will run on triggering the workflow. YAML has `jobs` keyword to define different jobs 

Let’s look into the complete syntax and learn about it afterward:

```yaml
    jobs:
      build:
        runs-on: ubuntu-latest
        
        steps:
        - name: Checkout code
          uses: actions/checkout@v2
          
        - name: Setup Node.js
          uses: actions/setup-node@v2
          with:
            node-version: '14'
            
        - name: Install dependencies
          run: npm install
          
        - name: Run tests
          run: npm test
```

`update-readme` is the name of the job. Inside it is the runners, defined with the keyword `runs-on` , which is the machine on which the command will run. You can get the full list of runners [here](https://docs.github.com/en/actions/using-github-hosted-runners/about-github-hosted-runners#supported-runners-and-hardware-resources).

Now, we have the crucial `steps` keyword to define all the steps that should be executed while running the workflow. You can define various steps in an order with mainly two keywords `name` and `uses`. name keyword is used to provide a descriptive name for the specific step in the workflow. While uses keyword is used to define the action or a Docker contain that should run to perform the task.

The first step with the name uses `action/checkout` action that will fetch the repository, checkout ref such as branch, tag or commit SHA and prepare the workspace for further steps. The next step is to use the setup of the tool that requires to run the command. In our case it is Node.js. After that, we are running the command to install the dependencies.

The last step is where the actual code run which will produce the output. In our case, we are running the `npm test`  command to run the test. You can also run any node file that is present in the repository.

```yaml
    - name: Update README
    - run: node update-readme.js
```

Now, the overall code for the YAML file will look like this:

```yaml
    name: GitHub Actions 
    
    on:
      schedule:
        - cron: "0 */12 * * *"
    
    jobs:
      build:
        runs-on: ubuntu-latest
        
        steps:
        - name: Checkout code
          uses: actions/checkout@v2
          
        - name: Setup Node.js
          uses: actions/setup-node@v2
          with:
            node-version: '14'
            
        - name: Install dependencies
          run: npm install
          
        - name: Run tests
          run: npm test
```

## Debugging and Troubleshooting 

While writing GitHub actions, you can encounter errors such as failed execution of job or invalid syntax. Since YAML does not have any inbuilt debugger, it becomes challenging to debug any error. But there are some methods and tools that can help you in debugging GitHub Actions. Here are those:

- **GitHub Actions Extension**: GitHub has an official actions extension for VS Code. It can help you in managing and running the actions. It’s validation and code completion can help you in writing correct syntax. You can get it from [here](https://marketplace.visualstudio.com/items?itemName=GitHub.vscode-github-actions).
- **Conditional Debugging**: This method is not only valid for YAML but for other languages too. In this, you try to use conditions to selectively enable steps to run it. This can help you in finding where the error lies. You can use the `if` conditions to test it.
- **Workflow Logs**: Github generates logs when running the GitHub actions. These logs are well-detailed with every step’s execution. It can help you in learning which steps have failed. You can view the logs by clicking on the `Actions` tab in your repository. 
- **Act**: It is a terminal that helps in running the GitHub Actions locally. It can help you in testing the actions locally first and then push them to GitHub. It will save time as you don’t have to push/fork/pull every time to trigger the actions. You can look at its repository [here](https://github.com/nektos/act).
## The benefit of using GitHub Actions

Here are some of the benefits of using GitHub Actions:

- **Cron Jobs**: GitHub actions can perform cron jobs. You can define code in a file and run it at a particular period using GitHub actions.
- **Rich Ecosystem**: GitHub provides you with the ecosystem of git which helps you seamlessly integrate actions in the workflow. The trigger regarding pull, push, or fork can easily be utilized on GitHub. Along with that, they have a marketplace for pre-built actions from where you can get many useful actions for your project.
- **Scalability**: As you know GitHub can manage projects from small to large projects. Along with that, GitHub allows for creating multiple workflows and actions to trigger different jobs based on a trigger.
- **Security**: ****You can define GitHub secrets such as API keys in your setting of the repository. The YAML will have access to that secrets. Making it secure to use environment variables. 
    Access the secret through the below code:

```yaml
    - name: Update README
      run: node update-readme.js
      env:
        GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} # accessing the secret
```

## Conclusion

GitHub actions can perform various tasks as per your requirement as we see in this article. We go through understanding actions and then learn the syntax and flow of defining an action. In the end, we learn about some benefits of using it. The marketplace makes it easier to quickly add pre-built actions into your workflow. 

I hope this article has helped you in understanding GitHub Actions. Thanks for reading the article.

## Connect With Me

Let's connect and stay informed on all things tech, innovation, and beyond! 🚀

- [Twitter](https://twitter.com/surajondev) 
- [LinkedIn](https://www.linkedin.com/in/surajondev/)