Easier CI/CD with GitHub Actions

Easier CI/CD with GitHub Actions

Overview

GitHub Actions is a native CI/CD solution within GitHub that enables teams to automate tasks within their software development lifecycle. Workflows can be triggered from GitHub events such as pushing to a branch or opening a pull request.

It has quickly become the preferred CI/CD platform for many organizations, thanks to its seamless integration with GitHub, extensive collection of community-contributed actions, and ease of use.

The 2023 Octoverse Report showed that developers' use of GitHub Actions in public projects grew 169% over the previous year .


Saying Goodbye to Jenkins

For a long time, the de facto CI/CD tool was Jenkins, a self-hosted open-source server that offers many customization options but also has a steep learning curve.

Jenkins is a mature product and quite capable of providing great CI/CD functionality. However, the platform suffers from a number of issues that has caused teams headaches and frustration.

  • Jenkins does not have an officially managed offering and needs to be self-hosted.
  • Its complexity requires deep knowledge to build, operate and maintain at scale. This means experienced admins are often needed when new jobs, builds or pipelines are required.
  • Advanced pipeline functionality requires the use of a Groovy-like syntax which has a learning curve for those unfamiliar with Groovy.
  • Managing the collection of plugins and the dependencies between them can be challenging.
  • GitHub integration requires configuring plugins and webhooks as triggers for the pipeline.

Many engineering teams, including CTG, have begun migrating their workflows from Jenkins to GitHub Actions for these reasons.


Advantages of GitHub Actions

Here are several reasons why developers and organizations should consider choosing GitHub Actions for their CI/CD needs.

Seamless Integration with GitHub

Since GitHub Actions operates within the GitHub ecosystem, it has direct access to your repository, simplifying the setup process and reducing the need for complex configurations.

Ease of Use and Configuration

Workflows are defined using YAML files, which are easy to read and write. This approach makes it simple to define, understand, and maintain CI/CD pipelines as code.

Security and Compliance

Actions run in isolated environments, ensuring that each workflow is securely sandboxed. Additionally, GitHub provides features like encrypted secrets and environment protection rules to safeguard sensitive information and control workflow access.


How GitHub Actions Works

GitHub Actions operates via workflows which are automated processes defined in YAML files stored under the .github/workflows directory in your repository.

A workflow consists of one or more jobs, and each job can contain multiple steps. Here's a basic overview of the components:

  • Workflow: Automated processes defined in YAML configuration files.
  • Job: A set of steps that run on the same runner (a virtual machine or container).
  • Action: A pre-built or custom script that performs a specific task.
  • Event: Specify events that trigger workflows, such as pushes, pull requests, or scheduled times.
  • Step: An individual task that is part of a job.
Source: https://www.liatrio.com/resources/blog/github-actions-workflows

Secrets

The use of secrets is straightforward. To set a secret, navigate to Settings > Secrets and variables > Actions in your repository. Add a new secret by giving it a name and value, and save it (e.g. MY_SECRET).

In workflows, these secrets are accessed using ${{ secrets.MY_SECRET }} syntax. This allows developers to safely use sensitive data without hardcoding it into scripts or configuration files.

It's important to note that GitHub does not allow you to view the value of a secret in the UI after it has been saved.

Organization-level secrets are also supported for situations where you want to make the sensitive data available across multiple repositories.


Marketplace

GitHub Actions Marketplace is a large repository of pre-built actions created by the community and verified publishers.

These actions can be easily integrated into workflows to perform a variety of tasks, such as setting up programming languages, running tests, deploying applications, and much more.

By using pre-built actions from the Marketplace, teams can save time and effort, avoiding the need to write custom scripts for common tasks.

You can explore the marketplace here.

GitHub Actions Marketplace

Runners

Runners are the machines that execute the jobs defined in GitHub Actions workflows. GitHub supports two types of runners: hosted and self-hosted.

Hosted Runners

Hosted runners are managed by GitHub and come pre-configured with a wide array of tools and environments, making it easy to get started with minimal setup.

These runners automatically scale to meet the demands of your workflows and are included in GitHub's pricing plans.

Self-Hosted Runners

Self-hosted runners are machines that you manage and configure.

These runners establish outbound connections to GitHub for various purposes, including receiving jobs and uploading logs and artifacts.

By using self-hosted runners, teams can leverage their existing infrastructure while still benefiting from the automation capabilities of GitHub Actions.

You can learn more about managing self-hosted runners from the official docs here.


Example workflow - Node + S3 + CloudFront

The below workflow is something I have personally used to deploy a React app to AWS S3.

name: Node.js CI/CD

on:
  push:
    branches: [main]

jobs:
  build-and-deploy:
    runs-on: ubuntu-latest

    steps:
      - uses: actions/checkout@v4
      - name: Use Node.js
        uses: actions/setup-node@v4
        with:
          node-version: '20'
      - name: Install dependencies
        run: npm ci
      - name: Build project
        run: npm run build
      - name: Deploy to S3
        run: aws s3 sync build/ s3://example.com --delete
          env:
            AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }}
            AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
      - name: Clear CloudFront cache
        run: aws cloudfront create-invalidation --distribution-id XXXXXXXXXXXXXX --paths "/*"

It triggers on a push to the main branch, sets up a Node environment, installs npm dependencies and caches them, and then runs the build script.

After a successful build and test run, the workflow configures AWS credentials and deploys the built application to an S3 bucket using repository secrets.

Finally, it clears the CloudFront cache to ensure that the latest version of the application is served. This setup helps maintain a reliable and efficient CI/CD pipeline, ensuring that only tested code is deployed.

Note that if a step fails in the workflow, the job will stop running, and the workflow run will be marked as failed.


Costs

There is a free tier for GitHub Actions with 2,000 minutes of free runner usage per month for public and private repositories.

For larger projects and organizations, GitHub Actions operates on a pay-as-you-go model, allowing you to scale usage as needed without upfront infrastructure costs. This flexibility helps manage budgets effectively while meeting CI/CD requirements.

More detailed information about billing can be found here.


Conclusion

GitHub Actions has emerged as a robust and user-friendly CI/CD solution, offering seamless integration with GitHub repositories, an extensive library of pre-built actions, and straightforward YAML-based configuration.

It allows engineering teams to focus more on building and deploying high-quality software rather than managing DevOps infrastructure.