Per my previous post, this post covers my continuous integration / continuous deployment design decisions for my open source ArmorPowerShell project.

General Configuration

Building Specific Branches

You can whitelist and/or blacklist branches here, but I chose to build all branches in this project and included logic in the various scripts to limit actions prior to merging into master.

# whitelist
#branches:
  #only:
    #- master

# blacklist
#branches:
  #except:
    #-

Jobs

You can granularly define build stages as well as conditional builds based on criteria such as branch, release tag, et cetera in the Jobs section.  I have not implemented this so far.

#jobs:
  #include:
    #- stage:

Language

I recommend setting the Language to generic for scripting language projects (which is not listed in the Language documentation, but is briefly mentioned here), because all I needed for installing PowerShell Core was bash, curl, & apt for Ubuntu and homebrew for macOS, but there are a wide variety of choices if you require otherwise.

language: generic

Runtime

You can also define specific runtime versions for certain applications.  If more than one runtime version is specified for the same item, a job will be created for each version.  I did not need to implement any of these for this project though.

#dotnet:
#gemfile:
#mono:
#php:
#python:
#rvm:

Git

In the Git section, you can specify a [clone depth limit][clone depth] or disable cloning of submodules to optimize job performance.  As of 20171128, the default commit depth on Travis CI is 50, which should provide sufficient commit history for most projects with accommodation for job queuing.

#git:
  #depth:
  #submodules:

Environment Configuration

Environment Variables

If you plan to test your open-source PowerShell project on multiple CI providers such as Travis CI and AppVeyor, I recommend defining a few global environment variables such as the ones listed below that abstract the CI specific variables to minimize the logic needed for handling each in your build scripts.  If you define a variable more than once, another job will be created for each definition.  You can also define matrix-specific environment variables in this section, or at the image level in the Matrix section.

# environment variables
env:
 global:
 - BUILD_PATH="$TRAVIS_BUILD_DIR"
 - MODULE_NAME="<insert module name>"
 - MODULE_PATH="$BUILD_PATH/$MODULE_NAME"
 - MODULE_VERSION="{set module version in build script}"
 - OWNER_NAME="$(echo $TRAVIS_REPO_SLUG | cut -d '/' -f1)"
 - PROJECT_NAME="$(echo $TRAVIS_REPO_SLUG | cut -d '/' -f2)"
 - secure: <secure string>
  #matrix:

Services

There are lots of terrific services and databases that are installed and available in each image should you need them.

# enable service required for build/tests
#services:
  #- cassandra # start Apache Cassandra
  #- couchdb # start CouchDB
  #- elasticsearch # start ElasticSearch
  #- memcached # start Memcached
  #- mongodb # start MongoDB
  #- mysql # start MySQL
  #- neo4j # start Neo4j Community Edition
  #- postgresql # start PostgreSQL
  #- rabbitmq # start RabbitMQ
  #- redis-server # start Redis
  #- riak # start Riak

Global Image Settings

You can define your build images at the global scope; however, I chose to use the matrix build image configuration as recommended here for multiple operating system build configurations, because it is cleaner.  For example, when osx_image is defined at the global scope, your Ubuntu builds will receive the xcode tag, even though it does not apply.

xcode tag assigned to Ubuntu Trusty build image

xcode tag assigned to Ubuntu Trusty build image

# Build worker image (VM template)
#os:
#- linux
#- osx

#sudo: required

#dist: trusty

#osx_image: xcode9.1

Build Matrix

The Matrix section allows you to customize each image that will build your code.  I cover most of these features sufficiently in the previous post, but the two that I did not are:

  1. allow_failures, which will permit the specified build image to pass regardless of any errors that occur.  I’ll likely never use this feature because it defeats the purpose of implementing continuous integration in my opinion.
  2. exclude, which prevents building specified images when you define combinations of environment variables, runtime versions, and/or matrix images.  I don’t foresee my scripting language projects being complicated enough to require this feature.
matrix:
  include:
    - os: linux
      dist: trusty
      sudo: false
      addons:
        apt:
          sources:
            - sourceline: "deb [arch=amd64] https://packages.microsoft.com/ubuntu/14.04/prod trusty main"
              key_url: "https://packages.microsoft.com/keys/microsoft.asc"
          packages:
            - powershell
    - os: osx
      osx_image: xcode9.1
      before_install:
        - brew tap caskroom/cask
        - brew cask install powershell 
  fast_finish: true
  #allow_failures:
  #exclude:

Add-Ons

In the addons section, you can define hostnames, prepare for headless testing, upload build artifacts, add SSH known hosts, et cetera.  I have not needed any of these so far for this project.

#addons:
  #artifacts:
    #paths:
      #-
  #chrome:
  #firefox:
  #hosts:
  #mariadb:
  #rethinkdb:
  #sauce_connect:
    #username:
    #access_key:
  #ssh_known_hosts:

APT Add-ons

To install packages not included in the default container-based-infrastructure you need to use the APT addon, as sudo apt-get is not available.

For now, I have only used this to setup the Microsoft PowerShell Core package management repository and install PowerShell Core on my Ubuntu Trusty container image defined in my build matrix.

If the APT Add-ons step exits with a non-zero error code, the build is marked as error and stops immediately.

#addons:
  #apt:
    #sources:
      #- sourceline:
        #key_url:
    #packages:
      #-

Build Cache

You can cache files and folders to preserve them between builds such as if you have low-volatility, large files that take a while to clone.  I did not.  Tabula rasa.

If the cache step exits with a non-zero error code, the build is marked as error and stops immediately.

# build cache to preserve files/folders between builds
#cache:

Before Install

In a before_install step, you can install additional dependencies required by your project such as Ubuntu packages or custom services.

One important thing to be aware of is that matrix image instructions override global instructions.  Since I placed the homebrew commands to install PowerShell in the Before Install step of the macOS build matrix image, if I were to define a global Before Install step, the macOS build matrix image would ignore it.  Alternatively, you could use conditional logic in the global step if you only wanted to perform some instructions on a specific operating system, and some on all build images.

If the before_install step exits with a non-zero error code, the build is marked as error and stops immediately.

#before_install:

Install

As of 20171128, there is no default dependency installation step for PowerShell projects on Travis CI.  In the install step, I chose to install and import the necessary PowerShell modules on all build images, and implemented it via a PowerShell script so that I always utilize the same logic in my AppVeyor builds with no additional configuration (ie: DRY).

If the install step exits with a non-zero error code, the build is marked as error and stops immediately.

install:
- pwsh -file ./build/shared/install-dependencies.ps1
Improve this page

Comments