Ok, I've written this up into a proposal... I've tried to faithfully capture everything above.
Gist: Proposal for Release Management
A message was moved here from #ideas > Monorepo? by Luke Boswell.
Looking for any feedback - or even an emoji :thumbs_up: or :thumbs_down:
@Anton will likely have the veto here, but trying to consolidate our discussion into a single resource.
Reading now!
I'm sure the devil will be in the details, but I am +1 overall
Would we maybe want to support roc-json? I know it's not owned by the roc repository, but it's pretty important
Also, if it's possible to do automatic builds every week, that would be much better than requiring a manual build
Even biweekly would be fine for manual builds, but weekly is a lot of busy work IMO
i think it would be best if we do automatic promotion every week if all of the core platforms and packages work with the prerelease
So by default it is no work
If something breaks, it can alert us
We can either do a quick bug fix if it is just a bug or increment the breaking version number cause we missed something
I think this should be reasonable to automate
Just roc test on a number of trusted packages along with the tests for basic cli and basic webserver.
If we decide to go this direction, and we want to remove the basic-cli cli tests, I would like to do that in my rebuild-host PR. It's touched all of those tests already, and I need to get in and do a merge to update everything again if builtin Task lands, and so if we are removing them then this will be so much easier to merge and prepare it for review.
Or I guess we could do it in a separate PR, merge that, and then I merge main...
Where would the basic-cli tests currently in roc-lang/roc go?
Well I think most of them are already in roc-lang/examples.
Yeah, they're already covered over there
Except the combine-tasks.roc example you recently added Sam. That should probably be moved across to the effects zig test platform -- also makes sense to do that in my build-host PR.
Great, code clean up is always nice
Thanks @Luke Boswell, this looks pretty good :)
Just for:
Daily
A CI job that tests all-the-things.
Uses the latest available pre-release for roc and platforms.
If the pre-release only changes weekly, there is no need for daily testing right?
0.0.0-alpha.12+479feca looks quite hairy and unconventional.
Inluding both 0.0.0 and alpha would be redundant in my opinion
I would prefer alpha-12+479feca
can we call it like build instead of alpha?
I know the modern definitions are muddied, but to me, "alpha" has always meant "internal only testing release" and "beta" has always meant "public testing release"
whereas this is just "here's a particular build of this commit, we're not setting any expectations about the intended audience or the quality level whatsoever"
I think the name is all about user expectation:
0.0.0-alpha.12+abc probably too strong a signal
alpha.12+abc I think this is the right level
build.12+abc I think people will consider this a real release and judge it more
"we're not even a version 0.0.0"
"What do you mean your system says version 12"
"actually it's breaking change number 12"
"Oh ................."
what about 0.0.0-build-12+abc?
Richard Feldman said:
what about
0.0.0-build-12+abc?
According to https://semver.org/, the prerelease field (a.k.a. "build-12") is supposed to be dot-separated
But otherwise, that works for me
I wonder if we could derive the build number (or maybe call it the commit number?) from the commit
e.g. if it's the 12345th commit in the repo, call it 0.0.0-commit-12345+abc
because that way it's monotonically increasing (so we can easily tell which ones are newer than the previous ones) but also the implication is that all you should need is that commit, and we don't do multiple builds of the same commit using different information outside the commit
You know what, that works. I don't think "which breaking version, specifically, are we on?" is important to communicate
And it's deterministic, automatable, and human-readable
That doesn't work
We want people to be able to upgrade without question if there are no breaking changes
So i think it is really important to have a breaking change number
That enables platforms to depend on roughly 0.0.0-build-12+*
I think this is a super important property for maintenance of this system
Brendan Hansknecht said:
We want people to be able to upgrade without question if there are no breaking changes
I think if we want this then we should ship an 0.1 and then do semver
I mean i think that is essentially the feature we want. It is really what we need to decouple platforms from the main roc repo head version.
I think we just are less confident about giving this a true semver for 2 reasons:
But I think for this decoupling, it is quite important that all platforms attempt to use the latest minor version.
Cause we still need that feedback to catch regressions and keep roc functional
So maybe 0.1.<breaking-patch>-alpha.<next int OR commit number>+<commit hash>?
Basically, this is live at head but with a little bit of delay and a grace period for breaking versions to decouple work.
Or maybe just 0.1.<breaking-patch>-alpha+<commit hash>
To be fair, this could be dealt with without versioning
It could just be recommended and nightly releases.
Recommended is updated when all core platforms/packages work with nightly
So by default, recommended would also update nightly
On breaking changes, there would be a longer lag time
But I do think that is the core of the decoupling we are trying to facilitate.
I know the worry with introducing any non-zero semver is you get a Hollow Knight: Silksong situation. Just implying that there will be a release sometime will make people upset if it doesn't happen in a year or two
Yeah, and 0.1.0 is practically seen as production ready nowadays. Definitely by 0.10.0 or so.
So if this is really about setting expectations as well as making a weak contract between Roc, its platforms, and app authors, then we should probably avoid even 0.1
Yeah, unironically
Not that it should be, but it's the world we live in
I think 0.0.X would be fine for communicating a "we aren't even thinking about releasing anything soon"
I'd be happy with that. Though we do need two numbers. 0.0.X+<commit-hash> cause X is only incremented on breaking changes. If no breaking changes, commit hash just keeps going up.
Or well, keeps changing.
Cause commit hash is random
So... 0.0.<breaking-version>-alpha+<commit-hash>? I'm okay with or without the alpha prerelease segment
I think 0.0.X+<commit-hash> would work. :plus:
Anton said:
I would prefer
alpha-12+479feca
I also think this could work, but I prefer the one above because it's still just semver.
So when we do decide it's time for a minor numbered release we just increment one number. So from 0.0.<breaking>+<commit-hash> to 0.<minor>.<patch>+<commit-hash>
I don't follow this last comment with 0.<minor>.<patch>+<commit-hash>...
Oh, do you mean when we decide to make the jump to 0.1.0?
Yeah, eventually we will want to have a numbered release and provide some kind of stability guarantee. Like, you can use 0.xand we will backport any serious bug fixes, but you can sit on that until the next 0.x release. (I assume -- I haven't done this kind of release management before)
Maybe by then it would be better to go to a 1.minor.patch but that sounds like a long way away.
yup
I'm getting excited that the rebuild host PR is almost ready to land... in preparation I've updated the above process. Looking for endorsement or concerns. I'd like to make an Issue for this so we can start thinking about the work we need to do to implement.
This proposal aims to provide improved stability for Roc users while enabling compiler development to progress without being blocked by the need to fix all known issues in dependent platforms and packages.
While Roc is early in its development with many known breaking changes ahead, user feedback is crucial for validating design assumptions. This process outlines a methodology to enable validation during the development of the compiler, language, and broader ecosystem.
The core concept is that Roc maintains a recommended nightly version, updated when "supported" packages and platforms are working correctly with the latest nightly build. When the Roc main branch receives a breaking change, supported platforms (like basic-cli and basic-webserver) can be updated subsequently.
The recommended nightly is then updated once all components are working together harmoniously, including website examples.
New roc version format: 0.0.<breaking>+<commit-hash> e.g. 0.0.12+479feca
<breaking>: An incrementing number stored in the repository, increased only when breaking changes are introduced.<commit>: The hash of the latest commit in the version.Build pre-releases:
New platform releases should use the newest Roc pre-release
If fixes are required:
A daily CI job tests the entire ecosystem:
roc-lang/examples (hosted on the website)roc-lang/basic-cliroc-lang/basic-webserverlukewilliamboswell/basic-ssg (used to generate the website)roc-lang/unicoderoc-lang/path (WIP)lukewilliamboswell/roc-jsonlukewilliamboswell/roc-parserNote: CI jobs may fail when platforms haven't been upgraded due to breaking changes or bugs. These issues are tracked and linked in the release tracking issue to facilitate coordination.
roc-lang/rocNon-breaking changes
- Target roc-lang/roc/tree/main branch
- No change to <breaking> version
Breaking changes
- Target roc-lang/roc/tree/main branch
- Must increment the <breaking> version
The plan looks good to me! I'm wondering if we might consider moving important crates to the roc-lang organization, like roc-json. It implies a greater level of stability, like packages in the rust-lang-nursery. It does lose the benefit of us figuring out migration for packages outside of the main org.
(deleted)
I'm hoping someone writes a fast json package. :sweat_smile:
My concern with adding more supported packages is just our limited resources. It's already a lot to coordinate when we have a big breaking change, and if we add more things like json and parser etc in then we will feel pressure to do those as well. OTOH they're also super easy to maintain and usually I can do it in a couple hours for all these packages. Similar to elm, there just doesn't seem to be many things that mean they have to be upgraded.
I don't quite follow the weekly tasks and how this all fits together.
My assumption was that the daily CI job would post a new recommended nightly whenever it passes. If it fails, we would have to manually intervene to update the breaking change number and each individual platform. Once all platforms are updated, the CI job will pass again and update the recommended version to the version with the incremented breaking change number.
So by default, no one touches any of this and CI just runs by itself. There would be no weekly work. Just work each time the CI job fails due to a new breaking change entering the pipeline.
Should we cut v0.1.0 this week for the sake of AoC newcomer UX?
My motivation: https://roc.zulipchat.com/#narrow/channel/316715-contributing/topic/Help.20upgrade.2Ftest.20purity.20inference/near/483803483
Well it would be 0.0.1+479feca and not until Monday next week I think ... but yeah I would like to. :smiley:
:loudspeaker: Bumping for consensus :interrobang:
We'll see if there is time, I would like to finish PR#6921 first and I've got a couple of other things I need to do before I can get to that PR.
Assuming we start doing non-nightly perma-releases next week, how about we name one of them v0.0.1-2024aoc1?
That feels a little weird to me, it would make me wonder if this version contains special changes for aoc; "If I'm not using roc for aoc, does that mean I should get a different version?". The commit short sha feels self-evident, at least for those familiar with git.
Ok, new Proposal for Release Management v3 .
I've updated this based on all of our discussion. Please let me know if you have any serious concerns.
This looks really good to me!
When would we want to start implementing this? After snake_case, PNC, and Task removal?
Today I hope
I'm not sure if we need a new build... maybe we can just rename the current one? But it would be helpful to land the breaking changes from that other thread.
Im not sure on our status with th PI upgrades etc. We wanted to update the examples and exercism etc.
Examples are 97% done: https://github.com/search?q=repo%3Aroc-lang%2Fexamples%20Task&type=code
Exercism is done too https://github.com/exercism/roc/pull/171
The proposal looks good @Luke Boswell!
Maybe we should go with 0.0.0 as in 0.0.0-alpha<breaking>+<commit> instead of 0.1.0-alpha<breaking>+<commit>, to not give the impression that a 0.1.0 release is immenent?
Would we still do nightly releases as well, or just update the commit sha on a near daily basis?
I think updating the sha replaces nighties. It is versioned roc.
Just with potentially delayed updating of the recommended version.
Minor proposal change (clarification?), lets make our github releases be for 0.0.0-alpha<breaking>-*.
This will avoid bloating our releases with tons and tons of versions.
Instead, it is one rolling release for each breaking change group.
This is really just about what appears as github headers. Avoids making a release header for every single nightly run.
Nice, didn't know about that
I was debating just trying to implement this outside the roc repo (for testing,
but I thought it would be more valuable to first just write out my thoughts.
This is an expansion on the proposal above to attempt to get concrete on what the github action flow would look like.
Currently alpha12-abc is released.
Roc breaking change number is still 12 as well.
As such, on the roc github releases page there is version alpha12-*.
It is the latest release.
In nightly job, build and test all core platforms with the newest commit to roc.
Also runs all roc repo tests to avoid bugs that sneak into main.
If it passes, replace the binaries in alpha12-* with the newer roc binaries.
So yesterday, alpha12-* had binaries for alpha12-abc, but after a successful job it would have binaries for alpha12-def.
If any tests fail, fail the job, noting that the breaking change number likely needs to be incremented.
If the failure was a flake or a temporary bug, we just leave everything alone.
The next nightly build will grab the bug fixes and successfully update alpha12-*
If the failure was a missed breaking change, we update the breaking change number.
Note, we should increment this number preemptively if we know something is a breaking change.
In some cases, due to breaking changes, roc will move ahead of the core platforms.
For this example, we will say that the platforms are still using alpha12-*, but roc is on alpha13-*
In this setup, we don't get as much testing, but that is ok, alpha13-* is a pre-release and not the recommended release.
To begin with, no platforms even have pre-releases for alpha13-*.
As such, the nightly job for alpha13-* will only be testing the roc repo.
It will be best effort to increment the breaking change number to 14 when a breaking change comes in.
That said, at this stage, with no platform have pre-releases even, it is more likely to accidentally be missed.
As platforms get pre-released, we will add the pre-release url to the nightly job (not sure if this can be automatic, but a small PR after core platform pre-release would be fine).
The job will pass and fail the same way as the base release flow, just with less platforms.
Once all core platforms have a prerelease that is passing with on alpha13-*, we will manually trigger a promotion actions to promote alpha13-* to the latest release and promote all platform pre-releases as well.
This step is manually triggered (we also would make sure any docs are updated as needed before triggering this).
This will do one final check using the published binaries in alpha13-* against the pre-releases to make sure everything is good.
Note: I assume this job may start as manual work before we iron things out.
The recommend release may fall multiple breaking change versions behind the latest pre-release. Recommended alpha12-*. Platform pre-releases alpha13-*. Current roc main alpha14-*. This is fine. This is part of the reason why promotion is manually triggered. We likely will next trigger a promotion to alpha13-* even though alpha14-* is already pre-released.
Looks good!
One issue that I'm not sure how we can get around:
The reason that there is a manual step to the nightly process right now is because our GITHUB_TOKEN can be compromised. This is because we use self-hosted CI runners. The GITHUB_TOKEN is now set to read only.
Automatically uploading releases would need (at least limited) write access for CI.
If we need to make it just do the tests and separately have someone run a script to actually push the update, that is ok...just not as nice
I'd like to keep the current (old) nightly available and was thinking about publishing that one as 0.0.0-alpha1-* and then current TESTING as 0.0.0-alpha2-*, while also turning current nightly-TESTING into nightly-latest. So an incremental change to the new release management without any automation for now. Thoughts?
Are you thinking of throwing away releases? I thought the idea was that platforms can upgrade at their own pace. So if there's an issue with a release, we just bump the breaking number and make another.
If we throw the releases away then that breaks anyone uses an older version. Or is it just we keep one release per breaking number?
One thing I really wish is that roc-lang owned platforms had their versions somehow harmonized with the compiler version they are compatible with
Are you thinking of throwing away releases?
No I want to do the opposite :big_smile: , make the old nightly available under 0.0.0-alpha1-* and the new one under 0.0.0-alpha2-* and keep those around forever
One thing I really wish is that roc-lang owned platforms had their versions somehow harmonized with the compiler version they are compatible with
Yeah, I think we already agreed on the feature of putting the version in the main roc file of a platform or app, so the supported version is clear.
Sounds good. Why do we need the TESTING thing though? Let's just bump the breaking number if we want it to be clearly a new one.
We can do away with TESTING after today assuming the release goes right
This is awesome @Anton. I think it will be really useful to start enabling this new flow even if though manual version and best effort version bumping. My time dried up after the holidays and I have not been able to look into anything automated for this
Last updated: Jun 16 2026 at 16:19 UTC