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

Migration-Tool: add a new option for overwrite current and target version + fix _label handling #5509

Merged
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
67 changes: 39 additions & 28 deletions packages/tools/kolibri-cli/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -92,12 +92,14 @@ kolibri migrate <path>

#### Options

| Option | Description | Type | Default |
| ------------------------------ | ---------------------------------------------- | :------------------: | :------: |
| `--format` | Try to format the modified files with prettier | boolean | true |
| `--ignore-greater-version` | Allows execution with greater versions | boolean | false |
| `--ignore-uncommitted-changes` | Allows execution with uncommitted changes | boolean | false |
| `--remove-mode` | Prefix property name or delete property | `delete` \| `prefix` | `prefix` |
| Option | Description | Type | Default |
| ------------------------------ | ------------------------------------------------------------------ | :------------------: | :-----------------------: |
| `--format` | Try to format the modified files with prettier | boolean | true |
| `--overwrite-current-version` | Migrate from this current version instead of the installed version | version | current installed version |
| `--overwrite-target-version` | Migrate to this target version instead of the version of the CLI | version | version of the CLI |
| `--ignore-greater-version` | Allows execution with greater versions | boolean | false |
| `--ignore-uncommitted-changes` | Allows execution with uncommitted changes | boolean | false |
| `--remove-mode` | Prefix property name or delete property | `delete` \| `prefix` | `prefix` |

#### Configuration

