Skip to content

fix(github): Skip prereleases and ignore floating tags in version lookup - #969

Merged
BYK merged 2 commits into
masterfrom
fix/floating-tags-prerelease-and-lookup
Nov 6, 2026
Merged

BYK merged 2 commits into
masterfrom
fix/floating-tags-prerelease-and-lookup

Conversation

@sentry-junior

@sentry-junior sentry-junior Bot commented Nov 6, 2026

Copy link
Copy Markdown
Contributor

Fixes two floatingTags bugs that keep repos with v-prefixed release tags from using it.

Prereleases moved floating tags. updateFloatingTags had no prerelease check, so a pre release like 0.54.0-alpha.0 moved v0 to the alpha for everyone pinned to @v0. It now skips (and logs) when the version has a semver prerelease identifier.

Floating tags hid the previous release. git describe --tags --match 'v*' also matches v0. When v0 and v0.53.0 are on the same commit, git picks v0, Craft can't parse a version from it, and auto computes from 0.0.0 (a vitest-evals dry run gave 0.0.0 -> 0.1.0). findLatestTag now skips tags with no version after the prefix (v0, v0.53, latest) by excluding them and describing again, the same loop it already used to skip prereleases. getLatestTag goes through it too, so prepare, auto/pre versioning, the changelog base, and craft changelog all get the fix. Prefixed monorepo tags and prerelease handling are unchanged.

Tests cover a prerelease leaving floating tags alone, a stable release still moving them, and a real git repo where v0 and latest sit on the v0.53.0 commit, which now resolves to v0.53.0 for every lookup. The GitHub target docs mention both behaviors.

This unblocks getsentry/warden#567 and getsentry/vitest-evals#117 replacing their update-major-tag.sh scripts with floatingTags: ["v{major}"].

via @BYK.

--

View Session [Sentry]

Prereleases no longer move floatingTags, so users pinned to a floating
tag like v0 keep getting stable releases only.

Previous-release lookups now skip tags without a version after the tag
prefix. A floating tag such as v0 on the same commit as v0.53.0 sorted
first in git describe and hid the release, so auto versioning restarted
from 0.0.0.

Co-Authored-By: BYK <126780+BYK@users.noreply.github.com>
@github-actions

github-actions Bot commented Nov 6, 2026 •

Copy link
Copy Markdown
Contributor
PR Preview Action v1.8.1
Preview removed because the pull request was closed.
2026-11-06 14:26 UTC

Comment thread docs/src/content/docs/targets/github.md Resolved
@BYK
BYK merged commit 064af7c into master Nov 6, 2026
39 of 40 checks passed
@BYK
BYK deleted the fix/floating-tags-prerelease-and-lookup branch November 6, 2026 14:25
BYK added a commit to getsentry/vitest-evals that referenced this pull request Nov 7, 2026
BYK asked to move the Craft repos to the latest Craft release workflow
with the full bump set, the same as `getsentry/junior`. Review feedback
then asked to remove the release-tag workarounds.

## What changed

**Release workflow**
- `release.yml` now uses `getsentry/craft@v3` and no longer uses
`getsentry/action-prepare-release@v1`. It passes these inputs:
  - `version: ${{ inputs.version || inputs.bump }}`
  - `force`
  - `llm_api_key: ${{ github.token }}`
- `release.yml` also gets the `copilot-requests: write` permission.
- New inputs:
  - `bump`: `auto` (default), `pre`, `patch`, `minor`, `major`
  - `version`: an optional exact version
  - `force`
- Removed inputs: `prerelease` and `prerelease_id`.
- Use `pre` for an `alpha` prerelease of the version that `auto` would
release.
- For a `beta` or `rc` line, set `version`, for example `0.19.0-beta.0`.
- `scripts/calculate-release-version.mjs` is removed. Craft now computes
the version.

