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

feat: add lerna at the root of a new otter project #1956

Merged
merged 1 commit into from
Jul 24, 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
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.7"
},
"engines": {
"node": "^18.19.1 || ^20.11.1 || >=22.0.0"
Expand Down
21 changes: 20 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,21 @@ 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 defaultOptions = getDefaultExecSyncOptions();
// eslint-disable-next-line @typescript-eslint/naming-convention
const execAppOptions = {...defaultOptions, cwd: workspacePath, env: {...defaultOptions.env, NX_CLOUD_ACCESS_TOKEN: ''}};
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');
vscaiceanu-1a marked this conversation as resolved.
Show resolved Hide resolved
expect(rootPackageJson.scripts).toHaveProperty('test', 'lerna run test');
expect(rootPackageJson.scripts).toHaveProperty('lint', 'lerna run lint');
expect(() => packageManagerRun({script: 'build'}, execAppOptions)).not.toThrow();
expect(() => packageManagerRun({script: 'test'}, execAppOptions)).not.toThrow();
expect(() => packageManagerRun({script: 'lint'}, execAppOptions)).not.toThrow();
expect(rootPackageJson.workspaces).toContain('libs/*');
expect(rootPackageJson.workspaces).toContain('apps/*');
});
});
kpanot marked this conversation as resolved.
Show resolved Hide resolved
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,8 @@ import { chain } from '@angular-devkit/schematics';
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 { DEFAULT_ROOT_FOLDERS, getPackageManager, 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,43 @@ 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 {
vscaiceanu-1a marked this conversation as resolved.
Show resolved Hide resolved
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'
vscaiceanu-1a marked this conversation as resolved.
Show resolved Hide resolved
};

const lernaJson: { $schema: string; version: string; npmClient?: string } = {
'$schema': 'https://github.com/lerna/lerna/blob/main/packages/lerna/schemas/lerna-schema.json',
'version': rootPackageJsonObject.version || '0.0.0-placeholder'
};
if (getPackageManager() === 'yarn') {
lernaJson.npmClient = 'yarn';
}
tree.create('/lerna.json', JSON.stringify(lernaJson, 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
6 changes: 5 additions & 1 deletion packages/@o3r/workspace/schematics/ng-add/schema.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import type { SchematicOptionObject } from '@o3r/schematics';

export type PresetNames = 'basic' | 'cms';
/** Monorepo manager to use */
export type MonorepoManager = 'lerna' | 'none';
vscaiceanu-1a marked this conversation as resolved.
Show resolved Hide resolved

export interface NgAddSchematicsSchema extends SchematicOptionObject {
/** Skip the linter process */
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
Loading