The source for this document is maintained at https://github.com/hbz/hbz.github.com | General hbz page: hbz.github.io
This section documents how we create software in the Lobid team at hbz.
We develop our software on GitHub. We don’t publish the results of our development process on GitHub, but instead do the actual development (track issues, change code, discuss changes) in the open. Publishing our development process in this document is part of this transparent process.
We use the simple GitHub workflow: the master branch in always the version that is actually deployed to production, new features are developed in feature branches, which are merged into the master after review in pull requests. See details on the GitHub flow.
We have different Git repositories under different GitHub organisations. New repositories are created under the
hbz organisation. We use GitHub issues to keep track of requirements, new features and bugs. Bugs (i.e. defects in existing functionality) are marked with the
bug
label and are prioritized over new features.
For a unified view of all issues in the various repositories we use a board at https://github.com/orgs/hbz/projects/2.
The columns of our board correspond the subsequent stages of our development process, from left to right:
Backlog
->
Ready
->
Working
->
Review
->
Deploy
->
Done
Columns are set up on the project on GitHub, i.e. moving a card from
working
to
review
is the same as changing the setting under 'Projects' from
working
to
review
on the issue in GitHub. New issues need to be added to the board/project (again, either on the board, or from the issue).
The backlog contains all planned issues.
An item is
ready
if it’s possible to start working on it, i.e. there are no blocking dependencies and requirements are clear enough to start working. Dependencies are expressed through simple referencing of the blocking issue (e.g.
dependes on #111
), see
details on referencing. Prioritized items (like
bugs
) are moved to the top of the
ready
column.
When we start working on an issue, we move it to the
working
column. Ideally, every person should only work on one issue at a time. That way the
working
column provides an overview of who is currently working on what. Issues are only moved into or out of the working column by the person who is assigned. Issues in working are only reassigned by the person who is currently assigned.
We include references to the corresponding issue in the commit messages. We don’t use keywords for closing issues in the commit messages, since the resolution decision does not happen during implementation, but during review (see below).
When an issue is completed on the technical side, we push the corresponding commits to a feature branch that contains the corresponding issue number and additional info for convenience (using camelCaseFormatting, e.g.
111-featureDesciption
). If the issue is in a different repo than the branch, we prefix the repo name, e.g.
nwbib-111-ui
.
We then open a pull request for the feature branch with a summary of the changes as its title, and a link to the corresponding issue using keywords for closing issues (like Will resolve #123, this will create a link from the issue to the pull request). We leave the pull request unassigned at this point.
We then deploy the changes from the feature branch to our stage or test system by merging the feature branch on the server and restarting the system.
To submit the changes for functional review, we now add instructions and links for testing the changed behavior on the stage or test system in the issue, assign the issue for functional review, and move it to the
review
column.
If the reviewers find problems during the review, they describe the issues, providing links that show the behavior, and reassign the team member that submitted the issue for review, leaving the issue in the review column.
If everything works as expected, the reviewers post a
+1
comment on the issue, unassign the issue, and assign the corresponding pull request for code review (the pull request is linked from the issue due to the closing keywords used in the pull request).
Changes during the review process are created in additional commits, which are pushed to the feature branch. They are added to the existing pull request automatically. See details on pull requests.
At the end of the code review, the reviewer posts a
+1
comment, reassigns the pull request to its original creator, and moves the associated issue to the
deploy
column (or changes the project setting on the issue using the GitHub issue UI, this will move the card into the
deploy column).
We use Travis CI for continuous integration. The CI is integrated into the GitHub review process: when a pull request is opened, Travis builds the resulting merged code and provides feedback right in the pull request. For details, see
this post. The creator of the pull request should ensure the Travis build was successful. Since code reviews conclude with a
+1
comment (and not with a merge), the reviewers can give their
+1
even if the Travis build is failing.
After the code review, the developer of the feature merges the pull request, deploys the new functionality to production, and deletes the corresponding branch. We don’t deploy to production on Friday afternoons or right before leaving for a vacation. To ensure that the master is always the deployed state, and to only close issues when they are actually deployed to production, merging the pull request should not happen using the GitHub web UI, but on the production server:
1. Log in to the server for the production system, and go to the repo you want to deploy
2. Pull the feature branch into the master, e.g.
git -c "user.name=First Last" -c "user.email=name@example.com" pull --no-ff origin 111-ui
(we have a single deployment user on our server, so we have to pass our name and email to the git pull command)
3. Restart the production app: sh restart.sh service-name
and test the new functionality
4. Amend the merge commit:
git commit --amend
to include a reference to the resolved issue using
keywords for closing issues and instructions on how to replicate the change in production (usually a link to the production system demonstrating the new functionality), e.g.
Resolves https://github.com/hbz/nwbib/issues/239
See http://nwbib.de/search?q=Neuehrenfeld
5. Push the changes to master:
git push origin master
, and delete the feature branch, e.g.
git push origin :111-ui
After deployment, both the issue and the pull request are closed automatically, and their card is moved to the
done
column.
We use a custom Eclipse formatter profile to ensure consistent formatting. We use custom Eclipse compiler settings to ensure consistent coding style. The settings are checked in to the repos and require no specific setup. Code that is submitted to review should contain no warnings in Eclipse. The formatting is applied automatically through Eclipse Save Actions.
Git commits should be as granular as possible. When working on a fix for issue X, we try not to add other things we notice (typos, formatting, refactorings, etc.) to the same commit. Eclipse has UI for partial staging, which is very useful to keep commits focussed.
We follow the established conventions for Git commit messages: imperative mood (e.g.
Fix UI issue
, not
Fixes UI issue
), short lines (max 72 chars), and either just one line, or one line, a blank line, and one or more paragraphs. For details, see
these
posts.
Every commit should be related to a GitHub issue. This allows us to understand why certain changes were applied. When committing to the same repo that contains the issue, it’s enough to just mention the issue number with a prefixed
#
mark, e.g.
Fix UI issue (#111)
. If the issue is in a different repo, we have to add the full link (in a paragraph under the summary line, see above).
We don’t use the GitHub shortcuts for closing issues from commits (like
fixes #111
), since in our process, the issue is not solved by the commit, but by the reviewed change, after it’s deployed to production (see above).
As a general rule, we never change public commit history, i.e. we don’t use
--force
or
-f
with
git push
. The only exception are branches prefixed with
wip-
(work in progress), which are considered private to the developer. Pull requests should always be opened for non-wip branches. Local amending and rebasing before pushing to GitHub is no problem and will not require to
--force
when pushing. While we consider this general rule as directive, we condone force pushing as long as the branch has no open pull request yet
and only one person is working on this branch. In case of a force push we use --force-with-lease
to ensure that we do not overwrite any remote commits. In case of an open pull request, instead of force pushing
we open a new branch from master and cherry-pick
needed commits or add new code in this branch. The old branch and the existing pull request should be closed then.
For increased reuse, we’re trying to apply the idea of a unified macro (see above) and micro architecture to the development of new Lobid modules. For reference implementations of the Lobid micro architecture, see https://github.com/hbz/lobid-organisations (data module) and https://github.com/hbz/nwbib (application module).
Lobid data modules are implemented with Metafacture, Elasticsearch, and the Playframework. A basic idea of the Lobid micro architecture is to provide a focused, independently deployable module that does one thing: provide 1 data set, with 1 Elasticsearch index (and thus, 1 index config file), 1 build, 1 CI config, 1 README. The goal is to have a single point of entry for each of these project facets.
Lobid application modules share this general goal of a focussed module that does one thing. They should usually not require a Metafacture transformation (which suggests an additional data module), but may use an app-specific Elasticsearch index. They implement their HTTP data communication, URL routes, and HTML/JS/CSS rendering with the Playframework.