Skip to content

Commit

Permalink
feat(version): add json option (#3858)
Browse files Browse the repository at this point in the history
  • Loading branch information
amorscher committed Oct 13, 2023
1 parent 914dd96 commit 86f22f4
Show file tree
Hide file tree
Showing 9 changed files with 221 additions and 18 deletions.
38 changes: 38 additions & 0 deletions e2e/version/src/positional-arguments.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -263,4 +263,42 @@ describe("lerna-version-positional-arguments-npm", () => {
`);
});

it("should support outputting json format", async () => {
const output = await fixture.lerna("version prerelease -y --json");
expect(output.combinedOutput).toMatchInlineSnapshot(`
lerna notice cli v999.9.9-e2e.0
lerna info current version 0.0.0
lerna info Assuming all packages changed
[
{
"name": "package-a",
"version": "0.0.0",
"private": false,
"location": "/tmp/lerna-e2e/lerna-version-positional-arguments-npm/lerna-workspace/packages/package-a",
"newVersion": "0.0.1-alpha.0"
}
]
lerna info auto-confirmed
lerna info execute Skipping releases
lerna info git Pushing tags...
lerna success version finished
`);

// should output valid json format
expect(JSON.parse(output.stdout)).toMatchInlineSnapshot(
`
Array [
Object {
location: /tmp/lerna-e2e/lerna-version-positional-arguments-npm/lerna-workspace/packages/package-a,
name: package-a,
newVersion: 0.0.1-alpha.0,
private: false,
version: 0.0.0,
},
]
`
);
});
});
35 changes: 35 additions & 0 deletions libs/commands/version/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,7 @@ Running `lerna version --conventional-commits` without the above flags will rele
- [`--ignore-changes`](#--ignore-changes)
- [`--ignore-scripts`](#--ignore-scripts)
- [`--include-merged-tags`](#--include-merged-tags)
- [`--json`](#--json)
- [`--message <msg>`](#--message-msg)
- [`--no-changelog`](#--no-changelog)
- [`--no-commit-hooks`](#--no-commit-hooks)
Expand Down Expand Up @@ -373,6 +374,40 @@ lerna version --include-merged-tags

Include tags from merged branches when detecting changed packages.

### `--json`

```sh
lerna version --json
```

Outputs updated packages in json format. Here an example of the output:

```json
[
{
"name": "footer",
"version": "0.0.4",
"private": false,
"location": "/home/ammo/git/lerna-getting-started-example/packages/footer",
"newVersion": "0.0.5"
},
{
"name": "header",
"version": "0.0.4",
"private": false,
"location": "/home/ammo/git/lerna-getting-started-example/packages/header",
"newVersion": "0.0.5"
},
{
"name": "remixapp",
"version": "0.0.4",
"private": true,
"location": "/home/ammo/git/lerna-getting-started-example/packages/remixapp",
"newVersion": "0.0.5"
}
]
```

### `--message <msg>`

This option is aliased to `-m` for parity with `git commit`.
Expand Down
4 changes: 4 additions & 0 deletions libs/commands/version/src/command.ts
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,10 @@ const command: CommandModule = {
describe: "Include tags from merged branches when detecting changed packages.",
type: "boolean",
},
json: {
describe: "Outputs changed packages in json format",
type: "boolean",
},
m: {
describe: "Use a custom commit message when creating the version commit.",
alias: "message",
Expand Down
34 changes: 21 additions & 13 deletions libs/commands/version/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ import {
runProjectsTopologically,
throwIfUncommitted,
updateChangelog,
formatJSON,
} from "@lerna/core";
import chalk from "chalk";
import dedent from "dedent";
Expand Down Expand Up @@ -59,6 +60,7 @@ interface VersionCommandConfigOptions extends CommandConfigOptions {
allowBranch?: string | string[];
conventionalCommits?: boolean;
amend?: boolean;
json?: boolean;
commitHooks?: boolean;
gitRemote?: string;
gitTagVersion?: boolean;
Expand Down Expand Up @@ -388,7 +390,6 @@ class VersionCommand extends Command {
if (!this.composed) {
this.logger.success("version", "finished");
}

return {
updates: this.updates,
updatesVersions: this.updatesVersions,
Expand Down Expand Up @@ -591,19 +592,26 @@ class VersionCommand extends Command {
}

confirmVersions() {
const changes = this.updates.map((node) => {
const pkg = getPackage(node);
let line = ` - ${pkg.name}: ${pkg.version} => ${this.updatesVersions.get(node.name)}`;
if (pkg.private) {
line += ` (${chalk.red("private")})`;
}
return line;
});
if (this.options.json) {
const updatedProjectsJson = formatJSON(this.updates, ({ name }) => ({
newVersion: this.updatesVersions.get(name),
}));
output(updatedProjectsJson);
} else {
const changes = this.updates.map((node) => {
const pkg = getPackage(node);
let line = ` - ${pkg.name}: ${pkg.version} => ${this.updatesVersions.get(node.name)}`;
if (pkg.private) {
line += ` (${chalk.red("private")})`;
}
return line;
});

output("");
output("Changes:");
output(changes.join(os.EOL));
output("");
output("");
output("Changes:");
output(changes.join(os.EOL));
output("");
}

if (this.options.yes) {
this.logger.info("auto-confirmed", "");
Expand Down
71 changes: 71 additions & 0 deletions libs/commands/version/src/lib/version-command.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ import {
initFixtureFactory,
loggingOutput,
showCommit,
tempDirSerializer,
} from "@lerna/test-helpers";
import execa from "execa";
import fs from "fs-extra";
Expand Down Expand Up @@ -84,6 +85,9 @@ const listDirty = (cwd) =>
// stabilize commit SHA
expect.addSnapshotSerializer(gitSHASerializer);

// normalize temp directory paths in snapshots
expect.addSnapshotSerializer(tempDirSerializer);

describe("VersionCommand", () => {
describe("normal mode", () => {
it("versions changed packages", async () => {
Expand Down Expand Up @@ -497,6 +501,73 @@ describe("VersionCommand", () => {
});
});

describe("--json", () => {
it("prints json format", async () => {
const testDir = await initFixture("normal");

await lernaVersion(testDir)("--yes", "--json", "patch");

// Output should be a parseable string
const jsonOutput = JSON.parse(output.logged());
expect(jsonOutput).toMatchInlineSnapshot(`
Array [
Object {
"location": "__TEST_ROOTDIR__/packages/package-1",
"name": "package-1",
"newVersion": "1.0.1",
"private": false,
"version": "1.0.0",
},
Object {
"location": "__TEST_ROOTDIR__/packages/package-2",
"name": "package-2",
"newVersion": "1.0.1",
"private": false,
"version": "1.0.0",
},
Object {
"location": "__TEST_ROOTDIR__/packages/package-3",
"name": "package-3",
"newVersion": "1.0.1",
"private": false,
"version": "1.0.0",
},
Object {
"location": "__TEST_ROOTDIR__/packages/package-4",
"name": "package-4",
"newVersion": "1.0.1",
"private": false,
"version": "1.0.0",
},
Object {
"location": "__TEST_ROOTDIR__/packages/package-5",
"name": "package-5",
"newVersion": "1.0.1",
"private": true,
"version": "1.0.0",
},
]
`);
});

it("prints NO json format", async () => {
const testDir = await initFixture("normal");

await lernaVersion(testDir)("--yes", "patch");

expect(output.logged()).toMatchInlineSnapshot(`
"
Changes:
- package-1: 1.0.0 => 1.0.1
- package-2: 1.0.0 => 1.0.1
- package-3: 1.0.0 => 1.0.1
- package-4: 1.0.0 => 1.0.1
- package-5: 1.0.0 => 1.0.1 (private)
"
`);
});
});

describe("--exact", () => {
it("updates matching local dependencies of published packages with exact versions", async () => {
const testDir = await initFixture("normal");
Expand Down
2 changes: 1 addition & 1 deletion libs/core/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ export { getPackageManifestPath } from "./lib/get-package-manifest-path";
export * from "./lib/get-packages-for-option";
export { gitCheckout } from "./lib/git-checkout";
export { hasNpmVersion } from "./lib/has-npm-version";
export { listableFormatProjects } from "./lib/listable-format-projects";
export { listableFormatProjects, formatJSON } from "./lib/listable-format-projects";
export { ListableOptions, listableOptions } from "./lib/listable-options";
export { logPacked } from "./lib/log-packed";
export { Conf } from "./lib/npm-conf/conf";
Expand Down
31 changes: 30 additions & 1 deletion libs/core/src/lib/listable-format-projects.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
import { loggingOutput, tempDirSerializer, windowsPathSerializer } from "@lerna/test-helpers";
import chalk from "chalk";
import tempy from "tempy";
import { listableFormatProjects } from "./listable-format-projects";
import { formatJSON, listableFormatProjects } from "./listable-format-projects";
import { ListableOptions } from "./listable-options";
import { Package, RawManifest } from "./package";
import {
Expand Down Expand Up @@ -101,6 +101,35 @@ pkg-3 v3.0.0 pkgs/pkg-3 (PRIVATE)
`);
});

