Skip to content
This repository has been archived by the owner on Nov 4, 2024. It is now read-only.

Support prereleases #292

Closed
fmal opened this issue Apr 4, 2021 · 13 comments · Fixed by #379
Closed

Support prereleases #292

fmal opened this issue Apr 4, 2021 · 13 comments · Fixed by #379
Assignees
Labels
enhancement New feature or request
Milestone

Comments

@fmal
Copy link
Contributor

fmal commented Apr 4, 2021

I'm so glad i found this - finally a nice release management tool that is designed to be compatible with yarn berry. Finally a chance to say goodbye to lerna and stop relying on some ugly patches 😄
Thanks for open-sourcing this.
I'm very hyped for this project and i think it will soon gain some deserved recognition.

What i'm really missing at this point is support for pre-releasing packages.

I have main and next branches. next is a default branch and any commits merged there trigger a pre-release, something like lerna version --conventional-commits --conventional-prerelease --no-changelog --preid=next.
Prereleases would be tagged as <pkg>@x.x.x-next.x and published to NPM with next distribution tag (#223).
I don't want to generate changelog for preleaseses and spam the repository with release commit messages, so i would skip --persist-versions in that case.

When the state of the next branch is ready to become a production release, I merge next branch into main. This would trigger a standard workflow: create tag, write changelog, bump packages, commit, publish to NPM as latest, publish github releases. Basically what this tool does out of the box and equivalent of lerna version --conventional-commits --conventional-graduate --create-release github.

monodeploy is already very useful and i started migrating some minor project, but If you could add support for mentioned scenario, this would be my tool of choice for releasing every monorepo 🚀

@noahnu
Copy link
Contributor

noahnu commented Apr 4, 2021

I think this is a great idea. I need to read up some more on how lerna handles preleases, specifically how does a version bump work? (Exact flow)

We currently grab the latest dist tag from npm and do a semver.increment on it depending on the version strategy from conventional changelog.

I wonder if semver supports pre-release increments. Otherwise we can always do something custom.

I'll investigate this this week, but might only make substantial progress next weekend.


We're actually still not using v2 internally (except for a couple open source projects) as we're still in the process of migrating a yarn v1 monorepo to yarn v2 (a lot of annoying dependency issues), but we're hoping to complete that migration in the next month or so. Only reason I mention that, is since dogfooding will give us an opportunity to fine tune performance and stability of this project. Feedback is definitely welcome, and we're glad you like it.

@fmal
Copy link
Contributor Author

fmal commented Apr 4, 2021

Awesome, thanks for your fast reply!

Yes, i believe semver does support them.

Here are direct links to lerna and standard-version flows for getting a version bump with semver.inc highlighted
https://github.com/lerna/lerna/blob/2d0a97aade2b17cb58ce8c0afdbfd950033f46db/core/conventional-commits/lib/recommend-version.js#L65
https://github.com/conventional-changelog/standard-version/blob/master/lib/lifecycles/bump.js#L30

https://github.com/npm/node-semver#prerelease-identifiers

Hope that it's at least some starting point to port that into monodeploy

Regarding the version strategies:

const implicitVersionStrategies = await getImplicitVersionStrategies(
Does that mean that if i make a commit with changes in the scope of pkgA and pkgB is relying on it via workspace:* protocol, monodeploy would figure out pkgB requires a minor bump as well? That's wonderful 👍

Been through migrating a big repo to yarn 2, so i see, but it's a rewarding effort in terms of pkg maintenence, speed on CI etc. The only missing piece for me was a tool to auto release packages working seemlessly with yarn workspaces and here comes monodeploy 👍

@noahnu
Copy link
Contributor

noahnu commented Apr 4, 2021

Unless it explicitly has a commit that would indicate a minor bump, dependents always get patch bumps. This was lerna behaviour as well I believe.

Monodeploy processes each commit separately, so we actually support batching version bumps to some degree (a minor bump to pkg1 and a major bump to pkg2), which I think lerna doesn't support.

@fmal
Copy link
Contributor Author

fmal commented Apr 4, 2021

Yes, what i actually meant was a patch, not a minor bump for dependents. Thanks a lot for the clarification, sounds perfect - will give it a try 😄

@noahnu noahnu added the enhancement New feature or request label Apr 5, 2021
@noahnu noahnu self-assigned this May 19, 2021
@noahnu
Copy link
Contributor

noahnu commented May 19, 2021

Action Plan for Implementing Prereleases

  • Add config option for: prereleaseId (the suffix such as "next" or "rc") and npmDistTag (default to "latest").
  • Update the "fetch tags" logic to support fetching arbitrary dist-tags and for parsing versions with suffixes
  • Update publish logic to use npmDistTag rather than hardcoded "latest"

I don't believe anything special has to be done around graduating a pre-release tag. I think you'd just merge "next" into "main" and ensure npmDistTag -> latest, and prereleaseId is not set.

I imagine we'd also treat breaking changes as "minor" updates for prereleases when going from a prerelease to a prerelease. So the first prelease is a major bump, and subsequent prereleases are only minor at most.

@noahnu noahnu added this to the Lerna Parity milestone May 20, 2021
@fmal
Copy link
Contributor Author

fmal commented May 21, 2021

@noahnu sounds perfect, agree with your thinking.

I would expect that the X in the major.minor.patch-preid.X version is incremented,
so when the latest tag is 1.0.0 and on a next branch you do a commit of type fix the prerelease would be 1.0.1-preid.0 and for subsequent commits of the same type only X index would be incremented.
Then when you do a feat commit the index would reset and the version would be 1.1.0-preid.0 and so on.

Regarding the configuration: would one trigger a prerelease by running monodeploy --prerelease or some similar arg, or by pointing to a prerelease branch in the config?

Big thanks for taking time to address this!

@noahnu
Copy link
Contributor

noahnu commented Jul 4, 2021

Re-opening until the new pre-release functionality is actually released. It should work on the master branch right now, but I'd like to do some more testing as well as write up better documentation around it. It'll be ready for use (and released) before the end of this week, as we'll be relying on the pre-release functionality internally.

@noahnu noahnu reopened this Jul 4, 2021
@noahnu
Copy link
Contributor

noahnu commented Jul 7, 2021

We did a prerelease in this repo for some dogfooding. The e2e test covers a complete scenario.

Internally we'll be actively using pre-release in the next couple weeks and will identify and fix any bugs as they come up, though overall I'm feeling confident in the implementation. Will close out this issue.

Note that documentation can still be improved.

@noahnu noahnu closed this as completed Jul 7, 2021
@fmal
Copy link
Contributor Author

fmal commented Jul 9, 2021

@noahnu I'ill be testing the new functionality over the weekend, will post any feedback here. What a great project! 😀

@fmal
Copy link
Contributor Author

fmal commented Jul 13, 2021

@noahnu i tried it on a company monorepo and after some config tweaking everything works as expected!

Couple of observations:

  • I really liked that you can use "unofficial" lifecycle hooks such as postpublish in addition to prepack for example. This was useful in one of the packages where i wanted to do the site deployment only after bumping package version. Too bad they're not documented.

  • i tried to disable creating tags for prereleases but then realised this is wrong because version strategy is determined based on git tags and then the package tags from the registry are bumped accordingly. Is there any use case where one would want to disable creating tags?

    git: {
      push: true,
      tags: false
    }
    
  • i have noticed that the tags are applied to the commit before the release commit (created when auto-commit is true). The release commit can contain changed package.json files in multiple workspaces.

    Screenshot 2021-07-13 at 14 16 41

    Now when you do a commit that is fixing a bug in particular workspace, you would expect only the changed workspace with the bug fix to be published. However because of the release commit appearing after the tag containing changes in multiple workspaces, several packages get republished.

  • when in prerelese mode the previousVersion in changelog and changeset is using latest tag purposefully? I guess you always want to compare prerelease with the latest "stable" release in changelog.
    It got me a little confused when i saw this in the log when doing a prerelease:
    Screenshot 2021-07-13 at 14 32 39
    I expected the message to be something like 1.3.0-next.5 -> 1.3.0-next.6 because that's the actual bump happening in package.json. What do you think about correcting the console message to use currentPrereleaseVersion instead of currentLatestVersion in prerelease mode?

@noahnu
Copy link
Contributor

noahnu commented Jul 13, 2021

Thanks for the feedback. I'll loop back to this today to answer / propose next steps.

@noahnu
Copy link
Contributor

noahnu commented Jul 13, 2021

I really liked that you can use "unofficial" lifecycle hooks such as postpublish in addition to prepack for example. This was useful in one of the packages where i wanted to do the site deployment only after bumping package version. Too bad they're not documented.

They're official hooks, documented here: https://docs.npmjs.com/cli/v7/using-npm/scripts#life-cycle-scripts. We can definitely have our own documentation in the monodeploy project though with a diagram of the complete lifecycle. Created: #401

i tried to disable creating tags for prereleases but then realised this is wrong because version strategy is determined based on git tags and then the package tags from the registry are bumped accordingly. Is there any use case where one would want to disable creating tags?

Internally we disable tag creation for a sort of "test publish" where we publish to a test registry. It's almost like a dry run, but it actually publishes to the registry. I suppose alternatively, we could just not commit/push.

i have noticed that the tags are applied to the commit before the release commit (created when auto-commit is true). The release commit can contain changed package.json files in multiple workspaces.

I'm assuming your conventional changelog config treats "chore" as a patch? We don't encounter this internally since we treat "chore" as a no-op and so it's filtered out by the diff detection anyway. The current flow ensures the release tags are on the commit with the actual feature change / bug fix. I can see wanting to attach the tags to the "release" though so it's on the same commit as what modifies the package.jsons. This should be fairly easy to do and I'm not too attached to the current workflow. Can you create a feature request/bug report for this one?

when in prerelese mode the previousVersion in changelog and changeset is using latest tag purposefully? I guess you always want to compare prerelease with the latest "stable" release in changelog.

That's a bug and is because of this line:

tag: 'latest',
. I missed this when implementing pre-release -- it's a remnant of an earlier refactor. You can't just change it from "latest" to the npm dist tag though, because for a first prerelease, you do want to use "latest". We'll need to expose the information which we have in the applyReleases stage. Can you extract this issue into a separate bug report?

@fmal
Copy link
Contributor Author

fmal commented Jul 13, 2021

Thanks for the clarifications, very appreciated 👍

By "unofficial" i meant i couldn't find it in Yarn berry docs, but great that NPM docs cover it.

You're right about conventional changelog config treating chore as a patch: https://github.com/conventional-changelog/conventional-changelog/blob/master/packages/conventional-changelog-conventionalcommits/conventional-recommended-bump.js#L11 (it uses patch by default)

Sure, will open 2 issues then!

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
enhancement New feature or request
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants