Skip to content

Commit

Permalink
feat: add lerna at the root of a new otter project
Browse files Browse the repository at this point in the history
  • Loading branch information
vscaiceanu-1a committed Jul 16, 2024
1 parent 9e984e8 commit a9c0842
Show file tree
Hide file tree
Showing 7 changed files with 76 additions and 6 deletions.
3 changes: 2 additions & 1 deletion packages/@o3r/workspace/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -110,7 +110,8 @@
"@angular/material": "~18.0.0",
"@ngrx/router-store": "~18.0.0",
"@ngrx/effects": "~18.0.0",
"@ngrx/store-devtools": "~18.0.0"
"@ngrx/store-devtools": "~18.0.0",
"lerna": "^8.1.5"
},
"engines": {
"node": "^18.19.1 || ^20.11.1 || >=22.0.0"
Expand Down
19 changes: 18 additions & 1 deletion packages/@o3r/workspace/schematics/index.it.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,12 @@ import {
getDefaultExecSyncOptions, getGitDiff,
packageManagerExec,
packageManagerInstall,
packageManagerRun,
packageManagerRunOnProject
} from '@o3r/test-helpers';
import { existsSync } from 'node:fs';
import { existsSync, promises as fs } from 'node:fs';
import * as path from 'node:path';
import type { PackageJson } from 'type-fest';

describe('new otter workspace', () => {
test('should add sdk to an existing workspace', () => {
Expand Down Expand Up @@ -78,4 +80,19 @@ describe('new otter workspace', () => {
generatedLibFiles.forEach(file => expect(existsSync(path.join(inLibraryPath, file))).toBe(true));
expect(() => packageManagerRunOnProject(libName, true, { script: 'build' }, execAppOptions)).not.toThrow();
});

test('should generate a monorepo setup', async () => {
const { workspacePath } = o3rEnvironment.testEnvironment;
const execAppOptions = {...getDefaultExecSyncOptions(), cwd: workspacePath};
expect(() => packageManagerInstall(execAppOptions)).not.toThrow();
const rootPackageJson = JSON.parse(await fs.readFile(path.join(workspacePath, 'package.json'), 'utf-8')) as PackageJson;
expect(rootPackageJson.scripts).toHaveProperty('build', 'lerna run build');
expect(rootPackageJson.scripts).toHaveProperty('test', 'lerna run test');
expect(rootPackageJson.scripts).toHaveProperty('lint', 'lerna run lint');
expect(() => packageManagerRun({script: 'build'}, execAppOptions)).not.toThrow();

Check failure on line 92 in packages/@o3r/workspace/schematics/index.it.spec.ts

View workflow job for this annotation

GitHub Actions / it-tests / it-tests (ubuntu-latest, yarn, o3r-project-with-app)

new otter workspace › should generate a monorepo setup

expect(received).not.toThrow() Error name: "Error" Error message: "Command failed: yarn run build STDERR: /home/runner/work/otter/it-tests/test-app-workspace3/.pnp.cjs:28737 Error.captureStackTrace(firstError); ^· Error: lerna tried to access strip-ansi, but it isn't declared in its dependencies; this makes the require call ambiguous and unsound.· Required package: strip-ansi Required by: lerna@npm:8.1.6 (via /home/runner/work/otter/otter/.cache/test-app/cache/lerna-npm-8.1.6-6ba921c4b3-10c0.zip/node_modules/lerna/dist/)· Require stack: - /home/runner/work/otter/otter/.cache/test-app/cache/lerna-npm-8.1.6-6ba921c4b3-10c0.zip/node_modules/lerna/dist/index.js - /home/runner/work/otter/otter/.cache/test-app/cache/lerna-npm-8.1.6-6ba921c4b3-10c0.zip/node_modules/lerna/dist/cli.js at require$$0.Module._resolveFilename (/home/runner/work/otter/it-tests/test-app-workspace3/.pnp.cjs:28737:13) at Module._load (node:internal/modules/cjs/loader:986:27) at require$$0.Module._load (/home/runner/work/otter/it-tests/test-app-workspace3/.pnp.cjs:28628:31) at Module.require (node:internal/modules/cjs/loader:1233:19) at require (node:internal/modules/helpers:179:18) at libs/core/src/lib/npmlog/gauge/wide-truncate.ts (/home/runner/work/otter/otter/.cache/test-app/cache/lerna-npm-8.1.6-6ba921c4b3-10c0.zip/node_modules/lerna/dist/index.js:319:21) at __require (/home/runner/work/otter/otter/.cache/test-app/cache/lerna-npm-8.1.6-6ba921c4b3-10c0.zip/node_modules/lerna/dist/index.js:12:50) at libs/core/src/lib/npmlog/gauge/render-template.ts (/home/runner/work/otter/otter/.cache/test-app/cache/lerna-npm-8.1.6-6ba921c4b3-10c0.zip/node_modules/lerna/dist/index.js:453:24) at __require (/home/runner/work/otter/otter/.cache/test-app/cache/lerna-npm-8.1.6-6ba921c4b3-10c0.zip/node_modules/lerna/dist/index.js:12:50) at libs/core/src/lib/npmlog/gauge/plumbing.ts (/home/runner/work/otter/otter/.cache/test-app/cache/lerna-npm-8.1.6-6ba921c4b3-10c0.zip/node_modules/lerna/dist/index.js:660:26)· Node.js v20.15.0· OUTPUT: ,,/home/runner/work/otter/it-tests/test-app-workspace3/.pnp.cjs:28737 Error.captureStackTrace(firstError); ^· Error: lerna tried to access strip-ansi, but it isn't declared in its dependencies; this makes the require call ambiguous and unsound.· Required package: strip-ansi Required by: lerna@npm:8.1.6 (via /home/runner/work/otter/otter/.cache/test-app/cache/lerna-npm-8.1.6-6ba921c4b3-10c0.zip/node_modules/lerna/dist/)· Require stack: - /home/runner/work/otter/otter/.cache/test-app/cache/lerna-npm-8.1.6-6ba921c4b3-10c0.zip/node_modules/lerna/dist/index.js - /home/runner/work/otter/otter/.cache/test-app/cache/lerna-npm-8.1.6-6ba921c4b3-10c0.zip/node_modules/lerna/dist/cli.js at require$$0.Module._resolveFilename (/home/runner/work/otter/it-tests/test-app-workspace3/.pnp.cjs:28737:13) at Module._load (node:internal/modules/cjs/loader:986:27) at require$$0.Module._load (/home/runner/work/otter/it-tests/test-app-workspace3/.pnp.cjs:28628:31) at Module.require (node:internal/modules/cjs/loader:1233:19) at require (node:internal/modules/helpers:179:18) at libs/core/src/lib/npmlog/gauge/wide-truncate.ts (/home/runner/work/otter/otter/.cache/test-app/cache/lerna-npm-8.1.6-6ba921c4b3-10c0.zip/node_modules/lerna/dist/index.js:319:21) at __require (/home/runner/work/otter/otter/.cache/test-app/cache/lerna-npm-8.1.6-6ba921c4b3-10c0.zip/node_modules/lerna/dist/index.js:12:50) at libs/core/src/lib/npmlog/gauge/render-template.ts (/home/runner/work/otter/otter/.cache/test-app/cache/lerna-npm-8.1.6-6ba921c4b3-10c0.zip/node_modules/lerna/dist/index.js:453:24) at __require (/home/runner/work/otter/otter/.cache/test-app/cache/lerna-npm-8.1.6-6ba921c4b3-10c0.zip/node_modules/lerna/dist/index.js:12:50) at libs/core/src/lib/npmlog/gauge/plumbing.ts (/home/runner/work/otter/otter/.cache/test-app/cache/lerna-npm-8.1.6-6ba921c4b3-10c0.zip/node_modules/lerna/dist/index.js:660:26)· Node.js v20.15.0 " 81 | // Yarn doesn't log errors on stder

Check failure on line 92 in packages/@o3r/workspace/schematics/index.it.spec.ts

View workflow job for this annotation

GitHub Actions / it-tests / it-tests (windows-latest, yarn, o3r-project-with-app)

new otter workspace › should generate a monorepo setup

expect(received).not.toThrow() Error name: "Error" Error message: "Command failed: yarn run build STDERR: D:\\a\\otter\\it-tests\\test-app-workspace3\\.pnp.cjs:28737· Error.captureStackTrace(firstError);· ^··· Error: lerna tried to access strip-ansi, but it isn't declared in its dependencies; this makes the require call ambiguous and unsound.··· Required package: strip-ansi· Required by: lerna@npm:8.1.6 (via D:\\a\\otter\\otter\\.cache\\test-app\\cache\\lerna-npm-8.1.6-6ba921c4b3-10c0.zip\\node_modules\\lerna\\dist\\)··· Require stack:· - D:\\a\\otter\\otter\\.cache\\test-app\\cache\\lerna-npm-8.1.6-6ba921c4b3-10c0.zip\\node_modules\\lerna\\dist\\index.js· - D:\\a\\otter\\otter\\.cache\\test-app\\cache\\lerna-npm-8.1.6-6ba921c4b3-10c0.zip\\node_modules\\lerna\\dist\\cli.js· at require$$0.Module._resolveFilename (D:\\a\\otter\\it-tests\\test-app-workspace3\\.pnp.cjs:28737:13)· at Module._load (node:internal/modules/cjs/loader:986:27)· at require$$0.Module._load (D:\\a\\otter\\it-tests\\test-app-workspace3\\.pnp.cjs:28628:31)· at Module.require (node:internal/modules/cjs/loader:1233:19)· at require (node:internal/modules/helpers:179:18)· at libs/core/src/lib/npmlog/gauge/wide-truncate.ts (D:\\a\\otter\\otter\\.cache\\test-app\\cache\\lerna-npm-8.1.6-6ba921c4b3-10c0.zip\\node_modules\\lerna\\dist\\index.js:319:21)· at __require (D:\\a\\otter\\otter\\.cache\\test-app\\cache\\lerna-npm-8.1.6-6ba921c4b3-10c0.zip\\node_modules\\lerna\\dist\\index.js:12:50)· at libs/core/src/lib/npmlog/gauge/render-template.ts (D:\\a\\otter\\otter\\.cache\\test-app\\cache\\lerna-npm-8.1.6-6ba921c4b3-10c0.zip\\node_modules\\lerna\\dist\\index.js:453:24)· at __require (D:\\a\\otter\\otter\\.cache\\test-app\\cache\\lerna-npm-8.1.6-6ba921c4b3-10c0.zip\\node_modules\\lerna\\dist\\index.js:12:50)· at libs/core/src/lib/npmlog/gauge/plumbing.ts (D:\\a\\otter\\otter\\.cache\\test-app\\cache\\lerna-npm-8.1.6-6ba921c4b3-10c0.zip\\node_modules\\lerna\\dist\\index.js:660:26)··· Node.js v20.15.0·· OUTPUT: ,,D:\\a\\otter\\it-tests\\test-app-workspace3\\.pnp.cjs:28737· Error.captureStackTrace(firstError);· ^··· Error: lerna tried to access strip-ansi, but it isn't declared in its dependencies; this makes the require call ambiguous and unsound.··· Required package: strip-ansi· Required by: lerna@npm:8.1.6 (via D:\\a\\otter\\otter\\.cache\\test-app\\cache\\lerna-npm-8.1.6-6ba921c4b3-10c0.zip\\node_modules\\lerna\\dist\\)··· Require stack:· - D:\\a\\otter\\otter\\.cache\\test-app\\cache\\lerna-npm-8.1.6-6ba921c4b3-10c0.zip\\node_modules\\lerna\\dist\\index.js· - D:\\a\\otter\\otter\\.cache\\test-app\\cache\\lerna-npm-8.1.6-6ba921c4b3-10c0.zip\\node_modules\\lerna\\dist\\cli.js· at require$$0.Module._resolveFilename (D:\\a\\otter\\it-tests\\test-app-workspace3\\.pnp.cjs:28737:13)· at Module._load (node:internal/modules/cjs/loader:986:27)· at require$$0.Module._load (D:\\a\\otter\\it-tests\\test-app-workspace3\\.pnp.cjs:28628:31)· at Module.require (node:internal/modules/cjs/loader:1233:19)· at require (node:internal/modules/helpers:179:18)· at libs/core/src/lib/npmlog/gauge/wide-truncate.ts (D:\\a\\otter\\otter\\.cache\\test-app\\cache\\lerna-npm-8.1.6-6ba921c4b3-10c0.zip\\node_modules\\lerna\\dist\\index.js:319:21)· at __require (D:\\a\\otter\\otter\\.cache\\test-app\\cache\\lerna-npm-8.1.6-6ba921c4b3-10c0.zip\\node_modules\\lerna\\dist\\index.js:12:50)· at libs/core/src/lib/npmlog/gauge/render-template.ts (D:\\a\\otter\\otter\\.cache\\test-app\\cache\\lerna-npm-8.1.6-6ba921c4b3-10c0.zip\\node_modules\\lerna\\dist\\index.js:453:24)· at __require (D:\\a\\otter\\otter\\.cache\\test-app\\cache\\lerna-npm-8.1.6-6ba921c4b3-10c0.zip\\node_modules\\lerna\\dist\\index.js:12:50)· at libs/core/src/lib/npmlog/gauge/plumbing.ts (D:\\a\\otter\\otter\\.cache\\test-app\\cache\\lerna-npm-8.1.6-6ba921c4b3-10c0.zip\\node_modules\\lerna\\dist\\index.js:660:26)··· Node.js v20.15.0· " 81 | // Yarn doesn't log errors on stderr, so we need to get them from s
expect(() => packageManagerRun({script: 'test'}, execAppOptions)).not.toThrow();
expect(() => packageManagerRun({script: 'lint'}, execAppOptions)).not.toThrow();
expect(rootPackageJson.workspaces).toContain('libs/*');
expect(rootPackageJson.workspaces).toContain('apps/*');
});
});
37 changes: 37 additions & 0 deletions packages/@o3r/workspace/schematics/ng-add/helpers/npm-workspace.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import type { Rule, SchematicContext, Tree } from '@angular-devkit/schematics';
import { SchematicsException } from '@angular-devkit/schematics';
import type { PackageJson } from 'type-fest';
import { DEFAULT_ROOT_FOLDERS, isNxContext, setupSchematicsParamsForProject, WorkspaceLayout, WorkspaceSchematics } from '@o3r/schematics';
import type { MonorepoManager } from '../schema';

/**
* Update root package.json to include workspaces
Expand Down Expand Up @@ -75,3 +76,39 @@ export function filterPackageJsonScripts(tree: Tree, _context: SchematicContext)
tree.overwrite(rootPackageJsonPath, JSON.stringify(rootPackageJsonObject, null, 2));
return tree;
}

/**
* Add a monorepo manager at the root of the project
* @param o3rWorkspacePackageJson the @o3r/workspace package.json
* @param manager the monorepo manager
*/
export function addMonorepoManager(o3rWorkspacePackageJson: PackageJson & { generatorDependencies: Record<string, string> }, manager: MonorepoManager): Rule {
return (tree: Tree, _context: SchematicContext) => {
if (manager === 'lerna') {
const rootPackageJsonPath = '/package.json';
if (!tree.exists(rootPackageJsonPath)) {
throw new SchematicsException('Root package.json does not exist');
}

const rootPackageJsonObject = tree.readJson(rootPackageJsonPath) as PackageJson;
rootPackageJsonObject.devDependencies = {
...rootPackageJsonObject.devDependencies,
'lerna': o3rWorkspacePackageJson.generatorDependencies.lerna
};
rootPackageJsonObject.scripts = {
...rootPackageJsonObject.scripts,
'build': 'lerna run build',
'test': 'lerna run test',
'lint': 'lerna run lint'
};

tree.create('/lerna.json', JSON.stringify({
'$schema': 'https://github.com/lerna/lerna/blob/main/packages/lerna/schemas/lerna-schema.json',
'version': rootPackageJsonObject.version || '0.0.0-placeholder'
}, null, 2));

tree.overwrite(rootPackageJsonPath, JSON.stringify(rootPackageJsonObject, null, 2));
}
return tree;
};
}
8 changes: 5 additions & 3 deletions packages/@o3r/workspace/schematics/ng-add/project-setup.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,11 +10,12 @@ import type { DependencyToAdd } from '@o3r/schematics';
import { NodeDependencyType } from '@schematics/angular/utility/dependencies';
import * as fs from 'node:fs';
import * as path from 'node:path';
import { addWorkspacesToProject, filterPackageJsonScripts } from './helpers/npm-workspace';
import { addMonorepoManager, addWorkspacesToProject, filterPackageJsonScripts } from './helpers/npm-workspace';
import { generateRenovateConfig } from './helpers/renovate';
import type { NgAddSchematicsSchema } from './schema';
import { shouldOtterLinterBeInstalled } from './helpers/linter';
import { updateGitIgnore } from './helpers/gitignore-update';
import type { PackageJson } from 'type-fest';

/**
* Enable all the otter features requested by the user
Expand All @@ -34,7 +35,7 @@ export const prepareProject = (options: NgAddSchematicsSchema): Rule => {
const ownSchematicsFolder = path.resolve(__dirname, '..');
const ownPackageJsonPath = path.resolve(ownSchematicsFolder, '..', 'package.json');
const depsInfo = getO3rPeerDeps(ownPackageJsonPath);
const ownPackageJsonContent = JSON.parse(fs.readFileSync(ownPackageJsonPath, { encoding: 'utf-8' }));
const ownPackageJsonContent = JSON.parse(fs.readFileSync(ownPackageJsonPath, { encoding: 'utf-8' })) as PackageJson & { generatorDependencies: Record<string, string> };

return async (tree, context) => {
if (!ownPackageJsonContent) {
Expand Down Expand Up @@ -74,7 +75,8 @@ export const prepareProject = (options: NgAddSchematicsSchema): Rule => {
ngAddToRun: internalPackagesToInstallWithNgAdd
}),
!options.skipLinter && installOtterLinter ? applyEsLintFix() : noop(),
addWorkspacesToProject()
addWorkspacesToProject(),
addMonorepoManager(ownPackageJsonContent, options.monorepoManager)
])(tree, context);
};
};
9 changes: 9 additions & 0 deletions packages/@o3r/workspace/schematics/ng-add/schema.json
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,15 @@
"type": "boolean",
"description": "Use a pinned version for otter packages",
"default": false
},
"monorepoManager": {
"description": "Which monorepo manager to use",
"type": "string",
"default": "lerna",
"enum": [
"lerna",
"none"
]
}
},
"additionalProperties": true,
Expand Down
4 changes: 4 additions & 0 deletions packages/@o3r/workspace/schematics/ng-add/schema.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import type { SchematicOptionObject } from '@o3r/schematics';

export type MonorepoManager = 'lerna' | 'none';
export type PresetNames = 'basic' | 'cms';

export interface NgAddSchematicsSchema extends SchematicOptionObject {
Expand All @@ -17,4 +18,7 @@ export interface NgAddSchematicsSchema extends SchematicOptionObject {

/** Use a pinned version for otter packages */
exactO3rVersion?: boolean;

/** Monorepo manager to use */
monorepoManager: MonorepoManager;
}
2 changes: 1 addition & 1 deletion packages/@o3r/workspace/src/cli/set-version.cts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import * as path from 'node:path';
import * as winston from 'winston';
import { clean } from 'semver';

const defaultIncludedFiles = ['**/package.json', '!/**/templates/**/package.json', '!**/node_modules/**/package.json'];
const defaultIncludedFiles = ['**/package.json', '!/**/templates/**/package.json', '!**/node_modules/**/package.json', '**/lerna.json'];

const collect = (pattern: string, patterns: string[]) => {
if (patterns === defaultIncludedFiles && pattern) {
Expand Down

0 comments on commit a9c0842

Please sign in to comment.