**Action bundle on `main`**
- `github-reporter/dist/action/index.js` is now committed. It is no
longer gitignored, `.gitattributes` marks it `linguist-generated`, and
Biome skips it.
- CI keeps the bundle fresh. The release bot key is never used on
`pull_request`:
- `action-bundle` (`test.yml`) checks out the PR head with
`persist-credentials: false`, installs, and runs
`scripts/check-action-bundle.sh` (`pnpm build:action`) with no secrets.
On same-repo PRs that Dependabot did not open, a stale bundle is
uploaded as the `action-bundle` artifact. On fork PRs, Dependabot PRs,
and `main`, a stale bundle fails the job. A stale bundle can only reach
`main` past a failing check.
- The `test` job, which builds the PR merge commit, also runs
`scripts/check-action-bundle.sh` in fail-only mode. A bundle that is
fresh on the branch but stale after the merge with `main` cannot go
green. To fix it, merge or rebase on `main`, and CI then rebuilds the
bundle.
- `push-action-bundle.yml` runs on `workflow_run` when `Test` completes.
GitHub always runs this file from `main`, so a PR cannot change it.
- It reads the PR's identity from the `workflow_run` payload:
`head_sha`, `head_branch`, `head_repository`. It runs only when the
event is `pull_request`, the head repo is this repo, the actor is not
Dependabot, and the branch is not the default branch or `release/*`.
- It runs only scripts from the default-branch checkout:
`scripts/find-action-bundle-artifact.sh` and
`scripts/push-action-bundle.sh`. The PR is checked out in a separate
directory at `head_sha` with `persist-credentials: false`. No PR code
runs.
- It downloads the artifact from that exact run (`actions: read`) and
treats it as untrusted data. The push script accepts only regular files
and directories under `action/`, so symlinks, special files and extra
entries fail. It also checks that the checkout is at `head_sha`.
- It creates the app token last. The commit and push run with hooks
turned off. The push is fast-forward only on top of `head_sha`, so a
moved branch is rejected and the new head gets its own run. The app
token push starts CI again, and that run finds no change because the
build always gives the same bytes.
- This closes Warden VRG-9C6, XHC-8WM and VJW-URC. `workflow_run` only
runs from the default branch, so the first real run happens after this
merges.
- The old flow is removed:
  - the detached "Build github-reporter action" commits
  - the `vX.Y.Z-src` tags
  - the force-move of `vX.Y.Z`
  - the local tag remap before `craft prepare`
