Skip to content

Commit 1796041

Browse files
committed
Add: go updates to match sample repository.
1 parent 70264c3 commit 1796041

File tree

1 file changed

+80
-99
lines changed

1 file changed

+80
-99
lines changed

jekyll/_cci2/language-go.md

Lines changed: 80 additions & 99 deletions
Original file line numberDiff line numberDiff line change
@@ -33,13 +33,15 @@ jobs: # basic units of work in a run
3333
build: # runs not using Workflows must have a `build` job as entry point
3434
docker: # run the steps with Docker
3535
# CircleCI Go images available at: https://hub.docker.com/r/circleci/golang/
36-
- image: circleci/golang:1.12 #
36+
- image: circleci/golang:1.12
3737
# CircleCI PostgreSQL images available at: https://hub.docker.com/r/circleci/postgres/
3838
- image: circleci/postgres:9.6-alpine
3939
environment: # environment variables for primary container
4040
POSTGRES_USER: circleci-demo-go
4141
POSTGRES_DB: circle_test
4242

43+
parallelism: 2
44+
4345
environment: # environment variables for the build itself
4446
TEST_RESULTS: /tmp/test-results # path to where test results will be saved
4547

@@ -48,51 +50,37 @@ jobs: # basic units of work in a run
4850
- run: mkdir -p $TEST_RESULTS # create the test results directory
4951

5052
- restore_cache: # restores saved cache if no changes are detected since last run
51-
# Read about caching dependencies: https://circleci.com/docs/2.0/caching/
5253
keys:
53-
- v1-pkg-cache
54+
- go-mod-v4-{{ checksum "go.sum" }}
5455

55-
# Normally, this step would be in a custom primary image;
56-
# we've added it here for the sake of explanation.
57-
- run: go get github.com/lib/pq
58-
- run: go get github.com/mattes/migrate
59-
- run: go get github.com/jstemmer/go-junit-report
60-
61-
# CircleCi's Go Docker image includes netcat
62-
# This allows polling the DB port to confirm it is open before proceeding
56+
# Wait for Postgres to be ready before proceeding
6357
- run:
6458
name: Waiting for Postgres to be ready
65-
command: |
66-
for i in `seq 1 10`;
67-
do
68-
nc -z localhost 5432 && echo Success && exit 0
69-
echo -n .
70-
sleep 1
71-
done
72-
echo Failed waiting for Postgres && exit 1
59+
command: dockerize -wait tcp://localhost:5432 -timeout 1m
7360

7461
- run:
7562
name: Run unit tests
7663
environment: # environment variables for the database url and path to migration files
7764
CONTACTS_DB_URL: "postgres://circleci-demo-go@localhost:5432/circle_test?sslmode=disable"
78-
CONTACTS_DB_MIGRATIONS: /go/src/github.com/CircleCI-Public/circleci-demo-go/db/migrations
79-
# Store the results of our tests in the $TEST_RESULTS directory
65+
CONTACTS_DB_MIGRATIONS: /home/circleci/project/db/migrations
66+
67+
# store the results of our tests in the $TEST_RESULTS directory
8068
command: |
81-
trap "go-junit-report <${TEST_RESULTS}/go-test.out > ${TEST_RESULTS}/go-test-report.xml" EXIT
82-
make test | tee ${TEST_RESULTS}/go-test.out
69+
PACKAGE_NAMES=$(go list ./... | circleci tests split --split-by=timings --timings-type=classname)
70+
gotestsum --junitfile ${TEST_RESULTS}/gotestsum-report.xml -- $PACKAGE_NAMES
8371
8472
- run: make # pull and build dependencies for the project
8573

86-
- save_cache: # Store cache in the /go/pkg directory
87-
key: v1-pkg-cache
74+
- save_cache:
75+
key: go-mod-v4-{{ checksum "go.sum" }}
8876
paths:
89-
- "/go/pkg"
77+
- "/go/pkg/mod"
9078

