Build Debian packages (.deb) using Travis

In this article, we are going to describe the steps required to build and deploy .deb packages allowing to distribute a custom-made software for any Debian or Ubuntu servers, using a 3rd-party service for the build process.

As mentioned in a previous article on building Python projectsTravis CI is service to provide continuous integration of projects hosted on GitHub. This is the 3rd-party service that we will be using to generate .deb packages from our files, being scripts, source code or compiled binaries.

The advantage of using a service to compile your code and build your packages is to avoid to have to maintain the infrastructure, share your work with anyone around the world, and allow to work from anywhere.

Debian packages structure

Overview

A Debian package is basically a tar archive consisting of multiple files, typically located in a DEBIAN directory with the permissions set to 755, which control how and where a package is installed. Not all files are mandatory and needed, but the non-exhaustive list below will allow to create a package:

  • control  contains information about a package
  • preinst  responsible to do any task before installation starts
  • postinst  responsible to do any task after extraction of the content of the package
  • prerm  responsible to do any task before removal of any file installed by the package, like stopping some services etc.
  • postrm  responsible to remove any file installed by the package
  • install  files to be added in the packages and their destinations

Additionally, a directory containing the files to be installed in a compiled form or not will be referenced to be included in the archive.

dh_make

dh_make is a tool that can be used to create the directory structure, with all the mandatory and optional files that compose a debian archive.
To use it, create a directory named after the package and the version such as:

# create structure with mandatory and optional files
cd <package>-<version>
dh_make --createorig

This commands will generate the directories and files of a typical Debian packages. It is a great example to show what are all the files needed and what each files contains.

To use them and package your Debian archive, you will need to edit each one and amend with the details of your package.

Generating Debian package archive (.deb)

Once the installation files and the directory are layed out correctly on your project, you can generate the package archive with the dpkg-deb tool:

dpkg --contents <package_name>

This will create the Debian package archive with the files layed out in the way specified by the installation scripts. A follow-up task required to sign this archive before distributing it to ensure it wasn’t tampered during the transport.

Using Travis to automate the process

Once the folder structure to create the package is created, we are able to deliver the code in GitHub and automate the build of source code, creating of the package archive, signing, and distributing the packages (via FTP to a private Debian repository or to a PPA using Launchpad). To do so, all what is required is a .travis.yml file in your project!

.travis.yaml

env:
  global:
  - PACKAGE_NAME=<package_name>

before_install:
- export BUILD_VERSION=$(date "+%Y%m%d").$TRAVIS_BUILD_NUMBER
- export PACKAGE_NAME_VERSION=$PACKAGE_NAME.$BUILD_VERSION.deb

script:
- dpkg-deb --build $PACKAGE_NAME
- mv $PACKAGE_NAME.deb $PACKAGE_NAME_VERSION

after_success:
- ls -l $PACKAGE_NAME_VERSION
- md5sum $PACKAGE_NAME_VERSION
- dpkg --contents $PACKAGE_NAME_VERSION

after_script:
- |
  echo "Uploading package(s) to $FTP_URL ..."
  curl -u $FTP_USER:$FTP_PASSWORD --ftp-create-dirs -T $PACKAGE_NAME_VERSION ftp://$FTP_URL/repos/$PACKAGE_NAME_VERSION || DEPLOY_FAILURE=true ;
  if [[ $DEPLOY_FAILURE == 'true' ]]; then echo "Uploading package(s) failed!"; travis_terminate 1; fi;

Note: The above file is referencing environment variables that need to be set in Travis CI settings for this project.

Resources