There are a million ways to do CI.  My goal is to keep it as simple as possible.  Concepts:

  • My target projects include multi-platform C++ applications, Firefox addons, cross-platform desktop apps, mobile apps, and web apps with lots of JavaScript and JavaScript libraries.
  • I want to use a simple-to-use very-capable cross-platform scripting language.  I’ve concluded that I will use JavaScript via Node.js.  It is async and portable from the day it was born.  Installing a node.js module for scripts means they are available from any path on any platform’s command line.
  • For CI tasks, I will avoid dependencies on anything else.  The core Node.js API is very capable.  Modules are available if needed (eg the amazing aws-sdk) but will be avoided whenever possible.
  • I need intelligent placement of CI windows (eg a popup shell for build-on-save).  My Ubuntu i3 window manager is capable of this, as is Autohotkeys under Windows.  These auto-placed windows will always run cross-platform node scripts.
  • If you want to use Powershell, for the love of all that’s holy, make sure you fix its terrible default of hiding debug output with:
       $global:DebugPreference = "Continue"
  • Goals:
    • on code save: automatically build
    • on code commit: automatically build, do any custom build steps, run any unit tests, run any end-to-end tests, and report results dynamically
    • on app production release: compile artifacts, assist in automatic versioning

See the wiki for details.

I’m a cross-platform developer, with about 17 different development environments. Most projects have a remote central team repository. git lets me cast my code out to all my local locations and effortlessly remained synced with the team repo. In addition, I can work exclusively in my local repos, as long as I need to, without touching the team repo until I’m ready to push my stuff to it. I’ve refined my process down to just the right number of branches to accomplish this. Here’s my git bliss:

First, set up a local centralized repo:

ssh me@my-central-repo-server
git clone ssh://me@the-team-repo/big-project
cd big-project
git branch daily_grind # create working branch but do NOT check it out

Next, set up a [git merge-to] command (huge THANKS to this gist):

emacs .git/config
  [alias]
    merge-to = "!gitmergeto() { export tmp_branch=`git branch | grep '* ' | tr -d '* '` && git checkout $1 && git merge $tmp_branch && git checkout $tmp_branch; unset tmp_branch; }; gitmergeto"

Now we can set up a clone in many new locations – repeat this on each dev box:

ssh me@my-laptop
git clone ssh://me@my-central-repo-server/big-project
cd big-project
git checkout -b daily_grind origin/daily_grind

This location is now a work site. Work in the daily_grind branch. Always pull before you get started working, and push when done:

ssh me@my-laptop
git pull
# work work work!
git commit -a
git push

When you are ready to share with the team, all your commits from all your dev locations will be in your central repo, in the daily_grind branch. Just merge your work with the team’s:

ssh me@my-central-repo-server
git pull # to get the team's latest
git merge daily_grind # to merge in your latest
# resolve any conflicts
git push # to push your changes to the team
git merge-to daily_grind # to push team changes to your work repo

If there were any team changes, you’ll get them in your local repos the next time you pull.

And away we go.