change peer dependent bump type to `patch` by beeequeue · Pull Request #2090 · changesets/changesets · GitHub
Skip to content
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
10 changes: 10 additions & 0 deletions .changeset/wide-feet-lie.md
46 changes: 0 additions & 46 deletions packages/assemble-release-plan/src/determine-dependents.ts
Original file line number Diff line number Diff line change
Expand Up @@ -87,20 +87,6 @@ export function determineDependents({
for (const { depType, versionRange } of dependencyVersionRanges) {
if (nextRelease.type === "none") {
continue;
} else if (
shouldBumpMajor({
dependent,
depType,
versionRange,
releases,
nextRelease,
preInfo,
onlyUpdatePeerDependentsWhenOutOfRange:
config.___experimentalUnsafeOptions_WILL_CHANGE_IN_PATCH
.onlyUpdatePeerDependentsWhenOutOfRange,
})
) {
type = "major";
} else if (
(!releases.has(dependent) ||
releases.get(dependent)!.type === "none") &&
Expand Down Expand Up @@ -240,35 +226,3 @@ function getDependencyVersionRanges(
}
return dependencyVersionRanges;
}

function shouldBumpMajor({
dependent,
depType,
versionRange,
releases,
nextRelease,
preInfo,
onlyUpdatePeerDependentsWhenOutOfRange,
}: {
dependent: string;
depType: DependencyType;
versionRange: string;
releases: Map<string, InternalRelease>;
nextRelease: InternalRelease;
preInfo: PreInfo | undefined;
onlyUpdatePeerDependentsWhenOutOfRange: boolean;
}) {
// we check if it is a peerDependency because if it is, our dependent bump type might need to be major.
return (
depType === "peerDependencies" &&
nextRelease.type !== "none" &&
nextRelease.type !== "patch" &&
// 1. If onlyUpdatePeerDependentsWhenOutOfRange set to true, bump major if the version is leaving the range.
// 2. If onlyUpdatePeerDependentsWhenOutOfRange set to false, bump major regardless whether or not the version is leaving the range.
(!onlyUpdatePeerDependentsWhenOutOfRange ||
!semverSatisfies(incrementVersion(nextRelease, preInfo), versionRange)) &&
// bump major only if the dependent doesn't already has a major release.
(!releases.has(dependent) ||
(releases.has(dependent) && releases.get(dependent)!.type !== "major"))
);
}
80 changes: 62 additions & 18 deletions packages/assemble-release-plan/src/index.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -595,7 +595,7 @@ describe("assembleReleasePlan", () => {
},
{
name: "pkg-b",
newVersion: "2.0.0",
newVersion: "1.0.1",
},
]);
});
Expand Down Expand Up @@ -734,10 +734,58 @@ describe("assembleReleasePlan", () => {
},
{
name: "pkg-b",
newVersion: "2.0.0",
newVersion: "1.0.1",
},
]);
});

// https://github.com/changesets/changesets/issues/963
// https://github.com/changesets/changesets/issues/1759
it("should not bump fixed packages due to peer dependents", () => {
const setup = new FakeFullState({ changesets: [] });

setup.addPackage("@ex/core", "0.1.0");
setup.addPackage("@ex/errors", "0.1.0");
setup.addPackage("@ex/api", "0.1.0");
setup.addPackage("some-peer", "0.1.0"); // optional peer
setup.addPackage("@ex/components", "0.1.0");

setup.updateDependencies("@ex/api", [
{ name: "@ex/core", range: "0.1.0" },
{ name: "@ex/errors", range: "0.1.0" },
{ name: "some-peer", range: "0.1.0", type: "peer" },
]);
setup.updateDependencies("@ex/components", [
{ name: "@ex/api", range: "0.1.0" },
{ name: "some-peer", range: "0.1.0" },
]);

setup.addChangeset({ releases: [{ name: "@ex/core", type: "minor" }] });

const result = assembleReleasePlan(
setup.changesets,
setup.packages,
{
...defaultConfig,
fixed: [
[
"@ex/core",
"@ex/errors",
"@ex/api",
"some-peer",
"@ex/components",
],
],
},
undefined,
);

expect(result.releases).toHaveLength(5);
expect(
result.releases.every((release) => release.newVersion === "0.2.0"),
"every bump should be to 0.2.0",
).toBe(true);
});
});

