Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

H-3691: Replace lockfile-lint with yarn constraints #5858

Merged
merged 5 commits into from
Dec 13, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 0 additions & 13 deletions .github/workflows/lint.yml
Original file line number Diff line number Diff line change
Expand Up @@ -228,19 +228,6 @@ jobs:
exit 1
fi
- name: Run yarn lint:lockfile-lint
if: ${{ success() || failure() }}
run: |
if ! yarn lint:lockfile-lint; then
echo ''
echo ''
echo 'ℹ️ ℹ️ ℹ️'
echo 'Try resetting yarn.lock to its previous state and then run `yarn install`.'
echo 'If your `~/.npmrc` mentions a custom registry, you should remove this setting first.'
echo 'ℹ️ ℹ️ ℹ️'
exit 1
fi
- name: Run yarn lint:license-in-workspaces
if: ${{ success() || failure() }}
env:
Expand Down
16 changes: 8 additions & 8 deletions apps/hash/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -54,28 +54,28 @@ To run HASH locally, please follow these steps:
```sh
git --version
## β‰₯ 2.17

node --version
## β‰₯ 20.12

yarn --version
## β‰₯ 1.16

rustup --version
## β‰₯ 1.27.1 (Required to match the toolchain as specified in `rust-toolchain.toml`)

docker --version
## β‰₯ 20.10

docker compose version
## β‰₯ 2.17.2

docker buildx version
## β‰₯ 0.10.4

protoc --version
## β‰₯ 25

java --version
## β‰₯ 8
```
Expand Down
21 changes: 3 additions & 18 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,6 @@
"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",
"lint:markdownlint": "markdownlint --dot .",
"lint:prettier": "prettier --check --ignore-unknown .",
"lint:taplo": "taplo fmt --check",
Expand All @@ -56,7 +55,7 @@
"postinstall": "turbo run postinstall",
"seed-data:opensearch": "yarn workspace @apps/hash-search-loader clear-opensearch",
"seed-data:redis": "yarn workspace @apps/hash-realtime clear-redis",
"seed-data": "concurrently \"yarn:seed-data:*\"",
"seed-data": "npm-run-all --parallel \"seed-data:*\"",
"test": "npm-run-all --continue-on-error \"test:*\"",
"test:unit": "turbo run test:unit --env-mode=loose --",
"test:integration": "turbo run test:integration --env-mode=loose --",
Expand All @@ -68,19 +67,9 @@
},
"prettier": {
"plugins": [
"prettier-plugin-packagejson",
"prettier-plugin-sh"
"prettier-plugin-packagejson"
],
"trailingComma": "all",
"overrides": [
{
"files": "*.sql",
"options": {
"keywordCase": "upper",
"language": "postgresql"
}
}
]
"trailingComma": "all"
},
"resolutions": {
"@artilleryio/int-commons@npm:2.11.0": "patch:@artilleryio/int-commons@npm%3A2.11.0#~/.yarn/patches/@artilleryio-int-commons-npm-2.11.0-5b69c05121.patch",
Expand Down Expand Up @@ -116,15 +105,11 @@
"@sentry/cli": "^2.39.1",
"@taplo/cli": "0.7.0",
"@yarnpkg/types": "^4.0.0",
"concurrently": "7.6.0",
"lefthook": "1.9.2",
"lockfile-lint": "4.14.0",
"markdownlint-cli": "0.43.0",
"npm-run-all2": "7.0.1",
"prettier": "3.4.2",
"prettier-plugin-packagejson": "2.5.6",
"prettier-plugin-sh": "0.14.0",
"suppress-exit-code": "3.2.0",
"turbo": "2.3.3"
},
"packageManager": "yarn@4.5.3+sha512.3003a14012e2987072d244c720506549c1aab73ee728208f1b2580a9fd67b92d61ba6b08fe93f6dce68fd771e3af1e59a0afa28dd242dd0940d73b95fedd4e90"
Expand Down
107 changes: 81 additions & 26 deletions yarn.config.cjs
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,8 @@ const ignoredWorkspaces = [
"@blocks/person",
];

