Skip to content

Commit

Permalink
H-3689: Replace check-dependency-version-consistency with yarn cons…
Browse files Browse the repository at this point in the history
…traints (#5769)
  • Loading branch information
indietyp authored Dec 3, 2024
1 parent c311b1f commit 6a10e5e
Show file tree
Hide file tree
Showing 12 changed files with 106 additions and 204 deletions.
1 change: 0 additions & 1 deletion .github/actions/prune-repository/action.yml
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,6 @@ runs:
if [[ ! -f "out/$DIRECTORY/Cargo.toml" ]]; then
mkdir -p "out/$DIRECTORY/src"
echo > "out/$DIRECTORY/src/lib.rs"
echo "cargo-features = [\"edition2024\"]" > "out/$DIRECTORY/Cargo.toml"
echo "[package]" >> "out/$DIRECTORY/Cargo.toml"
echo "name = \"$(yq '.package.name' -p toml -oy $line)\"" >> "out/$DIRECTORY/Cargo.toml"
echo "edition.workspace = true" >> "out/$DIRECTORY/Cargo.toml"
Expand Down
6 changes: 3 additions & 3 deletions .github/workflows/lint.yml
Original file line number Diff line number Diff line change
Expand Up @@ -215,14 +215,14 @@ jobs:
cargo -Zscript run --manifest-path ".github/scripts/rust/sync-turborepo.rs" . | xargs yarn prettier --write >/dev/null
git --no-pager diff --exit-code --color '**/package.json'
- name: Run yarn lint:dependency-version-consistency
- name: Run yarn lint:constraints
if: ${{ success() || failure() }}
run: |
if ! yarn lint:dependency-version-consistency; then
if ! yarn lint:constraints; then
echo ''
echo ''
echo 'ℹ️ ℹ️ ℹ️'
echo 'Try running `yarn fix:dependency-version-consistency` locally to apply autofixes.'
echo 'Try running `yarn fix:constraints` locally to apply autofixes.'
echo 'ℹ️ ℹ️ ℹ️'
exit 1
fi
Expand Down
5 changes: 2 additions & 3 deletions apps/hash-ai-worker-ts/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -34,9 +34,9 @@
"lint:tsc": "tsc --noEmit",
"sanitize-html": "NODE_ENV=development yarn exe ./scripts/sanitize-html.ts",
"sentry:sourcemaps": "sentry-cli sourcemaps inject --org hashintel --project hash-temporal-worker-ai ./dist && sentry-cli sourcemaps upload --org hashintel --project hash-temporal-worker-ai ./dist",
"start": "cross-env NODE_ENV=production NODE_OPTIONS=--max-old-space-size=2048 node ./dist/main.js",
"start": "NODE_ENV=production NODE_OPTIONS=--max-old-space-size=2048 node ./dist/main.js",
"start:healthcheck": "wait-on --timeout 120000 http-get://localhost:4100/health",
"start:test": "cross-env NODE_ENV=test NODE_OPTIONS=--max-old-space-size=2048 node ./dist/main.js",
"start:test": "NODE_ENV=test NODE_OPTIONS=--max-old-space-size=2048 node ./dist/main.js",
"start:test:healthcheck": "wait-on --timeout 120000 http-get://localhost:4100/health",
"test:unit": "vitest --run --exclude \"**/*.ai.test.ts\""
},
Expand Down Expand Up @@ -110,7 +110,6 @@
"@types/papaparse": "5.3.15",
"@types/sanitize-html": "2.13.0",
"@vitest/coverage-istanbul": "2.1.8",
"cross-env": "7.0.3",
"eslint": "8.57.0",
"rimraf": "6.0.1",
"typescript": "5.6.3",
Expand Down
5 changes: 2 additions & 3 deletions apps/hash-api/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,10 @@
"generate-ontology-type-ids": "tsx ./src/generate-ontology-type-ids.ts; yarn prettier --write ../../libs/@local/hash-isomorphic-utils/src/ontology-type-ids.ts",
"lint:eslint": "eslint --report-unused-disable-directives .",
"lint:tsc": "tsc --noEmit",
"start": "cross-env NODE_ENV=production NODE_OPTIONS=--max-old-space-size=2048 tsx ./src/index.ts",
"start": "NODE_ENV=production NODE_OPTIONS=--max-old-space-size=2048 tsx ./src/index.ts",
"start:healthcheck": "wait-on --timeout 300000 http://0.0.0.0:5001",
"start:migrate": "NODE_ENV=production tsx ./src/ensure-system-graph-is-initialized.ts",
"start:test": "cross-env NODE_ENV=test NODE_OPTIONS=--max-old-space-size=2048 tsx ./src/index.ts",
"start:test": "NODE_ENV=test NODE_OPTIONS=--max-old-space-size=2048 tsx ./src/index.ts",
"start:test:healthcheck": "wait-on --timeout 300000 http://0.0.0.0:5001",
"start:test:migrate": "NODE_ENV=test tsx ./src/ensure-system-graph-is-initialized.ts",
"test:unit": "vitest --run"
Expand Down Expand Up @@ -122,7 +122,6 @@
"@types/mime-types": "2.1.4",
"@types/nodemailer": "6.4.17",
"@vitest/coverage-istanbul": "2.1.8",
"cross-env": "7.0.3",
"eslint": "8.57.0",
"prettier": "3.4.1",
"rimraf": "6.0.1",
Expand Down
5 changes: 2 additions & 3 deletions apps/hash-integration-worker/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,9 @@
"lint:eslint": "eslint --report-unused-disable-directives .",
"lint:tsc": "tsc --noEmit",
"sentry:sourcemaps": "sentry-cli sourcemaps inject --org hashintel --project hash-temporal-worker-integration ./dist && sentry-cli sourcemaps upload --org hashintel --project hash-temporal-worker-integration ./dist",
"start": "cross-env NODE_ENV=production NODE_OPTIONS=--max-old-space-size=2048 tsx ./src/main.ts",
"start": "NODE_ENV=production NODE_OPTIONS=--max-old-space-size=2048 tsx ./src/main.ts",
"start:healthcheck": "wait-on --timeout 120000 http-get://localhost:4300/health",
"start:test": "cross-env NODE_ENV=test NODE_OPTIONS=--max-old-space-size=2048 tsx ./dist/main.js",
"start:test": "NODE_ENV=test NODE_OPTIONS=--max-old-space-size=2048 tsx ./dist/main.js",
"start:test:healthcheck": "wait-on --timeout 120000 http-get://localhost:4300/health"
},
"dependencies": {
Expand Down Expand Up @@ -44,7 +44,6 @@
"@local/tsconfig": "0.0.0-private",
"@sentry/cli": "^2.39.1",
"@types/dotenv-flow": "3.3.3",
"cross-env": "7.0.3",
"eslint": "8.57.0",
"rimraf": "6.0.1",
"typescript": "5.6.3",
Expand Down
5 changes: 2 additions & 3 deletions apps/hash-realtime/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,8 @@
"fix:eslint": "eslint --fix .",
"lint:eslint": "eslint --report-unused-disable-directives .",
"lint:tsc": "tsc --noEmit",
"start": "cross-env NODE_ENV=production NODE_OPTIONS=--max-old-space-size=2048 tsx ./src/index.ts",
"start:test": "cross-env NODE_ENV=test NODE_OPTIONS=--max-old-space-size=2048 tsx ./src/index.ts"
"start": "NODE_ENV=production NODE_OPTIONS=--max-old-space-size=2048 tsx ./src/index.ts",
"start:test": "NODE_ENV=test NODE_OPTIONS=--max-old-space-size=2048 tsx ./src/index.ts"
},
"dependencies": {
"@local/hash-backend-utils": "0.0.0-private",
Expand All @@ -26,7 +26,6 @@
"@local/tsconfig": "0.0.0-private",
"@types/node": "22.10.0",
"@types/set-interval-async": "1.0.3",
"cross-env": "7.0.3",
"eslint": "8.57.0",
"typescript": "5.6.3"
}
Expand Down
3 changes: 1 addition & 2 deletions apps/hash-search-loader/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
"fix:eslint": "eslint --fix .",
"lint:eslint": "eslint --report-unused-disable-directives .",
"lint:tsc": "tsc --noEmit",
"start": "cross-env NODE_ENV=production NODE_OPTIONS=--max-old-space-size=2048 tsx ./src/index.ts"
"start": "NODE_ENV=production NODE_OPTIONS=--max-old-space-size=2048 tsx ./src/index.ts"
},
"dependencies": {
"@apps/hash-api": "0.0.0-private",
Expand All @@ -25,7 +25,6 @@
"@local/eslint-config": "0.0.0-private",
"@local/tsconfig": "0.0.0-private",
"@types/node": "22.10.0",
"cross-env": "7.0.3",
"eslint": "8.57.0",
"typescript": "5.6.3"
}
Expand Down
1 change: 0 additions & 1 deletion libs/@local/graph/client/typescript/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,6 @@
"@redocly/cli": "1.25.14",
"@rust/hash-graph-api": "0.0.0-private",
"@types/node": "22.10.0",
"eslint": "8.57.0",
"fix-esm-import-path": "1.10.1",
"rimraf": "6.0.1",
"typescript": "5.6.3"
Expand Down
1 change: 0 additions & 1 deletion libs/@local/internal-api-client/typescript/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,6 @@
"@local/eslint-config": "0.0.0-private",
"@openapitools/openapi-generator-cli": "2.15.3",
"@types/node": "22.10.0",
"eslint": "8.57.0",
"prettier": "3.4.1",
"rimraf": "6.0.1",
"typescript": "5.6.3"
Expand Down
14 changes: 5 additions & 9 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -36,15 +36,15 @@
"generate-ontology-type-ids": "yarn workspace @apps/hash-api generate-ontology-type-ids",
"fix": "npm-run-all --continue-on-error \"fix:*\"",
"@TODO.1": "Upgrade or remove these blocks and remove the --ignore-package options (also @TODO.2)",
"fix:dependency-version-consistency": "check-dependency-version-consistency --fix . --ignore-dep=@blockprotocol/graph --ignore-dep=@sentry/webpack-plugin --ignore-package=@apps/hashdotdev --ignore-package=@blocks/embed --ignore-package=@blocks/person",
"fix:constraints": "yarn constraints --fix",
"fix:eslint": "turbo --continue fix:eslint --",
"fix:taplo": "taplo fmt",
"fix:markdownlint": "markdownlint --dot --fix .",
"fix:prettier": "prettier --write --ignore-unknown .",
"fix:yarn-deduplicate": "yarn dedupe --strategy highest",
"lint": "npm-run-all --continue-on-error \"lint:*\"",
"@TODO.2": "Upgrade or remove these blocks and remove the --ignore-package options (also @TODO.1)",
"lint:dependency-version-consistency": "check-dependency-version-consistency . --ignore-dep=@blockprotocol/graph --ignore-dep=@sentry/webpack-plugin --ignore-package=@apps/hashdotdev --ignore-package=@blocks/embed --ignore-package=@blocks/person",
"lint:constraints": "yarn constraints",
"lint:eslint": "turbo --continue lint:eslint --",
"lint:license-in-workspaces": "yarn workspace @local/repo-chores exe scripts/check-license-in-workspaces.ts",
"lint:lockfile-lint": "lockfile-lint --path yarn.lock --type yarn --allowed-hosts npm yarn",
Expand All @@ -69,7 +69,8 @@
"lint-staged": {
"**": [
"suppress-exit-code markdownlint --fix",
"suppress-exit-code prettier --write"
"suppress-exit-code prettier --write",
"suppress-exit-code yarn constraints --fix"
]
},
"prettier": {
Expand Down Expand Up @@ -122,22 +123,17 @@
"@sentry/cli": "^2.39.1",
"@taplo/cli": "0.7.0",
"@yarnpkg/types": "^4.0.0",
"check-dependency-version-consistency": "3.0.3",
"concurrently": "7.6.0",
"cross-env": "7.0.3",
"dotenv-flow": "3.3.0",
"husky": "8.0.3",
"lint-staged": "15.2.10",
"lockfile-lint": "4.14.0",
"markdownlint-cli": "0.43.0",
"npm-run-all2": "7.0.1",
"postinstall-postinstall": "2.1.0",
"prettier": "3.4.1",
"prettier-plugin-packagejson": "2.5.6",
"prettier-plugin-sh": "0.14.0",
"suppress-exit-code": "3.2.0",
"turbo": "2.3.3",
"wait-on": "8.0.1"
"turbo": "2.3.3"
},
"packageManager": "[email protected]+sha512.3003a14012e2987072d244c720506549c1aab73ee728208f1b2580a9fd67b92d61ba6b08fe93f6dce68fd771e3af1e59a0afa28dd242dd0940d73b95fedd4e90"
}
136 changes: 86 additions & 50 deletions yarn.config.cjs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,31 @@
/** @type {import('@yarnpkg/types')} */
const { defineConfig } = require(`@yarnpkg/types`);

