Skip to content

Commit

Permalink
chore: take2, reify once, later (#1425)
Browse files Browse the repository at this point in the history
<!-- For Coveo Employees only. Fill this section.

CDX-764

-->

The reification fails for some packages for obscure reasons (gut
feeling, arborist bug).
Trying to do like coveo/ui-kit
  • Loading branch information
louis-bompart authored Feb 15, 2024
1 parent 38270ca commit 70db6c1
Show file tree
Hide file tree
Showing 5 changed files with 126 additions and 21 deletions.
12 changes: 11 additions & 1 deletion package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,7 @@
"release:github": "npx -p=@coveord/release github-publish",
"nx:graph": "nx graph --file=topology.json",
"release:phase0": "npx -p=@coveord/release git-lock",
"release:phase1": "nx run-many --target=release:phase1 --all --parallel=false --output-style=stream",
"release:phase1": "nx run-many --target=release:phase1 --all --parallel=false --output-style=stream && npx -p=@coveord/release reify",
"release:phase2": "npx -p=@coveord/release is-cli-release"
},
"workspaces": [
Expand Down
18 changes: 0 additions & 18 deletions utils/release/npm-publish-package.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,6 @@ import {fileURLToPath} from 'node:url';
import retry from 'async-retry';
import {inc, compareBuild, gt, SemVer} from 'semver';
import {json as fetchNpm} from 'npm-registry-fetch';
import Arborist from '@npmcli/arborist';

/**
* Check if the package json in the provided folder has changed since the last commit
Expand Down Expand Up @@ -169,7 +168,6 @@ async function updateWorkspaceDependent(version) {
dependentPackageJsonPath,
JSON.stringify(dependentPackageJson)
);
await updateLockfileEntries(dependencyPackageJson.name);
}
}

Expand All @@ -191,22 +189,6 @@ function updateDependency(packageJson, dependency, version) {
}
}

/**
* Check the dependency tree from the lockfile and make sure all entries
* of `entryName` satisfies the package.json files entries.
* @param {string} entryName the package to update across the tree
*/
async function updateLockfileEntries(entryName) {
const arb = new Arborist({savePrefix: '', path: rootFolder});
await arb.loadVirtual();
await arb.buildIdealTree({
update: {
names: [entryName],
},
});
await arb.reify();
}

function isPrivatePackage() {
const packageJson = JSON.parse(
readFileSync('package.json', {encoding: 'utf-8'})
Expand Down
4 changes: 3 additions & 1 deletion utils/release/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
"@octokit/auth-app": "^4.0.9",
"async-retry": "1.3.3",
"conventional-changelog-angular": "5.0.13",
"dependency-graph": "1.0.0",
"npm-registry-fetch": "14.0.5",
"octokit": "2.0.14",
"semver": "7.5.2",
Expand All @@ -23,7 +24,8 @@
"npm-publish": "./npm-publish-package.mjs",
"git-publish-all": "./git-publish-all.mjs",
"github-publish": "./create-github-release.mjs",
"is-cli-release": "./is-cli-release.mjs"
"is-cli-release": "./is-cli-release.mjs",
"reify": "./reify.mjs"
},
"scripts": {
"test": "tsc"
Expand Down
111 changes: 111 additions & 0 deletions utils/release/reify.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,111 @@
#!/usr/bin/env node
import Arborist from '@npmcli/arborist';
import {DepGraph} from 'dependency-graph';
import {dirname, resolve} from 'node:path';
import {fileURLToPath} from 'node:url';
const REPO_FS_ROOT = resolve(
dirname(fileURLToPath(import.meta.url)),
'..',
'..'
);

if (!process.env.INIT_CWD) {
throw new Error('Should be called using npm run-script');
}
process.chdir(process.env.INIT_CWD);

/**
* Current strategy: reify each package (along with their dependants transitively) in topological (parents->dependants) order.
*
* Other (untested) strategies that may work:
* * Strategy A: reify each package individually in topological (parents->dependants) order.
* * Strategy B: reify all packages at once.
*/

/**
* @typedef {Map<string, Omit<Arborist.Edge, 'to'> & {workspace: boolean, to: Arborist.Link}>} EdgeMap
*/

/**
* @param {Arborist.Node} rootNode
*/
function buildDependencyGraph(rootNode) {
const graph = /** @type {DepGraph<Arborist.Node>} */ (new DepGraph());
/**
* @param {Arborist.Node} node
*/
function getWorkspaceDependencies(node) {
const edgesOut =
node.edgesOut instanceof Map
? Array.from(node.edgesOut.values())
: node.edgesOut;
const workspaces = edgesOut.filter(
(edge) =>
edge.to.package.name && rootNode.workspaces?.has(edge.to.package.name)
);
return workspaces.map((edge) =>
edge.to instanceof Arborist.Link ? edge.to.target : edge.to
);
}

/**
* @param {Arborist.Node} node
*/
function addWorkspaceDependencies(node) {
const dependencies = getWorkspaceDependencies(node);
for (const dependency of dependencies) {
if (!node.package.name || !dependency.package.name) {
throw 'Workspaces must all have a name.';
}
graph.addDependency(node.package.name, dependency.package.name);
addWorkspaceDependencies(dependency);
}
}

const workspaces = getWorkspaceDependencies(rootNode);
for (const workspace of workspaces) {
if (!workspace.package.name) {
throw 'Workspaces must all have a name.';
}
graph.addNode(workspace.package.name, workspace);
}
for (const workspace of workspaces) {
addWorkspaceDependencies(workspace);
}
return graph;
}

async function initArborist() {
const registry = process.env.npm_config_registry;
const arb = new Arborist({
savePrefix: '',
path: REPO_FS_ROOT,
registry,
});
console.log('Loading virtual tree.');
await arb.loadVirtual();
return arb;
}

const graph = buildDependencyGraph(
/** @type {Arborist.Node} */ ((await initArborist()).virtualTree)
);
for (const packageToUpdate of graph.overallOrder()) {
const names = [
packageToUpdate,
...graph.dependantsOf(packageToUpdate),
].flatMap((packageName) => [
graph.getNodeData(packageName).name,
packageName,
]);
console.log('Updating package-lock for', names);
const arb = await initArborist();
console.log('Building ideal tree');
await arb.buildIdealTree({
update: {
names,
},
});
console.log('Applying ideal tree.');
await arb.reify();
}

0 comments on commit 70db6c1

Please sign in to comment.