Skip to content

Workflow updates & release improvements #465

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

Open
wants to merge 9 commits into
base: master
Choose a base branch
from

Conversation

TheMrCam
Copy link
Collaborator

@TheMrCam TheMrCam commented May 21, 2025

Overview

This PR focuses on updating the GitHub Actions stack and improving the usability of CI and GitHub releases.

I'm happy to make any further changes, just figured a PR with an example diff was a better starting point for discussion than without.

Details

ci.yml & docs.yml

I didn't do much to these workflows, just updated the action and Node.js versions to latest.

release.yml

I focused my efforts in this PR on release.yml, specifically on generating release notes.

First, I updated all the action versions like above. While doing so, I learned that actions/create-release was deprecated in March 2021. They suggest a few alternatives, including softprops/action-gh-release, which is used by PDAL so I figured it's a safe bet.

Once I had that new release action working1, I decided I wasn't happy with the default generate_release_notes: true release notes. Based on this suggestion, I introduced mikepenz/release-changelog-builder-action which does a better job of detecting the "previous release." The new changelog generation is configured via the new .github/changelog.json, and I've already added a few labels to this repository to categorize changes for the next release.

The following summary describes the release note categories and their associated tags:

Category Labels Notes
Breaking breaking Implies major release
Features feature, enhancement Implies minor release
Fixes fix, bugfix Implies patch release
Documentation docs, documentation
Infrastructure dependencies, maintenance, ci
Uncategorized Includes all un-tagged PRs
Ignored ignore, ci-ignore Does not appear in release notes

I also made a few decisions about the GitHub releases here that we can alter or revert if desired:

  • Includes tarball from npm pack
  • Includes link to npm for version
  • Does prerelease if version contains - (implying npm version pre*)
    • Prerelease changelog compares to last (pre)release, full release changelog compares to last full release
  • Largely uses default mikepenz/release-changelog-builder-action configuration, but did tweak the categories and pr_template

version.yml

This is an entirely new workflow for this repository (and for myself). I had the idea of triggering everything at the click of a button, including the npm version <> and git push origin <> steps, and this workflow (plus release.yml) is my result.

The idea here is that, from the repository page, we can go Actions > Push new version > patch and GitHub will handle the rest for us. version.yml just runs npm version [major | minor | patch | premajor | preminor | prepatch | prerelease] (from a dropdown choice), then pushes the changes back to the branch and the created tag to the repo. The fun part is, through a PAT VERSION_TOKEN, that tag push will automatically trigger release.yml.

I'm not entirely certain if this workflow is needed or wanted here, and no worries if we want it removed from this PR. I mostly just dislike manually doing git push && git push origin vX.Y.Z and put this together as a solution for myself.

I made a few decisions here as well that I want to call out:

  • preId is required if version starts with "pre"
  • preId is 'beta' (if version starts with "pre")
    • This isn't true with npm, but I personally prefer it this way. Can easily change things up if we want to allow e.g. 2.2.0-0
  • Uses ${{ github.actor }} as commit user and ${{ github.actor }}@users.noreply.github.com as email
    • These field are required for npm version, but I'm sure we could use something else (like dependabot?)

TODO

The following needs to be completed for version.yml to function correctly:

  • Add secrets.VERSION_TOKEN secret PAT with contents: write permission to repository
    • or decide we don't want version.yml

Process

These changes and ideas are based on a toy repository I setup to figure out how I'd want to do this. As such, I'd be glad to discuss additions, revisions, or any other issues with these workflows.

My process based on these workflows went along the lines of:

  1. Categorically label PRs
  2. Merge desired changes for release
    • Assuming ci.yml passed on all PRs, ci.yml should pass on master
  3. Trigger update Actions > Push new version > patch
  4. Wait for release.yml to publish to npm and release to GitHub

I admit my repository was a very minimal reproduction example meant to test a simplified equivalent to geotiff.js's build process, and I did ignore docs generation (so we'll want to watch it closely for breakages).

The version.yml push does also re-trigger ci.yml, which may be undesirable since it's much more intensive here than my test example. Theoretically, bumping the package.json version shouldn't suddenly change the result of ci.yml, so we may want to check for this.

Other options

I'm sure there's millions of ways we could configure CI for this package, and I'm willing to explore other options and ideas.

