Exercise 5: Extend the pipeline by adding further steps¶
Objective¶
Add another step to the .gitlab-ci.yml file to test the docker image itself, not just the executable.
Introduction¶
The test stage in the .gitlab-ci.yml file runs the hello executable directly, to check that it works. However, we then build and upload a docker image for it, but we don’t test the image. We can do that, to make sure it works correctly.
- in the stages section, add a new stage, test-docker
- below, add a new stanza for the test-docker stage.
- give this step a meaningful name, e.g. run-docker, configure it to run the test-docker stage.
- this will need to use the latest docker image and the docker-in-docker service, so make sure they’re declared.
- you also need to set the dependencies correctly, so it has whichever artifacts it needs to download. (Hint: I’m misleading you here!)
- then edit the script part, so that it does the docker login, and then just runs the container, like you did previously.
- commit your code to the repository, add a new git tag for it, and push it, with the tag, to the server:
git add .
git commit -m "Add new section to test the docker image"
git tag v2.0
git push --tags
If you’re getting YAML errors, go to CI/CD -> Pipelines and look for the CI Lint button, top-right. There you can paste in the contents of your .gitlab-ci.yml file, click Validate, and see where it reports an error.
You can even edit in that window to try to correct the error, then when you’ve solved the problem, you can update your local file accordingly.
Conclusion¶
You now know how to add stages to your pipeline so you can implement complex builds and tests.
Best Practices¶
- Each stage in your pipeline should perform a well-specified action, with a clear definition of success and failure. Don’t make your builds any more complex than necessary.
- If your build is unavoidably complex, consider coding the build script as an external script, which you debug separately, rather than hand-coding it in the .gitlab-ci.yml file. This keeps the YAML file cleaner, at the expense of making it harder to see the details of what it’s actually doing.
Cheat-sheet¶
In case you get stuck, this is what your .gitlab-ci.yml file should now look like. Don’t peek until you’ve had a go yourself though!
> cat .gitlab-ci.yml
variables:
DOCKER_TLS_CERTDIR: ""
GIT_STRATEGY: clone
REGISTRY_USER: tonywildish
APPLICATION: tiny-test
LATEST_IMAGE: $CI_REGISTRY/$REGISTRY_USER/$APPLICATION:latest
RELEASE_IMAGE: $CI_REGISTRY/$REGISTRY_USER/$APPLICATION:$CI_BUILD_REF_NAME
DOCKER_DRIVER: overlay
before_script:
- echo "Starting..."
- export DOCKER_IMAGE=$RELEASE_IMAGE
- if [ "$CI_BUILD_REF_NAME" == "master" ]; then export DOCKER_IMAGE=$LATEST_IMAGE; fi
- echo "Build docker image $DOCKER_IMAGE"
stages:
- build
- test
- deploy
- test-docker
compile:
stage: build
image: gcc:6
services:
- docker:dind
artifacts:
name: "${CI_BUILD_NAME}_${CI_BUILD_REF_NAME}"
untracked: true
expire_in: 1 week
script:
- make
run:
stage: test
dependencies:
- compile
only:
- tags
script:
- echo "Testing application. First, list the files here, to show we have the git repo + the artifacts from the build step"
- ls -l
- echo 'Now try running it'
- ./hello
- echo "If that failed you won't see this because you'll have died already"
install:
stage: deploy
image: docker:latest
services:
- docker:dind
dependencies:
- compile
script:
- echo $CI_REGISTRY_PASSWORD | docker login -u $CI_REGISTRY_USER --password-stdin $CI_REGISTRY
- echo Building $DOCKER_IMAGE
- docker build -t $DOCKER_IMAGE .
- echo Deploying $DOCKER_IMAGE
- docker push $DOCKER_IMAGE
run-docker:
stage: test-docker
image: docker:latest
services:
- docker:dind
script:
- echo $CI_REGISTRY_PASSWORD | docker login -u $CI_REGISTRY_USER --password-stdin $CI_REGISTRY
- docker run $DOCKER_IMAGE
after_script:
- echo "Congratulations, this step succeeded"