Skip to content

Commit 976c4f6

Browse files
committed
Add Babel 8 preset smoke
1 parent dc1f658 commit 976c4f6

3 files changed

Lines changed: 304 additions & 3 deletions

File tree

.github/workflows/babel8-smoke.yml

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
name: Babel 8 smoke
2+
3+
on:
4+
push:
5+
branches:
6+
- "main"
7+
paths:
8+
- ".github/workflows/babel8-smoke.yml"
9+
- "package.json"
10+
- "yarn.lock"
11+
- "package/babel/**"
12+
- "package/rules/babel.ts"
13+
- "package/utils/**"
14+
- "test/packages/babel8-smoke.test.js"
15+
pull_request:
16+
paths:
17+
- ".github/workflows/babel8-smoke.yml"
18+
- "package.json"
19+
- "yarn.lock"
20+
- "package/babel/**"
21+
- "package/rules/babel.ts"
22+
- "package/utils/**"
23+
- "test/packages/babel8-smoke.test.js"
24+
workflow_dispatch:
25+
26+
concurrency:
27+
group: ${{ github.workflow }}-${{ github.ref }}
28+
cancel-in-progress: true
29+
30+
jobs:
31+
babel8-smoke:
32+
name: Babel 8 smoke
33+
runs-on: ubuntu-latest
34+
timeout-minutes: 10
35+
36+
steps:
37+
- uses: actions/checkout@v4
38+
with:
39+
persist-credentials: false
40+
41+
- name: Use Node.js 22
42+
uses: actions/setup-node@v4
43+
with:
44+
node-version: "22.x"
45+
cache: yarn
46+
47+
- name: Install dependencies
48+
run: yarn --frozen-lockfile --non-interactive --prefer-offline
49+
50+
- name: Build TypeScript
51+
run: yarn build
52+
53+
- name: Babel 8 smoke
54+
run: yarn jest test/packages/babel8-smoke.test.js --runInBand
55+
env:
56+
BABEL_ENV: production
57+
RUN_BABEL8_SMOKE: "1"

.github/workflows/node.yml

Lines changed: 2 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:

test/packages/babel8-smoke.test.js

