release workflow in .github/workflows/release.yml. A maintainer starts it by hand from the Actions tab, on main.
The GitHub Action, the CLI and the MCP server (@resnovas/action, @resnovas/smartcloud and @resnovas/smartcloud-mcp) form one fixed release group, so they always share a version. The libraries under packages/ are bundled into them and are never released on their own.
What a release does
- Nx reads the conventional commits since the last
v*tag and picks the bump:featis minor,fix,perfandrevertare patch, and a breaking change is major. Other types appear in the notes, or are hidden, without bumping. Aspecifierinput overrides this. - Nx writes the new version to the three apps’
package.jsonfiles, and the action is bundled intodist/index.jsfrom that source. - The workflow commits both, removes the vendored
externals/directory (every run of the action downloads the whole tagged tree), and signs the commit off asgithub-actions[bot]. The commit is on no branch: its parent is the head ofmain. - Only the
v<version>tag is pushed.mainnever receives a release commit or the bundle, so no branch protection is bypassed. - Nx writes the release notes to a GitHub release on the tag, and the
v<major>tag moves to it, which is what workflows pin. It writes the same notes to the changelog files, below. - The
changelogsjob opens a pull request that brings the changelog files tomain. - A last job checks out the tag, rebuilds the action and stops unless the bundle matches the tagged one. It then bundles the CLI and MCP server, with the released version stamped in, and publishes
@resnovas/smartcloudto npm with provenance, through trusted publishing.
tools/release/sourcemaps.ts has PostHog’s CLI inject a chunk id into the bundle and upload its map to error tracking as the release smartcloud@<version>, then deletes the map. Neither the tag nor the npm package ships a map: the tagged tree is downloaded by every run of the action, and PostHog resolves stack traces from its own copy. The maps name sources relative to the bundle, never a path on the machine that built it.
The tag is the only record of the current version: the apps’ versions on main stay 0.0.0, and a local build reports 0.0.0.
Release notes and changelogs
The GitHub release on each tag holds the main release notes. Nx writes the same notes, rendered bytools/release/changelog-renderer.ts (Nx’s default renderer with its emoji replaced by words), to:
The libraries under
packages/ get no changelog of their own: they are never published, and their changes appear under the apps that bundle them.
The release commit is never on main, and main takes changes only through pull requests, with signed commits, through the merge queue. So the changelogs job, after the release job has tagged and released, commits the files to a release/changelogs-v<version> branch through the GitHub API as the Resnovas Bot app, which makes GitHub sign the commit, and opens a pull request titled chore(release): changelogs for v<version>. The commit is signed off by the app’s bot account for the DCO check, and the house preset trusts that account. Review and merge it like any other pull request, before the next release: each release adds its entry to the files as main holds them.
The job mints the app’s token itself and runs none of the repository’s code or dependencies; the release job, which installs and runs them, hands it the files as an artifact and never sees the app’s key. If the pull request cannot be opened, the files stay in the run’s changelogs artifact for a week.
Running a release
Open Actions, choose release, then Run workflow onmain.
Run it once as a dry run, check the notes, then run it again with
dry-run cleared. When no commit since the last tag calls for a release, the workflow says so and stops.
The first v2 release
v1’s tags, up to1.0.0-beta.8, have no v prefix, so Nx finds no earlier v* tag to count from. Run the first release with:
specifier:2.0.0first-release: ticked
1.0.0-beta.8), so they cover the v2 work rather than the whole history. From then on, leave both inputs empty.
To preview it locally:
Before the first release
- Add a repository secret named
POSTHOG_CLI_TOKEN: a PostHog personal API key with theerror tracking writeandorganization readscopes, for the Smartcloud project (285077) in PostHog’s EU cloud. The workflow passes it to PostHog’s CLI asPOSTHOG_CLI_API_KEY. Without it the maps are still deleted, but none is uploaded, so errors from that release show bundle lines rather than source lines. A dry run never uploads. - The
changelogsjob authenticates as the Resnovas Bot GitHub app (resnovas-smartcloud), from the organisation variableRESNOVAS_BOT_APP_IDand secretRESNOVAS_BOT_PRIVATE_KEY. The app must be installed on this repository with contents and pull requests write access. A real release stops before tagging when either is missing. - The workflow pushes tags with its own token. If a tag ruleset protects
v*, let GitHub Actions bypass it for tag creation and updates. - Trusted publishing needs
@resnovas/smartcloudon npm to trust this repository’srelease.ymlworkflow.