For one, I have a workflow for personal repositories that recognizes -alpha. tags and publishes to npm using --tag alpha rather than the default latest. I almost added that feature here, but I'm uncertain if that has any benefit to this package (based on previous publishings, at least).

Additionally, I've had some ideas about something like holding off on the actual npm publish until the draft GitHub release is published as a true release. I didn't attempt that yet as I'm still gaining an understanding of GitHub releases and CI, but would be willing to try putting something like that together if it's desirable.

Footnotes

  1. For those curious: my testing

TheMrCam added 4 commits May 20, 2025 23:03
Updated the versions of the used actions (where I noticed possible).
Also replaced actions/create-release with softprops/action-gh-release
because the former was archived in 2021.

Based on a single suggestion I saw somewhere online, it's best to
--ignore-scripts with npm ci. So I did that here too.
I wasn't extremely happy with the default github-generated release
notes, specifically the changelog tag detection, so I used the
suggestions I found in the softprops repo: mikepenz's
release-changelog-builder-action.

Added .github/changelog.json to customize the labels, categories, and
output templates for the release notes.

For it to work how I'd like, I had to manually construct the compare
link from the action's detected tags and manually construct the NPM
package url.

Also had to add a manual npm pack step in order to provide the .tgz in
the GitHub release assets, but that can be removed if desired.
Added a new workflow file: version.yml. This workflow simply runs npm
version with the desired values and pushes the commit and tag back to
the repository. Along with release.yml, this functionally creates
on-demand npm and github releases from the click of a button.

This workflow requires a PAT in-place of the GITHUB_TOKEN, as the
workflow default GITHUB_TOKEN will **not** trigger GitHub Actions.
Whoops, forgot to add back the pull-request: read permissions while
trying to keep a clean history and diff.

And I accidentally left a comment that I didn't mean to. Also decided
to change the "Push version" action to "Push new version".
@TheMrCam TheMrCam added the ci Related to workflows & actions label May 21, 2025
@constantinius
Copy link
Member

Thanks @TheMrCam for taking the time and setting this up for discussion.

Regarding realease.yml: I like all the changes! We could tone it down a notch with the emoji use, but even that is no blocker ;)

I also like the manual version thingy. To me it sounds useful, only concerns are permissions (who is able to press that button in the end). Also (I guess this is the case): git push origin ${{ env.version }} pushes the tag created by npm version? I would also love to hear other opinions who are more in the JavaScript space (@DanielJDufour, @ahocevar for example)

@TheMrCam
Copy link
Collaborator Author

TheMrCam commented Jun 2, 2025

Of course! Happy to help see this through.

Regarding realease.yml: I like all the changes! We could tone it down a notch with the emoji use, but even that is no blocker ;)

Yeah sounds good to me, the emojis are just remnants from the action repository I pulled some examples from.

I also like the manual version thingy. To me it sounds useful, only concerns are permissions (who is able to press that button in the end).

According to GitHub Docs, anyone with write permissions to geotiff.js. Not exactly sure what that means for security here, or if we could configure it further.

Also (I guess this is the case): git push origin ${{ env.version }} pushes the tag created by npm version?

Right! In order to ensure it always grabs the correct tag, I export the output from npm version to $GITHUB_ENV.version and push that newly created tag back to the repo (to trigger release.yml). I'd be happy to find out there's a nicer way to accomplish this :)

TheMrCam added 2 commits June 2, 2025 10:09
Per PR suggestion— and to align with personal preference— removed the
emojis from the generated release notes category titles.
Not sure why the emoji commit broke CI, but it seems transient...
testing...
@constantinius
Copy link
Member

According to GitHub Docs, anyone with write permissions to geotiff.js. Not exactly sure what that means for security here, or if we could configure it further.

Okay, that is fine. Anyone with write permissions could also push tags on his own, thus doing a release this way. So works for me!

Right! In order to ensure it always grabs the correct tag, I export the output from npm version to $GITHUB_ENV.version and push that newly created tag back to the repo (to trigger release.yml). I'd be happy to find out there's a nicer way to accomplish this :)

I think this is fine and a clean way to do it!

I would love to get some more feedback on this. But if none arrives we could merge this by the end of the week unless you want to refine it.

@DanielJDufour
Copy link
Contributor

