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: the update command should update to compatible versions by default #7809

Merged
merged 5 commits into from
Sep 27, 2023
Merged
Show file tree
Hide file tree
Changes from 1 commit
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
29 changes: 28 additions & 1 deletion e2e/harmony/update-cmd.e2e.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ describe('update command', function () {
after(() => {
helper.scopeHelper.destroy();
});
describe('updates policies', function () {
describe('updates policies to latest versions', function () {
describe('policies added by the user', function () {
let configFile;
let componentJson;
Expand Down Expand Up @@ -110,6 +110,33 @@ describe('update command', function () {
});
});
});
describe('updates policies to compatible versions', function () {
describe('policies added by deps set', function () {
before(() => {
helper.scopeHelper.reInitLocalScope();
helper.fixtures.populateComponents(1);
helper.command.dependenciesSet('comp1', '[email protected]');
helper.command.update('--yes --compatible');
});
it('should update the version range', function () {
const showOutput = helper.command.showComponentParsed('comp1');
expect(showOutput.packageDependencies['is-negative']).to.equal('1.0.1');
});
});
describe('policies added by deps set. savePrefix is present', function () {
before(() => {
helper.scopeHelper.reInitLocalScope();
helper.extensions.bitJsonc.addKeyValToDependencyResolver('savePrefix', '^');
helper.fixtures.populateComponents(1);
helper.command.dependenciesSet('comp1', '[email protected]');
helper.command.update('--yes --compatible');
});
it('should update the version range', function () {
const showOutput = helper.command.showComponentParsed('comp1');
expect(showOutput.packageDependencies['is-negative']).to.equal('^1.0.1');
});
});
});
(supportNpmCiRegistryTesting ? describe : describe.skip)('updates dependencies from the model', () => {
let configFile;
let npmCiRegistry: NpmCiRegistry;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ import {
import { DependencyResolverAspect } from './dependency-resolver.aspect';
import { DependencyVersionResolver } from './dependency-version-resolver';
import { DepLinkerContext, DependencyLinker, LinkingOptions } from './dependency-linker';
import { ComponentModelVersion, getAllPolicyPkgs, OutdatedPkg } from './get-all-policy-pkgs';
import { ComponentModelVersion, getAllPolicyPkgs, OutdatedPkg, CurrentPkgSource } from './get-all-policy-pkgs';
import { InvalidVersionWithPrefix, PackageManagerNotFound } from './exceptions';
import {
CreateFromComponentsOptions,
Expand Down Expand Up @@ -1411,7 +1411,7 @@ export class DependencyResolverMain {
componentPolicies: Array<{ componentId: ComponentID; policy: any }>;
components: Component[];
patterns?: string[];
forceVersionBump?: 'major' | 'minor' | 'patch';
forceVersionBump?: 'major' | 'minor' | 'patch' | 'compatible';
}): Promise<MergedOutdatedPkg[]> {
const localComponentPkgNames = new Set(components.map((component) => this.getPackageName(component)));
const componentModelVersions: ComponentModelVersion[] = (
Expand Down Expand Up @@ -1466,7 +1466,7 @@ export class DependencyResolverMain {
forceVersionBump,
}: {
rootDir: string;
forceVersionBump?: 'major' | 'minor' | 'patch';
forceVersionBump?: 'major' | 'minor' | 'patch' | 'compatible';
},
pkgs: Array<
{ name: string; currentRange: string; source: 'variants' | 'component' | 'rootPolicy' | 'component-model' } & T
Expand All @@ -1489,7 +1489,9 @@ export class DependencyResolverMain {
const outdatedPkgs = compact(
await Promise.all(
pkgs.map(async (pkg) => {
const latestVersion = await tryResolve(`${pkg.name}@${newVersionRange(pkg.currentRange, forceVersionBump)}`);
const latestVersion = await tryResolve(
`${pkg.name}@${newVersionRange(pkg.currentRange, { pkgSource: pkg.source, forceVersionBump })}`
);
if (!latestVersion) return null;
const currentVersion = semver.valid(pkg.currentRange.replace(/[\^~]/, ''));
// If the current version is newer than the latest, then no need to update the dependency
Expand Down Expand Up @@ -1696,12 +1698,21 @@ function repeatPrefix(originalSpec: string, newVersion: string): string {
}
}

function newVersionRange(currentRange: string, forceVersionBump?: 'major' | 'minor' | 'patch') {
if (forceVersionBump == null || forceVersionBump === 'major') return 'latest';
function newVersionRange(
currentRange: string,
opts: { pkgSource: CurrentPkgSource; forceVersionBump?: 'major' | 'minor' | 'patch' | 'compatible' }
) {
if (opts.forceVersionBump == null || opts.forceVersionBump === 'major') return 'latest';
const currentVersion = semver.valid(currentRange.replace(/[\^~]/, ''));
if (opts.forceVersionBump === 'compatible') {
if ((opts.pkgSource === 'component' || opts.pkgSource === 'component-model') && currentVersion === currentRange) {
return `^${currentVersion}`;
}
return currentRange;
}
if (!currentVersion) return null;
const [major, minor] = currentVersion.split('.');
switch (forceVersionBump) {
switch (opts.forceVersionBump) {
case 'patch':
return `>=${currentVersion} <${major}.${+minor + 1}.0`;
case 'minor':
Expand Down
12 changes: 11 additions & 1 deletion scopes/dependencies/dependency-resolver/get-all-policy-pkgs.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,20 @@ import { VariantPolicyConfigObject, WorkspacePolicy } from './policy';
import { DependencyLifecycleType } from './dependencies/dependency';
import { KEY_NAME_BY_LIFECYCLE_TYPE } from './dependencies';

export type CurrentPkgSource =
// the variants section of "workspace.jsonc"
| 'variants'
// these are dependencies set via "bit deps set" or "component.json"
| 'component'
// these are dependencies from the dependencies policy in "workspace.jsonc"
| 'rootPolicy'
// the are dependencies of imported components
Copy link
Member

Choose a reason for hiding this comment

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

the -> these

Copy link
Member

Choose a reason for hiding this comment

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

Also I'm not sure this definition is accurate

| 'component-model';

type CurrentPkg = {
name: string;
currentRange: string;
source: 'variants' | 'component' | 'rootPolicy' | 'component-model';
source: CurrentPkgSource;
variantPattern?: string | null;
componentId?: ComponentID;
isAuto?: boolean;
Expand Down
2 changes: 1 addition & 1 deletion scopes/workspace/install/install.main.runtime.ts
Original file line number Diff line number Diff line change
Expand Up @@ -578,7 +578,7 @@ export class InstallMain {
* @param options.all {Boolean} updates all outdated dependencies without showing a prompt.
*/
async updateDependencies(options: {
forceVersionBump?: 'major' | 'minor' | 'patch';
forceVersionBump?: 'major' | 'minor' | 'patch' | 'compatible';
patterns?: string[];
all: boolean;
}): Promise<ComponentMap<string> | null> {
Expand Down
6 changes: 5 additions & 1 deletion scopes/workspace/install/update.cmd.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ type UpdateCmdOptions = {
major?: boolean;
minor?: boolean;
patch?: boolean;
compatible?: boolean;
};

export default class UpdateCmd implements Command {
Expand All @@ -32,18 +33,21 @@ export default class UpdateCmd implements Command {
['', 'patch', 'update to the latest patch version. Semver rules are ignored'],
['', 'minor', 'update to the latest minor version. Semver rules are ignored'],
['', 'major', 'update to the latest major version. Semver rules are ignored'],
['', 'compatible', 'update to the highest semver compatibe version'],
] as CommandOptions;

constructor(private install: InstallMain) {}

async report([patterns = []]: [string[]], options: UpdateCmdOptions) {
let forceVersionBump: 'major' | 'minor' | 'patch' | undefined;
let forceVersionBump: 'major' | 'minor' | 'patch' | 'compatible' | undefined;
if (options.major) {
forceVersionBump = 'major';
} else if (options.minor) {
forceVersionBump = 'minor';
} else if (options.patch) {
forceVersionBump = 'patch';
} else if (options.compatible) {
forceVersionBump = 'compatible';
}
await this.install.updateDependencies({
all: options.yes === true,
Expand Down