Expand All @@ -110,25 +112,21 @@ You can configure the migration with the `.kolibri.config.json` file in your pro
"migrate": {
"tasks": {
".gitignore-add-rule-.kolibri.migrate.json": true,
"vscode-settings-reconfigure-html.customData": true,
"tsconfig-reconfigure-compilerOptions.types": true,
"remove--cpy-cli,rimraf": true,
"add--cpy-cli,rimraf": true,
"package.json-reconfigure-scripts.postinstall": true,
"merge-html-codicon-in-index.html": true,
"remove-public/assets/codicons": true,
"exec-npx cpy \"node_modules/@public-ui/components/assets/**/*\" \"public/assets\" --dot": true,
".npmrc-add-rule-save-exact=true": true,
"vscode-settings-reconfigure-html.customData": true,
"kol-abbr-rename-property-_align-to-_tooltip-align": true,
"kol-abbr-rename-property-_title-to-_label": true,
"kol-accordion-rename-property-_heading-to-_label": true,
"kol-alert-rename-property-_heading-to-_label": true,
"kol-badge-rename-property-_icon-only-to-_hide-label": true,
"kol-badge-remove-property-_hide-label": true,
"kol-badge-remove-property-_icon-only": true,
"kol-badge-rename-property-_icon-to-_icons": true,
"kol-breadcrumb-rename-property-_aria-label-to-_label": true,
"kol-button-link-remove-property-_aria-current": true,
"kol-button-link-remove-property-_aria-label": true,
"kol-button-link-rename-property-_icon-only-to-_hide-label": true,
"kol-button-link-rename-property-_icon-to-_icons": true,
"kol-button-remove-property-_aria-current": true,
"kol-button-remove-property-_aria-label": true,
"kol-button-remove-property-_icon-align": true,
Expand All @@ -148,28 +146,33 @@ You can configure the migration with the `.kolibri.config.json` file in your pro
"kol-date-rename-property-_list-to-_suggestions": true,
"kol-input-email-rename-property-_icon-to-_icons": true,
"kol-input-email-rename-property-_list-to-_suggestions": true,
"kol-input-email-remove-property-_size": true,
"kol-input-file-rename-property-_icon-to-_icons": true,
"kol-input-number-rename-property-_icon-to-_icons": true,
"kol-input-number-rename-property-_list-to-_suggestions": true,
"kol-input-number-remove-property-_type": true,
"kol-input-password-rename-property-_icon-to-_icons": true,
"kol-input-password-remove-property-_size": true,
"kol-input-radio-rename-property-_list-to-_options": true,
"kol-input-range-rename-property-_icon-to-_icons": true,
"kol-input-range-rename-property-_list-to-_suggestions": true,
"kol-input-rename-property-_icon-to-_icons": true,
"kol-input-text-rename-property-_icon-to-_icons": true,
"kol-input-text-rename-property-_list-to-_suggestions": true,
"kol-link-button-remove-property-_aria-control": true,
"kol-input-text-remove-property-_size": true,
"kol-link-button-remove-property-_aria-controls": true,
"kol-link-button-remove-property-_aria-expanded": true,
"kol-link-button-remove-property-_aria-label": true,
"kol-link-button-remove-property-_aria-selected": true,
"kol-link-button-remove-property-_disabled": true,
"kol-link-button-rename-property-_aria-current-to-_listen-aria-current": true,
"kol-link-button-rename-property-_icon-only-to-_hide-label": true,
"kol-link-button-rename-property-_icon-to-_icons": true,
"kol-link-group-rename-property-_heading-to-_label": true,
"kol-link-group-remove-property-_heading": true,
"kol-link-group-remove-property-_ordered": true,
"kol-link-group-rename-property-_aria-label-to-_label": true,
"kol-link-remove-property-_aria-control": true,
"kol-link-remove-property-_aria-controls": true,
"kol-link-remove-property-_aria-expanded": true,
"kol-link-remove-property-_aria-label": true,
"kol-link-remove-property-_aria-selected": true,
Expand All @@ -180,6 +183,7 @@ You can configure the migration with the `.kolibri.config.json` file in your pro
"kol-link-remove-property-_use-case": true,
"kol-link-rename-property-_aria-current-to-_listen-aria-current": true,
"kol-link-rename-property-_icon-only-to-_hide-label": true,
"kol-link-rename-property-_icon-to-_icons": true,
"kol-logo-rename-property-_abbr-to-_org": true,
"kol-modal-rename-property-_aria-label-to-_label": true,
"kol-nav-remove-property-_variant": true,
Expand All @@ -192,15 +196,20 @@ You can configure the migration with the `.kolibri.config.json` file in your pro
"kol-select-rename-property-_height-to-_rows": true,
"kol-select-rename-property-_icon-to-_icons": true,
"kol-select-rename-property-_list-to-_options": true,
"kol-select-remove-property-_size": true,
"kol-skip-nav-rename-property-_aria-label-to-_label": true,
"kol-span-rename-property-_icon-only-to-_hide-label": true,
"kol-span-rename-property-_icon-to-_icons": true,
"kol-split-button-remove-property-_aria-label": true,
"kol-split-button-rename-property-_show-dropdown-to-_show": true,
"kol-split-button-remove-property-_access-key": true,
"kol-split-button-remove-property-_show-dropdown": true,
"kol-split-button-remove-property-_show": true,
"kol-symbol-rename-property-_aria-label-to-_label": true,
"kol-table-rename-property-_caption-to-_label": true,
"kol-tabs-rename-property-_aria-label-to-_label": true,
"kol-tabs-rename-property-_icon-to-_icons": true,
"kol-tabs-rename-property-_tab-align-to-_align": true,
"kol-tabs-rename-property-_icon-only-to-_hide-label": true,
"kol-toast-remove-property-_show-duration": true,
"kol-toast-rename-property-_heading-to-_label": true,
"kol-version-rename-property-_version-to-_label": true,
Expand All @@ -223,7 +232,17 @@ You can configure the migration with the `.kolibri.config.json` file in your pro
"kol-card-mark-removed-slot-header": true,
"kol-accordion-rename-slot-content-to-": true,
"kol-card-rename-slot-content-to-": true,
"refactor-property-label-replace-false": true
"refactor-property-label-replace-false": true,
"kol-card-remove-property-_has-footer": true,
"kol-link-group-remove-property-_level": true,
"remove--cpy-cli,rimraf": true,
"add--cpy-cli,rimraf": true,
"package.json-reconfigure-scripts.postinstall": true,
"remove-public/assets/codicons": true,
"exec-npx cpy \"node_modules/@public-ui/components/assets/**/*\" \"undefined/assets\" --dot": true,
"kol-button-link-remove-property-_access-key": true,
"kol-button-remove-property-_access-key": true,
"kol-nav-remove-property-_has-compact-button": true
}
}
}
Expand All @@ -235,6 +254,8 @@ If the migration failed, you can reset the migration with `git reset --hard HEAD

Use the configuration (`.kolibri.config.json`) to exclude some tasks.

If your project is already on a newer version of KoliBri, but you want to repeat the migration from a previous version, you can use this `--overwrite-current-version` option. It overwrites the offset version from which the migration originally starts, instead of using the installed version.

If there are multiple obsolete properties that have been migrated to just one new property, the new property may appear multiple times in the tag. You can then decide which variant to use and remove all other variants accordingly.

Maybe it can help to prepare your code in the tricky places for migration.
Expand All @@ -248,13 +269,3 @@ You have always the possibility of a dry run. Because before the migration will
After the migration you can check the result with `git status` and `git diff`.

Is anything wrong, you can reset the migration with `git reset --hard HEAD~1` or by discarding the affected files.

## Changelog

### 1.7.1

- Fix version handling by adding the absolut min version 1.4.2
- Add post message feature for more details
- Add `${` support by `_label` migration
- Activate Expert-Slot refactoring for `_label` migration
- Prevents `@public-ui/kolibri-cli` from being changed by the update process
59 changes: 46 additions & 13 deletions packages/tools/kolibri-cli/src/migrate/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,9 +29,13 @@ type MigrateOption = {
format: boolean;
ignoreGreaterVersion: boolean;
ignoreUncommittedChanges: boolean;
overwriteCurrentVersion: string;
overwriteTargetVersion: string;
removeMode: RemoveMode;
testTasks: boolean;
};
const currentVersionOfPublicUi = getVersionOfPublicUiComponents();
const targetVersionOfPublicUi = getVersionOfPublicUiKoliBriCli();

/**
* This function is used to register the migrate command.
Expand All @@ -43,6 +47,14 @@ export default function (program: Command): void {
.description('This command migrates KoliBri code to the current version.')
.argument('[string]', 'Source code folder to migrate', 'src')
.addOption(new Option('--format', 'Try to format the modified files with prettier').default(true))
.addOption(
new Option('--overwrite-current-version <version>', 'Migrate from this current version instead of the installed version of KoliBri').default(
currentVersionOfPublicUi,
),
)
.addOption(
new Option('--overwrite-target-version <version>', 'Migrate to this target version instead of the version of the CLI').default(targetVersionOfPublicUi),
)
.addOption(new Option('--ignore-greater-version', 'Allows execution with greater versions').default(false))
.addOption(new Option('--ignore-uncommitted-changes', 'Allows execution with uncommitted changes').default(false))
.addOption(new Option('--remove-mode <mode>', 'Prefix property name or delete property').choices(REMOVE_MODE).default('prefix'))
Expand All @@ -54,21 +66,31 @@ export default function (program: Command): void {
return;
}

if (!semver.valid(options.overwriteCurrentVersion)) {
throw logAndCreateError('Please specify a valid version for the --overwrite-current-version option.');
}

if (!semver.valid(options.overwriteTargetVersion)) {
throw logAndCreateError('Please specify a valid version for the --overwrite-target-version option.');
}

if (!baseDir) {
throw logAndCreateError('Please specify the source code folder to migrate.');
}

if (!options.ignoreUncommittedChanges && stdout) {
throw logAndCreateError('There are uncommitted changes');
throw logAndCreateError('There are uncommitted changes', 'If you want to ignore this, use the --ignore-uncommitted-changes option.');
}

setRemoveMode(options.removeMode);

const versionOfPublicUiComponents = getVersionOfPublicUiComponents();
const versionOfPublicUiKoliBriCli = getVersionOfPublicUiKoliBriCli();

console.log(`
Current version of @public-ui/components: ${versionOfPublicUiComponents}
Current version of @public-ui/*: ${options.overwriteCurrentVersion}
Target version of @public-ui/*: ${options.overwriteTargetVersion}
Source folder to migrate: ${baseDir}
`);

if (!options.ignoreGreaterVersion && semver.lt(versionOfPublicUiKoliBriCli, versionOfPublicUiComponents)) {
if (!options.ignoreGreaterVersion && semver.lt(options.overwriteTargetVersion, options.overwriteCurrentVersion)) {
throw logAndCreateError(
'Your current version of @public-ui/components is greater than the version of @public-ui/kolibri-cli. Please update @public-ui/kolibri-cli or force the migration with --ignore-greater-version.',
);
Expand All @@ -84,7 +106,7 @@ Source folder to migrate: ${baseDir}
}
}

const runner = new TaskRunner(baseDir, versionOfPublicUiKoliBriCli, versionOfPublicUiComponents, config);
const runner = new TaskRunner(baseDir, options.overwriteTargetVersion, options.overwriteCurrentVersion, config);
runner.registerTasks(commonTasks);
runner.registerTasks(v1Tasks);
runner.registerTasks(v2Tasks);
Expand All @@ -94,7 +116,7 @@ Source folder to migrate: ${baseDir}
runner.registerTasks(testTasks);
}

let version = versionOfPublicUiComponents;
let version = options.overwriteCurrentVersion;

/**
* Creates a replacer function for the package.json file.
Expand Down Expand Up @@ -139,13 +161,13 @@ Source folder to migrate: ${baseDir}
// Tasks
version = runner.getPendingMinVersion();
setVersionOfPublicUiPackages(version, runLoop);
} else if (semver.lt(version, versionOfPublicUiKoliBriCli)) {
} else if (semver.lt(version, options.overwriteTargetVersion)) {
// CLI
version = versionOfPublicUiKoliBriCli;
version = options.overwriteTargetVersion;
setVersionOfPublicUiPackages(version, finish);
} else if (semver.lt(version, versionOfPublicUiComponents)) {
} else if (semver.lt(version, options.overwriteCurrentVersion)) {
// Components
version = versionOfPublicUiComponents;
version = options.overwriteCurrentVersion;
setVersionOfPublicUiPackages(version, finish);
} else {
finish();
Expand All @@ -160,7 +182,18 @@ Source folder to migrate: ${baseDir}
Status of all executed Tasks:`);

const status = runner.getStatus(true);
fs.writeFileSync(configFile, JSON.stringify(status.config, null, 2));

// Merge config with current config of Runner
config = {
migrate: {
tasks: {
...status.config.migrate?.tasks,
...config.migrate?.tasks,
},
},
};

fs.writeFileSync(configFile, JSON.stringify(config, null, 2));

console.log(`
Modified files: ${MODIFIED_FILES.size}`);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ export class TaskRunner {
this.setBaseDir(baseDir);
this.setCliVersion(cliVersion);
this.setProjectVersion(projectVersion);
this.setConfig(config);
this.setConfig({ ...config }); // clone config
}

private setBaseDir(baseDir: string): void {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import fs from 'fs';

import { COMPONENT_FILE_EXTENSIONS, MARKUP_EXTENSIONS } from '../../../../types';
import { COMPONENT_FILE_EXTENSIONS, CUSTOM_ELEMENT_FILE_EXTENSIONS, MARKUP_EXTENSIONS } from '../../../../types';
import {
filterFilesByExt,
isPropertyKebabCaseRegExp,
Expand All @@ -25,8 +25,8 @@ export class LabelExpertSlot extends AbstractTask {

private constructor(
identifier: string,
tag: string,
private readonly property: string,
private readonly tag: string,
readonly property: string,
versionRange: string,
dependentTasks: AbstractTask[],
options: TaskOptions,
Expand Down Expand Up @@ -91,7 +91,7 @@ export class LabelExpertSlot extends AbstractTask {
if (typeof args[2] === 'string' && args[2].includes('{')) {
args[2] = args[2].replace(/\{/g, '${');
}
return `<${args[1]} ${this.propertyInCamelCase}={\`${args[2]}\`} />`;
return `<${args[1]} ${this.propertyInCamelCase}={\`${args[2]}\`}/>`;
})
.replace(this.componentNoLabelPropRegExp, this.addMissingEmptyLabelToActivateExpertSlot.bind(this));
if (content !== newContent) {
Expand All @@ -102,13 +102,18 @@ export class LabelExpertSlot extends AbstractTask {
}

private transpileCustomElementFileDelete(baseDir: string): void {
filterFilesByExt(baseDir, COMPONENT_FILE_EXTENSIONS).forEach((file) => {
filterFilesByExt(baseDir, CUSTOM_ELEMENT_FILE_EXTENSIONS).forEach((file) => {
const content = fs.readFileSync(file, 'utf8');
const newContent = content
// Replacements
.replace(this.customElementRegExp, removeLineBreaksAndSpaces)
.replace(this.customElementRegExp, `<$1 ${this.property}="$2"></$1>`)
.replace(this.componentNoLabelPropRegExp, this.addMissingEmptyLabelToActivateExpertSlot.bind(this));
.replace(this.customElementRegExp, (...args) => {
if (typeof args[2] === 'string' && args[2].includes('{')) {
args[2] = args[2].replace(/\{/g, '${');
}
return `<${args[1]} ${this.propertyInCamelCase}="${args[2]}"></${this.tag}>`;
})
.replace(this.customElementNoLabelPropRegExp, this.addMissingEmptyLabelToActivateExpertSlot.bind(this));
if (content !== newContent) {
MODIFIED_FILES.add(file);
fs.writeFileSync(file, newContent);
Expand Down
Loading