The previous chapter has left us with the beginning of a GoCD pipeline. It automatically builds a Debian package each time new commits are pushed to Git and generates a unique version number for each build. Finally, it captures as artifacts the built package and a file called version containing the version number. The next tasks are to upload it into a Debian repository and deploy it on the target machines.
10.1 Uploading in the Pipeline
Chapter 6, on distributing packages, already introduced a small program for creating and filling Debian repositories managed with Aptly. If you add it to the deployment-utils Git repository from that chapter, you can automatically upload the newly built packages with this additional GoCD configuration (Listing 10-1), to be inserted after the build stage.
GoCD Configuration for Uploading a Freshly Built Package to the testing Repository
The fetchartifact task fetches, you guessed it, an artifact that is stored in the GoCD server’s artifact repository. Here, it fetches the directory python-matheval, into which the previous stage uploaded the Debian package. The empty string for the pipeline name instructs GoCD to use the current pipeline.
In the invocation of the add-package script, testing refers to the name of the environment (which you can choose freely, as long as you are consistent), not the testing distribution of the Debian project.
Finally, the aptly resource selects a GoCD agent with the same resource to run the job on (see Figure 10-1). If you anticipate that your setup will grow a bit, you should have a separate machine for serving these repositories. Install a GoCD agent on it and assign it this resource. You can even have separate machines for the testing and production repositories and give them more specific resources (such as aptly-testing and aptly-production).
User Accounts and Security
In the previous sample configuration, the add-package script runs as the go system user, whose home directory on Linux-based systems is /var/go by default. This will create repositories in a directory such as /var/go/aptly/testing/stretch/.
In Chapter 6, the assumption was that Aptly runs under its own system user account. You still have to give the go user permissions to add packages to the repository, but you can prevent the go user from modifying existing repositories and, more important, from getting access from the GPG key with which the packages are signed.
If you keep the repository under a separate user, you need a way to cross the user account barrier, and the traditional way to do that for command-line applications is to allow the go user to call add-package through the sudo command. But to get an actual security benefit, you have to copy the add-package command to a location where the go user has no write permissions. Otherwise, an attacker with access to the go user account could just modify this command to do whatever he/she sees fit.
Assuming you intend to copy it to /usr/local/bin, you can add this line:
The --set-home flags tells sudo to set the HOME environment variable to the home directory of the target user, here aptly.
If you choose not to go the sudo route, you have to adapt the web server configuration to serve files from /var/go/aptly/ instead of /home/aptly/aptly.
10.2 Deploying in the Pipeline
In Chapter 7, we saw how to upgrade (or install, if it’s not yet installed) a package through Ansible (see Figure 10-2), as follows:
$ ansible -i testing web -m apt
-a 'name=python-matheval state=latest update_cache=yes'
where testing is the inventory file of the same name as the environment, web is the group of hosts to deploy to, and python-matheval is the name of the package.
You can do this in GoCD as a separate stage, after the upload-testing stage (Listing 10-3).
GoCD Configuration for Automatically Installing a Package
This assumes that you add the inventory files in the ansible directory of the deployment-utils Git repository, and that the Debian repository is already configured on the target machine, as discussed in Chapter 7.
10.3 Results
To run the new stage, either trigger a complete run of the pipeline by hitting the “play” triangle in the pipeline overview on the web front end or do a manual trigger of that one stage in the pipe history view. You can log in on the target machine, to check if the package was successfully installed.
Uploading and deploying to production works the same as with the testing environment. So, all that’s required is to duplicate the configuration of the last two pipelines, replace every occurrence of testing with production, and add a manual approval button, so that production deployment remains a conscious decision (Listing 10-4).