-
Notifications
You must be signed in to change notification settings - Fork 469
Convert update-supported-enterprise-server-versions script to TypeScript
#3916
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
Merged
+473
−94
Merged
Changes from all commits
Commits
Show all changes
16 commits
Select commit
Hold shift + click to select a range
c05837d
Scaffold `update-ghes-versions.ts` script
mbg 04d4fd5
Add `semver` dependency
mbg 952a538
Add constant for `API_COMPATIBILITY_FILE`
mbg d98bedf
Add constant for `FIRST_SUPPORTED_RELEASE`
mbg 4536424
Throw if `ENTERPRISE_RELEASES_PATH` is not set
mbg da26a01
Add `readApiCompatibility`
mbg f580827
Add `readEnterpriseReleases`
mbg 71b697d
Add helpers for GHES versions
mbg 51cc08a
Add `determineSupportedRange`
mbg 15f19e1
Add `date` as a parameter for `determineSupportedRange`
mbg f9feddd
Add tests for `update-ghes-versions.ts`
mbg 5aed9f7
Update workflow to use `update-ghes-versions.ts`
mbg 3e85884
Remove Python version
mbg 74374a3
Rebuild (newer `semver` version)
mbg 7ba697a
Fix comment and clear time component
mbg 839edd2
Merge branch 'main' into mbg/ts/update-ghes-versions
mbg File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Some comments aren't visible on the classic Files Changed page.
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
9 changes: 0 additions & 9 deletions
9
.github/workflows/update-supported-enterprise-server-versions/Pipfile
This file was deleted.
Oops, something went wrong.
27 changes: 0 additions & 27 deletions
27
.github/workflows/update-supported-enterprise-server-versions/Pipfile.lock
This file was deleted.
Oops, something went wrong.
51 changes: 0 additions & 51 deletions
51
.github/workflows/update-supported-enterprise-server-versions/update.py
This file was deleted.
Oops, something went wrong.
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,204 @@ | ||
| #!/usr/bin/env npx tsx | ||
|
|
||
| /* | ||
| * Tests for the update-ghes-versions.ts script | ||
| */ | ||
|
|
||
| import * as assert from "node:assert/strict"; | ||
| import { describe, it } from "node:test"; | ||
|
|
||
| import { | ||
| addWeeks, | ||
| determineSupportedRange, | ||
| type EnterpriseReleases, | ||
| parseEnterpriseVersion, | ||
| printEnterpriseVersion, | ||
| } from "./update-ghes-versions"; | ||
|
|
||
| describe("parseEnterpriseVersion", async () => { | ||
| await it("parses a two-component version string", () => { | ||
| const ver = parseEnterpriseVersion("3.10"); | ||
| assert.notEqual(ver, null); | ||
| assert.equal(ver!.major, 3); | ||
| assert.equal(ver!.minor, 10); | ||
| assert.equal(ver!.patch, 0); | ||
| }); | ||
|
|
||
| await it("parses a three-component version string", () => { | ||
| const ver = parseEnterpriseVersion("3.10.2"); | ||
| assert.notEqual(ver, null); | ||
| assert.equal(ver!.major, 3); | ||
| assert.equal(ver!.minor, 10); | ||
| assert.equal(ver!.patch, 2); | ||
| }); | ||
|
|
||
| await it("returns null for invalid input", () => { | ||
| assert.equal(parseEnterpriseVersion("not-a-version"), null); | ||
| }); | ||
| }); | ||
|
|
||
| describe("printEnterpriseVersion", async () => { | ||
| await it("prints only major.minor when patch is 0", () => { | ||
| const ver = parseEnterpriseVersion("3.10")!; | ||
| assert.equal(printEnterpriseVersion(ver), "3.10"); | ||
| }); | ||
|
|
||
| await it("includes patch when non-zero", () => { | ||
| const ver = parseEnterpriseVersion("3.10.2")!; | ||
| assert.equal(printEnterpriseVersion(ver), "3.10.2"); | ||
| }); | ||
| }); | ||
|
|
||
| describe("addWeeks", async () => { | ||
| await it("adds weeks to a date", () => { | ||
| const date = new Date("2025-01-01T00:00:00Z"); | ||
| const result = addWeeks(date, 2); | ||
| assert.equal(result.toISOString(), "2025-01-15T00:00:00.000Z"); | ||
| }); | ||
|
|
||
| await it("does not mutate the original date", () => { | ||
| const date = new Date("2025-01-01T00:00:00Z"); | ||
| addWeeks(date, 2); | ||
| assert.equal(date.toISOString(), "2025-01-01T00:00:00.000Z"); | ||
| }); | ||
| }); | ||
|
|
||
| /** | ||
| * Helper to build a release entry with a feature freeze and end-of-life date. | ||
| * Dates are ISO date strings (e.g. "2025-06-01"). | ||
| */ | ||
| function release(featureFreeze: string, end: string) { | ||
| return { feature_freeze: featureFreeze, end }; | ||
| } | ||
|
|
||
| describe("determineSupportedRange", async () => { | ||
| // A fixed "today" for deterministic tests. | ||
| const today = new Date("2025-06-15"); | ||
|
|
||
| const farPastEnd = "2020-01-01"; | ||
| const farFutureEnd = "2099-12-31"; | ||
| const farPastFreeze = "2020-01-01"; | ||
| const farFutureFreeze = "2099-12-31"; | ||
|
|
||
| await it("returns the only supported release as both min and max", () => { | ||
| const releases: EnterpriseReleases = { | ||
| "3.10": release(farPastFreeze, farFutureEnd), | ||
| }; | ||
| const result = determineSupportedRange( | ||
| today, | ||
| { minimumVersion: "3.10", maximumVersion: "3.10" }, | ||
| releases, | ||
| ); | ||
| assert.equal(result.minimumVersion, "3.10"); | ||
| assert.equal(result.maximumVersion, "3.10"); | ||
| }); | ||
|
|
||
| await it("determines the range from multiple supported releases", () => { | ||
| const releases: EnterpriseReleases = { | ||
| "3.10": release(farPastFreeze, farFutureEnd), | ||
| "3.11": release(farPastFreeze, farFutureEnd), | ||
| "3.12": release(farPastFreeze, farFutureEnd), | ||
| }; | ||
| const result = determineSupportedRange( | ||
| today, | ||
| { minimumVersion: "3.10", maximumVersion: "3.12" }, | ||
| releases, | ||
| ); | ||
| assert.equal(result.minimumVersion, "3.10"); | ||
| assert.equal(result.maximumVersion, "3.12"); | ||
| }); | ||
|
|
||
| await it("drops an end-of-life release from the minimum", () => { | ||
| const releases: EnterpriseReleases = { | ||
| // 3.10 has been end of life for a long time. | ||
| "3.10": release(farPastFreeze, farPastEnd), | ||
| "3.11": release(farPastFreeze, farFutureEnd), | ||
| "3.12": release(farPastFreeze, farFutureEnd), | ||
| }; | ||
| const result = determineSupportedRange( | ||
| today, | ||
| { minimumVersion: "3.10", maximumVersion: "3.12" }, | ||
| releases, | ||
| ); | ||
| assert.equal(result.minimumVersion, "3.11"); | ||
| assert.equal(result.maximumVersion, "3.12"); | ||
| }); | ||
|
|
||
| await it("bumps the maximum when a newer release's feature freeze has passed", () => { | ||
| const releases: EnterpriseReleases = { | ||
| "3.10": release(farPastFreeze, farFutureEnd), | ||
| "3.11": release(farPastFreeze, farFutureEnd), | ||
| // 3.12 has a feature freeze far in the past, so it should be picked up. | ||
| "3.12": release(farPastFreeze, farFutureEnd), | ||
| }; | ||
| const result = determineSupportedRange( | ||
| today, | ||
| // The stored maximum is 3.11, but 3.12 should be picked up. | ||
| { minimumVersion: "3.10", maximumVersion: "3.11" }, | ||
| releases, | ||
| ); | ||
| assert.equal(result.minimumVersion, "3.10"); | ||
| assert.equal(result.maximumVersion, "3.12"); | ||
| }); | ||
|
|
||
| await it("does not bump the maximum when feature freeze is far in the future", () => { | ||
| const releases: EnterpriseReleases = { | ||
| "3.10": release(farPastFreeze, farFutureEnd), | ||
| "3.11": release(farPastFreeze, farFutureEnd), | ||
| // 3.12 has a feature freeze far in the future, so it should NOT be picked up. | ||
| "3.12": release(farFutureFreeze, farFutureEnd), | ||
| }; | ||
| const result = determineSupportedRange( | ||
| today, | ||
| { minimumVersion: "3.10", maximumVersion: "3.11" }, | ||
| releases, | ||
| ); | ||
| assert.equal(result.minimumVersion, "3.10"); | ||
| assert.equal(result.maximumVersion, "3.11"); | ||
| }); | ||
|
|
||
| await it("ignores releases older than the first supported release (2.22)", () => { | ||
| const releases: EnterpriseReleases = { | ||
| "2.21": release(farPastFreeze, farFutureEnd), | ||
| "3.10": release(farPastFreeze, farFutureEnd), | ||
| "3.11": release(farPastFreeze, farFutureEnd), | ||
| }; | ||
| const result = determineSupportedRange( | ||
| today, | ||
| { minimumVersion: "3.10", maximumVersion: "3.11" }, | ||
| releases, | ||
| ); | ||
| // 2.21 is older than 2.22, so it should be ignored — 3.10 remains the minimum. | ||
| assert.equal(result.minimumVersion, "3.10"); | ||
| assert.equal(result.maximumVersion, "3.11"); | ||
| }); | ||
|
|
||
| await it("throws when no supported releases remain", () => { | ||
| const releases: EnterpriseReleases = { | ||
| // All releases are end of life. | ||
| "3.10": release(farPastFreeze, farPastEnd), | ||
| "3.11": release(farPastFreeze, farPastEnd), | ||
| }; | ||
| assert.throws( | ||
| () => | ||
| determineSupportedRange( | ||
| today, | ||
| { minimumVersion: "3.10", maximumVersion: "3.11" }, | ||
| releases, | ||
| ), | ||
| /Could not determine oldest supported release/, | ||
| ); | ||
| }); | ||
|
|
||
| await it("throws when maximumVersion is not a valid version", () => { | ||
| assert.throws( | ||
| () => | ||
| determineSupportedRange( | ||
| today, | ||
| { minimumVersion: "3.10", maximumVersion: "invalid" }, | ||
| {}, | ||
| ), | ||
| /is not a valid semantic version/, | ||
| ); | ||
| }); | ||
| }); |
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.