Good practices for package development in the Julia ecosystem

This is up to you. Having a separate dev branch is called GitFlow.

http://datasift.github.io/gitflow/IntroducingGitFlow.html

This is normally used for deployment systems where master branch should always be working so that hotfix branches can be merged and put directly to deployment. I don’t think that matches many Julia package structures, so it can be unnecessary overhead. Packages which used to use it like Plots.jl no longer do so because it was unnecessary.

Instead, I prefer a modified version of GitFlow, thinking about tags as deployment and master as my working development branch. Here are some tenants I follow:

  1. You should keep master always working and master should always have passing tests.
  2. Small changes where tests pass, if it’s a lonely repo, can be pushed directly to master.
  3. Anything that breaks tests should be a PR. It’s funny at first to make PRs to yourself, but that makes them easy to merge in later and keeps things tidy rather than having just a branch (you will easily forget what it’s for if it waits a year :smile:)
  4. Tag early and often. Since master is always working, if it’s sitting around with some changes that are tested then you might as well release it. It’s easier on METADATA maintainers to check and merge a small diff frequently than it is to check large diffs infrequently (that’s my opinion at least, and I am one of these METADATA maintainers. You’ll see that if it’s a small diff and both tests pass then I’ll quickly review and merge those, but leave the larger ones because they take more work!).
  5. Try to keep users off of master. Always release after fixing a user-reported bug: it’s just a friendly way to keep the release version as your best face. Master is for package development only.

And just one point for me:

  1. Don’t spend too much time working on compatibility. This is controversial, but I find that people stay on old versions of Julia because they have an old code that they don’t want to change right now, and the worst thing you can do is start changing their packages. This has led to me showing people how to pin packages more often then not. So if it’s easy, keep compatibility, otherwise I wouldn’t worry too much about supporting v0.5 next year.

The package resolver is finicky. Package resolving in general is a very hard problem and you should avoid this when necessary. Set bounds when known, but don’t chuck them on there willy nilly because that’s the versions you’re using locally / on Travis. Only put upper bounds when you know there’s an incompatibility. Generally these will be set by other packages directly in METADATA.jl when they update and JuliaCIBot finds breaks, or when they know they will break downstream packages (you can PR to METADATA to add upper bounds to previous versions of packages which is when/how this is done). Lower bounds come from fixing problems that put an upper bound, or when you find incompatible versions because some user pinned an ancient ForwardDiff version and you want a better error.

16 Likes