Lines changed: 245 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,245 @@
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+
14+
const repoRoot = path.resolve(__dirname, "../..")
15+
const builtPackageDir = path.join(repoRoot, "package")
16+
const builtPresetPath = path.join(builtPackageDir, "babel/preset.js")
17+
const webpackPath = require.resolve("webpack")
18+
const babel8SmokePackages = [
19+
"@babel/core@8.0.1",
20+
"@babel/plugin-transform-runtime@8.0.1",
21+
"@babel/preset-env@8.0.2",
22+
"@babel/runtime@8.0.0",
23+
"babel-loader@10.1.1"
24+
]
25+
const optedIn = process.env.RUN_BABEL8_SMOKE === "1"
26+
const coreIsBuilt = fs.existsSync(builtPresetPath)
27+
28+
const toolVersion = (cmd) => {
29+
const r = spawnSync(cmd, ["--version"], {
30+
encoding: "utf8",
31+
cwd: os.tmpdir()
32+
})
33+
return r.status === 0 ? r.stdout.trim() : null
34+
}
35+
36+
const npmVersion = toolVersion("npm")
37+
const hasNpm = npmVersion !== null
38+
const shouldRun = optedIn && coreIsBuilt && hasNpm
39+
40+
const run = (cmd, args, options) => {
41+
const r = spawnSync(cmd, args, {
42+
encoding: "utf8",
43+
timeout: 180000,
44+
...options
45+
})
46+
if (r.status !== 0) {
47+
throw new Error(
48+
`${cmd} ${args.join(" ")} failed in ${options.cwd}\nstdout:\n${r.stdout}\nstderr:\n${r.stderr}`
49+
)
50+
}
51+
return r
52+
}
53+
54+
const packageVersion = (appRequire, packageName) => {
55+
const packageJsonPath = appRequire.resolve(`${packageName}/package.json`)
56+
return appRequire(packageJsonPath).version
57+
}
58+
59+
const installBuiltShakapackerPackage = (workRoot) => {
60+
const packageRoot = path.join(workRoot, "node_modules/shakapacker")
61+
const sourcePackageJson = JSON.parse(
62+
fs.readFileSync(path.join(repoRoot, "package.json"), "utf8")
63+
)
64+
fs.mkdirSync(packageRoot, { recursive: true })
65+
fs.writeFileSync(
66+
path.join(packageRoot, "package.json"),
67+
JSON.stringify(
68+
{
69+
name: sourcePackageJson.name,
70+
version: sourcePackageJson.version,
71+
private: true,
72+
main: sourcePackageJson.main,
73+
exports: sourcePackageJson.exports,
74+
files: sourcePackageJson.files
75+
},
76+
null,
77+
2
78+
)
79+
)
80+
81+
fs.cpSync(builtPackageDir, path.join(packageRoot, "package"), {
82+
recursive: true
83+
})
84+
}
85+
86+
const writeWebpackSmokeRunner = ({ workRoot, srcDir, distDir, presetPath }) => {
87+
const runnerPath = path.join(workRoot, "run-webpack-smoke.cjs")
88+
fs.writeFileSync(
89+
runnerPath,
90+
`
91+
const { createRequire } = require("module")
92+
const path = require("path")
93+
const webpack = require(${JSON.stringify(webpackPath)})
94+
95+
const workRoot = ${JSON.stringify(workRoot)}
96+
const srcDir = ${JSON.stringify(srcDir)}
97+
const distDir = ${JSON.stringify(distDir)}
98+
const presetPath = ${JSON.stringify(presetPath)}
99+
const appRequire = createRequire(path.join(workRoot, "package.json"))
100+
101+
const compiler = webpack({
102+
mode: "development",
103+
context: workRoot,
104+
entry: path.join(srcDir, "index.js"),
105+
output: {
106+
path: distDir,
107+
filename: "bundle.js"
108+
},
109+
module: {
110+
rules: [
111+
{
112+
test: /\\.js$/,
113+
include: srcDir,
114+
use: [
115+
{
116+
loader: appRequire.resolve("babel-loader"),
117+
options: {
118+
cacheDirectory: false,
119+
cwd: workRoot,
120+
envName: "production",
121+
presets: [presetPath]
122+
}
123+
}
124+
]
125+
}
126+
]
127+
},
128+
optimization: {
129+
minimize: false
130+
}
131+
})
132+
133+
const finish = (failure) => {
134+
compiler.close((closeError) => {
135+
const finalError = closeError || failure
136+
if (finalError) {
137+
console.error(finalError.stack || finalError.message || String(finalError))
138+
process.exit(1)
139+
}
140+
})
141+
}
142+
143+
compiler.run((error, stats) => {
144+
if (error) {
145+
finish(error)
146+
return
147+
}
148+
149+
if (stats.hasErrors()) {
150+
finish(
151+
new Error(
152+
stats.toString({
153+
all: false,
154+
errors: true,
155+
errorDetails: true,
156+
moduleTrace: true
157+
})
158+
)
159+
)
160+
return
161+
}
162+
163+
finish()
164+
})
165+
`
166+
)
167+
return runnerPath
168+
}
169+
170+
const computeSkipReason = () => {
171+
if (!optedIn) return "RUN_BABEL8_SMOKE=1 not set"
172+
if (!coreIsBuilt) return "shakapacker not built (run `yarn build`)"
173+
if (!hasNpm) return "npm unavailable on PATH"
174+
return "unknown skip reason"
175+
}
176+
177+
describe("Babel 8 preset smoke (issue #1191)", () => {
178+
let workRoot
179+
180+
beforeAll(() => {
181+
if (!shouldRun) return
182+
183+
workRoot = fs.mkdtempSync(path.join(os.tmpdir(), "shaka-babel8-smoke-"))
184+
fs.writeFileSync(
185+
path.join(workRoot, "package.json"),
186+
JSON.stringify({ name: "shaka-babel8-smoke", private: true }, null, 2)
187+
)
188+
run(
189+
"npm",
190+
[
191+
"install",
192+
"--no-audit",
193+
"--no-fund",
194+
"--save-dev",
195+
...babel8SmokePackages
196+
],
197+
{ cwd: workRoot }
198+
)
199+
installBuiltShakapackerPackage(workRoot)
200+
}, 180000)
201+
202+
afterAll(() => {
203+
if (!workRoot) return
204+
fs.rmSync(workRoot, { recursive: true, force: true })
205+
})
206+
207+
if (!shouldRun) {
208+
test.todo(`Babel 8 smoke skipped (${computeSkipReason()})`)
209+
return
210+
}
211+
212+
test("compiles through babel-loader 10 with the Shakapacker Babel preset and Babel 8", () => {
213+
const srcDir = path.join(workRoot, "src")
214+
const distDir = path.join(workRoot, "dist")
215+
fs.mkdirSync(srcDir)
216+
const entryPath = path.join(srcDir, "index.js")
217+
fs.writeFileSync(entryPath, "var answer = 42;\nconsole.log(answer);\n")
218+
219+
const appRequire = createRequire(path.join(workRoot, "package.json"))
220+
const presetPath = appRequire.resolve("shakapacker/package/babel/preset.js")
221+
expect(packageVersion(appRequire, "@babel/core")).toBe("8.0.1")
222+
expect(packageVersion(appRequire, "@babel/preset-env")).toBe("8.0.2")
223+
expect(packageVersion(appRequire, "@babel/plugin-transform-runtime")).toBe(
224+
"8.0.1"
225+
)
226+
expect(packageVersion(appRequire, "@babel/runtime")).toBe("8.0.0")
227+
expect(packageVersion(appRequire, "babel-loader")).toBe("10.1.1")
228+
229+
const runnerPath = writeWebpackSmokeRunner({
230+
workRoot,
231+
srcDir,
232+
distDir,
233+
presetPath
234+
})
235+
236+
run(process.execPath, [runnerPath], {
237+
cwd: workRoot,
238+
env: { ...process.env, BABEL_ENV: "production" }
239+
})
240+
241+
expect(fs.readFileSync(path.join(distDir, "bundle.js"), "utf8")).toContain(
242+
"42"
243+
)
244+
}, 180000)
245+
})

0 commit comments

Comments
 (0)