PaulHatch / semantic-version

A GitHub Action to generate semantic version from a git repository's commit history.
MIT License
347 stars 63 forks source link

Incorrect version detected #106

Closed hoopty closed 1 year ago

hoopty commented 1 year ago

Hello -

It seems the latest version to use is not properly detected, it may be related that we had some releases with the v prefix and others without. Unfortunately this is a private repo so I can't give you access, but I'd be happy to run your node app against my local repo with debug flags or the like to help diagnose. I'm expecting my version to be v3.0.7-prerelease??? but it is coming up with v3.0.1-prerelease???. Hope this gets you the relevant info...

Here's the pipeline snippet:

    steps:
      - name: Checkout
        uses: actions/checkout@v3
        with:
          fetch-depth: 0      

        # https://github.com/PaulHatch/semantic-version
      - name: Version
        id: version
        uses: paulhatch/semantic-version@v5.0.3
        with:
          version_format: "${major}.${minor}.${patch}-prerelease${increment}"
          search_commit_body: true

Here's the pipeline output:

Screen Shot 2023-05-02 at 16 58 48 PM

Here's the GH releases (from GH cli):

v3.0.7   Latest  v3.0.7    about 22 days ago
3.0.6            v3.0.6    about 1 month ago
3.0.5            v3.0.5    about 2 months ago
3.0.4            v3.0.4    about 2 months ago
v3.0.3           v3.0.3    about 3 months ago
v3.0.2           v3.0.2    about 3 months ago
v3.0.1           v3.0.1    about 5 months ago
3.0.0            v3.0.0    about 7 months ago
2.0.31           2.0.31    about 7 months ago
2.0.30           v2.0.30   about 8 months ago

Here's the start and end of the tags (from git tag):

1.0.51
2.0.10
2.0.13
2.0.14
2.0.2
2.0.2-beta-2
2.0.3
2.0.31
2.0.4-beta
2.0.4-beta-2
v1
v1.0.1
... (remove interim vX.Y.Z* tags)
v2.05-beta
v2.06-beta
v2.07
v3.0.0
v3.0.1
v3.0.2
v3.0.3
v3.0.4
v3.0.5
v3.0.6
v3.0.7
hoopty commented 1 year ago

@PaulHatch any ideas here, just trying to see if I am missing something or this looks like an issue.

Thanks for the action, I think it will meet our needs nicely (if I can get this figured out).

PaulHatch commented 1 year ago

Hey @hoopty, sorry, I've been traveling the past few weeks and didn't see this initially.

While it's possible there's an issue here, this is a pretty core function and is pretty well tested, so my guess would be that either you've found an edge case or there's something else going on with the repo. From what you've shared it looks to me like you should be seeing version 3.0.7 as the previous release, and 3.0.8 as the next release.

The first thing that's going to happen here is the DefaultLastVersionResolver is going to run, if the current commit is not tagged, this command will run:

git for-each-ref --sort=-v:*refname --format=%(refname:short) --merged=${current} ${refPrefixPattern}${releasePattern}

Render in your example as:

git for-each-ref --sort=-v:*refname --format=%(refname:short) --merged=HEAD refs/tags/v*[0-9].*[0-9].*[0-9]

(You may need to drop the = and wrap the argument in quotes, depending on your terminal)

So the first thing I'd do is check that this command is also returning the tag you expect from the commit being built. Notice the --sort=-v:*refname, which means that the highest tag, sorted using refname, so regardless of date/commit order you should see the tags sorted by version. The first tag you see in your example should be v3.0.7. I'd run this from the workflow itself to make sure you're comparing apples to apples.

hoopty commented 1 year ago

Thanks Paul, that that is very good insight. I suspect a couple of things may be in play here: 1) Our default branch has changed since the tags were put in place 2) It looks like the tags may have been made on branches that were not the default branch at the time (I'll dig to confirm this next week).

Question for you, is there any chance the action can be configured to optionally treat tags as releases regardless of the branch they were on at the time?

You can see below that it looks as expected if I leave off the --merged=HEAD filter:

$git for-each-ref --sort=-v:*refname --format='%(refname:short)' --merged=HEAD 'refs/tags/v*[0-9].*[0-9].*[0-9]' | head -n 5
v3.0.0
v2.0.30
v2.0.29
v2.0.28
v2.0.27

$git for-each-ref --sort=-v:*refname --format='%(refname:short)' 'refs/tags/v*[0-9].*[0-9].*[0-9]' | head -n 5
v3.0.7
v3.0.6
v3.0.5
v3.0.4
v3.0.3
PaulHatch commented 1 year ago

The action doesn't actually know anything about releases, as those exist in GitHub itself and this action as of now is only looking at the git repo.

Branches and tags are both pointers to commits, so regardless of the change in branch the commit history (and tags) should be the same. For tag-based versioning branches aren't consider branches at all. It looks like you have some additional change and the new branch has a different commit history which does not include these tags. Regardless you can fix this in three ways:

hoopty commented 1 year ago

Apologies, I should not have use word release since it has a meaning in GitHub. Can I configure the plugin to treat each tag as a version that we have made available (in our case we have made GH release for that commit) so the plugin would then start recommending a subsequent version.

For your suggestions, we don't want to alter the git repo itself as the tags are on the desired commits. For #2, we just recently added the v3.0.7 tag and even after that it behaved the same way (recommending a v3.0.1-prereleaseXXX version, even though v3.0.8-prereleaseXXX would be desired).

Is there an (optional) way to configure the action to look at all version tags (and not just ones found with --merged=HEAD)?

PaulHatch commented 1 year ago

There is not, this would cause a number of problems. The key role of locating the previous version is to subsequently produce a list of commits since the last release. These commits are inspected to determine the type of versions change and the number of commits determines the increment number. If that version is on some random branch that isn't merged into the current position then it is impossible to get that list of commits.