Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Idea: detect next SemVer automatically by categories #902

Closed
ccremer opened this issue Sep 25, 2022 · 7 comments
Closed

Idea: detect next SemVer automatically by categories #902

ccremer opened this issue Sep 25, 2022 · 7 comments
Assignees

Comments

@ccremer
Copy link
Contributor

ccremer commented Sep 25, 2022

Context

I'm now well accustomed to categorizing PRs into Features, Bugfixes or documentation when authoring them. For example:
PRs labelled as "bugfix" or "dependency" always get a Patch release version increment (e.g. v1.2.3 to v1.2.4).
PRs labelled as "feature" always get a Minor release version increment (e.g. v1.2.3 to v1.3.0).
PRs labelled as "breaking" get a Major release version increment (v1.2.3 to v2.0.0).

Problem

After merging a bunch of them, when creating a new release, I have to manually go over the merged PRs to figure out the next version according to SemVer and make an accordingly git tag. The category with the "highest increment policy" wins if even 1 PR is in there. For example, there could be 100 bugfixes since the last release version and it would be just a new Patch release, but if even 1 feature PR is in the list, then SemVer dictates a Minor release.

Solution idea

What if this action can actually figure out the next release version by itself? All the information is there.

  • Each category gets an additional property in the configuration, I call it "incrementPolicy", which takes values as "patch", "minor", "major" (maybe "prerelease" but let's keep simple for this discussion)
  • If toTag is empty (or some other property saying "figure it out by PR labels"), then the action determines the next release version after categorizing the PRs.
  • Save the next version increment in the action output, so it can be used later on in the GH workflow. For example, a subsequent step would make a git tag and push it, and then others would continue with building & releasing artifacts, docker images etc. Such a workflow would then rather be triggered by on: workflow_dispatch, e.g. through GitHub browser or through other means than pushing a git tag.

Alternative

I have started to create my own action (https://github.com/ccremer/auto-detect-semver-action/tree/initial) inspired by yours, even sharing the same configuration.json with the added increment policy. But when I realized I could almost use the same code (get the PRs, categorize them, etc) as this action, I started to import that in the package.json.
Eventually I thought to discuss it here, whether it would make sense to add this functionality to this action. Technically this would avoid fetching and categorizing PRs twice in the same workflow. I would be willing to fork and contribute such a feature if you'd accept it.

Footnotes

  • I'm aware this action also supports categorization by commits, I guess all the problem description applies here as well.
  • We should also somehow support prereleases, e.g. if incrementPrelease is true then the action would, if fromTag contains a prerelease like v1.2.0-rc1, increment to v1.2.0-rc2
  • In case there is no initial version, choose 0.1.0.
@mikepenz
Copy link
Owner

Good day @ccremer
Thank you very much for the very detailed description on this proposal.

You are absolutely right that the action practically already has all the information to make such a decisions.


Right now the action was kept very specifically on the task of creating changelogs, excluding functionality like creating a release for example. These decisions were made to keep the action easier maintainable and there are already a ton of great actions out there doing these things.

Looking briefly into your source it looks that most of it seems to be handled by the SemVer plugin, but I am not sure how well that will hold up for more complex situations like pre-releases as you described?


So I was thinking on alternative ideas, but they also have downsides. For example this action could return the categories it collected and a step afterwards could parse this information to detect the next release version.

The major downside is that the TO_TAG placeholder would not be replaceable by the action itself.

This could allow to create the action deciding on the next version very precisely for that usecase (so it could even be used beyond that in other usecases) - while still keeping the changelog-builder focused on building the changelog.

@mikepenz mikepenz self-assigned this Sep 30, 2022
@ccremer
Copy link
Contributor Author

ccremer commented Sep 30, 2022

Hi.
I agree that releasing things should be out of scope of this action.
Determine the next semver is maybe not directly involved in this, but borderline already.

The alternative idea to put the categories into the output sounds okay to me. Technically, at least for the figuring out the next SemVer, it should be sufficient to have only a count of PRs for each category, But maybe it's better to put more meta information into it.
It probably makes sense to output this as JSON.

The major downside is that the TO_TAG placeholder would not be replaceable by the action itself.

Hm, yes. Not sure about dealing with that.
A very wild idea would be to introduce an optional 2-step process of changelog building:

  • First, fetch the PRs and categorize them, put them into the output.
  • Then, another step in the workflow would figure out the tag.
  • Invoke changelog builder again, with the output from first step as the input for the 2nd invocation to actually build the changelog (so the 2nd invocation doesn't need to fetch PRs again). It would also get the tag as an input from the 2nd step.
    But maybe this is as broken as it sounds 🙈

It's probably enough to put a special placeholder into the TO_TAG placeholder, so it can be replaced in the changelog by another step (sed or similar) before actually using the changelog in a releasing step.

@mikepenz
Copy link
Owner

@ccremer having this orchestration acts like an add-on, which I think is from a maintenance perspective I believe the cleanest solution.

It would actually be interesting to invoke an action as part of an action, like plugins but I fear that this would be too risky from a security perspective and very hard to control.


Returning as a json sounds more clever than "just" a comma separated list of which categories have been found.
There may be some limitations on the data to be returned by an action but I think we are not yet at this limitation.

For the placeholder, I think it's possibly edge-case enough whereas a sed or other string replacement should handle it. executing the changelog builder multiple times is not really advised as you may run into API quota limitations, also it just costs time :D

@ccremer
Copy link
Contributor Author

ccremer commented Sep 30, 2022

Yes I agree with the add-on bit.
But a plugin system is surely also quite a bit to maintain and probably should also be out of scope of this action.

There may be some limitations on the data to be returned by an action but I think we are not yet at this limitation.

I think we don't need to put in PRs with the full metadata, maybe just selected properties like ID, PR number. Maybe labels and author, but that's about it. It's enough so that a follow-up action /add-on can invoke the API again if needed. For figuring out the next semver as an add-on though, they're not required.

If we consider the next-semver-detecting as an add-on as "agreed upon", how should we continue here?
The add-on would somewhat depend on the changelog-builder since the JSON output is its input.
Is this something that you'd be willing to maintain in your GH space on your own, or should I start with an initial implementation and transfer/sponsor the action to you? Or should I completely maintain this under my name? Other ideas?

(I might not be as fast as I'd like, since I'm still just learning TypeScript atm.)

@sconix
Copy link

sconix commented Oct 5, 2022

We are kind of doing this already with the help of couple simple actions/steps:

- name: Determine the release type
        id: release-type
        uses: haya14busa/action-cond@v1.1.0
        with:
          cond: ${{ contains(steps.release-notes.outputs.changelog, '## 🚀 Features') }}
          if_true: minor
          if_false: patch

- name: Generate the release version
        id: release-version
        uses: actions-ecosystem/action-bump-semver@v1.0.0
        with:
          level: ${{ steps.release-type.outputs.value }}
          current_version: ${{ steps.current-version.outputs.value }}

This works nicely when there are only 2 levels i.e. minor / patch that you want to automate, but if you want major as well it would need another step or at least could not find nice 'switch/case' type of action with multiple conditions.

@mikepenz
Copy link
Owner

mikepenz commented Jun 4, 2023

I believe with: #1132 landing, we can close this as complete?

@mikepenz
Copy link
Owner

mikepenz commented Jun 4, 2023

Available in v4 (v4.0.0-b01)

@mikepenz mikepenz closed this as completed Jun 4, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

3 participants