Liftoff 1.0

Way back in January of 2013, we released Liftoff to help
developers quickly configure Xcode projects. We used it heavily internally,
but felt like it was only solving part of the problem. So we’ve improved it,
and are proud to announce Liftoff 1.0.

Distribution

Earlier versions of Liftoff were distributed as a Ruby gem, but that added
some weird overhead to the tool, since it isn’t used for Ruby development. For
this reason, Liftoff 1.0 is now distributed through Homebrew. We’re adding it
to our thoughtbot/formulae tap, and all future updates will be done there.

The RubyGems version will stay up, but is deprecated. If you install the
Homebrew version, you should make sure to uninstall the RubyGems version to
avoid confusion/potential conflicts.

liftoffrc

The next thing that we were able to improve was the way you configure Liftoff
itself. Originally, we used command line flags to enable specific
configurations (there was no way to selectively disable configurations). This
worked fine for us because we never touched these flags. But it
made Liftoff extremely rigid and clumsy for people who wanted to configure
their projects differently.

I had opened an issue after an internal conversation about
possibly using a config file instead of command line options, and after an
awesome contribution from @mokagio, we had a viable solution
for configuring projects quickly and easily, without increasing overhead for
users out of the box.

The liftoffrc file is written in YAML, and works with a 3 stage fallback
system on a per-key basis. The lookup order is:

Local (./.liftoffrc)

User (~/.liftoffrc)

Default (<liftoff installation location>/defaults/liftoffrc)

If a key isn’t defined at one level, it will fall back to the next level. So
you can safely override individual keys without changing the default behavior,
or build your own set of defaults at the User level and override those options
at the Local level.

Project Creation

The largest change in Liftoff 1.0 is that you can now use it to create new
projects from scratch, as opposed to only being able to use it for configuring
existing projects. Now, when you run liftoff in a directory that doesn’t
contain a project, you’ll get a prompt asking you for the project name, the
company name, your name, and the prefix. These values will be used to create a
directory structure, populate template files, and configure the new project.
You can see what the default directory/group structure will look like in the
default liftoffrc.

This becomes especially powerful when you consider that since the keys used to
generate the new project are defined in liftoffrc, they are easily
overridden for your specific needs. You can even pre-define some defaults for
the options collected at the command line to speed up the data entry. For
example, I’m setting author inside ~/.liftoffrc so that I don’t have to
enter my name any time I want to create a new project. I’m also setting
company: thoughtbot inside ~/Code/thoughtbot/.liftoffrc and company:
Gordon Fontenot inside ~/Code/personal/.liftoffrc. Now, projects I create
have sensible defaults based on where I’m creating them.

Additionally, you can completely redefine the project structure based on your
personal preference, or your employer’s requirements. Again, referring to the
default liftoffrc, you can see that the directory
structure is a simple dictionary. And since the directory structure is
mimicked in the group structure (including linking groups to their directory
counterparts, which Xcode doesn’t do by default), the group structure will
match.

We’re also creating .gitkeep files in each directory on disk, which is
critical, because Xcode is all-too-happy to delete a directory off disk once
it sees that there aren’t any files left in it. That’s a sure-fire way to end
up with merge-conflicts in your pbxproj file.

Wrapping up

So that’s Liftoff 1.0. We’ve put a lot of work into this release, and it’s
been a really great addition to our toolbelt so far. If you have ideas on how
to make it even better, open an issue, or even better:
submit a pull request. If you’re ready to check it out for yourself, install
it via Homebrew: