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 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
41 changes: 34 additions & 7 deletions 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 @@ -39,7 +39,7 @@ describe('update command', function () {
};
helper.componentJson.write(componentJson, 'comp2');
helper.command.install('[email protected]');
helper.command.update('--yes');
helper.command.update('--yes --latest');
configFile = helper.bitJsonc.read(helper.scopes.localPath);
componentJson = helper.componentJson.read('comp2');
});
Expand Down Expand Up @@ -82,7 +82,7 @@ describe('update command', function () {
},
});
helper.command.install();
helper.command.update('--yes is-posit*');
helper.command.update('--yes is-posit* --latest');
configFile = helper.bitJsonc.read(helper.scopes.localPath);
});
it('should update the version range of the selected package', function () {
Expand All @@ -102,14 +102,41 @@ describe('update command', function () {
helper.scopeHelper.reInitLocalScope();
helper.fixtures.populateComponents(1);
helper.command.dependenciesSet('comp1', '[email protected]');
helper.command.update('--yes');
helper.command.update('--yes --latest');
});
it('should update the version range', function () {
const showOutput = helper.command.showComponentParsed('comp1');
expect(showOutput.packageDependencies['is-negative']).not.to.equal('1.0.0');
});
});
});
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');
});
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');
});
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 Expand Up @@ -166,7 +193,7 @@ const isPositive = require("is-positive");`
helper.bitJsonc.setupDefault();
helper.extensions.bitJsonc.addKeyValToDependencyResolver('savePrefix', '^');
helper.command.import(`${helper.scopes.remote}/comp1`);
helper.command.update('--yes');
helper.command.update('--yes --latest');
configFile = helper.bitJsonc.read(helper.scopes.localPath);
});
it('should add an updated version of the dependency from the model to the workspace policies', function () {
Expand Down Expand Up @@ -201,7 +228,7 @@ const isPositive = require("is-positive");`
helper.scopeHelper.addRemoteScope();
helper.bitJsonc.setupDefault();
helper.command.import(`${helper.scopes.remote}/comp1`);
helper.command.update('--yes');
helper.command.update('--yes --latest');
configFile = helper.bitJsonc.read(helper.scopes.localPath);
});
it('should add an updated version of the dependency from the model to the bitmap', function () {
Expand Down Expand Up @@ -265,7 +292,7 @@ const isPositive = require("is-positive");`
helper.scopeHelper.addRemoteScope();
helper.command.import(`${helper.scopes.remote}/[email protected]`);
helper.command.import(`${helper.scopes.remote}/[email protected]`);
helper.command.update('--yes');
helper.command.update('--yes --latest');
configFile = helper.bitJsonc.read(helper.scopes.localPath);
});
after(() => {
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 @@ -1405,7 +1405,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 @@ -1460,7 +1460,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 @@ -1483,7 +1483,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 @@ -1690,12 +1692,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'
// these are dependencies stored in the component object (snapped/tagged version)
| '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 @@ -619,7 +619,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
8 changes: 6 additions & 2 deletions scopes/workspace/install/update.cmd.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,12 @@ type UpdateCmdOptions = {
major?: boolean;
minor?: boolean;
patch?: boolean;
latest?: boolean;
};

export default class UpdateCmd implements Command {
name = 'update [package-patterns...]';
description = 'update dependencies';
description = 'update dependencies. By default, dependencies are updated to the highest semver compatible versions.';
helpUrl = 'reference/dependencies/configuring-dependencies/#update-dependencies';
alias = 'up';
group = 'development';
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'],
['', 'latest', 'update to the latest version. Semver rules are ignored'],
] 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.latest) {
forceVersionBump = 'compatible';
}
await this.install.updateDependencies({
all: options.yes === true,
Expand Down