Step-by-Step Tutorial on Using GitHub Actions for Automation

Step-by-Step Tutorial on Using GitHub Actions for Automation

GitHub Actions is a powerful tool that allows you to automate your development workflows. With GitHub Actions, you can build, test, and deploy your code right from your GitHub repository. In this beginner's guide, we'll take a detailed walkthrough of how to set up and use GitHub Actions for the first time.

First, let's define some key terms:

  • Workflow: A workflow is a set of one or more jobs that can be executed on GitHub. Workflows are defined in YAML files called workflow files.

  • Event: An event is a specific activity that triggers a workflow to run. Examples of events include pushing code to a repository, opening a pull request, or releasing a new version of your code.

  • Action: An action is a reusable piece of code that performs a specific task in a workflow. Actions can be created and shared by the GitHub community, or you can create your own custom actions.

Now that we have a basic understanding of the key terms, let's dive into setting up our first workflow. Here are the steps to get started:

  1. Create a new workflow file

To create a new workflow, you'll need to create a new file in your repository. This file should have a .yml or .yaml extension. You can name the file anything you like, but it's common to name it something like workflow.yml or .github/workflows/main.yml.

  1. Define the event that triggers the workflow

Each workflow file must start by defining the event that triggers the workflow. You can do this by using the on keyword, followed by the name of the event. For example, if you want the workflow to run every time code is pushed to your repository, you can use the following code:

on:
  push:
  1. Define the jobs in the workflow

Next, you need to define the jobs that will be executed by the workflow. You can define one or more jobs, and each job must include at least one step. You can define a job using the jobs keyword, followed by the name of the job:

jobs:
  build:
    runs-on: ubuntu-latest
    steps:
    - name: Checkout code
      uses: actions/checkout@v2

In the above example, the job is named "build", and it runs on the latest version of Ubuntu. The first step in the job is to check out the code from your repository.

  1. Add steps to the job

Once you've defined the job, you can add one or more steps to it. Each step must include a name and an action. Here's an example of adding a step to build the code:

steps:
    - name: Checkout code
      uses: actions/checkout@v2
    - name: Build code
      run: make

The above example includes two steps: checkout code and build code.

  1. Triggering the workflow

Once you've saved the workflow file, the workflow will be triggered by the event you defined (e.g., pushing code to your repository). You can view the status of the workflow in your repository by going to the Actions tab.

  1. Using actions to build, test, and deploy your code

GitHub Actions allows you to easily use pre-built actions to build, test, and deploy your code. For example, you can use the actions/setup-node@v2 action to set up Node.js dependencies, or the actions/setup-python@v2 action to set up Python dependencies.

In addition to pre-built actions, you can also create your own custom actions. Custom actions allow you to reuse your own code across multiple workflows.

Automating CI/CD Pipelines with GitHub Actions

Continuous Integration (CI) and Continuous Delivery (CD) are crucial practices in modern software development. They allow development teams to build, test, and deploy code changes quickly and reliably. GitHub Actions is a powerful tool that enables you to automate your CI/CD pipelines, all within your GitHub repository.

In this post, we'll discuss how to use GitHub Actions to automate CI/CD pipelines, including building, testing, and deploying your code. We'll also cover how to use Docker to containerize your applications and deploy them.

Building and Testing Code

The first step in a CI/CD pipeline is building and testing your code. GitHub Actions provides a number of pre-built actions that you can use to build and test your code. Here's an example of a workflow that builds and tests code using the Node.js runtime:

name: Build and Test

on:
  push:
    branches:
      - main

jobs:
  build-and-test:
    runs-on: ubuntu-latest
    steps:
    - name: Checkout code
      uses: actions/checkout@v2
    - name: Use Node.js ${{ matrix.node-version }}
      uses: actions/setup-node@v2
      with:
        node-version: ${{ matrix.node-version }}
    - name: Install dependencies
      run: npm ci
    - name: Build and Test
      run: npm run build && npm test

This workflow checks out the code, sets up the Node.js runtime using the actions/setup-node action, installs dependencies using npm ci, and builds and tests the code using npm run build && npm test.

