Whether you're a project manager, part of a dev team, or flying solo, there is always the looming issue of incremental changes to your project. Gone are the days of waterfall development - Agile is the 'in' thing. You are running fortnightly sprints and releasing on a regular basis. You've probably seen a lot of options for deployment methods, lots of continuous integration/continuous delivery (CI/CD) pipelines, and much more.
On the face of it, this is a journey for getting the application on your local system deployed into the cloud in stages using a pipeline.
A pipeline allows you to work on small features independently and deploy them one by one without taking down the application, or better yet, prevent you from having to write the application all in one go and then deploying it in one big push. This will allow you to fail small and fail fast. In return, leaving less technical debt and allowing faster development.
The diagram below outlines the aim of this using a simple pull request example
Now you can see how simple it really is, in this blog, I will show you how to build, test, and deploy your application under one roof in a matter of minutes using IBM Cloud Toolchain. That's right.. in a matter of minutes.
But first, you will need some prerequisites:
1) IBM Cloud Lite account - sign up here
2) GitHub account
3) Golang installed on your machine
Let's get started!
Create your Go app and get it into GitHub
Step 1 - Create an empty repository in GitHub
Navigate to your GitHub profile, click on the +
in the top right corner and select "New repository". Give it a name and make sure it is public. Feel free to also add a license .gitignore file and a README.md if you like
Step 2 - Let's create a simple Golang HTTP Server with an accompanying test
In a terminal clone your new repository into $HOME/go/src/github.com
Navigate into the cloned project using the cd
command and initiate go modules with the command go mod init
(in some cases you may need to specify the exact project path) and then open it in your preferred editor (I use Visual Studio Code)
Note - if you do not have this folder tree already (go/src/github.com), then create it
Create a test file in the root of the project (main_test.go):
package main
import (
"net/http"
"net/http/httptest"
"testing"
)
func TestHomeRoute(t *testing.T) {
t.Run("returns message", func(t *testing.T) {
request, _ := http.NewRequest(http.MethodGet, "/", nil)
response := httptest.NewRecorder()
Home(response, request)
got := response.Body.String()
want := "This is a toolchain test PR"
if got != want {
t.Errorf("got %q, want %q", got, want)
}
})
}
Run the test and watch it fail using the following command in your terminal
go test ./...
Now it is time to write just enough code for the test to pass (this is called TDD - test-driven development)
Create a main file in the project root (main.go). This will be home to the sever code
package main
import (
"fmt"
"net/http"
)
func main() {
// Create the route handler listening on '/'
http.HandleFunc("/", Home)
fmt.Println("Starting server on port 8080")
// Start the sever
http.ListenAndServe(":8080", nil)
}
func Home(w http.ResponseWriter, r *http.Request) {
// Assign the 'msg' variable with a string value
msg := "This is a toolchain test PR"
// Write the response to the byte array - Sprintf formats and returns a string without printing it anywhere
w.Write([]byte(fmt.Sprintf(msg)))
}
Run the test command go test ./...
and your test should pass
To see this in action, you can run the program with the go run main.go
command and navigating to localhost:8080
in your web browser
To quit the program use the commands control + C
in your terminal
Step 3 - Push your code into the GitHub repository
Let's get this code into GitHub.. Don't worry it's pretty simple, just follow the following commands
git add .
- this command will add all of the new/modified files into staging ready to be committed
git commit -m "initial commit"
- this command commits the changes ready to be pushed with a message so they can easily be identified
git push origin master
- this will push the changes into the master/main branch - this is fine for an initial commit but going forward you will use feature branches
Awesome - you now have a simple Golang HTTP server with a test that you can push to any cloud, but what if you wanted to branch out and have others work on this? What if you had to add incremental changes and automate the deployment of it? - manual deployments need precision, they are time-consuming and weight on any chain for a team!
Let's use IBM Cloud Toolchain for this.
"What is IBM Cloud Toolchain?" you ask...
Well, that's quite simple. It is a tool that allows you to concatenate actions, called stages. Each stage will have 'jobs' and these allow you to choose what you want to do with your application in that stage, be it build, test, or deploy - heck, why not all of them?
In this blog, we will run a test stage to ensure the code compiles and the tests pass on the pull request. Then once the pull request is merged into the main production branch another stage will compile the code, run the tests, and then automatically deploy the application into Cloud Foundry. Sound good? - let's go!
Creating a toolchain
Login or sign up to IBM Cloud
Navigate to the DevOps section in IBM Cloud using the navigation menu on the left
Select your region and then create a new toolchain
Scroll down to the bottom and select "Build your own toolchain"
Choose an appropriate name and select the correct region for your toolchain
Cool, you now have the foundation - add a new tool to your toolchain
We want to have GitHub integration so search for "GitHub" and select the GitHub tool
Set up the GitHub tool to have the correct information for your project repository, as an example, mine is
You should now see that the GitHub tool on the toolchain overview has ticks and the word "configured". This will give it access to the repository information (you may be asked to confirm this on GitHub)
Next, you need to add a pipeline. On the toolchain overview, just like you did with the GitHub tool, select "Add tool" and search for "pipeline". Select "Delivery Pipeline"
Configure the pipeline by giving it a name and ensuring the pipeline type is "Classic" and not "TekTon"
If you haven't used a pipeline in IBM Cloud before, you may see the following error. You just need to add a continuous delivery service which will enable the CI/CD
Search for continuous delivery and select "Continuous Delivery" - You only need to do this once!
Setup the service. Make sure the region is set to the same as your toolchain, give it the same name as what you called your pipeline service. In this example, it is "CI-CD-Service". Once filled out, create it
Now head back to your toolchain and click on the Pipeline box itself. You will be taken to a blank page. In the top right select "Add Stage"
Call it the "Test Stage" and this will build the code and then run the tests. Make sure the input type is the git repository for your project, the branch is set to "master" and you want this stage to run "When a pull request is opened or updated"
Once the "Input" has been set up, move along to the "Jobs" and create 2 jobs. 1 x Build and 1 x Test. There is no Golang buildpack in the toolchain so we need to use a docker image with the environment set up for us
Add the following script into the build script box on the "Build" stage and modify it to suit your project. I called my directory "gohttpserver" but you can change it to be the name of your repository/project. This script just moved the code from a temporary directory on the virtual machine into the directory tree much like you would have locally on your machine. It then builds a binary to test the code compiles
#!/bin/bash
pwd
ls -la
cd $HOME
mkdir -p go/src/github.com
mkdir -p go/pkg
mkdir -p go/bin
export GOPATH=$HOME/go
export PATH=$PATH:$GOPATH/bin
cd $HOME/go/src/github.com
cp -ar /home/pipeline/* /root/go/src/github.com
mv ./* gohttpserver
cd gohttpserver
go build -o serverbinary
chmod -v +x serverbinary
pwd
ls -la
echo code compiled successfully
Move onto the "Test" stage and do the same. Copy the script from your "Build" stage and modify the end of it to look something like this
#!/bin/bash
pwd
ls -la
cd $HOME
mkdir -p go/src/github.com
mkdir -p go/pkg
mkdir -p go/bin
export GOPATH=$HOME/go
export PATH=$PATH:$GOPATH/bin
cd $HOME/go/src/github.com
cp -ar /home/pipeline/* /root/go/src/github.com
mv ./* gohttpserver
cd gohttpserver
go test ./...
echo test run successful
This is just running the tests within the repository and not building a binary
That is the Build/Test stage complete, now we need to create the deploy stage. This stage will run when the pull request is merged into the main/master branch
Go back to the stages overview and clone the first stage we created by clicking the cog on the stage and selecting "Clone stage"
Click the cog on the newly cloned stage and click "configure". Rename it to "Deploy" and we want this stage to be triggered by a new commit into the master/main branch and not on a new pull request. On the "Input" tab, check the box "When a commit is pushed"
On the "Jobs" section, add a new "Deploy" job and fill out the details for your project. You want to make sure the deployer type is Cloud Foundry (you can choose Kubernetes if you wish but the setup will be different). You will also need to create a new API key for the integration to work (shown below)
Make sure the region selected is the same as your toolchain and the application name is the same as your pipeline. The script is very simple and should be pre-populated for you. Once completed, save and exit
Your toolchain is now set up!
Time for a code change...
First, within your project, checkout a new local feature branch using the following command in a terminal
git checkout -b test-new-toolchain
Next, change the test file main_test.go
And then change the corresponding code in main.go
and push the code up to the new remote branch using the commands seen below
Now you can open a pull request in GitHub. Ensure the pull request is from the new branch you have just created, give it a meaningful title and description. Then click "Create pull request"
Once open, you will see the IBM Cloud toolchain integration. If you check the toolchain stages you will see it running the first stage you called "Test Stage"
Once the test stage has finished, you will be able to merge the pull request. Go ahead and merge it. Then check the toolchain and you will see
Once the build stage has finished, click on the link "View logs and history". Scroll to the bottom and you will see the result of the build and where it is deployed in Cloud Foundry. Navigate to the route in a browser and you will see your app running
If you check the merged pull request, you will see a message of successful deployment and a tag from the toolchain
You've now got a CI/CD IBM Cloud Toolchain set up.. how easy was that?!
Although this blog uses a Docker image for the Golang environment, many other projects can be built using the readily available buildpacks in IBM Cloud (a list of these can be found in the stage configurator)
If you have any questions or want to see more content like this, feel free to reach out!
Top comments (0)