A common pattern for continuous integration involves using pull requests to trigger testing & other automation tasks.
In the exercise below, we will walk through adding linting & testing for pull requests for a sample Golang application. This will trigger on pull request creation, as well as updates to code in the branch that the PR references.
- Checkout the default branch of your repository
- Create a new file named
.github/workflows/ci-cd.yaml
- Copy the contents below to the newly created file:
name: Continuous Integration & Delivery
on:
pull_request:
workflow_dispatch:
defaults:
run:
shell: bash
jobs:
ci:
name: Continuous Integration
runs-on: ubuntu-latest
defaults:
run:
working-directory: golang_app
steps:
- name: Clone
uses: actions/[email protected]
- name: Get Dependencies
run: go get app
- name: Build
run: go build
- name: Run Linting
uses: golangci/golangci-lint-action@v3
with:
working-directory: golang_app
- name: Run Tests
run: go test
- Add, commit, and push your changes to the default branch.
- Go to your repository, and view the Actions tab to see the workflow you created (
Continuous Integration
)
The result will be a workflow you can execute manually and automatically triggered by a pull request.
Branch protection is one of the feature GitHub has that allows you to control who, what, and when a branch can be pushed to. For continuous integration, continuous delivery, and continuous deployment, this feature is integral. In the below step, we will enable this so that no "bad code" can make it through.
- Enable branch protection for you default branch (instructions)
- After adding the branch name pattern, use the following settings. Leave everything unchecked except:
Require a pull request before merging
Require status checks to pass before merging
- Search for and add
Build, Lint, & Test
as a required status check (will appear once #2 is checked) Do not allow bypassing the above settings
(required for admins)
Now that the default branch is protected, we will add some "bad" code that will fail our linting. This will give us an example of how required status checks will prevent us from making mistakes.
-
From the default branch of your repository, create a new branch of code called
feature/bad
-
Replace the contents of the file golang_app/main.go with the contents in ./golang_replacements/13-unnused-func.go
-
Add & commit your changes, then push your branch.
-
Go to your repository, click the
Pull Requests
tab, and open a pull request to mergefeature/bad
to your default branch.
The result will be the inability to merge (the button will be disabled) because the status check for Build, Lint, & Test
will fail the Lint
step. This is how you ensure developer accountability and a quality of code.
Checks that are required have the Required
badge next to them. Further checks could be added to include static code analysis and more.
- Close the PR (do not merge)
- Delete the
feature/bad
branch