Really impressive work @TheMrCam ! I have to admit that I'm still a bit of a novice when it comes to publishing through Github actions. I still publish from my laptop using np.

I don't have much advice to give, but where possible, I think it would make sense to stick with the established pattern around version naming. I don't think "pre-" has been used before, but rather appending "-beta.1" for release candidates (link). It's not something I personally feel strongly about, just highlighting it as a point of possible confusion that may need clarification.

@TheMrCam
Copy link
Collaborator Author

TheMrCam commented Jun 4, 2025

Thank you @DanielJDufour! np looks interesting, I may have never touched GH Actions for publishing if I found that first.

I think it would make sense to stick with the established pattern around version naming. I don't think "pre-" has been used before, but rather appending "-beta.1" for release candidates

Ah, I somehow missed those -beta versions. I would've stuck with explicit preIds had I noticed the established pattern beforehand.

version.yml example

I'm happy to clarify things on version.yml, especially as it's something I created for this repository and haven't used yet in production personally. It's basically npm version <level> [--preId <identifier>], but public instead of local and on a button press.

I suppose it's slightly harder to imagine without seeing the workflow_dispatch form...

Screenshot 2025-06-04 at 08 53 11

Here it is from my tinkering repo.

The version level is a selection between patch, minor, major, prepatch, preminor, premajor, and prerelease. The first three ignore input from "Prerelease identifier", but the pre* versions require a value for the identifier—this is entirely personal preference, I prefer e.g. 3.0.0-rc.0 over 3.0.0-0 (can be optional if preferred here).

With the example of beta: to release a minor release candidate using the workflow_dispatch form, use preminor for version level and enter beta for prerelease identifier. The action will run npm version preminor --preId beta, resulting in v2.2.0-beta.0. To then release v2.2.0-beta.1, use version=prerelease and preId=beta, and to release v2.2.0 from there, use version=minor.

Resolution

I'd be happy to switch the text input to another selection since there's somewhat of an established pattern. I see beta, are there any other prerelease identifiers we'd like to use in the future? I'm partial to either an alpha/beta pair or just rc (all three is also good), but I'm open to input.

There's also the option of only ever using --preId beta (which I realized, after typing everything else, may have been what you meant originally...). That would allow preId to be abstracted away.

This does bring up a question I hinted at above: npmjs.com version tags (i.e. --tag latest). If we plan to use pre* version levels, should we differentiate them with tags at the publish level? In some other projects, I do so by using the latest tag and an alpha tag—npm publish --tag alpha whenever the tag contains -alpha., plain npm publish otherwise. I do this because I like to protect users from unintentionally installing prereleases with npm install package@latest, but I didn't immediately add it here because I don't want to be too disruptive to current processes. We could do something similar here, either with explicit preIds matching to publish tags or by publishing --tag beta (or something) on any push containing -*.

TL;DR

  • version.yml creates tags appended with -preId.n when version level is pre*
  • Happy to switch preId text input to selection
    • What options do we want, beyond beta, if any?
  • Should pre* tags be published under --tag latest (as is currently written)?

@DanielJDufour
Copy link
Contributor

Hi, @TheMrCam . Thanks for the quick and thoughtful response! You've taught me a lot about how GH Actions work! I'm happy to defer to @constantinius on the decision of whether to keep "beta" in the release candidate version names. Just wanted to surface the question :-)

TheMrCam added 3 commits June 5, 2025 12:10
Whoops, forgot to put id: publish on the npm-publish step, so the
generated release notes wouldn't have had the necessary values from that
step (or it would crash... not 100% sure).
After discussion in the PR, I've decided it is actually better to reduce
the complexity and hardcode the preId when making pre* level versions.

Leaving my comment blocks in this commit for posterity, but I'll delete
them in the next because I don't think it needs to exist in master.
Removed the unnecessary "optional" commented code blocks from
version.yml, and replaced them with a small explainer annotation at the
top.
@TheMrCam
Copy link
Collaborator Author

TheMrCam commented Jun 6, 2025

Quick update: I switched version.yml to always use --preid beta with version=pre*. It's nicer with less chance of confusion or errors, and it's not hard to change if someone wants e.g. --preid alpha for a release in the future.

I don't have any other immediate changes to make, so should be good to go for review.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
ci Related to workflows & actions
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants