One of the most valuable tasks every project should complete on their first day is to define their continuous integration process. Continuous integration has become such an essential part of modern day software development that having a continuous integration strategy on Day One establishes the automation infrastructure necessary to scale as your project and team grow.
Many Rails applications consider running
rake spec the definition of
a continuous integration process and although it's a good start, continuous
integration is about more than unit/integration tests.
The ultimate goal of a continuous integration test suite is to ensure the project is in a good state before being released to customers.
Now, The actual definition of “good state” is specific to each project/team, but at a high level, your continuous integration process will be automating as many checks and balances necessary to feel confident that you are releasing good code.
The Basics (Test suite)
Here are the basic structure I've developed and use for new projects to kickoff their continuous integration process on the right foot...
First off, your continuous integration process needs to make sure your test suite passes. Pick your framework (RSpec, Jasmine, etc), and use tools they provide. Nothing fancy is necessary. If the tests aren't green, go back to square one.
If the tests pass, that’s great BUT a project with zero tests technically qualifies as a successful build. So adding a test coverage check is extremely useful to ensure your code has an adequate level of testing in place. Test coverage is apparently a controversial topic now, but I have found adding test coverage checks to be extremely valuable for catching untested code paths and in raising confidence that you are shipping "good code".
Simplecov is very straightforward to integrate into a continuous integration suite, and I recommend 95%+ test coverage as a good starting point.
Best Practices (Styleguide)
Every developer has their own coding style, and every project should have a set of accepted principles for collaborating in a single codebase in order to write maintainable software. Most development communities have codified their best practices which provide an excellent baseline for your team to get started.
Establishing a coding style guide for your team on Day One saves you a significant amount of time versus trying to retro fit a set of best practices later on in the project development lifecycle. As your team grows, having a style guide in place makes it that much easier to onboard a new developer and ensure that new code is written inline with existing conventions. Sure, you could just encourage best practices via a static style guide document, but who would read it? Who would maintain it? Who would enforce it?
Another benefit of automating this task is that it removes the burden during the code review process from being "human syntax checkers" to focusing on the bigger picture issues (architecture, modeling, API design, etc).
Brakeman and BundlerAudit are two great tools to plug into your continuous integration process as an extra level of defense to ensure known vulnerabilities do not get released to production. They both run quickly and are worthwhile investments to include in your continuous integration process.
The goal is not to perform a full penetration test or security audit of the system. It is to give you an increased confidence that you are shipping "good code".
[optional] Project Reports/Metrics
Some teams benefit from having a standard set of reports generated with every continuous integration run. These reports should not fail the build and their objective is simply to get relevant information in front of developers to motivate future changes.
Some examples of reports that might be useful for your team include:
rake stats- high level overview of project codebase stats
rake notes- view all
FIXME, etc tags in the codebase
bundle outdated- view list of outdated gems that may need to be upgraded
It's been very interesting to see how simply surfacing this information every
time the build is run has led to developers actually caring about those
tags littered around the codebase and doing something about them.
These reports need to be fast to be included in the continuous integration process. If they take too long, it will only lead to developer frustration. If they are useful try very hard to have them run with every build. Having them run only occasionally makes it extremely unlikely that someone will see them and act accordingly.
The bottom line is:
If you find that a report has value then use it, otherwise, move along...
So, how do you wire this whole thing up? Here's my boilerplate Rake task that
I use for each of my projects. Just drop this into
Gemfile to include the necessary dependencies and you’re good to
go! This little template has provided a huge amount of value for new projects on
Day One, and is easily customizable for future needs.
Run the continuous integration process:
# Run the full continuous integration build $ rake ci
I also recommend aliasing the
ci Rake task to the Rake default task so you can
run Rake from the command line without any arguments. It helps
new developers get up and running quickly without having to hunt around and is
also useful when working with tools like Travis CI that run the default Rake
command without extra configuration.
# Rakefile require File.expand_path('../config/application', __FILE__) MyApp::Application.load_tasks task default: :ci
You can absolutely use a shell script instead of Rake for your build script (ex: bin/build) and the core principles of the process remain the same. I personally find Rake a bit nicer since it simplifies exit code management and is written in Ruby.
With this basic framework in place, you can start shipping good code with confidence on Day One of your next Rails application!
If you have an interesting continuous integration process that works for you, I'd love to hear about it!comments powered by Disqus