9179
- run:
9280
name: Start service
9381
environment:
9482
CONTACTS_DB_URL: "postgres://circleci-demo-go@localhost:5432/circle_test?sslmode=disable"
95-
CONTACTS_DB_MIGRATIONS: /go/src/github.com/CircleCI-Public/circleci-demo-go/db/migrations
83+
CONTACTS_DB_MIGRATIONS: /home/circleci/project/db/migrations
9684
command: ./workdir/contacts
9785
background: true # keep service running and proceed to next step
9886

@@ -102,12 +90,17 @@ jobs: # basic units of work in a run
10290
sleep 5
10391
curl --retry 10 --retry-delay 1 -X POST --header "Content-Type: application/json" -d '{"email":"[email protected]","name":"Test User"}' http://localhost:8080/contacts
10492
105-
- store_artifacts: # Upload test summary for display in Artifacts: https://circleci.com/docs/2.0/artifacts/
93+
- store_artifacts: # upload test summary for display in Artifacts
10694
path: /tmp/test-results
10795
destination: raw-test-output
10896

109-
- store_test_results: # Upload test results for display in Test Summary: https://circleci.com/docs/2.0/collect-test-data/
97+
- store_test_results: # upload test results for display in Test Summary
11098
path: /tmp/test-results
99+
workflows:
100+
version: 2
101+
build-workflow:
102+
jobs:
103+
- build
111104
```
112105
113106
{% endraw %}
@@ -141,49 +134,34 @@ This key is used to issue warnings about breaking changes.
141134
version: 2
142135
```
143136

144-
Next, we have a `jobs` key. Every config file must have a ‘build’ job. This is the only job that will be automatically picked up and run by CircleCI.
137+
Next, we have a `jobs` key. If we do not use workflows and have only one job, it must be named `build`. Below, our job specifies to use the `docker` executor as well as the CircleCI created docker-image for golang 1.12. Next, we use a *secondary image* so that our job can also make use of Postgres. Finally, we use the `environment` key to specify environment variables for the Postgres container.
145138

