fix(scripts/releaser/v1): remove doubled "v" in release calendar latest release link (#27260)

## Problem

The interactive releaser (`scripts/releaser`) renders the "Latest
Release"
cell of the release calendar with a doubled version prefix, e.g.
`[vv2.35.0](.../tag/v2.35.0)`.

`version.String()` already returns a `v`-prefixed string (e.g.
`v2.35.0`),
but `updateCalendar` wrapped it in a `"[v%s]"` template, so the link
label
gained a second `v`. The tag URL was already correct because release
tags
carry the `v` prefix.

## Fix

Drop the extra `v` from the label template (`"[v%s]"` → `"[%s]"`). The
URL is
unchanged.

- Label before: `[vv2.35.0]`
- Label after: `[v2.35.0]`

## Test

Added `scripts/releaser/v1/docs_test.go`:

- `TestUpdateCalendarLatestReleaseVersionPrefix` asserts the
`LatestRelease`
cell for a matching row on both a patch and a minor release. It fails on
the
  old code (`[vv2.35.x]`) and passes with the fix.
- `TestUpdateCalendarNotReleasedRowName` covers the `Not Released` →
`Mainline`
  promotion and the major.minor "Release name" link (patch omitted).

<details>
<summary>Investigation notes</summary>

- Entry path: `scripts/release.sh` → `go run ./scripts/releaser
--legacy` →
  `runRelease` → `promptAndUpdateDocs` → `updateReleaseDocs` →
`updateCalendarFile` → `updateCalendar` (`scripts/releaser/v1/docs.go`).
- Root cause in `updateCalendar`: `fmt.Sprintf("[v%s](%s)",
newVer.String(), ...)`
  combined with `version.String()` returning `v%d.%d.%d`.
- Only the link label was affected; the `releaseTagURLFmt` URL was
correct
  because tags are `v`-prefixed.
- The standalone `scripts/update-release-calendar.sh` is a separate
implementation and is not affected (it strips the `v` before re-adding
one).
- Companion PR for `release/2.35` (file `scripts/releaser/docs.go`):
#27259.

</details>

---
This PR was generated by Coder Agents.
This commit is contained in:
Marcin Tojek
2026-07-15 12:51:44 +02:00
committed by GitHub
parent 304f127d34
commit 2bea8fb382
2 changed files with 86 additions and 1 deletions
+1 -1
View File
@@ -171,7 +171,7 @@ func updateCalendar(
for i, r := range rows {
if r.Major == newVer.Major && r.Minor == newVer.Minor {
rows[i].LatestRelease = fmt.Sprintf(
"[v%s](%s)",
"[%s](%s)",
newVer.String(),
fmt.Sprintf(releaseTagURLFmt, newVer.String()),
)
+85
View File
@@ -0,0 +1,85 @@
package v1 //nolint:testpackage // Tests unexported release helpers.
import "testing"
// TestUpdateCalendarLatestReleaseVersionPrefix checks the formatting of the
// "Latest Release" cell produced by updateCalendar. version.String() already
// includes a leading "v", so the link label must not add a second one, while
// the release tag URL keeps the "v" because tags are prefixed with it.
func TestUpdateCalendarLatestReleaseVersionPrefix(t *testing.T) {
t.Parallel()
tests := []struct {
name string
newVer version
channel string
want string
}{
{
name: "patch release",
newVer: version{Major: 2, Minor: 35, Patch: 1},
channel: "mainline",
want: "[v2.35.1](https://github.com/coder/coder/releases/tag/v2.35.1)",
},
{
name: "minor release",
newVer: version{Major: 2, Minor: 35, Patch: 0},
channel: "mainline",
want: "[v2.35.0](https://github.com/coder/coder/releases/tag/v2.35.0)",
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
t.Parallel()
rows := []calendarRow{{
ReleaseName: "2.35",
Major: 2,
Minor: 35,
ReleaseDate: "February 03, 2026",
Status: "Mainline",
LatestRelease: "N/A",
}}
got := updateCalendar(rows, tt.newVer, tt.channel)
var cell string
for _, r := range got {
if r.Major == tt.newVer.Major && r.Minor == tt.newVer.Minor {
cell = r.LatestRelease
break
}
}
if cell != tt.want {
t.Fatalf("LatestRelease = %q, want %q", cell, tt.want)
}
})
}
}
// TestUpdateCalendarNotReleasedRowName checks that a "Not Released" row is
// promoted to "Mainline" with a major.minor "Release name" link (patch
// omitted) once its minor version is released.
func TestUpdateCalendarNotReleasedRowName(t *testing.T) {
t.Parallel()
rows := []calendarRow{{
ReleaseName: "2.36",
Major: 2,
Minor: 36,
Status: "Not Released",
LatestRelease: "N/A",
}}
got := updateCalendar(rows, version{Major: 2, Minor: 36, Patch: 0}, "mainline")
if got[0].Status != "Mainline" {
t.Errorf("Status = %q, want %q", got[0].Status, "Mainline")
}
const want = "[2.36](https://coder.com/changelog/coder-2-36)"
if got[0].ReleaseName != want {
t.Fatalf("ReleaseName = %q, want %q", got[0].ReleaseName, want)
}
}