const enforcedDevDependencies = {
prettier: { commands: ["prettier"], ident: "prettier" },
waitOn: { commands: ["wait-on"], ident: "wait-on" },
rimraf: { commands: ["rimraf"], ident: "rimraf" },
eslint: { commands: ["eslint"], ident: "eslint" },
typescript: { commands: ["tsc", "ts-node"], ident: "typescript" },
crossEnv: { commands: ["cross-env"], ident: "cross-env" },
};

const ignoredDependencies = ["@blockprotocol/graph", "@sentry/webpack-plugin"];
const ignoredWorkspaces = [
"@apps/hashdotdev",
"@blocks/embed",
"@blocks/person",
];

/**
*
* @param {Dependency} dependency
*/
const shouldIgnoreDependency = (dependency) =>
ignoredDependencies.includes(dependency.ident) ||
ignoredWorkspaces.includes(dependency.workspace.ident) ||
dependency.type === "peerDependencies";

/**
* Enforces consistent dependency versions across all workspaces in the project.
*
Expand All @@ -15,18 +40,37 @@ const { defineConfig } = require(`@yarnpkg/types`);
*/
function enforceConsistentDependenciesAcrossTheProject({ Yarn }) {
for (const dependency of Yarn.dependencies()) {
if (dependency.type === `peerDependencies`) continue;
if (shouldIgnoreDependency(dependency)) {
continue;
}

for (const otherDependency of Yarn.dependencies({
ident: dependency.ident,
})) {
if (otherDependency.type === `peerDependencies`) continue;
if (shouldIgnoreDependency(otherDependency)) {
continue;
}

dependency.update(otherDependency.range);
}
}
}