146-
In the job, we specify a `working_directory`. Go is very strict about the structure of the [Go Workspace](https://golang.org/doc/code.html#Workspaces), so we’ll need to specify a path that satisfies those requirements.
147139

148140
```yaml
149-
version: 2
150-
jobs:
151-
build:
152-
working_directory: /go/src/github.com/CircleCI-Public/circleci-demo-go
153-
```
154-
155-
This path will be used as the default working directory for the rest of the `job` unless otherwise specified.
156-
157-
Directly beneath `working_directory`, we’ll specify [primary container]({{ site.baseurl }}/2.0/glossary/#primary-container) images for this job under `docker`.
158-
159-
```yaml
160-
docker:
141+
jobs: # basic units of work in a run
142+
build: # runs not using Workflows must have a `build` job as entry point
143+
docker: # run the steps with Docker
144+
# CircleCI Go images available at: https://hub.docker.com/r/circleci/golang/
161145
- image: circleci/golang:1.12
162-
```
163-
164-
We'll use a custom image which is based on `golang:1.12.0` and includes also `netcat` (we'll need it later).
165-
166-
We're also using an image for PostgreSQL, along with 2 environment variables for initializing the database.
167-
168-
```yaml
146+
# CircleCI PostgreSQL images available at: https://hub.docker.com/r/circleci/postgres/
169147
- image: circleci/postgres:9.6-alpine
170-
environment:
171-
POSTGRES_USER: root
148+
environment: # environment variables for primary container
149+
POSTGRES_USER: circleci-demo-go
172150
POSTGRES_DB: circle_test
173151
```
174152
175153
After setting up Docker we will set an environment variable to store the path to
176-
our test results.
154+
our test results. Note, this environment variable is set for the entirety of the _job_ whereas the environment variables set for `POSTGRES_USER` and `POSTGRES_DB` are specifically for the Postgres container.
177155

178156
```yaml
179157
environment:
180158
TEST_RESULTS: /tmp/test-results
181159
```
182160

183-
Now we need to add several `steps` within the `build` job.
161+
Now we need to add several `steps` within the `build` job. Steps make up the bulk of a job.
184162

185163
Use the [`checkout`]({{ site.baseurl }}/2.0/configuration-reference/#checkout) step
186-
to check out source code. By default, source code is checked out to the path specified by `working_directory`.
164+
to check out source code.
187165

188166
```yaml
189167
steps:
@@ -199,63 +177,39 @@ Next we create a directory for collecting test results
199177
Then we pull down the cache (if present). If this is your first run, this won't do anything.
200178

201179
```yaml
202-
- restore_cache:
180+
- restore_cache: # restores saved cache if no changes are detected since last run
203181
keys:
204-
- v1-pkg-cache
182+
- go-mod-v4-{{ checksum "go.sum" }}
205183
```
206184

207185
And install the Go implementation of the JUnit reporting tool and other dependencies for our application. These are good candidates to be pre-installed in primary container.
208186

209-
```yaml
210-
- run: go get github.com/lib/pq
211-
- run: go get github.com/mattes/migrate
212-
- run: go get github.com/jstemmer/go-junit-report
213-
```
214-
215-
Both containers (primary and postgres) start simultaneously, however Postgres may require some time to get ready and if our tests start before that the job will fail. So it's good practice to wait until dependent services are ready. Here we have only Postgres, so we add this step:
187+
Both containers (primary and postgres) start simultaneously. Postgres, however, may require some time to get ready. If our tests start before Postgres is available, the job will fail. It is good practice to wait until dependent services are ready; in this example Postgres is the only dependent service.
216188

217189
```yaml
218190
- run:
219191
name: Waiting for Postgres to be ready
220-
command: |
221-
for i in `seq 1 10`;
222-
do
223-
nc -z localhost 5432 && echo Success && exit 0
224-
echo -n .
225-
sleep 1
226-
done
227-
echo Failed waiting for Postgres && exit 1
192+
command: dockerize -wait tcp://localhost:5432 -timeout 1m
228193
```
229194

230-
This is why `netcat` installed on the CircleCI Go image. We use it to validate that the port is open.
231-
232195
Now we run our tests. To do that, we need to set an environment variable for our database's URL and path to the DB migrations files. This step has some additional commands, we'll explain them below.
233196

234197
```yaml
235198
- run:
236199
name: Run unit tests
237200
environment:
238201
CONTACTS_DB_URL: "postgres://rot@localhost:5432/circle_test?sslmode=disable"
239-
CONTACTS_DB_MIGRATIONS: /go/src/github.com/CircleCI-Public/circleci-demo-go/db/migrations
202+
CONTACTS_DB_MIGRATIONS: /home/circleci/project/db/migrations
240203
command: |
241-
trap "go-junit-report <${TEST_RESULTS}/go-test.out > ${TEST_RESULTS}/go-test-report.xml" EXIT
242-
make test | tee ${TEST_RESULTS}/go-test.out
204+
PACKAGE_NAMES=$(go list ./... | circleci tests split --split-by=timings --timings-type=classname)
205+
gotestsum --junitfile ${TEST_RESULTS}/gotestsum-report.xml -- $PACKAGE_NAMES
243206
```
244207

245-
Our project uses `make` for building and testing (you can see `Makefile` [here](https://github.com/CircleCI-Public/circleci-demo-go/blob/master/Makefile)), so we can just run `make test`. In order to collect test results and upload them later (read more about test results in the [Project Tutorial]({{ site.baseurl }}/2.0/project-walkthrough/)) we're using `go-junit-report`:
246-
247-
```bash
248-
make test | go-junit-report > ${TEST_RESULTS}/go-test-report.xml
249-
```
250-
251-
In this case all output from `make test` will go straight into `go-junit-report` without appearing in `stdout`. We can solve this by using two standard Unix commands `tee` and `trap`. The first one allows us to duplicate output into `stdout` and somewhere else ([read more](http://man7.org/linux/man-pages/man1/tee.1.html)). The second one allows us to specify some command to be executed on script exit ([read more](http://man7.org/linux/man-pages/man1/trap.1p.html)). So we can do:
252-
253-
```bash
254-
trap "go-junit-report <${TEST_RESULTS}/go-test.out > ${TEST_RESULTS}/go-test-report.xml" EXIT
255-
make test | tee ${TEST_RESULTS}/go-test.out
256-
```
208+
The command for running unit tests is more complicated than some of our other
209+
steps. Here we are using [test splitting]({{ site.baseurl
210+
}}/2.0/parallelism-faster-jobs/#splitting-test-files) to allocate resources across parallel containers. Test splitting can help speed up your pipeline if your project has a large test suite.
257211

258-
Now we know that our unit tests succeeded we can start our service and validate it's running.
212+
Next we run our actual build command using `make` - the Go sample project uses make to run build commands. If this build happens to pull in new dependencies, we will cache them in the `save_cache` step.
259213

260214
```yaml
261215
- run: make
@@ -264,35 +218,62 @@ Now we know that our unit tests succeeded we can start our service and validate
264218
key: v1-pkg-cache
265219
paths:
266220
- ~/.cache/go-build
221+
```
222+
223+
224+
Now we will start the Postgres dependent service, using `curl` to ping it to validate that the service is up and running.
267225

226+
```yaml
268227
- run:
269228
name: Start service
270229
environment:
271-
CONTACTS_DB_URL: "postgres://root@localhost:5432/circle_test?sslmode=disable"
272-
CONTACTS_DB_MIGRATIONS: /go/src/github.com/CircleCI-Public/circleci-demo-go/db/migrations
230+
CONTACTS_DB_URL: "postgres://circleci-demo-go@localhost:5432/circle_test?sslmode=disable"
231+
CONTACTS_DB_MIGRATIONS: /home/circleci/project/db/migrations
273232
command: ./workdir/contacts
274-
background: true
233+
background: true # keep service running and proceed to next step
275234
276235
- run:
277236
name: Validate service is working
278-
command: curl --retry 10 --retry-delay 1 --retry-connrefused http://localhost:8080/contacts/test
237+
command: |
238+
sleep 5
239+
curl --retry 10 --retry-delay 1 -X POST --header "Content-Type: application/json" -d '{"email":"[email protected]","name":"Test User"}' http://localhost:8080/contacts
279240
```
280241

281-
After we pull and build the project's dependencies using `make`, we store any built packages in the cache. This is the recommended way to cache dependencies for your Go project.
282-
283-
To start the service we need to build it first. After that we use the same environment variables as we did in the testing step for the service to start. We're using `background: true` to keep the service running and proceed to the next step where we use `curl` to validate it successfully started and is responding to our request.
242+
If all went well, the service ran and successfully responded to the post request at `localhost:8080`.
284243

285-
Finally, let's specify a path to store the results of the tests.
244+
Finally, let's specify a path to store the results of the tests. The
245+
`store_test_results` step allows you to leverage insights to view how your test
246+
results are doing over time, while using the `store_artifacts` step allows you
247+
to upload any type of file; in this case, also the test logs if one would like
248+
to inspect them manually.
286249

287250
```yaml
288-
- store_test_results:
251+
- store_artifacts: # upload test summary for display in Artifacts
252+
path: /tmp/test-results
253+
destination: raw-test-output
254+
255+
- store_test_results: # upload test results for display in Test Summary
289256
path: /tmp/test-results
290257
```
291258

259+
260+
Finally, we specify the workflow block. This is not mandatory (as we only have one job to sequence) but it is recommended.
261+
262+
```yaml
263+
264+
workflows:
265+
version: 2
266+
build-workflow: # the name of our workflow
267+
jobs: # the jobs that we are sequencing.
268+
- build
269+
```
270+
292271
Success! You just set up CircleCI 2.0 for a Go app. Check out our [Job page](https://circleci.com/gh/CircleCI-Public/circleci-demo-go){:rel="nofollow"} to see how this looks when building on CircleCI.
293272

294273
## See Also
295274

296275
See the [Deploy]({{ site.baseurl }}/2.0/deployment-integrations/) document for example deploy target configurations.
297276

277+
How to use [workflows]({{ site.baseurl }}/2.0/workflows), which are particularly useful for optimizing your pipelines and orchestrating more complex projects.
278+
298279
Refer to the [Caching Dependencies]({{ site.baseurl }}/2.0/caching/) document for more caching strategies.

0 commit comments

Comments
 (0)