Skip to content

Commit 3db7afe

Browse files
committed
dedupe changesets
1 parent cb4efa3 commit 3db7afe

File tree

7 files changed

+142
-37
lines changed

7 files changed

+142
-37
lines changed

.changeset/spotty-queens-move.md

+5
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
'mock-workspace': patch
3+
---
4+
5+
This doesn't matter

NaN.json

+4
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
{
2+
"changesets": [],
3+
"releases": []
4+
}

__tests__/main.test.ts

+113-26
Original file line numberDiff line numberDiff line change
@@ -12,27 +12,11 @@ import * as github from '@actions/github'
1212
import * as main from '../src/main'
1313
import * as utils from '../src/utils'
1414

15-
// Mock the GitHub Actions core library
15+
// Mock the GitHub Actions library
1616
const infoMock = jest.spyOn(core, 'info')
17-
const setFailedMock = jest
18-
.spyOn(core, 'setFailed')
19-
.mockImplementation(console.debug)
20-
const inputMock = jest
21-
.spyOn(core, 'getInput')
22-
.mockImplementation((name: string): string => {
23-
switch (name) {
24-
case 'changed_files':
25-
return JSON.stringify([
26-
'./packages/pkg1/file1.css',
27-
'./packages/pkgB/file2.tsx'
28-
])
29-
default:
30-
return ''
31-
}
32-
})
33-
34-
jest.spyOn(exec, 'exec').mockImplementation(async () => 0)
35-
const getExecOutputMock = jest.spyOn(exec, 'getExecOutput')
17+
const setFailedMock = jest.spyOn(core, 'setFailed')
18+
const inputMock = jest.spyOn(core, 'getInput')
19+
const execSpy = jest.spyOn(exec, 'exec')
3620

3721
const originalContext = github.context
3822

@@ -41,7 +25,18 @@ const runMock = jest.spyOn(main, 'run')
4125