/**
* Enforces no dual-type dependencies across workspaces.
*
* This function ensures that a dependency is not listed in both "dependencies"
* and "devDependencies" for any workspace. If a dependency is found in both,
* it removes it from "dependencies", keeping it only in "devDependencies".
*
* @param {Context} context - The Yarn constraint context.
*/
function enforceNoDualTypeDependencies({ Yarn }) {
for (const devDependency of Yarn.dependencies({ type: "devDependencies" })) {
devDependency.workspace.unset(`dependency.${devDependency.ident}`);
}
}

/**
* Enforces the use of the `workspace:` protocol for all workspace dependencies.
*
Expand Down Expand Up @@ -74,75 +118,67 @@ function enforcePortalProtocolInsteadOfFileProtocol({ Yarn }) {
* @param {Context} context - The Yarn constraint context.
*/
function enforceDevDependenciesAreProperlyDeclared({ Yarn }) {
const rootWorkspace = Yarn.workspace();

// get all required versions from @apps/hash-api
const workspace = Yarn.workspace({ ident: "@apps/hash-api" });

/** @type {Dependency} */
const prettier = Yarn.dependency({
workspace: rootWorkspace,
ident: "prettier",
});
const waitOn = Yarn.dependency({
workspace: rootWorkspace,
ident: "wait-on",
});
/** @type {Dependency} */
const rimraf = Yarn.dependency({ workspace, ident: "rimraf" });
/** @type {Dependency} */
const eslint = Yarn.dependency({ workspace, ident: "eslint" });
/** @type {Dependency} */
const typescript = Yarn.dependency({ workspace, ident: "typescript" });
/** @type {Dependency} */
const crossEnv = Yarn.dependency({ workspace, ident: "cross-env" });

const workspaces = Yarn.workspaces();
for (const workspace of workspaces) {
if (workspace.ident === rootWorkspace.ident) {
continue;
}

const dependencies = Object.fromEntries(
Object.entries(enforcedDevDependencies).map(([key, { ident }]) => [
key,
Yarn.dependency({ ident }),
]),
);

for (const workspace of Yarn.workspaces()) {
/** @type {Record<string, string> | undefined} */
const scripts = workspace.manifest.scripts;

if (!scripts) {
continue;
}

// scripts is a key-value object
for (const value of Object.values(scripts)) {
if (value.includes("prettier")) {
workspace.set("devDependencies.prettier", prettier.range);
}

if (value.includes("wait-on")) {
workspace.set("devDependencies.wait-on", waitOn.range);
const dependsOn = {
prettier: false,
waitOn: false,
rimraf: false,
eslint: false,
typescript: false,
crossEnv: false,
};

for (const script of Object.values(scripts)) {
for (const [key, { commands }] of Object.entries(
enforcedDevDependencies,
)) {
const scriptSplit = script.split(" ");

if (commands.some((command) => scriptSplit.includes(command))) {
dependsOn[key] = true;
}
}
}

if (value.includes("rimraf")) {
workspace.set("devDependencies.rimraf", rimraf.range);
for (const [key, value] of Object.entries(dependsOn)) {
if (!value) {
workspace.unset(`devDependencies.${dependencies[key].ident}`);
continue;
}

if (value.includes("eslint")) {
workspace.set("devDependencies.eslint", eslint.range);
}
const dependency = dependencies[key];

if (value.includes("ts-node") || value.includes("tsc")) {
workspace.set("devDependencies.typescript", typescript.range);
if (dependency === null) {
workspace.error(
`missing devDependency ${key}, unable to automatically determine the version`,
);
continue;
}

if (value.includes("cross-env")) {
workspace.set("devDependencies.cross-env", crossEnv.range);
}
workspace.set(`devDependencies.${dependency.ident}`, dependency.range);
}
}
}

module.exports = defineConfig({
async constraints(context) {
// enforceWorkspaceDependenciesDeclaredAsSuch(context);
// enforceConsistentDependenciesAcrossTheProject(context);
enforceConsistentDependenciesAcrossTheProject(context);
enforceNoDualTypeDependencies(context);
// enforcePortalProtocolInsteadOfFileProtocol(context);
enforceDevDependenciesAreProperlyDeclared(context);
},
Expand Down
Loading

0 comments on commit 6a10e5e

Please sign in to comment.