- Craft now tags the release commit, which already contains the bundle.
Craft merges the release branch back with `--no-ff`, so `vX.Y.Z` is
reachable from `main`.
- `v0` now moves through Craft's github target, `floatingTags:
["v{major}"]`, and `minVersion` is `3.11.1`.
`scripts/update-major-tag.sh` and `update-action-tag.yml` are deleted.
Craft 3.11.1 (getsentry/craft#969) fixes the two bugs that blocked this
before. Prereleases do not move floating tags. The previous-release
lookup (`getLatestTag`, `getLatestStableTag`, `getChangelogBaseTag`)
skips tags without a full `major.minor.patch`, such as `v0`. `v0` lands
on the release commit, which already contains the bundle, so `@v0` users
get it.
- `merge-jobs.yml` runs `sh scripts/check-action-bundle.sh` on
`release/*` instead of only building. A stale bundle on a release branch
fails a status check, so Craft does not publish it.
- `pnpm release:check` now fails if the action entrypoint is not
committed. Its fixture and a new test cover this.

**First-release baseline guard**
- `scripts/check-release-baseline.sh` runs in a new "Check release
baseline" step in `release.yml`, only when `version` is empty. The
checkout fetches tags.
- The step stops the release unless the latest tag that `main` reaches
and that matches `v[0-9]*.[0-9]*.[0-9]*` is `v<version>` from
`packages/vitest-evals/package.json`, the file the release bumps.
Prerelease tags count, because publish merges a prerelease version into
`main`. `v0` does not match the pattern. The error says to pass an exact
`version`.
- Without the guard, Craft 3.11.1 reads `0.18.0-src` on today's `main`.
`auto`, `patch` and `minor` would then fail with "Nothing to commit",
`major` would release `1.0.0`, and `pre` would probably publish a `-src`
prerelease.

**Merge of `main`**
- 4fa1d7c merges `main` (#115). It keeps the new `report-ui-visual` job
next to `action-bundle` and keeps both `.gitignore` entries. 517b625
rebuilds the bundle, because #115 changed
`packages/core/src/report/metadata.ts`.

## Why the old flow existed

The bundle was gitignored, so `update-action-tag.yml` built it after
Craft published. The workflow committed the bundle on a commit outside
`main`, then force-moved `vX.Y.Z` and `vX` to that commit. As a result,
`main` could reach only the `vX.Y.Z-src` tags. Craft parses those tags
as prereleases. A dry run on today's `main` gives `auto` → `0.18.0-src
-> 0.18.0`, which is a release that already exists.

## Transition (one time)

`main` still reaches only `-src` tags, so the baseline guard stops any
release without `version`. **For the first release after this merges,
set `version` to an exact version, for example `0.18.1`.** That release
creates `v0.18.1` on a commit that `main` can reach. After that, `auto`
and the bump types work.

After the first release, run `git ls-remote origin refs/tags/v0` and
check that `v0` points at the `v0.18.1` commit. Craft moves floating
tags on a best-effort basis: if the move fails, it only logs a warning.
The README documents both steps. This PR does not push, move, or delete
any tags.

Changelog preview uses the same tag lookup, so it lists the full history
until that first release. After the first release it works normally.
There is no Craft setting that fixes this before then, so the
changelog-preview workflow is unchanged.

## Verification

- `actionlint` 1.7.12: the only new finding is the unknown
`copilot-requests` scope. junior's live workflow gets the same finding.
- `shellcheck --shell=sh --enable=check-extra-masked-returns`: passes on
both new scripts.
- I ran both new scripts under `dash`:
  - Both jobs' scripts, simulated against a local bare remote:
    - With a fresh bundle, the check passes and sets no output.
- With a stale bundle, the check fails on a fork PR or `main`, and sets
`stale=true` on a same-repo PR.
    - The push script pushes a bundle whose blob matches a fresh build.
- The push is rejected (non-fast-forward) when the branch moved after
the build.
- `check-action-bundle.sh` without `CAN_PUSH` exits 1 after a change to
`src/action/main.ts`, and it passes on the committed bundle.
- Craft 3.11.1 (`npx @sentry/craft@3.11.1 prepare --dry-run`), in a
scratch repo with `v0` and `v0.18.1` on the same commit (where raw `git
describe` returns `v0`): `auto` → `0.18.1 -> 0.19.0`, `patch` →
`0.18.2`, `pre` → `0.19.0-alpha.0`. On today's `main`, `auto` still
gives `0.18.0-src -> 0.18.0`, so the transition note still applies.
- Baseline guard under `dash`, against scratch repos:
- Today's `main` (only `-src` tags): fails with the exact-version error.
  - With an exact `version`: the step is skipped.
- After a simulated stable `v0.18.1` release, with `v0` on the same
commit: passes.
  - After a simulated prerelease: passes.
  - No tags: fails.
- `push-action-bundle.sh` under `dash`, against a local bare remote, run
from outside the PR checkout:
  - A stale bundle is pushed. A fresh bundle exits 0 with no commit.
- A wrong `head_sha`, a symlink, an extra top-level file and a FIFO in
the artifact are each rejected.
  - A moved branch is rejected as non-fast-forward.
- A planted pre-commit hook does not run. The token never appears in
`.git/config`.
- `find-action-bundle-artifact.sh` against a fake `gh`: it sets `found`
only when the artifact exists, and fails on an API error.
- CI on e83288c: `test`, `action-bundle`, CodeQL, Secret Scan, Socket
and the reporter smoke test pass. The new `workflow_run` workflow has
not run yet, because it only runs from `main`.
- The bundle build is deterministic: two builds give the same bytes.
- I ran `craft prepare --dry-run` (Craft master build, before 3.11.1):
  - On today's tags, `0.18.1` is accepted.
  - After a simulated merged `v0.18.1` release and a `feat` commit:
    - `auto` → `0.19.0`
    - `pre` → `0.19.0-alpha.0`
    - `patch` → `0.18.2`
- `pnpm release:check`, the release-config tests (6/6), `pnpm lint`, and
`pnpm build` pass.
- `pnpm test:ci`: 409 tests pass. One test fails: `report-ui` "returns
500 when asset reads fail". That test needs `chmod 000` to block reads,
and my sandbox ignores file permissions. That failure is not related to
this PR.

I did not run the Release workflow.

<!-- junior-request-attribution:start -->
via @BYK.
<!-- junior-request-attribution:end -->

<!-- junior-session-footer:start -->
<!-- junior-conversation-id:agent%3Adb2c94feac8d07d4ca60aeee13fbb0e0 -->

--

[View
Session](https://junior-prod.sentry.dev/conversations/agent%3Adb2c94feac8d07d4ca60aeee13fbb0e0)
[[Sentry]](https://sentry.sentry.io/explore/conversations/agent%3Adb2c94feac8d07d4ca60aeee13fbb0e0/?project=4510944073809921)

<!-- junior-session-footer:end -->

---------

Co-authored-by: sentry-junior[bot] <264270552+sentry-junior[bot]@users.noreply.github.com>
Co-authored-by: BYK <126780+BYK@users.noreply.github.com>
BYK added a commit to getsentry/warden that referenced this pull request Nov 7, 2026
BYK asked to move the Craft repos to the latest Craft release workflow,
with `auto` and the full bump set. This makes warden's Release workflow
match `getsentry/junior`, and lets Craft read warden's release tags with
no workarounds.

## What changed

- `release.yml` now uses `getsentry/craft@v3` (floating `v3` tag)
instead of `getsentry/action-prepare-release`, with `version: ${{
inputs.version || inputs.bump }}`.
- Inputs: `bump` (`auto`, `pre`, `patch`, `minor`, `major`; default
`auto`), an optional exact `version`, and `force`. Craft now resolves
the version.
- Added `permissions` (`contents: read`, `copilot-requests: write`) and
`llm_api_key: ${{ github.token }}`, the same as junior. This does
nothing until `.craft.yml` sets `changelog.aiSummary`.
- `.craft.yml` gets `minVersion: 3.11.1`. Older Craft rejects bump types
and `auto` (2.14.0), `pre` (3.9.0), and moves floating tags on
prereleases (fixed in 3.11.1).
- **The Action bundle is now committed to main.** `dist/action/` (the
ncc bundle files only) is tracked and marked `linguist-generated` in
`.gitattributes`. The CI `build` job rebuilds it and
`bin/check-action-dist.sh` fails when the result differs from the
committed files, including new or removed chunks. Fork and Dependabot
PRs can't get the auto-commit, so contributors there run `pnpm
build:action` and commit `dist/action/` (`CONTRIBUTING.md`,
`AGENTS.md`).
- **Same-repo PRs get the bundle committed back, in two workflows
(1143078).**
- `action-dist.yml` runs on `pull_request` with no secrets. Its `build`
job runs the PR install and build. On a same-repo, non-Dependabot PR
with a stale bundle, it uploads `dist/action` as an artifact.
- `commit-action-dist.yml` runs on `workflow_run` when `action-dist.yml`
completes. It takes the PR's identity (head SHA, head branch, head
repository) from the `workflow_run` payload, not from the artifact. It
skips unless the event is `pull_request`, the head repo is this repo,
the actor is not Dependabot, and the branch is not `main` or
`release/*`. It downloads the artifact from that run id and treats it as
untrusted data: it fails if the artifact holds anything other than
regular files and directories (such as symlinks or FIFOs), then copies
it into `dist/action/`. It runs no code from the PR.
`bin/commit-action-dist.sh` and `bin/push-action-dist.sh` come from the
default-branch checkout, and the PR checkout has `persist-credentials:
false` and hooks off (`core.hooksPath=/dev/null`). It creates the
release bot app token as the last step, so CI runs again on the new
commit, and pushes on top of the head SHA. If the branch moved, the push
is not a fast-forward and fails.
- No `pull_request` workflow uses the release bot key now.
`workflow_run` runs only from the default branch, so the first real run
happens after merge.
- **No more detached release tags, and Craft moves `v0`.**
`update-major-tag.yml` and `bin/update-major-tag.sh` are removed.
Craft's github target tags the release commit, which main reaches after
Craft merges the release branch back. On stable releases it also moves
`v0` there (`floatingTags: ['v{major}']`). Since Craft 3.11.1
([getsentry/craft#969](getsentry/craft#969)), a
prerelease never moves `v0`, and the previous-release lookup skips tags
without a full `major.minor.patch`, so `v0` on the release commit does
not hide `v0.53.0`. The release commit has the committed `dist/action/`,
so `@v0` and `@vX.Y.Z` run the same bundle.
- **CodeQL moved to advanced setup (0afc598).**
`.github/workflows/codeql.yml` scans `actions`, `javascript-typescript`
and `python` (the same languages as default setup) on `pull_request`,
push to main and a weekly schedule. `.github/codeql/codeql-config.yml`
ignores `dist/**`, so the committed bundle gives no alerts. **A repo
admin must turn off default setup** under Settings → Code security.
Until then, GitHub rejects the advanced uploads and the CodeQL jobs
fail. CodeQL is not a required check.
- Removed `bin/craft-release-tags.sh` (and its release.yml step) and
`bin/publish-action-bundle.sh`. `specs/release-process.md` describes the
new flow.

## Why the old flow existed

`dist/` was gitignored, so the bundle could only live on a commit off
main. After each release, a workflow built it, committed it on top of
the release tag, and force-moved `vX.Y.Z` and `v0` there. It left
`vX.Y.Z-src` on the source commit. main reached only those `-src` tags,
which Craft reads as prereleases, so this PR first needed a tag remap
script. Committing the bundle to main (the `actions/typescript-action`
pattern) removes the need for all of it.

## First release after merge

main still reaches only the old `v0.52.0-src` and `v0.46.0` tags.
Existing tags are not changed.

- **Run the first release with an exact `version`, for example
`0.53.0`.** Craft bumps from the latest tag, prereleases included, which
is `v0.52.0-src` on main. `auto`, `patch` and `minor` would give
`0.52.0`, `pre` `0.52.0-src.0`, and `major` `1.0.0`. A new `Check
release baseline` step (`bin/check-release-baseline.sh`) runs when
`version` is empty. It fails when the latest version tag is not `v` plus
the `packages/warden/package.json` version, so these runs stop before
Craft.
- Its changelog starts at `v0.46.0`, the latest stable tag main reaches,
so it repeats the 0.47.0 to 0.52.0 entries. Trim them on the
`release/0.53.0` branch before you approve the publish request.
- After the first release, confirm that `git ls-remote origin
refs/tags/v0` points to the `v0.53.0` commit. Craft logs only a warning
when it cannot move a floating tag. From the next release on, `auto`
works, because `v0.53.0` is on main.

## Verification

- `pnpm build:action` output is deterministic, the same on Node 22 and
Node 24, and byte-identical to the `dist/action` on the published
`v0.52.0` tag (all 50 files).
- `bin/check-action-dist.sh` passes on the committed bundle after a
rebuild, and fails on a changed file and on an untracked new chunk.
- `git check-ignore` confirms `.d.ts` and `.map` output and
`packages/*/dist` stay ignored.
- `validate-action-layout --require-dist` passes.
- Craft 3.11.1 (`npx @sentry/craft@3.11.1 changelog`) in a scratch repo
with `v0` and `v0.53.0` on the same commit (both annotated, and both
lightweight): `git describe --tags --match 'v*'` returns `v0`, and Craft
picks `v0.53.0` as the base. Craft source at 3.11.1 skips floating tags
for prereleases in `updateFloatingTags`.
- Local simulation of `commit-action-dist.yml`'s scripts against a local
bare remote: no artifact and an empty artifact make no commit, symlinks
and FIFOs in the artifact are rejected, unchanged content makes no
commit, a changed and a new chunk are committed and pushed, hooks do not
run, and a push after the branch moved is rejected as non-fast-forward.
The real `workflow_run` path is not verified until after merge.
- `actionlint` 1.7.12 passes. Its only finding is `copilot-requests`, a
scope it doesn't know yet (same on junior's `release.yml`). `shellcheck
--shell=sh --enable=check-extra-masked-returns` passes on the new
scripts.
- `pnpm lint` and typecheck pass. `pnpm test`: 2091 pass. The 9
`src/skills/remote.test.ts` real-git tests fail in my sandbox only,
because its git wrapper rejects the test's commit author. CI is the
source of truth there.
- I did not run `craft prepare` end to end, and the Release workflow was
not triggered.

The bundle went in as three commits (part 1 to 3) because the sandbox's
push proxy rejects large packs.

<!-- junior-request-attribution:start -->
via @BYK.
<!-- junior-request-attribution:end -->

<!-- junior-session-footer:start -->
<!-- junior-conversation-id:agent%3A981c8841b1c0ba2fdd8b32885b0c7457 -->

--

[View
Session](https://junior-prod.sentry.dev/conversations/agent%3A981c8841b1c0ba2fdd8b32885b0c7457)
[[Sentry]](https://sentry.sentry.io/explore/conversations/agent%3A981c8841b1c0ba2fdd8b32885b0c7457/?project=4510944073809921)

<!-- junior-session-footer:end -->

---------

Co-authored-by: sentry-junior[bot] <264270552+sentry-junior[bot]@users.noreply.github.com>
Co-authored-by: Burak Yigit Kaya <126780+BYK@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant