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(sdk-schematics): initialize git repository #1361

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
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
15 changes: 14 additions & 1 deletion packages/@ama-sdk/create/src/index.it.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import {
prepareTestEnv,
setupLocalRegistry
} from '@o3r/test-helpers';
import { execFileSync } from 'node:child_process';
import * as fs from 'node:fs';
import { cpSync, mkdirSync } from 'node:fs';
import * as path from 'node:path';
Expand All @@ -25,7 +26,7 @@ describe('Create new sdk command', () => {
beforeEach(async () => {
const isYarnTest = packageManager.startsWith('yarn');
const yarnVersion = isYarnTest ? getYarnVersionFromRoot(process.cwd()) || 'latest' : undefined;
sdkFolderPath = (await prepareTestEnv(projectName, {type: 'blank', yarnVersion })).workspacePath;
sdkFolderPath = (await prepareTestEnv(projectName, {type: 'blank', yarnVersion, skipGitSetup: true })).workspacePath;
sdkPackagePath = path.join(sdkFolderPath, sdkPackageName.replace(/^@/, ''));
execAppOptions.cwd = sdkFolderPath;

Expand All @@ -52,11 +53,23 @@ describe('Create new sdk command', () => {
test('should generate a full SDK when the specification is provided', () => {
expect(() =>
packageManagerCreate({script: '@ama-sdk', args: ['typescript', sdkPackageName, '--package-manager', packageManager, '--spec-path', './swagger-spec.yml']}, execAppOptions)).not.toThrow();
expect(fs.existsSync(path.join(sdkPackagePath, '.git'))).toBe(true);
expect(() => execFileSync('git', ['diff', '--quiet', '--exit-code'], { cwd: sdkPackagePath })).not.toThrow(); // git must be ready to commit all files
expect(() => packageManagerRun({script: 'build'}, { ...execAppOptions, cwd: sdkPackagePath })).not.toThrow();
});

test('should not generate a git repository when using --skip-git', () => {
expect(() => packageManagerCreate({
script: '@ama-sdk',
args: ['typescript', sdkPackageName, '--skip-git', '--package-manager', packageManager, '--spec-path', './swagger-spec.yml']
}, execAppOptions)).not.toThrow();
expect(fs.existsSync(path.join(sdkPackagePath, '.git'))).toBe(false);
});

test('should generate an empty SDK ready to be used', () => {
expect(() => packageManagerCreate({script: '@ama-sdk', args: ['typescript', sdkPackageName]}, execAppOptions)).not.toThrow();
expect(fs.existsSync(path.join(sdkPackagePath, '.git'))).toBe(true);
expect(() => execFileSync('git', ['diff', '--quiet', '--exit-code'], { cwd: sdkPackagePath })).not.toThrow(); // git must be ready to commit all files
expect(() => packageManagerRun({script: 'build'}, { ...execAppOptions, cwd: sdkPackagePath })).not.toThrow();
expect(() =>
packageManagerExec({
Expand Down
15 changes: 11 additions & 4 deletions packages/@ama-sdk/create/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,9 @@ const packageManagerEnv = process.env.npm_config_user_agent?.split('/')[0];
const defaultScope = 'sdk';
const binPath = resolve(require.resolve('@angular-devkit/schematics-cli/package.json'), '../bin/schematics.js');
const args = process.argv.slice(2);
const argv = minimist(args);
const argv = minimist(args, {
'boolean': ['skip-git']
});

let defaultPackageManager = 'npm';
if (packageManagerEnv && ['npm', 'yarn'].includes(packageManagerEnv)) {
Expand Down Expand Up @@ -64,14 +66,17 @@ const getYarnVersion = () => {
}
};

const skipGit = !!argv['skip-git'];

const schematicArgs = [
argv.debug !== undefined ? `--debug=${argv.debug as string}` : '--debug=false', // schematics enable debug mode per default when using schematics with relative path
'--name', name,
'--package', pck,
'--package-manager', packageManager,
'--directory', targetDirectory,
...(argv['spec-path'] ? ['--spec-path', argv['spec-path']] : []),
...(typeof argv['o3r-metrics'] !== 'undefined' ? [`--${!argv['o3r-metrics'] ? 'no-' : ''}o3r-metrics`] : [])
...(typeof argv['o3r-metrics'] !== 'undefined' ? [`--${!argv['o3r-metrics'] ? 'no-' : ''}o3r-metrics`] : []),
...(skipGit ? ['--skip-git'] : [])
];

const getSchematicStepInfo = (schematic: string) => ({
Expand All @@ -81,14 +86,16 @@ const getSchematicStepInfo = (schematic: string) => ({
const run = () => {

const runner = process.platform === 'win32' ? `${packageManager}.cmd` : packageManager;
const cwd = resolve(process.cwd(), targetDirectory);
const steps: { args: string[]; cwd?: string; runner?: string }[] = [
getSchematicStepInfo(schematicsToRun[0]),
...(
packageManager === 'yarn'
? [{ runner, args: ['set', 'version', getYarnVersion()], cwd: resolve(process.cwd(), targetDirectory)}]
? [{ runner, args: ['set', 'version', getYarnVersion()], cwd}]
: []
),
...schematicsToRun.slice(1).map(getSchematicStepInfo)
...schematicsToRun.slice(1).map(getSchematicStepInfo),
...(skipGit ? [] : [{ runner: 'git', args: ['add', '.'], cwd}])
];

const errors = steps
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -67,12 +67,14 @@ describe('Typescript Shell Generator', () => {
yarnTree = await runner.runSchematic('typescript-shell', {
name: 'test-scope',
package: 'test-sdk',
skipInstall: true
skipInstall: true,
skipGit: true
}, Tree.empty());
npmTree = await runner.runSchematic('typescript-shell', {
name: 'test-scope',
package: 'test-sdk',
skipInstall: true,
skipGit: true,
packageManager: 'npm'
}, Tree.empty());
});
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import {
Tree,
url
} from '@angular-devkit/schematics';
import {RepositoryInitializerTask} from '@angular-devkit/schematics/tasks';
import { createSchematicWithMetricsIfInstalled } from '@o3r/schematics';
import {dump, load} from 'js-yaml';
import {isAbsolute, posix, relative} from 'node:path';
Expand All @@ -29,6 +30,13 @@ function ngGenerateTypescriptSDKFn(options: NgGenerateTypescriptSDKShellSchemati
context.addTask(installTask);
};

const initGitRule = (_tree: Tree, context: SchematicContext) => {
const workingDirectory = options.directory ? (isAbsolute(options.directory) ? relative(process.cwd(), options.directory) : options.directory) : '.';
const defaultCommitOptions = { message: 'Initial commit' };
const commitOptions = options.commit === true ? defaultCommitOptions : typeof options.commit === 'object' ? {...defaultCommitOptions, ...options.commit} : undefined;
context.addTask(new RepositoryInitializerTask(workingDirectory, commitOptions));
};

const setupRule = async (tree: Tree, context: SchematicContext) => {
const amaSdkSchematicsPackageJson = await readPackageJson();

Expand Down Expand Up @@ -107,7 +115,8 @@ function ngGenerateTypescriptSDKFn(options: NgGenerateTypescriptSDKShellSchemati

return chain([
setupRule,
...(options.skipInstall ? [] : [installRule])
...(options.skipInstall ? [] : [installRule]),
...(options.skipGit ? [] : [initGitRule])
divdavem marked this conversation as resolved.
Show resolved Hide resolved
]);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,34 @@
"description": "Skip NPM install",
"default": false
},
"commit": {
"description": "Initial git repository commit information.",
"oneOf": [
{
"type": "boolean"
},
{
"type": "object",
"properties": {
"name": {
"type": "string"
},
"email": {
"type": "string",
"format": "email"
},
"message": {
"type": "string"
}
}
}
]
},
"skipGit": {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should also add the commit option
You can find an example in this file packages/@o3r/workspace/schematics/ng-add/schema.json

Copy link
Member Author

@divdavem divdavem Feb 19, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you @matthieu-crouzet for your comment! I have added the commit option in the shell generator schematics. However, it is currently not used anywhere.

I have some questions:

  • Should the commit option of the shell generator schematics be true by default?
  • Should the npm create @ama-sdk command create a commit?
  • Should the npm create @ama-sdk command use the commit option of the schematics to create a commit?
  • If the answer to the previous question is yes, the commit would only contain the shell files and neither the result of yarn set version nor the output of sdk generation... so for those extra changes, we could either create another commit or amend the previous one?

I personally prefer not creating a commit in npm create (as it is done in the current state of this PR), but if it is decided to create one, then I think it would be better to create it directly with the right files (calling the shell generator schematics with the commit option set to false and creating the commit at the end), rather than amending a commit. Note that if a repository already exists in a parent folder, the RepositoryInitializerTask does nothing, so we should be especially careful not to amend a previous commit in this case.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Indeed it should not be part of the shell schematic but more of the create script at the end with all the files.
It's the behavior that we have by default when run npm create @o3r if I'm not mistaken.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

npm create @o3r creates a commit, but does not include all changes in it.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In your opinion should we create an issue to handle it later
I think it could be great if the repo is "clean" when you finish the creation

"description": "Do not initialize a git repository.",
"type": "boolean",
"default": false
},
"packageManager": {
"type": "string",
"enum": [
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,4 +18,10 @@ export interface NgGenerateTypescriptSDKShellSchematicsSchema extends SchematicO

/** Skip NPM install */
skipInstall: boolean;

/** Initial git repository commit information. */
commit: boolean | { name?: string; email?: string; message?: string };

/** Do not initialize a git repository. */
skipGit: boolean;
}
9 changes: 7 additions & 2 deletions packages/@o3r/test-helpers/src/prepare-test-env.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,8 @@ export interface PrepareTestEnvOptions {
yarnVersion?: string;
/** Logger to use for logging */
logger?: Logger;
/** Skip git setup */
skipGitSetup?: boolean;
}

/**
Expand All @@ -42,6 +44,7 @@ export async function prepareTestEnv(folderName: string, options?: PrepareTestEn
const type = options?.type || process.env.PREPARE_TEST_ENV_TYPE || 'o3r-project-with-app';
const logger = options?.logger || console;
const yarnVersionParam = options?.yarnVersion;
const skipGitSetup = options?.skipGitSetup || false;
const rootFolderPath = process.cwd();
const itTestsFolderPath = path.resolve(rootFolderPath, '..', 'it-tests');
const workspacePath = path.resolve(itTestsFolderPath, folderName);
Expand Down Expand Up @@ -145,8 +148,10 @@ export async function prepareTestEnv(folderName: string, options?: PrepareTestEn

prepareFinalApp(appDirectory);

// Setup git and initial commit to easily make checks on the diff inside the tests
setupGit(workspacePath);
if (!skipGitSetup) {
// Setup git and initial commit to easily make checks on the diff inside the tests
setupGit(workspacePath);
}

return {
workspacePath,
Expand Down
Loading