Deploying Code

Once your code is built and tested, you can use GitHub Actions to deploy it to your production environment. Here's an example of a workflow that deploys code to a server using SSH:

name: Deploy to Production

on:
  push:
    branches:
      - main

jobs:
  deploy:
    runs-on: ubuntu-latest
    steps:
    - name: Checkout code
      uses: actions/checkout@v2
    - name: Install SSH key
      run: echo "${{ secrets.SSH_PRIVATE_KEY }}" | tr -d '\r' > ${{ secrets.SSH_KEY_PATH }}
      env:
        SSH_PRIVATE_KEY: ${{ secrets.SSH_PRIVATE_KEY }}
        SSH_KEY_PATH: /tmp/my-ssh-key
    - name: Deploy to server
      run: scp -r /tmp/my-ssh-key my-app production-server:/var/www/my-app

In this workflow, the code is first checked out, then a secret SSH private key is installed, and finally, the code is deployed to the server using the scp command.

Using Docker

In addition to building and deploying code, you can also use GitHub Actions to build and deploy Docker images. Here's an example of a workflow that builds and pushes a Docker image to Docker Hub:

name: Build and Push Docker Image

on:
  push:
    branches:
      - main

jobs:
  build-and-push-docker-image:
    runs-on: ubuntu-latest
    steps:
    - name: Checkout code
      uses: actions/checkout@v2
    -

Creating Custom GitHub Actions

GitHub Actions is a powerful tool that allows developers to automate their workflows. GitHub Actions provide pre-built actions for common tasks, but sometimes you may need to create your own custom actions for specific tasks. In this tutorial, we'll cover how to create a custom GitHub Action from scratch.

Creating a Docker Container for Your Action

The first step in creating a custom GitHub Action is to create a Docker container for it. This is because GitHub Actions runs in a containerized environment. Here's an example of a simple Dockerfile that creates a Node.js container:

FROM node:14

WORKDIR /app

COPY package*.json ./

RUN npm install

COPY . .

CMD [ "node", "index.js" ]

In this example, we're creating a Node.js container using the official Node.js image. We're copying the package.json file and installing the dependencies using npm install. Finally, we're copying the rest of the application and setting the entry point to index.js.

Writing the Necessary Scripts

Once you've created the Docker container, you need to write the necessary scripts to implement your custom action. The scripts should be written in Node.js or any other language that you prefer. Here's an example of a simple Node.js script for a custom GitHub Action:

const core = require('@actions/core');
const exec = require('@actions/exec');

async function run() {
  try {
    await exec.exec('npm', ['version']);
    const version = core.getInput('version');
    core.setOutput('new-version', version);
  } catch (error) {
    core.setFailed(error.message);
  }
}

run();

In this example, we're using the @actions/core and @actions/exec modules to run the npm version command and get the new version number as input. We're then setting the output of the action to the new version number using core.setOutput.

Publishing Your Action to the GitHub Marketplace

Once you've written the necessary scripts for your custom GitHub Action, you can publish it to the GitHub Marketplace. Here's how you can do it:

  1. Push your Docker container to a Docker registry like Docker Hub or GitHub Container Registry.

  2. Create a new GitHub repository for your custom GitHub Action and push your code to it.

  3. Create a new release for your custom GitHub Action and include the Docker container URL in the release description.

  4. Go to the GitHub Marketplace and click on "New Action".

  5. Provide the necessary details like the name, description, and input/output parameters for your custom GitHub Action.

  6. Provide the Docker container URL in the "Container" field.

  7. Click on "Publish Action".

Congratulations! You have now created a custom GitHub Action and published it to the GitHub Marketplace.

GitHub Actions vs. Other CI/CD Tools

Continuous Integration/Continuous Deployment (CI/CD) is an essential part of the software development lifecycle. There are various CI/CD tools available in the market, such as Travis CI, Jenkins, CircleCI, and GitHub Actions. In this post, we'll compare GitHub Actions with other popular CI/CD tools to help you decide which is the best fit for your needs.

GitHub Actions