const allowedGitDependencies = [];

/**
*
* @param {Dependency} dependency
Expand Down Expand Up @@ -72,40 +74,94 @@ function enforceNoDualTypeDependencies({ Yarn }) {
}

/**
* Enforces the use of the `workspace:` protocol for all workspace dependencies.
*
* This rule ensures that all dependencies that are part of the workspace are
* declared using the `workspace:` protocol.
* Enforce that the package protocols are correct.
*
* @param {Context} context - The Yarn constraint context.
* @param {Context} context
*/
function enforceWorkspaceDependenciesDeclaredAsSuch({ Yarn }) {
function enforceProtocols({ Yarn }) {
const workspaces = Yarn.workspaces();

for (const dependency of Yarn.dependencies()) {
if (
workspaces.some(
(workspace) =>
workspace.ident === dependency.ident &&
workspace.pkg.version === dependency.range,
)
) {
dependency.update("workspace:^");
if (shouldIgnoreDependency(dependency)) {
continue;
}

const workspaceDependency = workspaces.find(
(workspace) => workspace.ident === dependency.ident,
);

if (workspaceDependency) {
// turbo doesn't support the `workspace:` protocol when rewriting lockfiles, leading to inconsistent lockfiles
dependency.update(workspaceDependency.pkg.version);
}
}
}

/**
* This rule prohibits the use of the 'file:' protocol in dependency ranges
* and replaces it with the 'portal:' protocol.
*
* @param {Context} context - The Yarn constraint context.
*/
function enforcePortalProtocolInsteadOfFileProtocol({ Yarn }) {
for (const dependency of Yarn.dependencies()) {
if (dependency.range.startsWith("file:")) {
// the file: protocol makes problems when used in conjunction with pnpm mode, portal is the equivalent protocol
dependency.update(dependency.range.replace("file:", "portal:"));
}

if (dependency.range.startsWith("link:")) {
dependency.error(
`The link protocol allows for non-packages to be linked and is not allowed, dependency: ${dependency.ident}`,
);
}

if (dependency.range.startsWith("exec:")) {
dependency.error(
`The exec protocol allows for arbitrary code execution and is not allowed, dependency: ${dependency.ident}`,
);
}

let shouldCheckIfValidGitDependency = false;

if (
dependency.range.startsWith("https://") ||
dependency.range.startsWith("http://")
) {
// always prefix with the git protocol
dependency.update(`git:${dependency.range}`);
shouldCheckIfValidGitDependency = true;
}

if (dependency.range.startsWith("ssh://")) {
// always prefix with the git protocol
dependency.update(`git:${dependency.range.replace(/^ssh:\/\//, "git:")}`);
shouldCheckIfValidGitDependency = true;
}

if (
(shouldCheckIfValidGitDependency ||
dependency.range.startsWith("git:")) &&
!allowedGitDependencies.includes(dependency.ident)
) {
dependency.error(
`arbitrary git dependencies are not allowed, dependency: ${dependency.ident}`,
);
}

// patches are only allowed if they are for an `npm:` dpeendenct
if (dependency.range.startsWith("patch:")) {
const dependencySpecification = dependency.range.match(/^patch:([^#]+)/);
if (!dependencySpecification) {
dependency.error(
`invalid patch protocol, dependency: ${dependency.ident}`,
);
continue;
}

// locator is on the right side
// splitRight at `@`
const segments = dependencySpecification[1].split("@");
const last = segments.pop();
// urldecode the last segment
const version = decodeURIComponent(last);

if (!version.startsWith("npm:")) {
dependency.error(
`patch protocol is only allowed for npm dependencies, dependency: ${dependency.ident}, patches: ${version}`,
);
}
}
}
}

Expand Down Expand Up @@ -180,10 +236,9 @@ function enforceDevDependenciesAreProperlyDeclared({ Yarn }) {

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