Skip to content

Commit

Permalink
Flag to create empty changeset (#187)
Browse files Browse the repository at this point in the history
* --empty creates an empty changeset file

* Fixed test message

* Writing and parsing tests for empty changesets, added empty flag to README

* Update README.md
  • Loading branch information
itsjackgardner authored and Noviny committed Oct 11, 2019
1 parent 7e2fc8e commit 8dce96f
Show file tree
Hide file tree
Showing 11 changed files with 166 additions and 63 deletions.
7 changes: 7 additions & 0 deletions .changeset/thick-forks-film.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
---
"@changesets/cli": minor
"@changesets/parse": minor
"@changesets/read": minor
---

Added --empty flag to the add command for empty changeset files. New tests for adding, writing, parsing, and reading empty changesets.
2 changes: 2 additions & 0 deletions fixtures/empty-changeset/.changeset/empty-changeset.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
---
---
22 changes: 16 additions & 6 deletions packages/cli/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -95,13 +95,13 @@ This command sets up the `.changeset` folder. It generates a readme and a config
### add

```
changeset
changeset [--empty]
```

or

```
changeset add
changeset add [--empty]
```

This command will ask you a series of questions, first about what packages you want to release, then what semver bump type for each package, then it will ask for a summary of the entire changeset. At the final step it will show the changeset it will generate, and confirm that you want to add it.
Expand All @@ -120,6 +120,16 @@ A description of the major changes.

If you want to modify this file after it's generated, that's completely fine or if you want to write changeset files yourself, that's also fine.

- `--empty` - allows you to create an empty changeset if no packages are being bumped, usually only required if you have CI that blocks merges without a changeset.

A changeset created with the `empty` flag would look like this:

```md
---
---

```

If you set the `commit` option in the config, the command will add the updated changeset files and then commit them.

### version
Expand All @@ -144,7 +154,7 @@ changeset publish [--otp={token}]

Publishes to NPM repo, and creates git tags. Because this command assumes that last commit is the release commit you should not commit any changes between calling `version` and `publish`. These commands are separate to enable you to check if release commit is acurate.

`--otp={token}` - allows you to provide an npm one-time password if you have auth and writes enabled on npm. The CLI also prompts for the OTP if it's not provided with the `--otp` option.
- `--otp={token}` - allows you to provide an npm one-time password if you have auth and writes enabled on npm. The CLI also prompts for the OTP if it's not provided with the `--otp` option.

**NOTE:** You will still need to push your changes back to master after this

Expand All @@ -160,11 +170,11 @@ status [--verbose] [--output={filePath}] [--since-master]

The status command provides information about the changesets that currently exist. If there are no changesets present, it exits with an error status code.

Use verbose if you want to know the new versions, and get a link to the relevant changeset summary.
- `--verbose` - use if you want to know the new versions, and get a link to the relevant changeset summary.

You can use `output` to write the json object of the status out, for consumption by other tools, such as CI.
- `--output` - allows you to write the json object of the status out, for consumption by other tools, such as CI.

You can use the `since-master flag to only display information about changesets since the master branch. While this can be
- `--since-master` - to only display information about changesets since the master branch. While this can be
used to add a CI check for changesets, we recommend not doing this. We instead recommend using the [changeset bot](https://github.com/apps/changeset-bot)
to detect pull requests missing changesets, as not all pull requests need one.

Expand Down
22 changes: 20 additions & 2 deletions packages/cli/src/commands/add/__tests__/add.ts
Original file line number Diff line number Diff line change
Expand Up @@ -70,8 +70,9 @@ describe("Changesets", () => {

it("should generate changeset to patch a single package", async () => {
const cwd = await copyFixtureIntoTempDir(__dirname, "simple-project");

mockUserResponses({ releases: { "pkg-a": "patch" } });
await addChangeset(cwd, defaultConfig);
await addChangeset(cwd, { empty: false }, defaultConfig);

const expectedChangeset = {
summary: "summary message mock",
Expand All @@ -88,7 +89,24 @@ describe("Changesets", () => {
);

mockUserResponses({ releases: { "pkg-a": "patch" } });
await addChangeset(cwd, { ...defaultConfig, commit: true });
await addChangeset(
cwd,
{ empty: false },
{ ...defaultConfig, commit: true }
);
expect(git.add).toHaveBeenCalledTimes(1);
});
it("should create empty changeset when empty flag is passed in", async () => {
const cwd = await copyFixtureIntoTempDir(__dirname, "simple-project");

await addChangeset(cwd, { empty: true }, defaultConfig);

const expectedChangeset = {
releases: [],
summary: ""
};
// @ts-ignore
const call = writeChangeset.mock.calls[0][0];
expect(call).toEqual(expectedChangeset);
});
});
18 changes: 17 additions & 1 deletion packages/cli/src/commands/add/__tests__/writeChangeset.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,11 @@ const simpleChangeset: { summary: string; releases: Release[] } = {
releases: [{ name: "pkg-a", type: "minor" }]
};

const emptyChangeset: { summary: string; releases: Release[] } = {
summary: "",
releases: []
};

describe("simple project", () => {
let cwd: string;

Expand All @@ -33,9 +38,20 @@ describe("simple project", () => {
await writeChangeset(simpleChangeset, cwd);

const mdPath = path.join(cwd, ".changeset", `${changesetID}.md`);

const mdContent = await fs.readFile(mdPath, "utf-8");

expect(parse(mdContent)).toEqual(simpleChangeset);
});
it("should write an empty changeset", async () => {
const changesetID = "ascii";
// @ts-ignore
humanId.mockReturnValueOnce(changesetID);

await writeChangeset(emptyChangeset, cwd);

const mdPath = path.join(cwd, ".changeset", `${changesetID}.md`);
const mdContent = await fs.readFile(mdPath, "utf-8");

expect(parse(mdContent)).toEqual(emptyChangeset);
});
});
41 changes: 29 additions & 12 deletions packages/cli/src/commands/add/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,11 @@ import createChangeset from "./createChangeset";
import getChangesetBase from "../../utils/getChangesetBase";
import printConfirmationMessage from "./messages";

export default async function add(cwd: string, config: Config) {
export default async function add(
cwd: string,
{ empty }: { empty?: boolean },
config: Config
) {
const changesetBase = await getChangesetBase(cwd);

if (!fs.existsSync(changesetBase)) {
Expand All @@ -26,16 +30,23 @@ export default async function add(cwd: string, config: Config) {
return;
}

const changedPackages = await git.getChangedPackagesSinceMaster(cwd);
const changePackagesName = changedPackages
.filter(a => a)
.map(pkg => pkg.name);
const newChangeset = await createChangeset(changePackagesName, cwd);
printConfirmationMessage(newChangeset);
let newChangeset, confirmChangeset;
if (empty) {
newChangeset = {
releases: [],
summary: ``
};
confirmChangeset = true;
} else {
const changedPackages = await git.getChangedPackagesSinceMaster(cwd);
const changePackagesName = changedPackages
.filter(a => a)
.map(pkg => pkg.name);
newChangeset = await createChangeset(changePackagesName, cwd);
printConfirmationMessage(newChangeset);

const confirmChangeset = await cli.askConfirm(
"Is this your desired changeset?"
);
confirmChangeset = await cli.askConfirm("Is this your desired changeset?");
}

if (confirmChangeset) {
const changesetID = await writeChangeset(newChangeset, cwd);
Expand All @@ -45,9 +56,15 @@ export default async function add(cwd: string, config: Config) {
`CHANGESET: ${changesetID}. ${newChangeset.summary}`,
cwd
);
logger.log(chalk.green("Changeset added and committed"));
logger.log(
chalk.green(`${empty ? "Empty " : ""}Changeset added and committed`)
);
} else {
logger.log(chalk.green("Changeset added! - you can now commit it\n"));
logger.log(
chalk.green(
`${empty ? "Empty " : ""}Changeset added! - you can now commit it\n`
)
);
}

let hasMajorChange = [...newChangeset.releases].find(
Expand Down
12 changes: 8 additions & 4 deletions packages/cli/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ const { input, flags } = meow(
$ changesets [command]
Commands
init
add
add [--empty]
version
publish [--otp=code]
status [--since-master --verbose --output=JSON_FILE.json]
Expand All @@ -42,6 +42,9 @@ const { input, flags } = meow(
otp: {
type: "string",
default: undefined
},
empty: {
type: "boolean"
}
}
}
Expand Down Expand Up @@ -91,14 +94,15 @@ const cwd = process.cwd();
}

if (input.length < 1) {
const { empty }: CliOptions = flags;
// @ts-ignore if this is undefined, we have already exited
await add(cwd, config);
await add(cwd, { empty }, config);
} else if (input.length > 1) {
logger.error(
"Too many arguments passed to changesets - we only accept the command name as an argument"
);
} else {
const { sinceMaster, verbose, output, otp }: CliOptions = flags;
const { sinceMaster, verbose, output, otp, empty }: CliOptions = flags;
const deadFlags = ["updateChangelog", "isPublic", "skipCI", "commit"];

deadFlags.forEach(flag => {
Expand All @@ -120,7 +124,7 @@ const cwd = process.cwd();
switch (input[0]) {
case "add": {
// @ts-ignore if this is undefined, we have already exited
await add(cwd, config);
await add(cwd, { empty }, config);
return;
}
case "version": {
Expand Down
1 change: 1 addition & 0 deletions packages/cli/src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ export type CliOptions = {
verbose?: boolean;
output?: string;
otp?: string;
empty?: boolean;
};

export type CommandOptions = CliOptions & {
Expand Down
Loading

0 comments on commit 8dce96f

Please sign in to comment.