GitHub Actions is a CI/CD tool offered by GitHub, which allows you to create custom workflows for your projects directly from your GitHub repository. GitHub Actions offers a free plan for public repositories and a paid plan for private repositories.

Pros:

  • Integrated with GitHub: GitHub Actions is tightly integrated with GitHub, making it an excellent choice for GitHub users.

  • Easy to set up: GitHub Actions offers a simple and intuitive interface for creating workflows.

  • Highly customizable: GitHub Actions allows you to create highly customized workflows using Docker containers and scripts.

  • Unlimited concurrent jobs: GitHub Actions offers unlimited concurrent jobs for free, which is a significant advantage over other CI/CD tools.

Cons:

  • Limited performance: GitHub Actions offers limited performance compared to other CI/CD tools.

  • Limited build matrix: GitHub Actions has some limitations when it comes to build matrix configuration.

Travis CI

Travis CI is a popular CI/CD tool for open source projects and offers a free plan for public repositories and a paid plan for private repositories.

Pros:

  • Popular and well-documented: Travis CI is a well-established tool with extensive documentation and a large community.

  • Supports multiple languages: Travis CI supports various programming languages, including .NET, Java, Node.js, and Ruby.

  • Cache feature: Travis CI has a cache feature that allows you to persist data between builds, which can improve build times.

  • Unlimited concurrent jobs: Travis CI offers unlimited concurrent jobs for free.

Cons:

  • Limited customization: Travis CI is not as customizable as GitHub Actions and other CI/CD tools.

  • No GitHub integration: Travis CI is not natively integrated with GitHub, which may require extra setup.

Jenkins

Jenkins is an open-source CI/CD tool that offers extensive customization options and a large community. Jenkins is self-hosted, which means you have to manage your Jenkins server.

Pros:

  • Highly customizable: Jenkins allows you to create highly customized workflows using plugins and scripts.

  • Large community: Jenkins has a large community, making it easy to find answers to your questions.

  • Self-hosted: Jenkins can be self-hosted, giving you complete control over your CI/CD environment.

Cons:

  • Steep learning curve: Jenkins has a steep learning curve, which may require extensive training.

  • Maintenance: Self-hosting Jenkins requires maintenance and management, which can be time-consuming.

CircleCI

CircleCI is a popular CI/CD tool that offers a cloud-based and on-premises solution. CircleCI offers a free plan for open source projects and a paid plan for private repositories.

Pros:

  • Efficient build times: CircleCI offers efficient build times using cached images and container-based builds.

  • Integrated with GitHub: CircleCI is natively integrated with GitHub, making it a great choice for GitHub users.

  • Customizable: CircleCI offers customizable workflows using scripts and execution environments.

Cons:

  • Limited free plan: CircleCI's free plan has some limitations, such as limited resources and fewer features compared to other plans.

  • Complex pricing: CircleCI offers various plans, making it challenging to find the best fit for your needs.

1. Microsoft's Azure SDK

Microsoft's Azure SDK uses GitHub Actions to automate testing and deployment of their SDKs across multiple languages and platforms. They have a complex workflow that involves building and testing SDKs for languages like Java, Python, and .NET, deploying them to Azure, and then testing them again. With GitHub Actions, they've reduced their testing time from hours to minutes.

2. Docker's Docker Hub

Docker uses GitHub Actions to automate the building and publishing of Docker images on Docker Hub. When a change is made to a Dockerfile, GitHub Actions triggers a workflow that builds the image, runs tests, and pushes the image to Docker Hub. This ensures that the latest changes are always available to users.

3. Laravel's Framework

Laravel, a popular PHP framework, uses GitHub Actions to automate testing and deployment of their framework. When code changes are pushed to the Laravel repository, GitHub Actions runs a suite of tests, including unit tests, integration tests, and browser tests. If all tests pass, the updated framework is deployed to the official Laravel repository.

4. Ruby on Rails' Framework

Ruby on Rails, another popular web framework, uses GitHub Actions to automate testing and deployment of their framework. They have a complex workflow that involves running tests on multiple Ruby versions, deploying to Heroku, and updating their documentation.