test("JSON output with additional props", () => {
const text = formatJSON(projectNodes, ({ name }) => ({ projectName: name }));

expect(text).toMatchInlineSnapshot(`
[
{
"name": "pkg-1",
"version": "1.0.0",
"private": false,
"location": "__TEST_ROOTDIR__/pkgs/pkg-1",
"projectName": "pkg-1"
},
{
"name": "pkg-2",
"private": false,
"location": "__TEST_ROOTDIR__/pkgs/pkg-2",
"projectName": "pkg-2"
},
{
"name": "pkg-3",
"version": "3.0.0",
"private": true,
"location": "__TEST_ROOTDIR__/pkgs/pkg-3",
"projectName": "pkg-3"
}
]
`);
});

test("all JSON output", () => {
const { text } = formatWithOptions({ json: true, all: true });

Expand Down
17 changes: 14 additions & 3 deletions libs/core/src/lib/listable-format-projects.ts
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,12 @@ function filterResultList(
return result;
}

function toJSONList(resultList: ReturnType<typeof filterResultList>) {
function toJSONList(
resultList: ReturnType<typeof filterResultList>,
addtionalProperties: (project: ProjectGraphProjectNodeWithPackage) => {
[propt: string]: unknown;
} = () => ({})
) {
// explicit re-mapping exposes non-enumerable properties
return resultList.map((project) => {
const pkg = getPackage(project);
Expand All @@ -82,12 +87,18 @@ function toJSONList(resultList: ReturnType<typeof filterResultList>) {
version: pkg.version,
private: pkg.private,
location: pkg.location,
...addtionalProperties(project),
};
});
}

function formatJSON(resultList: ReturnType<typeof filterResultList>) {
return JSON.stringify(toJSONList(resultList), null, 2);
export function formatJSON(
resultList: ReturnType<typeof filterResultList>,
additionalProperties: (project: ProjectGraphProjectNodeWithPackage) => {
[propt: string]: unknown;
} = () => ({})
) {
return JSON.stringify(toJSONList(resultList, additionalProperties), null, 2);
}

function formatNDJSON(resultList: ReturnType<typeof filterResultList>) {
Expand Down
7 changes: 7 additions & 0 deletions packages/lerna/schemas/lerna-schema.json
Original file line number Diff line number Diff line change
Expand Up @@ -997,6 +997,9 @@
"ignoreScripts": {
"$ref": "#/$defs/commandOptions/shared/ignoreScripts"
},
"json": {
"$ref": "#/$defs/commandOptions/version/json"
},
"message": {
"$ref": "#/$defs/commandOptions/version/message"
},
Expand Down Expand Up @@ -1696,6 +1699,10 @@
"description": "During `lerna version`, an official GitHub or GitLab release for every version.",
"enum": ["github", "gitlab"]
},
"json": {
"type": "boolean",
"description": "During `lerna version` when true output is provided in json format."
},
"message": {
"type": "string",
"description": "For `lerna version`, the custom commit message to use when creating the version commit."
Expand Down

0 comments on commit 86f22f4

Please sign in to comment.