The purpose of this blog is to help those who want to set up CI/CD for their projects. There are many popular tools present in the market right now like CircleCI and TravisCI and Github Actions is one of them.
Before moving forward with GitHub Actions, it is necessary for us to understand what are software development workflows and why is the need for them to be automated.
In a software development project, there is a team that consists of several individuals who work on the project, and is it obvious that the project needs to be hosted on some Version control and source code management system like Github or Gitlab. Several organizational tasks need to be managed.
Let us consider a scenario where a team member has pushed some code and before merging it to the target branch, the maintainer needs to verify if it is passing all the test cases or not and also needs to verify if the project is building successfully or not.
Generally, if things had been manual, the maintainer had to run the tests first and test if the build is successful or not manually. Then after reviewing changes, the maintainer merges the source branch to the target branch.
Now considering a professional project which has multiple individuals working on it, the above tasks would have been a headache for the maintainer since there could have been multiple Pull Requests open at a time by several developers.
And above case is just one scenario, there can be multiple organizational tasks that needed to be performed like creating an artifact (Binary of your app, Container image, Website build, etc.), sending a message on slack after a PR is created, deploying code to certain environment testing/staging/production when code is merged on a particular branch.
Here comes CI/CD tools in the picture which can help you out with all these tasks which don’t need human involvement.
CD/CD stands for Continuous Integration and Continuous Deployment (or Delivery). These are practices in software development that allow teams to build projects together quickly, efficiently, and ideally with fewer errors.
Continuous Integration deals with managing tasks related to development workflow like build, test, etc branch before merging it with the main working branch. This helps to constantly make sure everyone’s code is working properly together and is well-tested.
Continuous Deployment deals with the deployment process which is in a continuous loop with CI.
So, in short, we can say that with the Continuous Integration process, you automate the building and the testing, whereas Continuous Deploymentwill automate deploying the project to an environment.
What are Github Actions?
Github Actions is a tool integrated into github which can be used to automate software development workflows.
GitHub Actions help you automate your software development workflows in the same place you store code and collaborate on pull requests and issues. You can write individual tasks, called actions, and combine them to create a custom workflow. Workflows are custom automated processes that you can set up in your repository to build, test, package, release, or deploy any code project on GitHub.
Whenever something happens TO or IN your github repository like PR created or issue created or PR merged etc, automatic actions can be executed in response using github actions.
LISTEN TO EVENT — — — — — — — — — — > TRIGGER WORKFLOW
This enables you to include CI/CD capabilities and many other features directly in your repository.
To learn more about the basics of Github Actions, click here.
Understanding Syntax of workflow files
name [optional]: is displayed on your repo’s action page
# Name of Workflow to be displayed on Github Console name: Github Workflow
on [required]: name of Github event/events that triggers the workflow
# Triggers the workflow on push or pull request events on: [push, pull_request] # Or you can separately configure for multiple events # Triggers the workflow on push or pull_request events on master # branch on: push: branches: [master] pull_request: branches: [master]
jobs [required]: job/jobs segregated by job_id, to be executed when event gets triggered and consists of a sequence of tasks(steps)
jobs: my_first_job: name: My first job # runs_on specifies the type of machine to run the job on. # The machine can be either a GitHub-hosted runner or a self-hosted # runner. runs_on: ubuntu-latest # steps can run commands, setup tasks or run an action steps: - name: Check out repository # uses selects an action to run as part of a step in your job. # action/checkout@v2 checks-out your repo under github workspace. uses: actions/checkout@v2 my_second_job: name: My second job runs_on: ubuntu-latest steps: - id: step2 # run runs command-line programs using the operating system's shell. run: echo "My Second Job"
Above are some of the most commonly used workflow syntaxes. To read more about workflow syntaxes, click here.
Now, let us move ahead and build a demo application where we can use github actions to automate workflow.
I will be using Golang for Writing the Code, and the commands in the upcoming parts will be golang specific but you can replace them with tools and commands specific to the programming language you choose.
Workflow to be automated
I will be using a code where the main function is just printing the current time on the console. In the below image, you can see the code in main.go file.
In the image below you can see the test cases for main.go in file main_test.go
So while raising a PR we will be checking for the following aspects :
1. Build should be successful
2. Test cases should be passing
3. go vet should not report any suspicious constructs
4. go fmt should check code formatting and pass
5. golint should pass without any error
We will also set up restrictions on Pull Request from getting Merged if checks fail.
Just for some fun, we will send a notification to Slack when a PR is created which fulfills all the above criteria. This will be covered in the other blog the link for which I have attached at the end of this blog.
Note: Just for the demonstration purpose, I will be tweaking the code a little bit in different PRs so we can see the working of checks when code is pushed on any branch. I will be attaching the links for the failed checks for each step so that you can see the code that caused failure.
Github Workflow Implementation
Depending on the tech stack you are using, you can already find multiple github-action templates in github marketplace. Now, we will create a workflow for our project.
Step 1: Create .github/workflows in your project’s root directory. Here we will be storing our YAML files consisting of workflow configurations.
Step 2: Configure the YAML file according to the workflow you wish to implement. Below we will be looking at the workflow setup step-by-step.
Create a file named build-workflow.yml in .github/workflows directory.
You can find the build-workflow.yml file at the end of this blog or here.
a} Setup Workflow name and Configure trigger events.
An example of events is push and pull_request which we will be using.
b} Setup Jobs to run in a workflow.
The code in the below image specifies a job with job_id build. Jobs can be run sequentially or in parallel or chained. Each Job has some steps.
The first 2 steps which we performed are setup go environment using pre-existing action setup-go and check out our current repo in github workspace using action checkout so the workflow can access it.
Now we will be performing the checks that we need to set up in our workflow.
c} Perform step: build package
This step will check for the build failures in our code.
Check out Failing Build Action on github event, here.
d} Perform step: run test cases
This step will check if all test cases under the package are passing or not.
Check out Failing Test Cases Action on github event, here.
e} Perform step: go vet
This step will check if Go source code reports suspicious constructs.
Check out Failing go vet Action on github event, here.
f} Perform step: go fmt
This step will check for formatting (indentation and blanks etc.) of our code.
Check out Failing go fmt Action on github event, here.
g} Perform step: go lint
This step will run lint on your code and will report if it fails.
But before running the lint command, we will first install the package.
Check out Failing go lint Action on github event, here.
Prevent Pull Request from getting Merged if Checks fail :
Step 1: Navigate to Settings on Github Repo. Select Branches and Click on Add Rule.
Step 2: Set Branch name pattern. I’ve set it to main since I want to prevent the main branch from unchecked merges, you can set it to * for protecting all branches.
Select from the options below based on your requirements, but just for protecting unchecked merge I have selected just one option “ Require status checks to pass before merging”.
After that, search for Status Checks (jobs) name on which you wish to depend on mergeability of branches and select them.
Click on Create at the bottom of the page to create a rule.
After the branch protection rule has been applied.
As you can see in the above image, after applying for branch protection we can see the message implying we can only merge if statuses pass.
Note: administrator of a repository can still merge the PR, this means this branch protection rule prevents non-administrators from merging.
Github action workflow file
Click here to get gist for build workflow.
As I mentioned earlier, we will also be setting up Slack Notifications when a PR is raised that passes all the build checks. To setup slack notification in your github workflow, follow this link.
Conclusion: In the end, I just hope this helped you with setting up build checks using Github Actions for your project. Though there are many things got covered in this blog, there are still a lot more things that you can explore.
If you have reached this point, Thank You for reading this blog.
Demo-Application-Repo : https://github.com/sagar23sj/github-workflow-demo
Github-Actions : https://docs.github.com/en/actions
Blog : https://presstige.io/p/Using-GitHub-Actions-with-Go-2ca9744b531f4f21bdae9976d1ccbb58