The .NET Core source code has been open sourced on GitHub for a while now, and the community is free to raise issues and submit pull requests – though I’d not really expected that I’d ever actually need to. That’s mainly because I always expect that thousands of other talented developers will have tested the code paths I’m working with and found (and solved) those issues before me.
But shortly after I installed .NET Core 2.0.0 Preview 1, I found that all my .NET Core projects that I had written for Windows 10 IoT Core suddenly stopped working – and the reason was that the executable file wasn’t being generated any more after I published the project.
I tested the hell out of this – I originally suspected that I had done something wrong or different, and I really didn’t want to report an issue and then find I was the one who had actually made a mistake. But I eventually concluded that something had changed in the code, so I raised a bug under the title “Publishing to win10-arm or win8-arm doesn’t generate an exe file for a Console application“, and this ultimately led to me committing some test code to the .NET Core codebase.
So the fact that .NET Core is completely open source and receiving community contributions suddenly became extremely relevant to me – previously I’d have just had to suffer the problem.
None of this stuff I write about below is a particularly big deal – just a part of software development – but dipping my toe into the waters of a massively public open source project was, well, a bit nerve wracking.
In some ways I felt like when I start a new job, where I’ve joined a team that has patterns and practices that I’m not entirely familiar with – I’m always worried I’ll do something that makes things harder for other developers, invokes justified wrath… and reminds me that it’s only Imposter Syndrome if I’m not actually stupid.
None of the stuff I was worried about happened – and was it was never going to happen. The .NET development team were super helpful, open, friendly, and encouraged me right from the start – and there were safety nets all along the way to stop anything bad happening. They even suggested a workaround to solve my problem on the same day I raised the issue, which massively helped me before the resolution was merged in.
I’ve written about my experiences below – things I got right, and things I got wrong – hopefully this will be useful to other developers thinking about putting their toe in the same waters.
Tips for a good issue report
The first part of this was writing up the issue – I think that there are essentially three parts to a good issue report:
- Steps to recreate the issue
- Actual behaviour
- Expected behaviour – don’t forget to say why you think this is the expected behaviour.
What sort of things do I need to do when submitting a pull request to the .NET Core repositories?
I wasn’t the developer who actually solved the issue – the .NET team get the credit for that – but I did see an opportunity to write a test to make sure the issue didn’t reoccur, and I submitted a PR for that code change.
First, fork the .NET Core SDK repository
This bit’s really easy – just click on the “Fork” button in the top right corner of the GitHub repository. This’ll create a fork of the original Microsoft source code in your own GitHub profile.
Clone the repo locally, and make sure you choose the correct branch to code against
I used TortoiseGit to clone the repository to my local development machine, and just started coding – and that turned out to be a bit too quick on the draw. I don’t think this is written down anywhere, but I should have targeted the release/2.0.0 branch.
How do I choose the right branch? I think the best way is to look at some recently closed pull requests, and see where the other developers are pushing their code.
With TortoiseGit, it’s easy to switch branches.
- Right click on the root of the repo you’ve cloned, select “TortoiseGit > Switch/Checkout”.
- A window will appear, where you can select the branch you want from a dropdown list. In the image below, you can see I’ve selected the release/2.0.0 branch. Click OK to switch your local repo to the code in this branch.
I initially (but wrongly) wrote my code against the default branch – in some repositories that’s possibly ok, but at the time of writing, the best branch to target in the .NET SDK repo is release/2.0.0. By the time I realised I should have targeted the release/2.0.0 branch and tried to switch to it, GitHub invited me to resolve lots of conflicts in files I hadn’t touched. Rather than trying to rebase and introducing lots of risk, I just closed the original pull request, selected the correct branch, and opened a new pull request which included my code change. Don’t make the same mistake I did!
Test that you can build the branch before making any changes
Once your locally cloned repository targets the correct branch, you should try building the code before making any changes. If it doesn’t build at this point or tests fail, then at least you know the problem isn’t caused by something you did.
In the root folder of the source for .NET Core’s SDK, there are three files which can be used to build the code:
Open a command prompt, and run whichever one of the three options that is your favourite.
If you find that the code doesn’t build or the tests don’t pass, check the build status on the repo’s home page.
Make your changes, commit them, and push the changes to the right branch in your remote fork on GitHub
Don’t forget your unit tests, make sure everything builds, and comment your changes appropriately.
Now create a pull request
From your forked repository, hit the “New Pull Request” button. Here are a few things that I think are useful to think about:
- You’ll need to enter a comment – make sure it’s a useful one.
- Describe why your change is valuable – does it fix an issue? Is it a unit test, related to another pull request?
- If you can, link to an issue or pull request in the comment to give the reviewers some context.
- I try not to submit a pull request which changes many files – lots of changes make it difficult to review. If you have to change lots of files, try to explain why it wasn’t possible to separate this out into smaller chunks.
- And remember to open the pull request against the correct branch!
What happens when I submit the pull request?
Once you submit your first pull request, it’ll immediately be assigned a label “cla-required” by the dnfclas bot.
cla is short for “contribution licence agreement“.
dnfclas means “dot net foundation contribution licence agreement” and is the Pull Request Bot.
To proceed beyond this point, you need to click on the link to https://cla2.dotnetfoundation.org to sign a Contribution Licence Agreement. When you click on that link, you’ll be redirected to a page like this.
Sign in using your GitHub credentials, and you’ll be invited to enter some details and sign the agreement. If you sign it, you’ll eventually be shown a page like the one below.
At this point, the dnfclas bot automatically recognises that you’ve signed the agreement (you don’t need to tell it), and it updates the label in the pull request from “cla-required” to “cla-signed”. You’ll see this on your pull request as an update, similar to the one below.
As you might expect, there’s a series of integration environments where your pull request will be tested. For the .NET Core SDK continuous integration process, there are presently 10 environments where code is automatically tested:
- OSX10.12 Debug
- OSX10.12 Release
- Ubuntu14.04 Debug
- Ubuntu14.04 Release
- Ubuntu16.04 Debug
- Ubuntu16.04 Release
- Windows_NT Debug
- Windows_NT Release
- Windows_NT_FullFramework Debug
- Windows_NT_FullFramework Release
There are lots of dotnet repositories, and an issue which manifests itself in one repo might have the root cause in another one – and this was the case for me. The issue that I observed in the SDK actually started in the .NET CoreFx repository.
It takes a while for fixes in one repo to flow across to the other, so if you submit a unit test to one repo for a fix that lives somewhere else, the test might fail for a while – and that’ll stop it being merged in immediately.
So if you’re only submitting tests, expect that all the checks will fail until the code you’re covering with your unit test flows across to the .NET Core SDK continuous integration environment.
Once the fixed code has flowed through, you’ll see this (assuming your code works…):
The .NET Team will choose a reviewer for you – you don’t need to choose anyone
Finally – and probably most importantly – someone from the .NET Core SDK team will review your code. I think it’s mandatory (as well as courteous) to address any comments from your reviewer – these are helpful pointers from a team of super smart people who care about good code.
One thing that caught me out was that GitHub marked some of the review comments as “outdated” (as shown below). I should have clicked on these – if I had, I would have seen a few comments that I hadn’t addressed.
Another thing was I wish I had a copy of Resharper on my development machine – one of the review comments was that I had left an unused variable in my code. Resharper would have caught this error for me.
So, much to my surprise, I’ve contributed to the .NET Core codebase – albeit in a very small way!
In summary, I was a bit nervous about submitting my first pull request to the .NET Core SDK repository – but I decided to create a simple test which covered a bug fix from the .NET team. Apart from signing a contribution licence agreement, this was a pretty standard process of submitting a pull request for review and automated testing. One really nice thing is that changes are tested not only against Windows, but also different versions of Ubuntu and OSX. Also, if you’re about to submit your own pull request to a .NET Core repo, I’d recommend checking out other pull requests first as a guideline – and don’t forget to look at what branch the developers are merging to.
Hopefully this description of my experiences will help other developers thinking of contributing feel a bit more confident. I’d recommend to anyone thinking of making their first contribution, choose something small – it’ll help you get familiar with the process.