The NDN team is very glad you are interested in contributing! The NDN (Named Data Networking) codebase is composed of many projects, with multiple universities across the world contributing. This documentation will help you understand how we work and what we expect from contributors.
NDN codebase development adheres to the Contributor Covenant, located in CODE_OF_CONDUCT.md
. By contributing, you are expected to also adhere to this code. If you feel someone has breached this code of conduct, please email us.
The NDN codebase continually needs help with, among other things:
The NDN team maintains a community (Redmine site) for issue tracking and documentation hosting. Redmine is the hub for design activity. In particular, all design discussion and decisions will either occur or be copied there.
Why did they do it this way? When writing code, if you ever have questions about why some design decision was made, the best approach is to use git blame
on a file to inspect the last commit for some line of code. In this view there will be a commit hash in hex (e.g. 0ab12e3a
) in the first column. Using our example, git show 0ab12e3a
would show the commit made for that line. In the commit view there should be a reference number (e.g. refs: #1234
). Using this number, you can find a pertaining issue on the Redmine (e.g., https://redmine.named-data.net/issues/1234
).
Additionally, in some cases there are published papers you can read in order to gain a better understanding of the project. Searching for these papers is not difficult; in many cases you can find a pertaining paper or technical report listed on the main NDN website. Usually the title of a project will be a good keyword.
If you cannot find an answer to your question, the best place to go is the mailing lists. There are multiple different lists for different interests, so be sure you are mailing the right list for a quick response.
As mentioned above, Redmine is the organizational hub of the NDN projects. As such, extensive use of it is made, and learning how it works will help you. In particular, there is a workflow associated with Redmine. Generally it is:
Redmine provides other facilities for managing your work on NDN projects, too, such as time logging and time estimation.
All NDN projects are hosted on GitHub, at various organizations, using git for version control:
If you are unfamiliar with git, some kind of tutorial on git should be your first step.
There is also a Git game you can play. Finally, there is a wiki page on NFD's Redmine that has more useful links.
There are a lot of different projects, so take some time to look through them for ones that pertain to your interests. NDN projects use Gerrit for code review purposes.
Occasionally there will be other repositories used privately to test changes, but this is uncommon. In general, you will not need to refer to these repositories.
Most NDN projects are written in C++, and there is a style guide. In general the NDN style is similar to the GNU style, but there are some significant changes. This style guide is not exhaustive, and in all cases not covered by the guide you should emulate the current style of the project.
There is a partial styleguide for Python. It applies many of the provisions from the C++ guide, in addition to some other Python-specific things.
Some NDN projects are writtin in JavaScript, and there is a style guide for that language, too.
Commit messages are very important, as they are usually the first thing (besides the changelog file) a developer looks at when trying to understand the timeline of a project. Commit messages should:
"Make foo a bar"
and not "Foo is now a bar"
"Make foo a bar"
and not "Made foo a bar"
To explain, the anatomy of a typical commit message is like this:
docs: write contributing guide and code of conduct refs: #3898 Change-Id: Ife89360305027dba9020f0b298793c1121ae1fd6c
Explaining this:
docs
is the module that the commit affects. We want this because it lets someone know at a glance what part of the project it changes. For some projects, there will be only one module or only very small other modules. This practice should be observed in those cases, too.#3898
is the Redmine issue number. Gerrit transforms these into clickable links, and it is useful to reviewers to gain background understanding of the issue. You can have multiple by separating them with commas.Change-Id
should be filled automatically. It is used by Gerrit to track changes.With a few exceptions, every patch needs to have unit tests that accompany them. For C++, we use the Boost unit test framework to help us out. Note that this link points to the newest version of the Boost Test library documentation, and you may need to refer to older documentation if you are using an older version of Boost. More information on this is available in the NFD Dev Guide
When designing and writing tests, a few things need to be kept in mind:
Writing unit tests using the Boost framework is quite simple, and you can refer to existing unit tests for examples. (This is a good example.)
This is mentioned in greater depth in the developer's readme, but the basic procedure is:
./waf distclean
. This removes all prior build files../waf configure --with-tests
. This configures the next build to also build the tests../waf
. This will build the tests.build
directory, and will be named unit-tests-<module name
, e.g. unit-tests-nlsr
or unit-tests-rib
. To run just one test suite, run ./unit-tests-exampleModule -t ExampleTestSuite
. To run a specific test in a suite, use ./unit-tests-exampleModule -t ExampleTestSuite/ExampleTestCase
.As mentioned above, NDN projects use Gerrit for code review. This is a web-hosted, open code review platform that allows for interactive code review, rebasing, and cross-linking with the Redmine, and a developer interacts with it using the familiar git. For issues that require a tracker reference, a particularly useful feature is that the refs: #...
becomes a clickable link to the issue for design discussion.
The first-time Gerrit setup goes like this:
Log in to Gerrit. You can authenticate using many different methods, including GitHub OAuth. You need to ensure that you have a Gerrit username:
Username
box, check for a name. If there's already one there, great.Set up your Gerrit credentials. This will depend on how you configured your Gerrit remote in step 1. Among other things, you need to set up identities so that the email on your Gerrit profile matches whatever email you will be committing with on your git repo. Note: We only support using SSH access to Gerrit.
This shows what the identities panel looks like. If you do not see the email here that you have configured git to use, you cannot upload to Gerrit.
In that case, add it under contact information panel. .
Gerrit itself has extensive documentation regarding error messages, and this identity-based one is by far the most common. This is the documentation for an identity error.
Clone the source for a project from Gerrit.
Projects
.Clone with commit-msg hook
tab.ssh
tab to select cloning over SSH. Note: This will require setting up SSH access to Gerrit first.git clone ...
command into your terminal to fetch the project source.After this, your remotes will be set up correctly, and pushing to Gerrit will only require git push origin HEAD:refs/for/master
after committing work. This section has some git tips and tricks to type less.
Most patches should have a corresponding Redmine issue that they can reference. If you search the Redmine and notice there is no relevant issue for a patch you are writing, please create an issue first. You will need a Redmine account, which can be created there.
After writing some changes, commit them locally as normal. After saving and exiting your editor, the commit hook will insert a unique Change-Id
to the message.
Once you have a commit message you are happy with, simply run git push HEAD:refs/for/master
.
Note: Gerrit separates commits into patch sets by the unique Change-Id
s. As a result, it is important that you either:
git rebase -i <initial commit>
, ensuring that the ultimate Change-Id
in the commit is the one on the patch set on Gerrit. This workflow is generally preferred.git commit --amend
.If you do not do this, what will happen is that each commit will be interpreted by Gerrit as a separate patch set. This is probably not what you want.
It is important to remember that code review is about improving the quality of code contributed, and nothing else. Further, code review is highly important, as every line of code that's committed comes with a burden of maintenance. Code review helps minimize the burden of that maintenance. Consider that when you are receiving comments, those comments are influenced by two things:
Remembering these things when reading comments helps to separate what can feel like needless negativity.
Code review is extremely important! We need every bit of code review you can give. In many cases this is the bottleneck for new contributors who do not fully understand how certain language constructs should be used, what best practices are, etc. In these cases it is important to give constructive feedback.
Writing comments is somewhat counter-intuitive on Gerrit. If you are signed in through a modern browser, you can leave a comment in a file either by clicking on the line number, by selecting some text you want to comment and pressing 'c', or by clicking on someone else's comment. After typing, click the Save
button there. After navigating through the patch set with the arrows at the top-right of the Gerrit UI, you then must click the up-arrow to get back to the Change screen. At this point your comments have not been made yet! You must then click the Reply...
button, and assign a score. If you correctly saved your comments, they will be shown at the bottom of that box. Once you click post, the comments will be made public to others.
Minimally, a review must include:
Optimally, a review should include:
If you observe that code review takes a long time, there are a few things that you can do to to expedite the process:
There are a few things to remember when responding to code review, including:
Reply...
. Your comments will be shown as drafts, and you must click Post
to make them visible to others.As a supplement to the code review process, every patch set is automatically compiled and tested on multiple platforms using our instance of Jenkins, the continuous integration system. Interacting with Jenkins is not usually necessary, as Jenkins automatically picks up new patch sets and posts the results. Typically the only interaction needed with Jenkins is when some kind of glitch occurs and a build needs to be retriggered.
It is expected that code is checked locally. Reviewers may wait until Jenkins checks the code before doing a more functional review of the code. Since Jenkins checks can take a while, you can save some time by checking yourself first.
If you encounter an error like this when trying to push work:
remote: ERROR: [4311462] missing Change-Id in commit message footer remote: remote: Hint: To automatically insert Change-Id, install the hook: remote: gitdir=$(git rev-parse --git-dir); scp -p -P 29418 someuser@gerrit.named-data.net:hooks/commit-msg ${gitdir}/hooks/ remote: And then amend the commit: remote: git commit --amend
Then your commit hook has not been set up correctly, somehow. Follow the instructions in the terminal to resolve this.
As part of CI, there is a script that checks every patch uploaded to Gerrit for code style consistency. Checking these kinds of things is notoriously difficult, and while the robot is very good in general, it will occasionally report false positives and miss things. So all issues it raises should be inspected manually to ensure they really are style problems. Further, since this automated check is not perfect, you should take steps (e.g., configure your editor or run a linter before you commit) to ensure you adhere to code style rules.
If typing HEAD:refs/for/master
feels repetitive, you have a few options:
You can configure git to do the work for you, as described in this blog post
Git has an alias system that you can use to specify certain commands. For example, you can use git config --global alias.pg "push origin HEAD:refs/for/master"
to make git pg
push to Gerrit. You can learn about git aliases.
If using Linux or macOS, it is relatively simple to create a shell alias: alias gs="git status"
for example, or alias gitpush="git push origin HEAD:refs/for/master
. The alias itself must be one word, but it can represent multiple words. To persist your aliases, they need to go in your environment file, which is generally at ~/.bashrc
or ~/.zshrc
or ~/.profile
. The exact syntax of aliases and the environment variables file will vary by shell. You should be careful not to overuse aliases, however.