5. Shopify's Theme Development

Shopify uses GitHub Actions to automate the testing and deployment of their theme development workflows. When a developer pushes changes to a theme repository, GitHub Actions triggers a workflow that runs tests, lints code, and deploys the updated theme to Shopify's platform.

6. CircleCI's GitHub Actions

Ironically, CircleCI, a continuous integration and delivery platform, uses GitHub Actions to automate parts of their own workflow. They use GitHub Actions to run tests, build, and deploy their own GitHub Apps, demonstrating the versatility of GitHub Actions.

7. WordPress' Plugin Development

WordPress uses GitHub Actions to automate the testing and deployment of their plugin development workflows. When a developer pushes changes to a plugin repository, GitHub Actions triggers a workflow that runs tests, lints code, and deploys the updated plugin to the WordPress Plugin Directory.

Benefits and Results

These examples demonstrate the benefits of using GitHub Actions, including:

  • Faster testing and deployment: GitHub Actions can significantly reduce the time it takes to test and deploy code changes, from hours to minutes.

  • Increased efficiency: Automating repetitive tasks like testing, building, and deployment frees up developers to focus on writing code and fixing bugs.

  • Improved reliability: GitHub Actions can ensure that code changes are thoroughly tested and deployed consistently, reducing the likelihood of errors and downtime.

  • Better collaboration: GitHub Actions can be used to automate workflows across multiple repositories and teams, making it easier to collaborate and maintain large projects.

By showcasing these real-world examples, we can see how GitHub Actions can be used to streamline development workflows, improve collaboration, and reduce the time and effort required to deliver high-quality software.

Here are some examples of GitHub Actions code for Python applications:

Simple Python Application

name: Python Application

on:
  push:
    branches:
      - main

jobs:
  deploy:
    runs-on: ubuntu-latest
    steps:
      - name: Checkout code
        uses: actions/checkout@v2

      - name: Install dependencies
        run: pip install -r requirements.txt

      - name: Run tests
        run: pytest

      - name: Deploy to production
        run: |
          git push origin main:prod
          ssh user@production-server "cd /path/to/app && git pull origin prod"

Django Application

name: Django Application

on:
  push:
    branches:
      - main

jobs:
  deploy:
    runs-on: ubuntu-latest
    steps:
      - name: Checkout code
        uses: actions/checkout@v2

      - name: Install dependencies
        run: pip install -r requirements.txt

      - name: Run tests
        run: pytest

      - name: Build Docker image
        run: |
          docker build -t my-django-app .
          docker tag my-django-app $GITHUB_SHA

      - name: Push Docker image
        uses: docker/login-action@v1
        uses: docker(push-action)@v1

      - name: Deploy to production
        run: |
          ssh user@production-server "cd /path/to/app && docker pull $GITHUB_SHA"
          ssh user@production-server "cd /path/to/app && docker-compose up -d"

Flask Application with(Code)coverage

name: Flask Application

on:
  push:
    branches:
      - main

jobs:
  deploy:
    runs-on: ubuntu-latest
    steps:
      - name: Checkout code
        uses: actions/checkout@v2

      - name: Install dependencies
        run: pip install -r requirements.txt

      - name: Run tests
        run: |
          coverage run -m pytest
          coverage report -m

      - name: Deploy to production
        run: |
          git push origin main:prod
          ssh user@production-server "cd /path/to/app && git pull origin prod"

Python Data Science Application with Jupyter Notebook

name: Python Data Science Application

on:
  push:
    branches:
      - main

jobs:
  deploy:
    runs-on: ubuntu-latest
    steps:
      - name: Checkout code
        uses: actions/checkout@v2

      - name: Install dependencies
        run: pip install -r requirements.txt

      - name: Run tests
        run: pytest

      - name: Build Jupyter Notebook
        run: |
          jupyter nbconvert --to notebook --execute my_notebook.ipynb

      - name: Deploy to production
        run: |
          git push origin main:prod
          ssh user@production-server "cd /path/to/app && git pull origin prod"