LCSR Development Model

Source Code Repository Hosting

There are two servers which host open-source LCSR resources, depending on their licenses and intended audience. Code meant for public use under an open-source license is hosted on GitHub, while any private code or code which is published only for reference may be hosted internally on the LCSR GitLab. Limited-access to private source code resources may also be granted on a case-by case basis.

See Software for an index of all active JHU LCSR GitHub organizations.

Git Forking Model

LCSR repositories follow a centralized git development model. The "central" repository follows a strict branching and tagging model (described below), but both developers and non-privileged users are encouraged to develop in forks and submit pull requests for contributions. See the section on code reviews below for details on reviewing pull requests.

Git Branching Model

The branching model used by LCSR projects based on a simplified version of the Git Flow development model. All repositories hosted on LCSR GitHub organizations must conform to this branching model.

Similarly to Git Flow, we use following standard branches and branch types (described in more detail in the subsequent sections):

Due to limited resources, we do not maintain release branches. As such, bugfixes do not get pushed back into older versions of the code, they are only merged into devel before being merged into master.

master

The master branch should always have an up-to-date README.md which describes how to build it for the target platforms. This file should also give a high-level overview of the design of the package.

This branch should be usable by people who expect the package to "just work" as described.

devel

The devel branch is used to test integration of features and bugfixes before merging into master. This branch should only be used by people who are ready to debug problems which may arise and who aren't worried about having to re-test their code.

feature-xxx

Features are either backwards-compatible or non-backwards compatible. When making a pull request, it should be determined whether a feature will break anything as described below.

Backwards-compatible features include changes such as:

A non-backwards-compatible feature is any change which has any of the following effects:

hack-xxx

These branches are expected to be made when prototyping or pushing towards a deadline. They're useful for archiving variants for experimental code which are not intended to eventually be merged into master.

Version Tagging Model

Git tags are used to track breaking changes in a repository via a three-number versioning system based on semantic versioning. In semantic versioning, each tag is a 3-element version number MAJOR.MINOR.PATCH. These elements are defined as follows:

Since we expect that research code developed by JHU LCSR will be more volatile than that which is developed for end-users, we will use a different semantic versioning system, called proto versioning. In this system, we also use a 3-element version number, but it corresponds to the following MORTAL.MAJOR.MINOR:

User Pattern

For repositories which you don't contribute to, you should either use the master branch, or always use a tagged version. This will allow you to rely on the code not changing.

Contributer Pattern

Generally, if you're not responsible for maintaining a repository, you should develop in your own fork of the repository. This will allow you to have the freedom to store and work on your own experiments without breaking someone else's code.

On either GitHub or GitLab, you can fork a repository into your own account, and once you want to contribute back, you can do so with a pull request into the original repository's devel branch.

If your code is out of date, you can merge or rebase changes from the original repository by adding it as a remote to your local clone:

git checkout feature-my-cool-thing
git remote add upstream https://github.com/jhu-lcsr/repo-name.git
git fetch upstream
git merge upstream devel

Maintainer Pattern

As the maintainer of a repository, you're responsible for deciding when to merge changes from the devel branch into the master branch and tagging versions according to the versioning scheme described above.

For new repositories or repositories which aren't intended to be used by more than one person, you can avoid maintaining separate devel and master branches. In order to make it clear that your repository is volatile, you should delete the master branch, and do all work directly in devel.

For repositories where development has already been happening directly in master, you can switch this with the following:

git checkout master               # make sure you're on "master"
git pull origin master            # make sure you have the latest version of "master"
git checkout -b devel             # create a new branch called "devel" identical to "master"
git push -u origin devel          # push the new "devel" branch and set "origin" as it's upstream
git branch -D master              # delete the local "master" branch
git push origin --delete master   # delete the remote "master" branch

Merging into master and Tagging Versions

Occasionally, as features and bugfixes are incorporated devel will be merged into master and master will be tagged with a new version. This is the closest action in the LCSR Development model to a release.

git checkout master
git merge devel
git push origin master

To determine whether to increment MORTAL, MAJOR or MINOR, you need to review the changes since the last tag.

NOTE: Due to limited resources, it might not be possible to guarantee whether backwards-incompatible changes have been introduced. In this case, it is better to be conservative, and to increment the MAJOR version element.

In order to list all of the commits since the last tag, you can run the following after merging locally:

git log `git describe --tags --abbrev=0`..HEAD --oneline --decorate --color

Merging of feature-xxx branches which are backwards-compatible necessitate incrementing the MINOR version, and merging of non-backwards compatible feature-xxx branches necessitate incrementing the MAJOR version, and re-setting the MINOR version to 0.

If it's clear that there has been a complete redesign of a package, it's necessary to increment the MORTAL version and re-set the MAJOR and MINOR versions to 0.

git tag $MORTAL.$MAJOR.$MINOR
git push orign --tags

Continuous Integration Testing

Continuous integration testing can be used to guarantee that a repository builds and passes any available tests. A simple way to do this which works well with GitHub is with Travis.

Code Standards

The most important thing is to be consistent within a given project or repository.

Code Reviews

Code reviews should be performed for all pull requests.