|
| 1 | +import { fileURLToPath, URL } from "node:url"; |
| 2 | + |
| 3 | +import { getFileInfo } from "prettier"; |
1 | 4 | import { describe, expect, it } from "vitest"; |
2 | 5 |
|
3 | 6 | import { |
| 7 | + classifyPushReleasePresence, |
4 | 8 | extractReleaseNotesFromChangelog, |
5 | 9 | validatePreparedReleasePullRequest, |
6 | 10 | validateGitHubRelease, |
@@ -130,6 +134,139 @@ function releaseFixture({ |
130 | 134 | }; |
131 | 135 | } |
132 | 136 |
|
| 137 | +describe("Release Please generated files", () => { |
| 138 | + it("leaves the action-owned CHANGELOG byte-for-byte unchanged by Prettier", async () => { |
| 139 | + const changelog = fileURLToPath( |
| 140 | + new URL("../CHANGELOG.md", import.meta.url), |
| 141 | + ); |
| 142 | + |
| 143 | + await expect( |
| 144 | + getFileInfo(changelog, { ignorePath: ".prettierignore" }), |
| 145 | + ).resolves.toMatchObject({ ignored: true }); |
| 146 | + expect( |
| 147 | + extractReleaseNotesFromChangelog( |
| 148 | + `# Changelog\n\n${releaseNotes()}\n\n## [0.1.0] - 2026-07-28\n\nPrevious.`, |
| 149 | + "0.1.1", |
| 150 | + ), |
| 151 | + ).toBe(releaseNotes()); |
| 152 | + expect(() => |
| 153 | + validateReleasePleasePullRequestBody( |
| 154 | + releaseBody().replace("supported options", "different options"), |
| 155 | + "0.1.1", |
| 156 | + releaseNotes(), |
| 157 | + ), |
| 158 | + ).toThrow(/pull request notes/i); |
| 159 | + }); |
| 160 | +}); |
| 161 | + |
| 162 | +describe("Release Please push classification", () => { |
| 163 | + function publishedCurrentRelease(overrides = {}) { |
| 164 | + return { |
| 165 | + draft: false, |
| 166 | + immutable: true, |
| 167 | + prerelease: false, |
| 168 | + tag_name: "v0.1.0", |
| 169 | + target_commitish: RELEASE_SHA, |
| 170 | + ...overrides, |
| 171 | + }; |
| 172 | + } |
| 173 | + |
| 174 | + it("ignores a metadata-only push whose current version remains published", () => { |
| 175 | + expect( |
| 176 | + classifyPushReleasePresence({ |
| 177 | + currentRelease: publishedCurrentRelease(), |
| 178 | + currentTagCommit: RELEASE_SHA, |
| 179 | + headCommit: BRANCH_SHA, |
| 180 | + manifestVersion: "0.1.0", |
| 181 | + packageChanged: false, |
| 182 | + previousVersion: "0.1.0", |
| 183 | + version: "0.1.0", |
| 184 | + }), |
| 185 | + ).toEqual({ mode: "ignore", version: "0.1.0" }); |
| 186 | + }); |
| 187 | + |
| 188 | + it("classifies an exact next-patch push as a release", () => { |
| 189 | + expect( |
| 190 | + classifyPushReleasePresence({ |
| 191 | + currentRelease: null, |
| 192 | + currentTagCommit: null, |
| 193 | + headCommit: RELEASE_SHA, |
| 194 | + manifestVersion: "0.1.1", |
| 195 | + packageChanged: true, |
| 196 | + previousVersion: "0.1.0", |
| 197 | + version: "0.1.1", |
| 198 | + }), |
| 199 | + ).toEqual({ mode: "release", version: "0.1.1" }); |
| 200 | + }); |
| 201 | + |
| 202 | + it.each([ |
| 203 | + [ |
| 204 | + "unchanged unpublished version", |
| 205 | + { currentRelease: null, currentTagCommit: null }, |
| 206 | + ], |
| 207 | + ["minor bump", { previousVersion: "0.1.0", version: "0.2.0" }], |
| 208 | + ["skipped patch", { previousVersion: "0.1.0", version: "0.1.2" }], |
| 209 | + ["metadata-only package change", { packageChanged: true }], |
| 210 | + ["manifest drift", { manifestVersion: "0.1.1" }], |
| 211 | + [ |
| 212 | + "published-version tag without a Release", |
| 213 | + { currentRelease: null, currentTagCommit: RELEASE_SHA }, |
| 214 | + ], |
| 215 | + ["published-version Release without a tag", { currentTagCommit: null }], |
| 216 | + [ |
| 217 | + "mutable published Release", |
| 218 | + { currentRelease: publishedCurrentRelease({ immutable: false }) }, |
| 219 | + ], |
| 220 | + [ |
| 221 | + "mismatched published target", |
| 222 | + { |
| 223 | + currentRelease: publishedCurrentRelease({ |
| 224 | + target_commitish: BRANCH_SHA, |
| 225 | + }), |
| 226 | + }, |
| 227 | + ], |
| 228 | + [ |
| 229 | + "candidate tag on another commit", |
| 230 | + { |
| 231 | + currentRelease: publishedCurrentRelease({ |
| 232 | + tag_name: "v0.1.1", |
| 233 | + target_commitish: BRANCH_SHA, |
| 234 | + }), |
| 235 | + currentTagCommit: BRANCH_SHA, |
| 236 | + previousVersion: "0.1.0", |
| 237 | + version: "0.1.1", |
| 238 | + }, |
| 239 | + ], |
| 240 | + ])("rejects a %s push", (_name, overrides) => { |
| 241 | + expect(() => |
| 242 | + classifyPushReleasePresence({ |
| 243 | + currentRelease: publishedCurrentRelease(), |
| 244 | + currentTagCommit: RELEASE_SHA, |
| 245 | + headCommit: RELEASE_SHA, |
| 246 | + manifestVersion: "0.1.0", |
| 247 | + packageChanged: false, |
| 248 | + previousVersion: "0.1.0", |
| 249 | + version: "0.1.0", |
| 250 | + ...overrides, |
| 251 | + }), |
| 252 | + ).toThrow(/release workflow/i); |
| 253 | + }); |
| 254 | + |
| 255 | + it("rejects an unchanged-version rerun even if the historical tag exists", () => { |
| 256 | + expect(() => |
| 257 | + classifyPushReleasePresence({ |
| 258 | + currentRelease: publishedCurrentRelease(), |
| 259 | + currentTagCommit: RELEASE_SHA, |
| 260 | + headCommit: BRANCH_SHA, |
| 261 | + manifestVersion: "0.1.0", |
| 262 | + packageChanged: true, |
| 263 | + previousVersion: "0.1.0", |
| 264 | + version: "0.1.0", |
| 265 | + }), |
| 266 | + ).toThrow(/package\.json push must change/i); |
| 267 | + }); |
| 268 | +}); |
| 269 | + |
133 | 270 | function attemptEvidenceFixture( |
134 | 271 | attempt, |
135 | 272 | { |
|
0 commit comments