Skip to content
This repository was archived by the owner on Jun 3, 2023. It is now read-only.

Commit c69e4d5

Browse files
committed
feat: adds rollback listener to reverse script mutations if cancelled
1 parent 9648eba commit c69e4d5

29 files changed

+486
-244
lines changed

.release-workspaces.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
{
22
"metadata": {
3-
"version": "0.6.7"
3+
"version": "0.7.12"
44
}
55
}

README.md

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
<a href="https://github.com/geotrev/release-workspaces/blob/main/LICENSE"><img src="https://img.shields.io/npm/l/release-workspaces.svg?sanitize=true&style=flat-square" alt="License"></a>
66
<a href="https://github.com/geotrev/release-workspaces/actions/workflows/test.yml?query=branch%3Amain"><img src="https://badgen.net/github/checks/geotrev/release-workspaces/main?style=flat-square" alt="CI status" /></a>
77
<div align="center">
8-
<img width="500px" height="auto" src="https://github.com/geotrev/release-workspaces/raw/main/demo.gif" />
8+
<img width="600px" height="auto" src="https://github.com/geotrev/release-workspaces/raw/main/demo2.gif" />
99
</div>
1010
</p>
1111

@@ -41,9 +41,8 @@
4141

4242
This tool assumes a few things about your workflow:
4343

44-
- You're using npm workspaces (of course) (node 17.x)
44+
- You're using npm workspaces (of course) (npm 7.x)
4545
- All your packages will use the same version for each release
46-
- You're working in a [module architecture](https://nodejs.org/api/packages.html#introduction)
4746

4847
## Usage
4948

bin/__tests__/commit.spec.js

Lines changed: 49 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,14 +2,23 @@ import "../../.jest/mocks.js"
22
import { ReportSteps } from "../helpers/constants.js"
33
import { getCommitCmd, getTagCmd, getPushCmd } from "../helpers/commands.js"
44
import { setVersionToString } from "../helpers/transformers.js"
5+
import { setRollback } from "../helpers/rollback.js"
56
import { reportCmd } from "../helpers/cmd.js"
67
import { runCommit } from "../modules/commit.js"
78

89
jest.mock("../helpers/cmd.js", () => ({
910
reportCmd: jest.fn(),
11+
cmd: jest.fn(),
12+
}))
13+
14+
jest.mock("../helpers/rollback.js", () => ({
15+
setRollback: jest.fn(),
1016
}))
1117

1218
const baseConfig = {
19+
npm: {
20+
increment: true,
21+
},
1322
releaseVersion: "0.0.0",
1423
hooks: {
1524
precommit: "npm test",
@@ -36,7 +45,7 @@ describe("runCommit()", () => {
3645
})
3746
})
3847

39-
describe("commit is true", () => {
48+
describe("commit and increment is true", () => {
4049
let config
4150

4251
beforeEach(async () => {
@@ -81,6 +90,35 @@ describe("runCommit()", () => {
8190
})
8291
)
8392
})
93+
94+
it("calls setRollback", async () => {
95+
expect(setRollback).toBeCalledWith(
96+
expect.objectContaining(config),
97+
expect.objectContaining({
98+
type: "commit",
99+
callback: expect.any(Function),
100+
})
101+
)
102+
})
103+
})
104+
105+
describe("increment is false", () => {
106+
let config
107+
108+
beforeEach(async () => {
109+
// Given
110+
config = {
111+
...baseConfig,
112+
npm: { increment: false },
113+
git: { ...baseConfig.git, commit: true, push: false, tag: false },
114+
}
115+
// When
116+
await runCommit(config)
117+
})
118+
119+
it("doesn't run commit command", async () => {
120+
expect(reportCmd).not.toBeCalledWith()
121+
})
84122
})
85123

86124
describe("tag is true", () => {
@@ -128,6 +166,16 @@ describe("runCommit()", () => {
128166
})
129167
)
130168
})
169+
170+
it("calls setRollback", async () => {
171+
expect(setRollback).toBeCalledWith(
172+
expect.objectContaining(config),
173+
expect.objectContaining({
174+
type: "tag",
175+
callback: expect.any(Function),
176+
})
177+
)
178+
})
131179
})
132180