4226
describe('action', () => {
4327
beforeEach(() => {
44-
jest.clearAllMocks()
28+
inputMock.mockImplementation((name: string): string => {
29+
switch (name) {
30+
case 'changed_files':
31+
return JSON.stringify([
32+
'./packages/pkg1/file1.css',
33+
'./packages/pkgB/file2.tsx'
34+
])
35+
default:
36+
return ''
37+
}
38+
})
39+
setFailedMock.mockImplementation(console.debug)
4540
})
4641

4742
afterEach(() => {
@@ -84,7 +79,8 @@ describe('action', () => {
8479
}
8580
}
8681
})
87-
getExecOutputMock
82+
jest
83+
.spyOn(exec, 'getExecOutput')
8884
// workspaces info
8985
.mockImplementationOnce(async () => ({
9086
stdout: JSON.stringify({
@@ -101,6 +97,12 @@ describe('action', () => {
10197
stderr: '',
10298
exitCode: 0
10399
}))
100+
// check changeset installed
101+
.mockImplementationOnce(async () => ({
102+
stdout: '',
103+
stderr: '',
104+
exitCode: 0
105+
}))
104106
// changeset info
105107
.mockImplementationOnce(async () => ({
106108
stdout: `🦋 info Packages to be bumped at patch:
@@ -123,6 +125,7 @@ describe('action', () => {
123125
// Assert
124126
expect(runMock).toHaveReturned()
125127
expect(setFailedMock).not.toHaveBeenCalled()
128+
expect(execSpy).not.toHaveBeenCalled()
126129

127130
// Verify that all of the core library functions were called correctly
128131
expect(infoMock).toHaveBeenNthCalledWith(
@@ -135,6 +138,74 @@ describe('action', () => {
135138
)
136139
})
137140

141+
it('installs changeset when not installed', async () => {
142+
// Arrange
143+
jest.spyOn(utils, 'getChangesets').mockImplementation(
144+
async (): Promise<utils.Changesets> =>
145+
Promise.resolve({
146+
releases: [
147+
{
148+
name: '@owner/pkg1',
149+
type: 'patch'
150+
},
151+
{
152+
name: '@owner/pkgB',
153+
type: 'patch'
154+
}
155+
]
156+
})
157+
)
158+
Object.defineProperty(github, 'context', {
159+
value: {
160+
...originalContext,
161+
eventName: 'pull_request',
162+
payload: {
163+
pull_request: {
164+
head: {
165+
sha: '1234567890'
166+
},
167+
base: {
168+
ref: 'main'
169+
}
170+
}
171+
}
172+
}
173+
})
174+
jest
175+
.spyOn(exec, 'getExecOutput')
176+
// workspaces info
177+
.mockImplementationOnce(async () => ({
178+
stdout: JSON.stringify({
179+
type: 'log',
180+
data: JSON.stringify({
181+
'@owner/pkg1': {
182+
location: './packages/pkg1'
183+
},
184+
'@owner/pkgB': {
185+
location: './packages/pkgB'
186+
}
187+
})
188+
}),
189+
stderr: '',
190+
exitCode: 0
191+
}))
192+
// check changeset installed
193+
.mockImplementationOnce(async () => ({
194+
stdout: '',
195+
stderr: '',
196+
exitCode: 1
197+
}))
198+
199+
// Act
200+
await main.run()
201+
202+
// Assert
203+
expect(runMock).toHaveReturned()
204+
205+
// Verify that all of the core library functions were called correctly
206+
expect(execSpy).toHaveBeenCalledWith('yarn add @changesets/cli@latest -W')
207+
})
208+
138209
it('fails when there are packages that need changeset entries', async () => {
139210
// Arrange
140211
Object.defineProperty(github, 'context', {
@@ -153,7 +224,8 @@ describe('action', () => {
153224
}
154225
}
155226
})
156-
getExecOutputMock
227+
jest
228+
.spyOn(exec, 'getExecOutput')
157229
// workspaces info
158230
.mockImplementationOnce(async () => ({
159231
stdout: JSON.stringify({
@@ -170,6 +242,12 @@ describe('action', () => {
170242
stderr: '',
171243
exitCode: 0
172244
}))
245+
// changeset installed
246+
.mockImplementationOnce(async () => ({
247+
stdout: '',
248+
stderr: '',
249+
exitCode: 0
250+
}))
173251
// changeset info
174252
.mockImplementationOnce(async () => ({
175253
stdout: '',
@@ -244,7 +322,8 @@ describe('action', () => {
244322
}
245323
}
246324
})
247-
getExecOutputMock
325+
jest
326+
.spyOn(exec, 'getExecOutput')
248327
// workspaces info
249328
.mockImplementationOnce(async () => ({
250329
stdout: JSON.stringify({
@@ -291,7 +370,8 @@ describe('action', () => {
291370
}
292371
}
293372
})
294-
getExecOutputMock
373+
jest
374+
.spyOn(exec, 'getExecOutput')
295375
// workspaces info
296376
.mockImplementationOnce(async () => ({
297377
stdout: '',
@@ -326,7 +406,8 @@ describe('action', () => {
326406
}
327407
}
328408
})
329-
getExecOutputMock
409+
jest
410+
.spyOn(exec, 'getExecOutput')
330411
// workspaces info
331412
.mockImplementationOnce(async () => ({
332413
stdout: JSON.stringify({
@@ -343,6 +424,12 @@ describe('action', () => {
343424
stderr: '',
344425
exitCode: 0
345426
}))
427+
// changeset installed
428+
.mockImplementationOnce(async () => ({
429+
stdout: '',
430+
stderr: '',
431+
exitCode: 0
432+
}))
346433
// changeset info
347434
.mockImplementationOnce(async () => ({
348435
stdout: JSON.stringify(`🦋 info Packages to be bumped at patch:

dist/index.js

+5-3
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,7 @@
7272
"devDependencies": {
7373
"@changesets/cli": "^2.26.2",
7474
"@types/jest": "^29.5.5",
75-
"@types/node": "^20.6.5",
75+
"@types/node": "^18.17.1",
7676
"@typescript-eslint/eslint-plugin": "^6.7.3",
7777
"@typescript-eslint/parser": "^6.7.2",
7878
"@vercel/ncc": "^0.38.0",

src/main.ts

+10-3
Original file line numberDiff line numberDiff line change
@@ -75,10 +75,17 @@ export async function run(): Promise<void> {
7575
return
7676
}
7777

78-
// right now, the only way to access JSON output is to create a file,
79-
// so we are just going to work with the pretty-printed output
78+
const changesetExists = await exec.getExecOutput(
79+
`yarn changeset --version`,
80+
undefined,
81+
{ ignoreReturnCode: true }
82+
)
83+
if (changesetExists.exitCode === 1) {
84+
core.info('Installing changeset CLI')
85+
await exec.exec(`yarn add @changesets/cli@latest -W`)
86+
}
87+
8088
const filePath = `${github.context.runId}.json`
81-
await exec.exec(`yarn add @changesets/cli@latest -W`)
8289
const changesetResult = await exec.getExecOutput(
8390
`yarn changeset status --since origin/${base} --output ${filePath}`,
8491
undefined,

yarn.lock

+4-4
Original file line numberDiff line numberDiff line change
@@ -1114,10 +1114,10 @@
11141114
resolved "https://registry.yarnpkg.com/@types/node/-/node-12.20.55.tgz#c329cbd434c42164f846b909bd6f85b5537f6240"
11151115
integrity sha512-J8xLz7q2OFulZ2cyGTLE1TbbZcjpno7FaN6zdJNrgAdrJ+DZzh/uFR6YrTb4C+nXakvud8Q4+rbhoIWlYQbUFQ==
11161116

1117-
"@types/node@^20.6.5":
1118-
version "20.6.5"
1119-
resolved "https://registry.yarnpkg.com/@types/node/-/node-20.6.5.tgz#4c6a79adf59a8e8193ac87a0e522605b16587258"
1120-
integrity sha512-2qGq5LAOTh9izcc0+F+dToFigBWiK1phKPt7rNhOqJSr35y8rlIBjDwGtFSgAI6MGIhjwOVNSQZVdJsZJ2uR1w==
1117+
"@types/node@^18.17.1":
1118+
version "18.18.0"
1119+
resolved "https://registry.yarnpkg.com/@types/node/-/node-18.18.0.tgz#bd19d5133a6e5e2d0152ec079ac27c120e7f1763"
1120+
integrity sha512-3xA4X31gHT1F1l38ATDIL9GpRLdwVhnEFC8Uikv5ZLlXATwrCYyPq7ZWHxzxc3J/30SUiwiYT+bQe0/XvKlWbw==
11211121

11221122
"@types/normalize-package-data@^2.4.0":
11231123
version "2.4.1"

0 commit comments

Comments
 (0)