One stop shop for DevOps
Our clients are always deeply interested in creating productive dev environments. The power of a dev environment comes from many places. First is time saved by reducing the number of manual steps and by preventing context switches for a developer. Improving flow enables a developer to catch bugs sooner when they’re still inexpensive. Consequently, moving toward continuous testing and integration is essential. In this post, we’ll discuss a continuous integration workflow using opensource tools.
The Challenge: How Best to Conduct Team-based Development
The keys to successful team-based development are as follows:
Enabling multiple contributions.
Maintaining a centralized repository.
Reviewing code changes before pushing to Master.
Not affecting others in the process of code changes and review.
Avoiding software development slowdowns.
Successful team-based development can best be handled in the following ways:
1. The Review-Before-Commit Approach
Patches are proposed either as attachments on bugs or by sharing during live meetings.
This ensures that there be no repository cruft and that nothing will negatively affect others in the process. However, This approach leads to a certain lack of control. Since the commit is made by spoken word, there’s no guarantee that reviewed and committed code will be the same.
2.The Review-After-Commit Approach
Proposed changes are committed to the repository and then reviewed by the group. Storing all changes in the master can cause repository cruft. There’s a good chance that the repository is housing changes that other team members prefer you don’t make or code that may contain bugs that other team members will find later.
3. A Review-After-Commit-on-Unique-Branch Approach
A method that combines the two previous approaches is to review after commit, but to push it to a unique branch. Pushing it to a unique branch won’t affect other developers because the code will be made visible to others only after passing code review and that the reviewed code is guaranteed to be the committed code. This approach prevents repository cruft on the main branch.
Three opensource solutions will support this workflow.
Git is the most popular distributed version control system used today. More than 2 million repositories and three-quarters of a million users use github.
Many opensource projects employ Git. It was written by Linus Torvalds to handle source code for Linux. Google uses it to store the Android operating system, Eclipse uses it to store Eclipse projects and Apache uses it for read-only views of its projects. By default it’s also used with Xcode 5, which allows implicit creation of a Git repository for any newly-created project.
Since Git uses distributed version control, you can make and manipulate changes before they’re published publically. Git even allows manipulation of multiple revisions by combining them into a single revision, breaking them apart, and then reordering them.
Gerrit is a git-backed code review system with a web-based interface that allows one to push changes from any git client, to review the changes online and then to auto-merge them with the master. Even though it’s a web application, it can also be configured as a remote git repository.
Gerrit is also used by Eclipse and Android. It helps large distributed teams review projects they’re collaborating on. It’s also helpful for smaller teams because it keeps track of the repositories and serves as a gatekeeper or a front-end to a centralized Git repository.
Patch sets are created for each made change. Gerrit allows various patch set comparisons. It also allows for feedback or review on specific lines, or for a review message on the entire patch. A reviewer can give one of 5 ratings:
+2 – Looks good to me, approved.
+1 – Looks good to me, but someone else must approve.
0 – No score.
-1 – I would prefer that you didn’t submit this.
-2 – Block submit.
By default, A +2 review implies the code can be submitted to the master. This is however configurable. Also by default the ratings aren’t additive which means that two +1’s don’t automatically constitute a +2.
Jenkins/Hudson is an automated web-based build platform that allows build process automation as and when changes occur. Note that Jenkins and Hudson can each work with or without Git or Gerrit. It has hooks that allow event triggers, so when a change occurs a build is made automatically. Jenkins used with Gerrit will mark success/failure to indicate whether builds have passed the tests.
Bringing It All Together
The following video illustrates how to bring everything together in order to create a great workflow: http://vimeo.com/23609339. These tools integrate very well with one another, and the steps in this process are outlined below:
1. Add Gerrit as a remote path in your .git/config. Any pushes should always be made to this remote path from now on.
2. Git supports running a script after a commit. Use it to generate a change-id that’s recognized by Gerrit. This will allow Gerrit to view amendments to a change as part of a series of changes, rather than as unique changes.
3. After receiving a commit from Git, Gerrit will create a change-set, or add a patch to an existing change-set, and then trigger an event in Jenkins.
4. Jenkins will perform the build and run the test regression. It will then publish run results as one of the reviewers on Gerrit. If the build fails, Jenkins will reject the patch. Depending on the quality of your continuous integration you may want either a -1, or a -2 if a test in your regression fails.
5. Other code reviewers will come and review the code along with the regression result from Jenkins. Once all reviews pass, the code can be pushed to a publicly visible repository.
6. This system can be improved by integrating bug trackers, emails on commits and reviews, and multiple tiers of regression. This is best conducted as an incremental process based on the team’s preferences.
So, which tools do you use for your workflow? Share your experiences in the comments section! We also welcome one-on-one discussions, so write to us at firstname.lastname@example.org.