describe("pre mode", () => {
Expand Down Expand Up @@ -1024,29 +1072,26 @@ describe("dependent bumping", () => {
Record<VersionType, Record<Range, string>>
>;

const defaultBumps: ExpectationTable[DepKind] = {
none: { "^": "1.0.0", "~": "1.0.0", "=": "1.0.0" },
patch: { "^": "1.0.0", "~": "1.0.0", "=": "1.0.1" },
minor: { "^": "1.0.0", "~": "1.0.1", "=": "1.0.1" },
major: { "^": "1.0.1", "~": "1.0.1", "=": "1.0.1" },
};

// oxfmt-ignore
const baseExpectations: ExpectationTable = {
// direct dependent has to be bumped only when dependency falls out of allowed range
// direct and peer dependents have to be bumped only when dependency falls out of allowed range
// otherwise, installing the latest versions of dependent and dependency would result in duplicate dependency package in the tree
dep: {
none: { "^": "1.0.0", "~": "1.0.0", "=": "1.0.0" },
patch: { "^": "1.0.0", "~": "1.0.0", "=": "1.0.1" },
minor: { "^": "1.0.0", "~": "1.0.1", "=": "1.0.1" },
major: { "^": "1.0.1", "~": "1.0.1", "=": "1.0.1" },
},
dep: defaultBumps,
peer: defaultBumps,
// devDependent should stay untouched, given the dev dependency doesn't affect production installations
dev: {
none: { "^": "1.0.0", "~": "1.0.0", "=": "1.0.0" },
patch: { "^": "1.0.0", "~": "1.0.0", "=": "1.0.0" },
minor: { "^": "1.0.0", "~": "1.0.0", "=": "1.0.0" },
major: { "^": "1.0.0", "~": "1.0.0", "=": "1.0.0" },
},
peer: {
none: { "^": "1.0.0", "~": "1.0.0", "=": "1.0.0" },
patch: { "^": "1.0.0", "~": "1.0.0", "=": "1.0.1" },
minor: { "^": "2.0.0", "~": "2.0.0", "=": "2.0.0" },
major: { "^": "2.0.0", "~": "2.0.0", "=": "2.0.0" },
},
};

// ---- Test cases ----
Expand Down Expand Up @@ -1232,19 +1277,18 @@ describe("dependent bumping", () => {
},
peer: {
patch: { "^": "1.0.1", "~": "1.0.1" },
minor: { "^": "1.0.1" },
},
},
});

// should not affect dependent bumps
describeDependentBumping("onlyUpdatePeerDependentsWhenOutOfRange: true", {
config: {
___experimentalUnsafeOptions_WILL_CHANGE_IN_PATCH: {
onlyUpdatePeerDependentsWhenOutOfRange: true,
},
},
overrides: {
peer: { minor: { "^": "1.0.0" } },
},
});

// weird case, should probably not be allowed
Expand Down
35 changes: 26 additions & 9 deletions packages/assemble-release-plan/src/test-utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -102,11 +102,32 @@ export class FakeFullState {
(a) => a.packageJson.name === dependent,
);
if (!pkg) throw new Error(`No "${dependent}" package`);
if (!pkg.packageJson.dependencies) {
pkg.packageJson.dependencies = {};
}
pkg.packageJson.dependencies ??= {};
pkg.packageJson.dependencies[dependency] = versionRange;
}
updateDependencies(
dependent: string,
deps: Array<{
name: string;
range: string;
type?: "direct" | "peer" | "dev";
}>,
) {
const pkg = this.packages.packages.find(
(p) => p.packageJson.name === dependent,
);
if (!pkg) throw new Error(`No "${dependent}" package`);
for (const { name, range, type } of deps) {
const property =
type === "dev"
? "devDependencies"
: type === "peer"
? "peerDependencies"
: "dependencies";
pkg.packageJson[property] ??= {};
pkg.packageJson[property][name] = range;
}
}
updateDevDependency(
dependent: string,
dependency: string,
Expand All @@ -116,9 +137,7 @@ export class FakeFullState {
(a) => a.packageJson.name === dependent,
);
if (!pkg) throw new Error(`No "${dependent}" package`);
if (!pkg.packageJson.devDependencies) {
pkg.packageJson.devDependencies = {};
}
pkg.packageJson.devDependencies ??= {};
pkg.packageJson.devDependencies[dependency] = versionRange;
}
updatePeerDependency(
Expand All @@ -130,9 +149,7 @@ export class FakeFullState {
(a) => a.packageJson.name === dependent,
);
if (!pkg) throw new Error(`No "${dependent}" package`);
if (!pkg.packageJson.peerDependencies) {
pkg.packageJson.peerDependencies = {};
}
pkg.packageJson.peerDependencies ??= {};
pkg.packageJson.peerDependencies[dependency] = versionRange;
}

Expand Down
6 changes: 3 additions & 3 deletions packages/cli/src/commands/version/version.test.ts