133181
describe("push is true", () => {

bin/__tests__/increment.spec.js

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@ const entryTwo = {
4040
const config = {
4141
dryRun: false,
4242
verbose: false,
43+
prevVersion: "0.0.0",
4344
releaseVersion: "0.0.1",
4445
packageNames,
4546
packages: [entryOne, entryTwo],
@@ -137,7 +138,6 @@ describe("runIncrement()", () => {
137138
expect.objectContaining({
138139
m: `fs.writeFileSync(path.resolve(dir, "package.json"), newPkgJson, "utf8")`,
139140
type: "info",
140-
indent: true,
141141
})
142142
)
143143
})
@@ -152,7 +152,6 @@ describe("runIncrement()", () => {
152152
expect.objectContaining({
153153
m: `fs.writeFileSync(path.resolve(dir, "package.json"), newPkgJson, "utf8")`,
154154
type: "info",
155-
indent: true,
156155
})
157156
)
158157
})
@@ -163,9 +162,8 @@ describe("runIncrement()", () => {
163162
// Then
164163
expect(report).toBeCalledWith(
165164
expect.objectContaining({
166-
m: "Version",
165+
m: `${entryTwo.name} | ${config.prevVersion} -> ${config.releaseVersion}`,
167166
type: "start",
168-
indent: true,
169167
})
170168
)
171169
})
@@ -176,9 +174,11 @@ describe("runIncrement()", () => {
176174
// Then
177175
expect(report).toBeCalledWith(
178176
expect.objectContaining({
179-
m: "Version successful",
180-
type: "succeed",
181-
indent: true,
177+
m: {
178+
text: `${entryTwo.name} | ${config.prevVersion} -> ${config.releaseVersion}`,
179+
symbol: "📦",
180+
},
181+
type: "stopAndPersist",
182182
})
183183
)
184184
})

bin/__tests__/npm.spec.js

Lines changed: 130 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,28 @@
11
import "../../.jest/mocks.js"
22
import path from "path"
3+
import { ReportSteps } from "../helpers/constants.js"
4+
import { getAddCommand } from "../helpers/commands.js"
35
import { report } from "../helpers/reporter.js"
6+
import { reportCmd, cmd } from "../helpers/cmd.js"
7+
import { setRollback } from "../helpers/rollback.js"
8+
import { setRootVersion } from "../helpers/set-root-version.js"
49
import { runNpm } from "../modules/npm.js"
510
import { runIncrement } from "../modules/increment.js"
611
import { runPublish } from "../modules/publish.js"
712

813
jest.mock("../helpers/reporter.js", () => ({
914
report: jest.fn(),
1015
}))
16+
jest.mock("../helpers/cmd.js", () => ({
17+
reportCmd: jest.fn(),
18+
cmd: jest.fn(),
19+
}))
20+
jest.mock("../helpers/set-root-version.js", () => ({
21+
setRootVersion: jest.fn(),
22+
}))
23+
jest.mock("../helpers/rollback.js", () => ({
24+
setRollback: jest.fn(),
25+
}))
1126
jest.mock("../modules/increment.js", () => ({
1227
runIncrement: jest.fn(),
1328
}))
@@ -23,6 +38,12 @@ const npmConfig = {
2338
const config = {
2439
releaseVersion: "0.0.1",
2540
npm: npmConfig,
41+
hooks: {
42+
preincrement: true,
43+
postincrement: true,
44+
prepublish: true,
45+
postpublish: true,
46+
},
2647
packages: [
2748
{
2849
name: "@test/one",
@@ -50,60 +71,136 @@ describe("runNpm()", () => {
5071
expect(runPublish).toBeCalledTimes(config.packages.length)
5172
})
5273

53-
it("does not increment", async () => {
74+
it("sets root version", async () => {
5475
// When
55-
await runNpm({
56-
...config,
57-
npm: {
58-
...npmConfig,
59-
increment: false,
60-
},
61-
})
76+
await runNpm(config)
6277
// Then
63-
expect(runIncrement).not.toBeCalled()
78+
expect(setRootVersion).toBeCalled()
6479
})
6580

66-
it("does not publish", async () => {
81+
it("adds changes to git", async () => {
6782
// When
68-
await runNpm({
69-
...config,
70-
npm: {
71-
...npmConfig,
72-
publish: false,
73-
},
74-
})
83+
await runNpm(config)
7584
// Then
76-
expect(runPublish).not.toBeCalled()
85+
expect(cmd).toBeCalledWith(getAddCommand(), config)
7786
})
7887

7988
describe("report", () => {
80-
it("reports for each package", async () => {
89+
it("reports version/publish success", async () => {
8190
// When
8291
await runNpm(config)
8392
// Then
84-
for (const pkg of config.packages) {
85-
expect(report).toBeCalledWith(
86-
expect.objectContaining({
87-
m: {
88-
text: `${pkg.name}@${config.releaseVersion}`,
89-
symbol: "📦",
90-
},
91-
type: "stopAndPersist",
92-
})
93-
)
94-
}
93+
expect(report).toBeCalledWith(
94+
expect.objectContaining({
95+
m: "All packages versioned/published successfully",
96+
type: "succeed",
97+
})
98+
)
9599
})
96100

97-
it("reports success", async () => {
101+
it("reports version success", async () => {
98102
// When
99-
await runNpm(config)
103+
await runNpm({ ...config, npm: { publish: false, increment: true } })
100104
// Then
101105
expect(report).toBeCalledWith(
102106
expect.objectContaining({
103-
m: "All packages versioned/published without errors",
107+
m: "All packages versioned successfully (publish skipped)",
104108
type: "succeed",
105109
})
106110
)
107111
})
112+
113+
it("reports publish success", async () => {
114+
// When
115+
await runNpm({ ...config, npm: { publish: true, increment: false } })
116+
// Then
117+
expect(report).toBeCalledWith(
118+
expect.objectContaining({
119+
m: "All packages published successfully (version skipped)",
120+
type: "succeed",
121+
})
122+
)
123+
})
124+
125+
it("reports version/publish skipped", async () => {
126+
// When
127+
await runNpm({ ...config, npm: { publish: false, increment: false } })
128+
// Then
129+
expect(report).toBeCalledWith(
130+
expect.objectContaining({
131+
m: "Version/publish skipped for all packages",
132+
type: "succeed",
133+
})
134+
)
135+
})
136+
})
137+
138+
describe("rollbacks", () => {
139+
it("adds changes action", async () => {
140+
// When
141+
await runNpm(config)
142+
// Then
143+
expect(setRollback).toBeCalledWith(
144+
expect.objectContaining(config),
145+
expect.objectContaining({
146+
type: "increment",
147+
callback: expect.any(Function),
148+
})
149+
)
150+
})
151+
})
152+
153+
describe("hooks", () => {
154+
it("runs preincrement hook", async () => {
155+
// When
156+
await runNpm(config)
157+
// Then
158+
expect(reportCmd).toBeCalledWith(
159+
config.hooks.preincrement,
160+
expect.objectContaining({
161+
...config,
162+
step: ReportSteps.PREINCREMENT,
163+
})
164+
)
165+
})
166+
167+
it("runs postincrement hook", async () => {
168+
// When
169+
await runNpm(config)
170+
// Then
171+
expect(reportCmd).toBeCalledWith(
172+
config.hooks.postincrement,
173+
expect.objectContaining({
174+
...config,
175+
step: ReportSteps.POSTINCREMENT,
176+
})
177+
)
178+
})
179+
180+
it("runs prepublish hook", async () => {
181+
// When
182+
await runNpm(config)
183+
// Then
184+
expect(reportCmd).toBeCalledWith(
185+
config.hooks.prepublish,
186+
expect.objectContaining({
187+
...config,
188+
step: ReportSteps.PREPUBLISH,
189+
})
190+
)
191+
})
192+
193+
it("runs postpublish hook", async () => {
194+
// When
195+
await runNpm(config)
196+
// Then
197+
expect(reportCmd).toBeCalledWith(
198+
config.hooks.postpublish,
199+
expect.objectContaining({
200+
...config,
201+
step: ReportSteps.POSTPUBLISH,
202+
})
203+
)
204+
})
108205
})
109206
})

0 commit comments

Comments
 (0)