Skip to content

Commit a6129d3

Browse files
authored
Merge pull request #617 from epicweb-dev/cursor/node-26-workshops-61ab
Looped with AI review and addressed all valid feedback before merge.
2 parents 6c6cbcb + 9ea233e commit a6129d3

4 files changed

Lines changed: 64 additions & 18 deletions

File tree

other/update-workshops/index.js

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import fs from 'fs/promises'
22
import path from 'path'
33
import { fileURLToPath } from 'url'
44
import { execa } from 'execa'
5+
import semver from 'semver'
56

67
const __filename = fileURLToPath(import.meta.url)
78
const __dirname = path.dirname(__filename)
@@ -14,6 +15,7 @@ const GITHUB_TOKEN =
1415
process.env.WORKSHOP_UPDATE_TOKEN ?? process.env.GITHUB_TOKEN
1516
const USING_WORKSHOP_UPDATE_TOKEN = Boolean(process.env.WORKSHOP_UPDATE_TOKEN)
1617
const CONCURRENCY = 5
18+
const TARGET_NODE_VERSION = '26.0.0'
1719
const ADDITIONAL_WORKSHOP_REPOS = ['ai-powered-apps', 'workshop-template']
1820

1921
if (!GITHUB_TOKEN) {
@@ -138,6 +140,42 @@ async function getLatestVersion() {
138140
}
139141
}
140142

143+
async function getPublishedWorkshopAppNodeRange(version) {
144+
try {
145+
const { stdout } = await execa('npm', [
146+
'show',
147+
`@epic-web/workshop-app@${version}`,
148+
'engines.node',
149+
])
150+
return stdout.trim()
151+
} catch (error) {
152+
console.error(
153+
`❌ Failed to get @epic-web/workshop-app@${version} node engine:`,
154+
error.message,
155+
)
156+
throw error
157+
}
158+
}
159+
160+
async function verifyWorkshopAppSupportsTargetNode(version) {
161+
const nodeRange = await getPublishedWorkshopAppNodeRange(version)
162+
if (!nodeRange) {
163+
throw new Error(
164+
`@epic-web/workshop-app@${version} does not publish an engines.node range`,
165+
)
166+
}
167+
168+
if (!semver.satisfies(TARGET_NODE_VERSION, nodeRange)) {
169+
throw new Error(
170+
`@epic-web/workshop-app@${version} supports Node ${nodeRange}, not Node ${TARGET_NODE_VERSION}. Aborting before updating workshops.`,
171+
)
172+
}
173+
174+
console.log(
175+
`✅ @epic-web/workshop-app@${version} supports Node ${TARGET_NODE_VERSION} (${nodeRange})`,
176+
)
177+
}
178+
141179
/**
142180
* Verify that the epicshop package is available on npm registry
143181
* This helps avoid 404 errors in workshop CI when npm registry replication is delayed
@@ -562,6 +600,7 @@ async function main() {
562600
console.log('📦 Getting latest version from npm...')
563601
const version = await getLatestVersion()
564602
console.log(`🔍 Updating to version ${version}`)
603+
await verifyWorkshopAppSupportsTargetNode(version)
565604

566605
// Verify that both epicshop and workshop-app are available on npm
567606
// before pushing updates to workshops to avoid 404 errors in workshop CI

other/update-workshops/package-lock.json

Lines changed: 14 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

other/update-workshops/package.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
},
88
"dependencies": {
99
"execa": "^9.6.1",
10-
"globby": "^16.2.0"
10+
"globby": "^16.2.0",
11+
"semver": "^7.8.5"
1112
}
1213
}

packages/workshop-cli/src/commands/start.test.ts

Lines changed: 9 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -15,30 +15,23 @@ const __dirname = path.dirname(fileURLToPath(import.meta.url))
1515
const repoRoot = path.resolve(__dirname, '..', '..', '..', '..')
1616

1717
const testIf = process.platform === 'win32' ? test.skip : test
18-
const nodeMajorVersion = Number(process.versions.node.split('.')[0])
19-
const typeScriptRunnerArgs =
20-
nodeMajorVersion >= 26 ? [] : ['--experimental-transform-types']
2118

2219
testIf(
2320
'start releases the child server port on shutdown',
2421
async () => {
2522
await using fixture = await createRunnerFixture()
2623
let child: ChildProcess | null = null
2724
try {
28-
child = spawn(
29-
process.execPath,
30-
[...typeScriptRunnerArgs, fixture.runnerPath],
31-
{
32-
cwd: repoRoot,
33-
env: {
34-
...process.env,
35-
EPICSHOP_APP_LOCATION: fixture.appDir,
36-
EPICSHOP_CONTEXT_CWD: fixture.appDir,
37-
NODE_ENV: 'development',
38-
},
39-
stdio: ['ignore', 'pipe', 'pipe'],
25+
child = spawn(process.execPath, [fixture.runnerPath], {
26+
cwd: repoRoot,
27+
env: {
28+
...process.env,
29+
EPICSHOP_APP_LOCATION: fixture.appDir,
30+
EPICSHOP_CONTEXT_CWD: fixture.appDir,
31+
NODE_ENV: 'development',
4032
},
41-
)
33+
stdio: ['ignore', 'pipe', 'pipe'],
34+
})
4235

4336
if (!child) {
4437
throw new Error('Failed to start runner process.')

0 commit comments

Comments
 (0)