Skip to content

Commit

Permalink
feat: support workspace ranges (#311)
Browse files Browse the repository at this point in the history
* feat: support workspace ranges

close #307

* Create itchy-pants-obey.md

* style: fix

* docs: update changesets

* test: apply-release-plan with workspace range

* test: add test to version.test.ts
  • Loading branch information
zkochan committed Apr 14, 2020
1 parent 042cc30 commit c3cc232
Show file tree
Hide file tree
Showing 11 changed files with 119 additions and 3 deletions.
5 changes: 5 additions & 0 deletions .changeset/fuzzy-tips-provide.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@changesets/get-dependents-graph": minor
---

Added support for workspace ranges. Package graph validation understands them now and allows them to satisfy dependents' required ranges.
5 changes: 5 additions & 0 deletions .changeset/itchy-pants-obey.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@changesets/apply-release-plan": minor
---

Added support for workspace ranges. They are now correctly kept and updated when applying a release plan.
3 changes: 3 additions & 0 deletions __fixtures__/simple-workspace-range-dep/.changeset/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
# We just want a file in here so git collects it

For this we have deliberately not included a config file, as we want to test the defaults
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
{}
11 changes: 11 additions & 0 deletions __fixtures__/simple-workspace-range-dep/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
{
"private": true,
"name": "simple-project",
"description": "three projects, each depending on one other",
"version": "1.0.0",
"bolt": {
"workspaces": [
"packages/*"
]
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
{
"name": "pkg-a",
"version": "1.0.0",
"dependencies": {
"pkg-b": "workspace:1.0.0"
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
{
"name": "pkg-b",
"version": "1.0.0"
}
37 changes: 37 additions & 0 deletions packages/apply-release-plan/src/index.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -148,6 +148,43 @@ describe("apply release plan", () => {
}
});
});
it("should update workspace ranges", async () => {
const releasePlan = new FakeReleasePlan(
[
{
id: "some-id",
releases: [{ name: "pkg-b", type: "minor" }],
summary: "a very useful summary"
}
],
[
{
changesets: ["some-id"],
name: "pkg-b",
newVersion: "1.1.0",
oldVersion: "1.0.0",
type: "minor"
}
]
);
let { changedFiles } = await testSetup(
"simple-workspace-range-dep",
releasePlan.getReleasePlan(),
releasePlan.config
);
let pkgPath = changedFiles.find(a => a.endsWith("pkg-a/package.json"));

if (!pkgPath) throw new Error(`could not find an updated package json`);
let pkgJSON = await fs.readJSON(pkgPath);

expect(pkgJSON).toEqual({
name: "pkg-a",
version: "1.1.0",
dependencies: {
"pkg-b": "workspace:1.1.0"
}
});
});
it("should update a version for two packages with different new versions", async () => {
const releasePlan = new FakeReleasePlan(
[],
Expand Down
7 changes: 6 additions & 1 deletion packages/apply-release-plan/src/version-package.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,8 +26,12 @@ export default function versionPackage(
if (deps) {
for (let { name, version } of versionsToUpdate) {
let depCurrentVersion = deps[name];
if (!depCurrentVersion) continue;
const usesWorkspaceRange = depCurrentVersion.startsWith("workspace:");
if (usesWorkspaceRange) {
depCurrentVersion = depCurrentVersion.substr(10);
}
if (
depCurrentVersion &&
// an empty string is the normalised version of x/X/*
// we don't want to change these versions because they will match
// any version and if someone makes the range that
Expand All @@ -36,6 +40,7 @@ export default function versionPackage(
) {
let rangeType = getVersionRangeType(depCurrentVersion);
let newNewRange = `${rangeType}${version}`;
if (usesWorkspaceRange) newNewRange = `workspace:${newNewRange}`;
deps[name] = newNewRange;
}
}
Expand Down
36 changes: 35 additions & 1 deletion packages/cli/src/commands/version/version.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -195,6 +195,40 @@ describe("running version in a simple project", () => {
});
});

describe("running version in a simple project with workspace range", () => {
temporarilySilenceLogs();
let cwd: string;

beforeEach(async () => {
cwd = await copyFixtureIntoTempDir(__dirname, "simple-workspace-range-dep");
console.error = jest.fn();
});

afterEach(async () => {
console.error = consoleError;
});

describe("When there is a changeset commit", () => {
it("should bump releasedPackages", async () => {
await writeChangesets([simpleChangeset2], cwd);
const spy = jest.spyOn(fs, "writeFile");

await versionCommand(cwd, modifiedDefaultConfig);

expect(getPkgJSON("pkg-a", spy.mock.calls)).toEqual(
expect.objectContaining({
name: "pkg-a",
version: "1.1.0",
dependencies: { "pkg-b": "workspace:1.0.1" }
})
);
expect(getPkgJSON("pkg-b", spy.mock.calls)).toEqual(
expect.objectContaining({ name: "pkg-b", version: "1.0.1" })
);
});
});
});

const f = fixturez(__dirname);

describe("pre", () => {
Expand Down Expand Up @@ -592,7 +626,7 @@ describe("pre", () => {
}
]);
});
it.only("should use the highest bump type for between all prereleases for every prerelease", async () => {
it("should use the highest bump type for between all prereleases for every prerelease", async () => {
let cwd = f.copy("simple-project");
await writeChangeset(
{
Expand Down
6 changes: 5 additions & 1 deletion packages/get-dependents-graph/src/get-dependency-graph.ts
Original file line number Diff line number Diff line change
Expand Up @@ -54,12 +54,16 @@ export default function getDependencyGraph(
const dependencies = [];
const allDependencies = getAllDependencies(pkg.packageJson);

for (const [depName, depVersion] of allDependencies) {
for (let [depName, depVersion] of allDependencies) {
const match = packagesByName[depName];
if (!match) continue;

const expected = match.packageJson.version;

if (depVersion.startsWith("workspace:")) {
depVersion = depVersion.substr(10);
}

// internal dependencies only need to semver satisfy, not '==='
if (!semver.satisfies(expected, depVersion)) {
valid = false;
Expand Down

0 comments on commit c3cc232

Please sign in to comment.