Skip to content

Commit 14a10f7

Browse files
committed
Add Babel 8 preset smoke
1 parent dc1f658 commit 14a10f7

2 files changed

Lines changed: 232 additions & 3 deletions

File tree

.github/workflows/node.yml

Lines changed: 28 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -82,8 +82,7 @@ jobs:
8282
git fetch origin ${{ github.event.pull_request.base.sha }}
8383
if git diff --name-only ${{ github.event.pull_request.base.sha }} ${{ github.sha }} | grep -q '^.github/workflows'; then
8484
echo "changed=true" >> "$GITHUB_OUTPUT"
85-
response=$(curl -sf https://api.github.com/repos/rhysd/actionlint/releases/latest)
86-
if [ $? -eq 0 ]; then
85+
if response=$(curl -sf https://api.github.com/repos/rhysd/actionlint/releases/latest); then
8786
actionlint_version=$(echo "$response" | jq -r .tag_name)
8887
if [ -z "$actionlint_version" ]; then
8988
echo "Failed to parse Actionlint version"
@@ -141,7 +140,7 @@ jobs:
141140
--skipLibCheck \
142141
--moduleResolution bundler \
143142
--types node \
144-
*.d.ts
143+
./*.d.ts
145144
test:
146145
name: Testing
147146
strategy:
@@ -169,3 +168,29 @@ jobs:
169168

170169
- name: Jest Specs
171170
run: yarn test
171+
172+
babel8-smoke:
173+
name: Babel 8 smoke
174+
runs-on: ubuntu-latest
175+
176+
steps:
177+
- uses: actions/checkout@v4
178+
with:
179+
persist-credentials: false
180+
- name: Use Node.js 24
181+
uses: actions/setup-node@v4
182+
with:
183+
node-version: "24.x"
184+
cache: yarn
185+
186+
- name: Install dependencies
187+
run: yarn --frozen-lockfile --non-interactive --prefer-offline
188+
189+
- name: Build TypeScript
190+
run: yarn build
191+
192+
- name: Babel 8 smoke
193+
run: yarn jest test/package/babel8-smoke.test.js --runInBand
194+
env:
195+
BABEL_ENV: production
196+
RUN_BABEL8_SMOKE: "1"

test/package/babel8-smoke.test.js

Lines changed: 204 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,204 @@
1+
// Opt-in Babel 8 compatibility smoke.
2+
//
3+
// The normal test suite intentionally keeps repository development pins on
4+
// Babel 7. Enable this smoke with RUN_BABEL8_SMOKE=1 after `yarn build`; it
5+
// installs Babel 8 packages into a temp app and runs Webpack through
6+
// babel-loader 10 with Shakapacker's built Babel preset.
7+
8+
const { spawnSync } = require("child_process")
9+
const fs = require("fs")
10+
const { createRequire } = require("module")
11+
const os = require("os")
12+
const path = require("path")
13+
const webpack = require("webpack")
14+
15+
const repoRoot = path.resolve(__dirname, "../..")
16+
const builtPackageFiles = [
17+
"package/babel/preset.js",
18+
"package/utils/errorCodes.js",
19+
"package/utils/errorHelpers.js",
20+
"package/utils/helpers.js"
21+
]
22+
const babel8SmokePackages = [
23+
"@babel/core@8.0.1",
24+
"@babel/plugin-transform-runtime@8.0.1",
25+
"@babel/preset-env@8.0.2",
26+
"@babel/runtime@8.0.0",
27+
"babel-loader@10.1.1"
28+
]
29+
const optedIn = process.env.RUN_BABEL8_SMOKE === "1"
30+
const coreIsBuilt = builtPackageFiles.every((file) =>
31+
fs.existsSync(path.join(repoRoot, file))
32+
)
33+
34+
const toolVersion = (cmd) => {
35+
const r = spawnSync(cmd, ["--version"], {
36+
encoding: "utf8",
37+
cwd: os.tmpdir()
38+
})
39+
return r.status === 0 ? r.stdout.trim() : null
40+
}
41+
42+
const npmVersion = toolVersion("npm")
43+
const hasNpm = npmVersion !== null
44+
const shouldRun = optedIn && coreIsBuilt && hasNpm
45+
46+
const run = (cmd, args, options) => {
47+
const r = spawnSync(cmd, args, { encoding: "utf8", ...options })
48+
if (r.status !== 0) {
49+
throw new Error(
50+
`${cmd} ${args.join(" ")} failed in ${options.cwd}\nstdout:\n${r.stdout}\nstderr:\n${r.stderr}`
51+
)
52+
}
53+
return r
54+
}
55+
56+
const packageVersion = (appRequire, packageName) => {
57+
const packageJsonPath = appRequire.resolve(`${packageName}/package.json`)
58+
return appRequire(packageJsonPath).version
59+
}
60+
61+
const installBuiltShakapackerPackage = (workRoot) => {
62+
const packageRoot = path.join(workRoot, "node_modules/shakapacker")
63+
fs.mkdirSync(packageRoot, { recursive: true })
64+
fs.writeFileSync(
65+
path.join(packageRoot, "package.json"),
66+
JSON.stringify(
67+
{ name: "shakapacker", version: "0.0.0-babel8-smoke", private: true },
68+
null,
69+
2
70+
)
71+
)
72+
73+
builtPackageFiles.forEach((relativePath) => {
74+
const targetPath = path.join(packageRoot, relativePath)
75+
fs.mkdirSync(path.dirname(targetPath), { recursive: true })
76+
fs.copyFileSync(path.join(repoRoot, relativePath), targetPath)
77+
})
78+
}
79+
80+
const runWebpack = (config) =>
81+
new Promise((resolve, reject) => {
82+
const compiler = webpack(config)
83+
compiler.run((error, stats) => {
84+
let resultError = error
85+
86+
if (!resultError && stats.hasErrors()) {
87+
resultError = new Error(stats.toString({ all: false, errors: true }))
88+
}
89+
90+
compiler.close((closeError) => {
91+
if (closeError) {
92+
reject(closeError)
93+
return
94+
}
95+
96+
if (resultError) {
97+
reject(resultError)
98+
return
99+
}
100+
101+
resolve(stats)
102+
})
103+
})
104+
})
105+
106+
const computeSkipReason = () => {
107+
if (!optedIn) return "RUN_BABEL8_SMOKE=1 not set"
108+
if (!coreIsBuilt) return "shakapacker not built (run `yarn build`)"
109+
if (!hasNpm) return "npm unavailable on PATH"
110+
return "unknown skip reason"
111+
}
112+
113+
describe("Babel 8 preset smoke (issue #1191)", () => {
114+
let workRoot
115+
let presetPath
116+
117+
beforeAll(() => {
118+
if (!shouldRun) return
119+
120+
workRoot = fs.mkdtempSync(path.join(os.tmpdir(), "shaka-babel8-smoke-"))
121+
fs.writeFileSync(
122+
path.join(workRoot, "package.json"),
123+
JSON.stringify({ name: "shaka-babel8-smoke", private: true }, null, 2)
124+
)
125+
run(
126+
"npm",
127+
[
128+
"install",
129+
"--no-audit",
130+
"--no-fund",
131+
"--save-dev",
132+
...babel8SmokePackages
133+
],
134+
{ cwd: workRoot }
135+
)
136+
installBuiltShakapackerPackage(workRoot)
137+
}, 180000)
138+
139+
afterAll(() => {
140+
if (!workRoot) return
141+
fs.rmSync(workRoot, { recursive: true, force: true })
142+
})
143+
144+
if (!shouldRun) {
145+
test.todo(`Babel 8 smoke skipped (${computeSkipReason()})`)
146+
return
147+
}
148+
149+
test("compiles through babel-loader 10 with the Shakapacker Babel preset and Babel 8", async () => {
150+
const srcDir = path.join(workRoot, "src")
151+
const distDir = path.join(workRoot, "dist")
152+
fs.mkdirSync(srcDir)
153+
fs.writeFileSync(
154+
path.join(srcDir, "index.js"),
155+
"const answer = () => ({ value: 42 });\nconsole.log(answer()?.value);\n"
156+
)
157+
158+
const appRequire = createRequire(path.join(workRoot, "package.json"))
159+
presetPath = appRequire.resolve("shakapacker/package/babel/preset.js")
160+
expect(packageVersion(appRequire, "@babel/core")).toBe("8.0.1")
161+
expect(packageVersion(appRequire, "@babel/preset-env")).toBe("8.0.2")
162+
expect(packageVersion(appRequire, "@babel/plugin-transform-runtime")).toBe(
163+
"8.0.1"
164+
)
165+
expect(packageVersion(appRequire, "@babel/runtime")).toBe("8.0.0")
166+
expect(packageVersion(appRequire, "babel-loader")).toBe("10.1.1")
167+
168+
await runWebpack({
169+
mode: "development",
170+
context: workRoot,
171+
entry: path.join(srcDir, "index.js"),
172+
output: {
173+
path: distDir,
174+
filename: "bundle.js"
175+
},
176+
module: {
177+
rules: [
178+
{
179+
test: /\.js$/,
180+
include: srcDir,
181+
use: [
182+
{
183+
loader: appRequire.resolve("babel-loader"),
184+
options: {
185+
cacheDirectory: false,
186+
cwd: workRoot,
187+
envName: "production",
188+
presets: [presetPath]
189+
}
190+
}
191+
]
192+
}
193+
]
194+
},
195+
optimization: {
196+
minimize: false
197+
}
198+
})
199+
200+
expect(fs.readFileSync(path.join(distDir, "bundle.js"), "utf8")).toContain(
201+
"42"
202+
)
203+
}, 180000)
204+
})

0 commit comments

Comments
 (0)