intuit / auto

Generate releases based on semantic version labels on pull requests.
https://intuit.github.io/auto/
MIT License
2.28k stars 204 forks source link

[Q or Feature Request] Need to bump version separately from `shipit` - currently get double bump #2399

Open rosskevin opened 1 year ago

rosskevin commented 1 year ago

Is your feature request related to a problem? Please describe.

It is a problem for me, perhaps I am missing something or perhaps this is a feature request.

I have been integrating auto into multiple libraries, both simple and monorepos and it has worked well with only minor setup. Now I'm trying to bring auto to a full stack CI process, and I am seeing a limitation.

In our full stack application monorepo, we build multiple images, integration test, release sourcemaps to sentry, etc in our CI process to determine if a release candidate is certified to be released. The version value is statically built into the docker images/codebase for traceability e.g. APP_VERSION: 3.1.0. Therefore, we must bump the version prior to build and shipit.

We perform the upfront bump with KIND=auto version and the result fed into lerna version $KIND so that auto's logic controls the semver bump. But, when shipit runs, it bumps again, resulting in a double bump. So what should be 3.0.18->3.1.0 ends up being 3.0.18->3.2.0.

Describe the solution you'd like

shipit --skip-version-bump

We want to run the typical shipit, but simply with a flag to omit the bump version process.

Describe alternatives you've considered

We must have the deterministic version statically upfront, so I'm not sure we have other options other than to revert to our homegrown release management.

Additional context

It may be important to know that in this use case, auto version up front is limited in value (versus shipit) and returns major/minor/patch etc, but if you want to release this code as a canary/next, auto version is insufficient in this two-phase scenario. That's not necessarily a problem in our case, because it is simply a go/no-go deployment to a production stack. BUT, if someone wants to use this two-phase system, they may want a full version resolution upfront e.g. instead of minor they may want 3.1.0-canary-tnoed283. This may mean that another command would be useful such as auto version --fully-resolved

I hope I'm simply missing a flag and that a two-part/separate bump+ship process is achievable as-is.

laughedelic commented 1 year ago

I think this is more or less the same ask as in https://github.com/intuit/auto/discussions/1965

rosskevin commented 1 year ago

Thanks @laughedelic, it looks like auto shipit --dry-run --quiet can resolve the deterministic version, so the only question would be how to get shipit to allow the arg version to be specified instead of resolved.

It is a similar issue in that I don't want to replicate logic to call latest(), canary() etc. As-is if I called latest it would still double bump (that's what it is doing behind the scenes).

hipstersmoothie commented 1 year ago

I'm definitely open to the arg being added to shipit. Makes sense to me. That logic might break down for indepenently versioned monorepos but a lot of other stuff does too. Happy to accept a PR here.

rosskevin commented 1 year ago

It looks like publishFullRelease() already accepts {useVersion} to override, but that is not used for canary|next functions. I'm still familiarizing myself with the code but it may be as simple as exposing that for latest().

rosskevin commented 1 year ago

It looks like (from auto.ts) that shipit, release and latest() allow --use-version as an option, though I think the behavior is not necessarily well defined as it is only included in the docs for release (I'm still perusing). Since shipit may call canary|next|latest|oldRelease() it might be important to clarify. It seems to me the right way to implement it is to document it, and expose it in each of the public commands. Does this sound like a reasonable implementation path @hipstersmoothie?

  {
    name: "shipit",
    group: "Release Commands",
    description: endent`
      Context aware publishing.

      1. call from base branch -> latest version released (LATEST)
      2. call from prerelease branch -> prerelease version released (NEXT)
      3. call from PR in CI -> canary version released (CANARY)
      4. call locally when not on base/prerelease branch -> canary version released (CANARY)
    `,
    examples: ["{green $} auto shipit"],
    options: [
      ...latestCommandArgs,
      {
        ...useVersion,
        description: `${useVersion.description} Currently only supported for the **npm plugin**.`,
      },

Implement useVersion for:

rosskevin commented 1 year ago

useVersion || bump (effectively) is in a lot of places. I suggest in the implementation this gets resolved early in each of the public interfaces and is taken as-is, instead of this-or-that in many places.

One of many:

      await this.hooks.publish.promise({
        bump,
        useVersion: options.useVersion,
      });

Why not resolve this once as bump and ignore useVersion beyond the public interface? I suggest consolidated resolution of the deterministic bump should be had at the public interface and propagated as resolved to the plugins (not as two options).

Answer: it appears bump is a kind like patch whereas useVersion is an actual version override.

rosskevin commented 1 year ago

Ok, so while this is not documented for shipit, --use-version does exist.

It appears that I can get satisfactory results as-is (npm plugin) with:

  1. Determine what shipit would use beforehand with yarn auto shipit --dry-run --quiet
  2. Instruct shipit to use a specific version yarn auto shipit --use-version 20.0.0

I'll try this path and see how it goes.

rosskevin commented 1 year ago

So I did get this to work with the existing code, though it is a bit of a workaround.

Here is how it worked:

First, get the shipit version and bump it with lerna:

      # start release here so that builds uses the correct version
      - run: yarn autoBumpVersion --verbose
      - run: ./node_modules/.bin/appVersion --verbose
      - run: yarn auto info

NOTE: autoBumpVersion is our own encapsulation of capturing version from auto shipit --dry-run --quiet output and using that as input to lerna version <version> --yes --no-git-tag-version --no-push

NOTE 2: appVersion is our own script to grab the version from lerna.json (in production conditions, it does other things in dev)

Second, do my intermediate things like build apps/tag images, etc.

Third, manipulate some conditions and shipit:

      - run:
          name: shipit
          # 1. Capture the bumped version
          # 2. Stash the lerna.json to allow shipit to modify/commit it (so that git commit inside shipit succeeds without erroring on zero changes)
          # 3. Commit the rest of the previously bumped changes
          # 4. Shipit
          command: |
            export USE_VERSION=`./node_modules/.bin/appVersion`
            git stash push lerna.json
            yarn autoCommitDiff --verbose
            yarn auto shipit --use-version $USE_VERSION

NOTE: autoCommitDiff is our own script that just does some logging and commits diffs from version bump changes in the very first part of the multi-stage build.

So, the only oddity here is that I have to specifically stash a file (any file that will get modified) so that shipit's execution of git commit doesn't report non-zero and fail.

So, this issue could be closed, I'm satisfied enough to move on, or it could be left open knowing that it could be perhaps better specified/documented. It's up to the maintainers to decide.

hipstersmoothie commented 8 months ago

@rosskevin if there is anywhere you think we could improve the docs here I'm happy to accept a PR