DEV Community

Tobias
Tobias

Posted on

A CI/CD Pipeline With GitHub Actions for Go

Continuous Integration/Continuous Deployment (CI/CD) is an essential practice for modern software development. It helps developers to streamline the software development process by automating testing, building, and deploying their applications. GitHub Actions is a powerful tool for setting up CI/CD pipelines for your projects. In this post, we will explore how to set up a CI/CD pipeline using GitHub Actions for Go, which will help you to deploy your applications quickly and reliably. We'll cover the steps needed to create a pipeline that deploys to a staging and production environment from the same branch.

Creating the Staging Pipeline

Image description

First we utilize golangci-lint, this helps us to identify potential bugs, errors and stylistic issues.
After that we will run unit tests and start the build and deployment process. For demonstration purposes we will perform a straightforward Docker build and tag command as our build process.

name: Build

on:
  push:
    branches: 
      - main
  pull_request:
    branches: 
      - main

jobs:
  build:
    runs-on: ubuntu-latest
    steps:
    - uses: actions/checkout@v3
    - name: Set up Go
      uses: actions/setup-go@v3
      with:
        go-version: 1.20
    - name: golangci-lint
      uses: golangci/golangci-lint-action@v3
      with:
        version: latest
    - name: Test
      run: go test -v ./...
    - name: Build
      run: docker build -t latest .
Enter fullscreen mode Exit fullscreen mode

To enhance the above process, I recommend setting up notifications to a slack channel or a commonly used tool in your environment. This eliminates the need to constantly monitor the GitHub Action. Additionally, a step similar to this can be added to sent notifications on job failure.

 - name: Notify on failure
   if: failure()
   run: # do something
Enter fullscreen mode Exit fullscreen mode

Releasing to Production

As mentioned before we wan't to do this within the same branch. To do this we will create two jobs, one which creates a release and tags the latest commit and another one which is triggered by the tag to start the deployment process.
This needs a bit of preparation, because GitHub Actions can't trigger another action.
To achieve this you can head to the branches settings and add a deploy key.
For the rest of the article I assume the key is named COMMIT_KEY.

Let' have a look at the change log generation action.

name: Deploy Production

on:
  workflow_dispatch:

jobs:
  deploy:
    runs-on: ubuntu-latest
    steps:
      - name: Checkout Code
        uses: actions/checkout@v3
        with:
          fetch-depth: 0
          ssh-key: "${{ secrets.COMMIT_KEY }}" # set deploy key here
      - name: Create Release Tag
        id: release-tag
        # for demonstration purposes GitHub run number is used
        run: echo "tag=r-$(printf $GITHUB_RUN_NUMBER)" >> $GITHUB_OUTPUT
      - name: Find last successful workflow 
        uses: SamhammerAG/last-successful-build-action@v2
        with:
          branch: "main"
          workflow: "Build"
          verify: true
      - name: Push Tag
        run: |
          git tag ${{ steps.release-tag.outputs.tag }} ${{ github.sha }}
          git push origin ${{ steps.release-tag.outputs.tag }}
      - name: Create Release
        uses: ncipollo/release-action@v1
        with:
          allowUpdates: true
          draft: false
          name: ${{ github.ref_name }}
          tag: ${{ steps.release-tag.outputs.tag }}
          body: # create a change log 
          token: ${{ secrets.GITHUB_TOKEN }}
Enter fullscreen mode Exit fullscreen mode

In this action we will fetch the commit of the last successful run of our deploy to staging action. Because of this we can assume that our code is in a deployable state and we can skip running tests again. If you are using conventional commits you could use this action to generate the body for the release.

Lastly, we have an action that initiates the release to the production environment triggered by a push event specifically targeting tags.

name: Release Production

on:
  push:
    tags:
      - '' # use regex to limit to certain tags
jobs:
  build:
    runs-on: ubuntu-latest
  steps:
    - uses: actions/checkout@v3
      with:
        ref: ${{ github.ref }} # set the ref
    - name: Build and Deploy # add your deployment process here
      run: docker build -t latest .
Enter fullscreen mode Exit fullscreen mode

In conclusion, setting up a CI/CD pipeline with GitHub Actions for Go is a relatively simple process that can bring significant benefits to your development workflow. By automating the build, test, and deployment processes, you can reduce errors, improve efficiency, and free up your time to focus on more important tasks. With the examples provided in this post, you should have a good starting point for setting up your own CI/CD pipeline with GitHub Actions and Go. Always test and refine your pipeline to ensure that it meets your specific needs and requirements.

Top comments (0)