1
0
mirror of https://github.com/home-assistant/frontend.git synced 2026-07-04 13:05:06 +01:00
Files
frontend/build-scripts/gulp/licenses.js
Bram Kragten 2c8d6c1a02 Add Playwright e2e tests for demo, test app, and gallery
Adds Playwright end-to-end tests covering three targets:
- the demo build
- a new lightweight test app exercising several scenarios (theming,
  admin/non-admin sidebar, panel navigation, more-info dialog)
- the component gallery

Includes the gulp/rspack build infra for the test app and an "E2E Tests"
GitHub Actions workflow that builds each target once, shares it via
artifacts, and runs the suites on Chromium and mobile Chrome. Browser
install is cached and retried to avoid intermittent download stalls.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-17 10:49:08 +02:00

122 lines
4.1 KiB
JavaScript

// Gulp task to generate third-party license notices.
import { readFile, access, readdir } from "fs/promises";
import { generateLicenseFile } from "generate-license-file";
import gulp from "gulp";
import path from "path";
import paths from "../paths.cjs";
const OUTPUT_FILE = path.join(
paths.app_output_static,
"third-party-licenses.txt"
);
const NODE_MODULES = path.resolve(paths.root_dir, "node_modules");
// The echarts package ships an Apache-2.0 NOTICE file that must be
// redistributed alongside the compiled output per Apache License §4(d).
const NOTICE_FILES = [path.join(NODE_MODULES, "echarts/NOTICE")];
// Some packages need a manual license override (e.g. they ship multiple
// license files and we must pick the right one for the bundled code).
//
// Each entry is pinned to a specific version. If a package is updated,
// this list must be reviewed and the version updated after verifying
// that the new version's license still matches. The build will fail if
// the pinned version is no longer installed.
const LICENSE_OVERRIDES = [
{
// type-fest ships two license files (MIT for code, CC0 for types).
// We use the MIT license since that covers the bundled code.
packageName: "type-fest",
version: "5.7.0",
licenseFile: "license-mit",
},
];
// Locate the directory of an installed package matching an exact version.
//
// The copy we care about may be hoisted to the top-level node_modules or
// nested under a dependency when a different version occupies the hoisted
// slot (e.g. a build-only dependency pulling in an older release). Searching
// both keeps this check independent of yarn's hoisting decisions, which can
// shift when unrelated dependencies are added.
async function findPackageDir(packageName, version) {
const candidateDirs = [path.join(NODE_MODULES, packageName)];
// Collect one level of nesting: node_modules/<dep>/node_modules/<pkg> and
// node_modules/@scope/<dep>/node_modules/<pkg>.
let topLevel = [];
try {
topLevel = await readdir(NODE_MODULES, { withFileTypes: true });
} catch {
// node_modules unreadable — fall back to the hoisted candidate only.
}
for (const entry of topLevel) {
if (!entry.isDirectory() || entry.name === packageName) {
continue;
}
if (entry.name.startsWith("@")) {
const scopeDir = path.join(NODE_MODULES, entry.name);
// eslint-disable-next-line no-await-in-loop
const scoped = await readdir(scopeDir, { withFileTypes: true }).catch(
() => []
);
for (const dep of scoped) {
if (dep.isDirectory()) {
candidateDirs.push(
path.join(scopeDir, dep.name, "node_modules", packageName)
);
}
}
} else {
candidateDirs.push(
path.join(NODE_MODULES, entry.name, "node_modules", packageName)
);
}
}
for (const dir of candidateDirs) {
// eslint-disable-next-line no-await-in-loop
const pkg = await readFile(path.join(dir, "package.json"), "utf-8")
.then(JSON.parse)
.catch(() => null);
if (pkg?.version === version) {
return dir;
}
}
return null;
}
gulp.task("gen-licenses", async () => {
const licenseOverrides = {};
for (const { packageName, version, licenseFile } of LICENSE_OVERRIDES) {
// eslint-disable-next-line no-await-in-loop
const packageDir = await findPackageDir(packageName, version);
if (!packageDir) {
throw new Error(
`License override for "${packageName}" is pinned to version ${version}, but that version is not installed. ` +
`Please verify the new version's license and update the override in build-scripts/gulp/licenses.js.`
);
}
const licensePath = path.join(packageDir, licenseFile);
try {
// eslint-disable-next-line no-await-in-loop
await access(licensePath);
} catch {
throw new Error(`License file not found or unreadable: ${licensePath}`);
}
licenseOverrides[`${packageName}@${version}`] = licensePath;
}
await generateLicenseFile(
path.resolve(paths.root_dir, "package.json"),
OUTPUT_FILE,
{ append: NOTICE_FILES, replace: licenseOverrides }
);
});