Continuous Delivery towards Flynn (CD), the self hosted platform as a service, is easily doable via Jenkins. Whereas the Jenkins specific parts are very low and they can be easily replaced with any other CI/CD software.

This posting skips the Continuous Integration part as this isn’t Flynn related and highly depends on the single project.

Some possible implementations are shown of a few scenarios I encountered using the git push deployment strategy of Flynn.

Prerequisites

It is necessary to have the CLI of Flynn installed and configured on the machine running Jenkins as well as the git client and plugin.

Even if the CLI isn’t directly used in the shown commands, it configures git to be able to push to Flynn.

Flynn itself is running here under the subdomain flynn.example.com and the app is called myapp.

Upfront Application Setup

The application on Flynn must be already setup and ready to receive git pushes. All environment variables should be set. This could be done in the CD job as well, but as it’s likely not to change that quickly, I currently prefer to do that upfront as setting environment variables with Flynn always creates a new release.

But nothing holds you back to set some variables within Jenkins like the build number.

The routes are also setup upfront.

The Most Simple Way.

The Jenkins job is triggered in whatever way you prefer and clones the master branch of the repository. With a shell build step, the repository is just pushed towards Flynn, note the comments:

# checkout the repository completely as Jenkins might do a sparse checkout
git checkout master
# add the flynn remote if not done yet
git remote add flynn https://git.flynn.example.com/myapp.git || true
# do the actual deployment
git push flynn master

Different Branches

It is likely that the deployment job won’t use the master branch but an environment specific one like “staging” or “production”. Jenkins offers an environment variable which we will use:

# checkout the repository completely as Jenkins might do a sparse checkout
git checkout ${GIT_BRANCH}
# add the Flynn remote if not done yet
git remote add flynn https://git.flynn.example.com/myapp.git || true
# do the actual deployment from our branch towards the Flynn master branch
git push flynn ${GIT_BRANCH}:master

Large Repositories

On older applications, the repository might grow to many hundreds of megabytes or even gigabytes. This is likely no data you want to have within Flynn and its caches and you might run into timeouts on deploying such repositories. So we create a new temporary repository and deploy that:

# delete the working directory from possible previous runs
rm -r deployment || true
# create the working directory
mkdir deployment
# copy everything into the new directory except the original repository
rsync -avz --exclude '.git' --exclude 'deployment' . deployment
# go to our new temporary home
cd deployment
# initialize a new repository
git init
# add the whole application
git add .
# and commit it
git commit -m "deployment commit"
# add the flynn remote if not done yet
git remote add flynn https://git.flynn.example.com/myapp.git || true
# finally do the actual deployment, no matter what previously was deployed
git push -f flynn master

Note that this method has one drawback: Flynn exits early with the other methods if it notices that nothing changed since the last deployment. Due to the creation of a new repository and force pushing it, this mechanism is circumvented and the whole deployment always happens.

Via this method, you could also manipulate the files before copying them into the deployment directory. Configuration files of legacy applications not using environment variables come into mind.

Final Thoughts

With the second and third method, the deployments towards Flynn works just fine here. But you may drop a line if you use it differently or have run into anything else interesting about this topic.

The Docker flow of Flynn hasn’t been covered here as I don’t use it (yet). But using the CLI, it should be straight forward.