From 65d67ce980053529a97a9fe589fa879807bc9222 Mon Sep 17 00:00:00 2001 From: Yoshiya Hinosawa Date: Tue, 17 Sep 2024 13:38:03 +0900 Subject: [PATCH] chore: check unstable module usage in stable modules (#5984) --- _tools/check_unstable_deps.ts | 74 +++++++++++++++++++++++++++++++++++ deno.json | 3 +- 2 files changed, 76 insertions(+), 1 deletion(-) create mode 100644 _tools/check_unstable_deps.ts diff --git a/_tools/check_unstable_deps.ts b/_tools/check_unstable_deps.ts new file mode 100644 index 000000000..78fea9893 --- /dev/null +++ b/_tools/check_unstable_deps.ts @@ -0,0 +1,74 @@ +// Copyright 2018-2024 the Deno authors. All rights reserved. MIT license. +// deno-lint-ignore-file no-console + +/** + * This script checks if the stable modules import the unstable modules. + * + * Usage: `deno run -A _tools/check_unstable_deps.ts` + * + * @module + */ + +// These 2 paths are known to include unstable module (net/unstable_get_network_address.ts) +// and should be ignored. +const EXCEPTIONS = [ + "std/http/file_server.ts", + "std/http/mod.ts", +]; + +import denoJson from "../deno.json" with { type: "json" }; +import { join } from "@std/path/unstable-join"; +import { greaterOrEqual, parse } from "@std/semver"; +import { zip } from "@std/collections/zip"; +import { resolveWorkspaceSpecifiers } from "./utils.ts"; +import { createGraph } from "@deno/graph"; + +type DenoJson = { version: string; exports: Record }; +function readDenoJson(path: string): Promise { + return Deno.readTextFile(join(path, "deno.json")).then(JSON.parse); +} +const semver1 = parse("1.0.0"); +function isStable(version: string) { + return greaterOrEqual(parse(version), semver1); +} + +const { workspace } = denoJson; +const packages = zip(workspace, await Promise.all(workspace.map(readDenoJson))); +const stablePackages = packages.filter(([_, { version }]) => isStable(version)); +const unstablePackagePaths = packages + .filter(([_, { version }]) => !isStable(version)) + .map(([path]) => join("std", path)); +const stableEntrypoints = stablePackages.flatMap(([dir, { exports }]) => + Object.values(exports) + .filter((path) => !path.includes("unstable_")) + .map((path) => new URL(`../${dir}/${path}`, import.meta.url).href) +); + +function isUnstableModule(specifier: string) { + return unstablePackagePaths.some((path) => specifier.includes(path)) || + specifier.includes("unstable_"); +} + +let hasError = false; +for (const path of stableEntrypoints) { + if (EXCEPTIONS.some((exception) => path.endsWith(exception))) { + console.log(`Skip checking ${path}`); + continue; + } + const graph = await createGraph(path, { + resolve: resolveWorkspaceSpecifiers, + }); + const dependencySpecifiers = graph.modules.map((m) => m.specifier); + const unstableDependencies = dependencySpecifiers.filter(isUnstableModule); + if (unstableDependencies.length > 0) { + console.error( + `Stable module ${path} imports unstable modules:`, + unstableDependencies, + ); + hasError = true; + } +} +if (hasError) { + Deno.exit(1); +} +console.log("No unstable module is used in stable modules."); diff --git a/deno.json b/deno.json index 32b8da129..ddcc9d865 100644 --- a/deno.json +++ b/deno.json @@ -18,7 +18,8 @@ "lint:tools-types": "deno check _tools/*.ts", "lint:docs": "deno run -A _tools/check_docs.ts", "lint:import-map": "deno run -A _tools/check_import_map.ts", - "lint": "deno lint && deno task fmt:licence-headers --check && deno task lint:circular && deno task lint:deprecations && deno task lint:tools-types && deno task lint:mod-exports && deno task lint:import-map && deno task lint:docs", + "lint:unstable-deps": "deno run -A _tools/check_unstable_deps.ts", + "lint": "deno lint && deno task fmt:licence-headers --check && deno task lint:circular && deno task lint:deprecations && deno task lint:tools-types && deno task lint:mod-exports && deno task lint:import-map && deno task lint:docs && deno task lint:unstable-deps", "typos": "typos -c ./.github/workflows/typos.toml", "build:crypto": "deno task --cwd crypto/_wasm wasmbuild", "wasmbuild": "deno run -A jsr:@deno/wasmbuild@0.17.1 --js-ext mjs --sync",