Skip to content

How to release in Travis (CI)

Will Sargent edited this page May 4, 2020 · 20 revisions

Release with Travis CI

Make sure you've read first How to set up your CI and the prelude of How to set up secure releases.

Setting up Travis CI in a secure fashion requires you to have two different build steps with the following properties:

  • Your build step is the script task where you run all tests.
  • Your publish step is the after_success task step where you only compile, package and publish.
    • You do not run any test.
    • You do not run the publish step for pull-requests.
    • You do not run the publish step if the build step has failed.

Luckily Travis CI helps us out, by not making the encrypted environment variables available to pull-request builds.

As a reference, you may have a .travis.yml like:

sudo: false
language: scala
scala:
- 2.12.3
script:
- sbt ++$TRAVIS_SCALA_VERSION coverage test
jdk:
- oraclejdk8

Now you'll need to perform the following tasks:

  • encrypt the generated keys using the Travis CLI and add them to your project.
    • First add local.* to your .gitignore file, because you don't want to accidentally add unencrypted files to the git repo.
    • create a travis directory inside your project: mkdir travis
    • copy the generated pubring.asc and secring.asc files to the travis directory and rename to local.pubring.asc and local.secring.asc. The rename together with the .gitignore rule makes it almost impossible to accidentally add your unencrypted keys to the git repository.
    • install travis client (if not installed yet): gem install travis
    • login to travis from command line: travis login
    • tar-gzip the files to be encoded: tar cv -C travis -f travis/local.secrets.tar local.pubring.asc local.secring.asc
    • encode the secrets.tar file: travis encrypt-file travis/local.secrets.tar -o travis/secrets.tar.enc -p . See https://docs.travis-ci.com/user/encrypting-files/#Encrypting-multiple-files for more details.
      • The command line client only allows one file to be encrypted, so if you have other keys such as ssh keys for ghpages then you must include the archive with all the data.
      • The command line client does not work with Windows.
    • add the following lines at the end of your .travis.yml file. This will decrypt the archive and make the local.pubring.asc and local.secring.asc available to the travis build, but only when it is NOT building a pull request.
      before_install:
      - if [ $TRAVIS_PULL_REQUEST = 'false' ]; then
          openssl aes-256-cbc -K $encrypted_474c3e42cec4_key -iv $encrypted_474c3e42cec4_iv -in travis/secrets.tar.enc -out travis/secrets.tar -d;
          tar xv -C travis -f travis/secrets.tar;
        fi
  • encrypt the PGP passphrase into PGP_PASS environment variable: travis encrypt 'PGP_PASS=YourActualPgpPassphrase' --add. The --add option will add the encrypted environment variable to your .travis.yml file. Also make sure to escape special characters as needed, check https://docs.travis-ci.com/user/encryption-keys/#Note-on-escaping-certain-symbols for more info.
  • depending on whether you're publishing to Bintray or Sonatype, you'll also need to encrypt the BINTRAY_USER and BINTRAY_PASS or SONATYPE_USER and SONATYPE_PASSWORD environment variables, using the travis encrypt command.
      $ travis encrypt BINTRAY_USER=<bintray account> --add 
      $ travis encrypt BINTRAY_PASS=<bintray api key> --add 
    
  • add an after_success step which calls the releaseEarly task of the plugin, but only when Travis is NOT building a pull-request:
    after_success:
    - if [ $TRAVIS_PULL_REQUEST = 'false' ]; then sbt ++$TRAVIS_SCALA_VERSION releaseEarly;
      fi
  • modify your build.sbt so that it knows the location of the unencrypted PGP keys:
    pgpPublicRing := file("./travis/local.pubring.asc")
    pgpSecretRing := file("./travis/local.secring.asc")

After this you'll end up with a .travis.yml like this:

sudo: false
language: scala
scala:
- 2.12.3
script:
- sbt ++$TRAVIS_SCALA_VERSION coverage test
jdk:
- oraclejdk8
after_success:
- if [ $TRAVIS_PULL_REQUEST = 'false' ]; then sbt ++$TRAVIS_SCALA_VERSION releaseEarly;
  fi
env:
  global:
  - secure: ...
  - secure: ...
  - secure: ... 
before_install:
- if [ $TRAVIS_PULL_REQUEST = "false" ]; then
    openssl aes-256-cbc -K $encrypted_xxxxx_key -iv $encrypted_xxxxx_iv -in travis/secrets.tar.enc -out travis/secrets.tar -d;
    tar xv -C travis -f travis/secrets.tar;
  fi

Finally add the encoded travis/secrets.tar.enc file to your repository and also commit the changes to your build.sbt and .travis.yml

Troubleshooting

If you try to use openssl on a pull request, it will fail with iv undefined when decrypt file using openssl because the encrypted environment variables are not available in pull requests

If you install gpg keys using Windows, it will fail with 139709116544672:error:0606506D:digital envelope routines:EVP_DecryptFinal_ex:wrong final block length:evp_enc.c:532: -- this is apparently a known bug. The only workaround is to use a Linux/MacOS machine to create and install keys.

travis encrypt-file only works with one encrypted file, so you cannot run it repeatedly. If you have multiple secrets, you must create an archive with all your encrypted secrets.

If you have a secret key with spaces or special characters then those characters may need to be encoded.

If you run travis encrypt multiple times against the same environment variable, it appends the environment variable setting rather than overwriting it, and the ordering of those settings is not defined. This means that a prior value may be set even when "overridden" by the new value. The safest thing to do is to remove all environment variables and add them again explicitly.