Skip to content

Commit 1539b1a

Browse files
committed
[RN][Releases] Automate the draft release creation
1 parent e704f8a commit 1539b1a

File tree

4 files changed

+473
-1
lines changed

4 files changed

+473
-1
lines changed
Lines changed: 301 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,301 @@
1+
/**
2+
* Copyright (c) Meta Platforms, Inc. and affiliates.
3+
*
4+
* This source code is licensed under the MIT license found in the
5+
* LICENSE file in the root directory of this source tree.
6+
*
7+
* @format
8+
*/
9+
10+
const {
11+
_verifyTagExists,
12+
_extractChangelog,
13+
_computeBody,
14+
_createDraftReleaseOnGitHub,
15+
} = require('../createDraftRelease');
16+
17+
const fs = require('fs');
18+
19+
const silence = () => {};
20+
const mockFetch = jest.fn();
21+
22+
jest.mock('../utils.js', () => ({
23+
log: silence,
24+
}));
25+
26+
global.fetch = mockFetch;
27+
28+
describe('Create Draft Release', () => {
29+
beforeEach(jest.clearAllMocks);
30+
31+
describe('#_verifyTagExists', () => {
32+
it('throws if the tag does not exists', async () => {
33+
const token = 'token';
34+
mockFetch.mockReturnValueOnce(Promise.resolve({status: 404}));
35+
36+
await expect(_verifyTagExists('0.77.1')).rejects.toThrowError(`Tag v0.77.1 does not exist`);
37+
expect(mockFetch).toHaveBeenCalledTimes(1);
38+
expect(mockFetch).toHaveBeenCalledWith('https://github.com/facebook/react-native/releases/tag/v0.77.1');
39+
});
40+
});
41+
42+
describe('#_extractChangelog', () => {
43+
it(`extracts changelog from CHANGELOG.md`, async () => {
44+
const mockedReturnValue = `# Changelog
45+
46+
## v0.77.2
47+
48+
- [PR #1234](https://github.com/facebook/react-native/pull/1234) - Some change
49+
- [PR #5678](https://github.com/facebook/react-native/pull/5678) - Some other change
50+
51+
52+
## v0.77.1
53+
### Breaking Changes
54+
- [PR #9012](https://github.com/facebook/react-native/pull/9012) - Some other change
55+
56+
#### Android
57+
- [PR #3456](https://github.com/facebook/react-native/pull/3456) - Some other change
58+
- [PR #3457](https://github.com/facebook/react-native/pull/3457) - Some other change
59+
60+
#### iOS
61+
- [PR #3436](https://github.com/facebook/react-native/pull/3436) - Some other change
62+
- [PR #3437](https://github.com/facebook/react-native/pull/3437) - Some other change
63+
64+
### Fixed
65+
- [PR #9012](https://github.com/facebook/react-native/pull/9012) - Some other change
66+
67+
#### Android
68+
- [PR #3456](https://github.com/facebook/react-native/pull/3456) - Some other change
69+
70+
#### iOS
71+
- [PR #3437](https://github.com/facebook/react-native/pull/3437) - Some other change
72+
73+
74+
## v0.77.0
75+
76+
- [PR #3456](https://github.com/facebook/react-native/pull/3456) - Some other change
77+
78+
## v0.76.0
79+
80+
- [PR #7890](https://github.com/facebook/react-native/pull/7890) - Some other change`;
81+
82+
jest.spyOn(fs, 'readFileSync').mockImplementationOnce(func => {
83+
return mockedReturnValue;
84+
});
85+
const changelog = _extractChangelog('0.77.1');
86+
expect(changelog).toEqual(`## v0.77.1
87+
### Breaking Changes
88+
- [PR #9012](https://github.com/facebook/react-native/pull/9012) - Some other change
89+
90+
#### Android
91+
- [PR #3456](https://github.com/facebook/react-native/pull/3456) - Some other change
92+
- [PR #3457](https://github.com/facebook/react-native/pull/3457) - Some other change
93+
94+
#### iOS
95+
- [PR #3436](https://github.com/facebook/react-native/pull/3436) - Some other change
96+
- [PR #3437](https://github.com/facebook/react-native/pull/3437) - Some other change
97+
98+
### Fixed
99+
- [PR #9012](https://github.com/facebook/react-native/pull/9012) - Some other change
100+
101+
#### Android
102+
- [PR #3456](https://github.com/facebook/react-native/pull/3456) - Some other change
103+
104+
#### iOS
105+
- [PR #3437](https://github.com/facebook/react-native/pull/3437) - Some other change`);
106+
});
107+
108+
it('does not extract changelog for rc.0', async () => {
109+
const changelog = _extractChangelog('0.77.0-rc.0');
110+
expect(changelog).toEqual('');
111+
});
112+
113+
it('does not extract changelog for 0.X.0', async () => {
114+
const changelog = _extractChangelog('0.77.0');
115+
expect(changelog).toEqual('');
116+
});
117+
});
118+
119+
describe('#_computeBody', () => {
120+
it('computes body for release', async () => {
121+
const version = '0.77.1';
122+
const changelog = `## v${version}
123+
### Breaking Changes
124+
- [PR #9012](https://github.com/facebook/react-native/pull/9012) - Some other change
125+
126+
#### Android
127+
- [PR #3456](https://github.com/facebook/react-native/pull/3456) - Some other change
128+
- [PR #3457](https://github.com/facebook/react-native/pull/3457) - Some other change
129+
130+
#### iOS
131+
- [PR #3436](https://github.com/facebook/react-native/pull/3436) - Some other change
132+
- [PR #3437](https://github.com/facebook/react-native/pull/3437) - Some other change`;
133+
const body = _computeBody(version, changelog);
134+
135+
expect(body).toEqual(`${changelog}
136+
137+
---
138+
139+
Hermes dSYMS:
140+
- [Debug](https://repo1.maven.org/maven2/com/facebook/react/react-native-artifacts/${version}/react-native-artifacts-${version}-hermes-framework-dSYM-debug.tar.gz)
141+
- [Release](https://repo1.maven.org/maven2/com/facebook/react/react-native-artifacts/${version}/react-native-artifacts-${version}-hermes-framework-dSYM-release.tar.gz)
142+
143+
ReactNativeDependencies dSYMs:
144+
- [Debug](https://repo1.maven.org/maven2/com/facebook/react/react-native-artifacts/${version}/react-native-artifacts-${version}-reactnative-dependencies-dSYM-debug.tar.gz)
145+
- [Release](https://repo1.maven.org/maven2/com/facebook/react/react-native-artifacts/${version}/react-native-artifacts-${version}-reactnative-dependencies-dSYM-release.tar.gz)
146+
147+
---
148+
149+
You can file issues or pick requests against this release [here](https://github.com/reactwg/react-native-releases/issues/new/choose).
150+
151+
---
152+
153+
To help you upgrade to this version, you can use the [Upgrade Helper](https://react-native-community.github.io/upgrade-helper/) ⚛️.
154+
155+
---
156+
157+
View the whole changelog in the [CHANGELOG.md file](https://github.com/facebook/react-native/blob/main/CHANGELOG.md).`);
158+
});
159+
});
160+
161+
describe('#_createDraftReleaseOnGitHub', () => {
162+
it('creates a draft release on GitHub', async () => {
163+
const version = '0.77.1';
164+
const url = 'https://api.github.com/repos/facebook/react-native/releases';
165+
const token = 'token';
166+
const headers = {
167+
Accept: 'Accept: application/vnd.github+json',
168+
'X-GitHub-Api-Version': '2022-11-28',
169+
Authorization: `Bearer ${token}`,
170+
};
171+
const body = `Draft release body`;
172+
const latest = true;
173+
const fetchBody = JSON.stringify({
174+
tag_name: `v${version}`,
175+
name: `${version}`,
176+
body: body,
177+
draft: true,
178+
prerelease: false,
179+
make_latest: `${latest}`,
180+
});
181+
182+
mockFetch.mockReturnValueOnce(
183+
Promise.resolve({
184+
status: 201,
185+
json: () =>
186+
Promise.resolve({
187+
html_url:
188+
'https://github.com/facebook/react-native/releases/tag/v0.77.1',
189+
}),
190+
}),
191+
);
192+
const response = await _createDraftReleaseOnGitHub(
193+
version,
194+
body,
195+
latest,
196+
token,
197+
);
198+
expect(mockFetch).toHaveBeenCalledTimes(1);
199+
expect(mockFetch).toHaveBeenCalledWith(
200+
`https://api.github.com/repos/facebook/react-native/releases`,
201+
{
202+
method: 'POST',
203+
headers: headers,
204+
body: fetchBody,
205+
},
206+
);
207+
expect(response).toEqual(
208+
'https://github.com/facebook/react-native/releases/tag/v0.77.1',
209+
);
210+
});
211+
212+
it('creates a draft release for prerelease on GitHub', async () => {
213+
const version = '0.77.0-rc.2';
214+
const url = 'https://api.github.com/repos/facebook/react-native/releases';
215+
const token = 'token';
216+
const headers = {
217+
Accept: 'Accept: application/vnd.github+json',
218+
'X-GitHub-Api-Version': '2022-11-28',
219+
Authorization: `Bearer ${token}`,
220+
};
221+
const body = `Draft release body`;
222+
const latest = true;
223+
const fetchBody = JSON.stringify({
224+
tag_name: `v${version}`,
225+
name: `${version}`,
226+
body: body,
227+
draft: true,
228+
prerelease: true,
229+
make_latest: `${latest}`,
230+
});
231+
232+
mockFetch.mockReturnValueOnce(
233+
Promise.resolve({
234+
status: 201,
235+
json: () =>
236+
Promise.resolve({
237+
html_url:
238+
'https://github.com/facebook/react-native/releases/tag/v0.77.1',
239+
}),
240+
}),
241+
);
242+
const response = await _createDraftReleaseOnGitHub(
243+
version,
244+
body,
245+
latest,
246+
token,
247+
);
248+
expect(mockFetch).toHaveBeenCalledTimes(1);
249+
expect(mockFetch).toHaveBeenCalledWith(
250+
`https://api.github.com/repos/facebook/react-native/releases`,
251+
{
252+
method: 'POST',
253+
headers: headers,
254+
body: fetchBody,
255+
},
256+
);
257+
expect(response).toEqual(
258+
'https://github.com/facebook/react-native/releases/tag/v0.77.1',
259+
);
260+
});
261+
262+
it('throws if the post failes', async () => {
263+
const version = '0.77.0-rc.2';
264+
const url = 'https://api.github.com/repos/facebook/react-native/releases';
265+
const token = 'token';
266+
const headers = {
267+
Accept: 'Accept: application/vnd.github+json',
268+
'X-GitHub-Api-Version': '2022-11-28',
269+
Authorization: `Bearer ${token}`,
270+
};
271+
const body = `Draft release body`;
272+
const latest = true;
273+
const fetchBody = JSON.stringify({
274+
tag_name: `v${version}`,
275+
name: `${version}`,
276+
body: body,
277+
draft: true,
278+
prerelease: true,
279+
make_latest: `${latest}`,
280+
});
281+
282+
mockFetch.mockReturnValueOnce(
283+
Promise.resolve({
284+
status: 401,
285+
}),
286+
);
287+
await expect(
288+
_createDraftReleaseOnGitHub(version, body, latest, token),
289+
).rejects.toThrowError();
290+
expect(mockFetch).toHaveBeenCalledTimes(1);
291+
expect(mockFetch).toHaveBeenCalledWith(
292+
`https://api.github.com/repos/facebook/react-native/releases`,
293+
{
294+
method: 'POST',
295+
headers: headers,
296+
body: fetchBody,
297+
},
298+
);
299+
});
300+
});
301+
});

0 commit comments

Comments
 (0)