Skip to content

Commit 5fe1456

Browse files
authored
feat: support nodejs org folder on post-release (#878)
* feat: support nodejs org folder on post-release * fix: adjust pre-release to use updateWebsiteBanner
1 parent eddb205 commit 5fe1456

File tree

3 files changed

+66
-38
lines changed

3 files changed

+66
-38
lines changed

components/git/security.js

+6-5
Original file line numberDiff line numberDiff line change
@@ -41,8 +41,8 @@ const securityOptions = {
4141
type: 'boolean'
4242
},
4343
'post-release': {
44-
describe: 'Create the post-release announcement',
45-
type: 'boolean'
44+
describe: 'Create the post-release announcement to the given nodejs.org folder',
45+
type: 'string'
4646
},
4747
cleanup: {
4848
describe: 'cleanup the security release.',
@@ -83,7 +83,7 @@ export function builder(yargs) {
8383
'Request CVEs for a security release of Node.js based on' +
8484
' the next-security-release/vulnerabilities.json'
8585
).example(
86-
'git node security --post-release',
86+
'git node security --post-release="../nodejs.org/"',
8787
'Create the post-release announcement on the Nodejs.org repo'
8888
).example(
8989
'git node security --cleanup',
@@ -164,11 +164,12 @@ async function requestCVEs() {
164164
return hackerOneCve.requestCVEs();
165165
}
166166

167-
async function createPostRelease() {
167+
async function createPostRelease(argv) {
168+
const nodejsOrgFolder = argv['post-release'];
168169
const logStream = process.stdout.isTTY ? process.stdout : process.stderr;
169170
const cli = new CLI(logStream);
170171
const blog = new SecurityBlog(cli);
171-
return blog.createPostRelease();
172+
return blog.createPostRelease(nodejsOrgFolder);
172173
}
173174

174175
async function startSecurityRelease() {

docs/git-node.md

+9
Original file line numberDiff line numberDiff line change
@@ -479,6 +479,15 @@ Example:
479479
git node security --pre-release="/path/to/nodejs.org"
480480
```
481481

482+
### `git node security --post-release`
483+
484+
This command creates the post-release announcement for the security release.
485+
Example:
486+
487+
```sh
488+
git node security --post-release="/path/to/nodejs.org"
489+
```
490+
482491
### `git node security --add-report=report-id`
483492

484493
This command adds a HackerOne report to the `vulnerabilities.json`.

lib/security_blog.js

+51-33
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,6 @@ import {
1111
import auth from './auth.js';
1212
import Request from './request.js';
1313

14-
const kChanged = Symbol('changed');
15-
1614
export default class SecurityBlog extends SecurityRelease {
1715
req;
1816

@@ -54,24 +52,23 @@ export default class SecurityBlog extends SecurityRelease {
5452

5553
const file = path.resolve(process.cwd(), nodejsOrgFolder, pathToBlogPosts, fileNameExt);
5654
const site = path.resolve(process.cwd(), nodejsOrgFolder, pathToBannerJson);
57-
const siteJson = JSON.parse(fs.readFileSync(site));
5855

5956
const endDate = new Date(data.annoucementDate);
6057
endDate.setDate(endDate.getDate() + 7);
61-
const capitalizedMonth = month[0].toUpperCase() + month.slice(1);
62-
siteJson.websiteBanners.index = {
58+
59+
this.updateWebsiteBanner(site, {
6360
startDate: data.annoucementDate,
6461
endDate: endDate.toISOString(),
65-
text: `${capitalizedMonth} Security Release is available`,
62+
text: `New security releases to be made available ${data.releaseDate}`,
6663
link: `https://nodejs.org/en/blog/vulnerability/${fileName}`,
6764
type: 'warning'
68-
};
65+
});
66+
6967
fs.writeFileSync(file, preRelease);
70-
fs.writeFileSync(site, JSON.stringify(siteJson, null, 2));
7168
cli.ok(`Announcement file created and banner has been updated. Folder: ${nodejsOrgFolder}`);
7269
}
7370

74-
async createPostRelease() {
71+
async createPostRelease(nodejsOrgFolder) {
7572
const { cli } = this;
7673
const credentials = await auth({
7774
github: true,
@@ -84,7 +81,7 @@ export default class SecurityBlog extends SecurityRelease {
8481
checkoutOnSecurityReleaseBranch(cli, this.repository);
8582

8683
// read vulnerabilities JSON file
87-
const content = this.readVulnerabilitiesJSON(cli);
84+
const content = this.readVulnerabilitiesJSON();
8885
if (!content.releaseDate) {
8986
cli.error('Release date is not set in vulnerabilities.json,' +
9087
' run `git node security --update-date=YYYY/MM/DD` to set the release date.');
@@ -95,47 +92,54 @@ export default class SecurityBlog extends SecurityRelease {
9592
const releaseDate = new Date(content.releaseDate);
9693
const template = this.getSecurityPostReleaseTemplate();
9794
const data = {
98-
// TODO: read from pre-sec-release
99-
annoucementDate: await this.getAnnouncementDate(cli),
95+
annoucementDate: releaseDate.toISOString(),
10096
releaseDate: this.formatReleaseDate(releaseDate),
10197
affectedVersions: this.getAffectedVersions(content),
10298
vulnerabilities: this.getVulnerabilities(content),
10399
slug: this.getSlug(releaseDate),
104-
author: await this.promptAuthor(cli),
100+
author: 'The Node.js Project',
105101
dependencyUpdates: content.dependencies
106102
};
107-
const postReleaseContent = await this.buildPostRelease(template, data, content);
108103

109-
const pathPreRelease = await this.promptExistingPreRelease(cli);
110-
// read the existing pre-release announcement
111-
let preReleaseContent = fs.readFileSync(pathPreRelease, 'utf-8');
104+
const pathToBlogPosts = path.resolve(nodejsOrgFolder, 'apps/site/pages/en/blog/release');
105+
const pathToBannerJson = path.resolve(nodejsOrgFolder, 'apps/site/site.json');
106+
107+
const preReleasePath = path.resolve(pathToBlogPosts, data.slug + '.md');
108+
let preReleaseContent = this.findExistingPreRelease(preReleasePath);
109+
if (!preReleaseContent) {
110+
cli.error(`Existing pre-release not found! Path: ${preReleasePath} `);
111+
process.exit(1);
112+
}
113+
114+
const postReleaseContent = await this.buildPostRelease(template, data, content);
112115
// cut the part before summary
113116
const preSummary = preReleaseContent.indexOf('# Summary');
114117
if (preSummary !== -1) {
115118
preReleaseContent = preReleaseContent.substring(preSummary);
116119
}
117-
118120
const updatedContent = postReleaseContent + preReleaseContent;
119121

120-
fs.writeFileSync(pathPreRelease, updatedContent);
121-
cli.ok(`Post-release announcement file updated at ${pathPreRelease}`);
122+
const endDate = new Date(data.annoucementDate);
123+
endDate.setDate(endDate.getDate() + 7);
124+
const month = releaseDate.toLocaleString('en-US', { month: 'long' });
125+
const capitalizedMonth = month[0].toUpperCase() + month.slice(1);
122126

123-
// if the vulnerabilities.json has been changed, update the file
124-
if (!content[kChanged]) return;
125-
this.updateVulnerabilitiesJSON(content);
126-
}
127+
this.updateWebsiteBanner(pathToBannerJson, {
128+
startDate: releaseDate,
129+
endDate,
130+
text: `${capitalizedMonth} Security Release is available`
131+
});
127132

128-
async promptExistingPreRelease(cli) {
129-
const pathPreRelease = await cli.prompt(
130-
'Please provide the path of the existing pre-release announcement:', {
131-
questionType: 'input',
132-
defaultAnswer: ''
133-
});
133+
fs.writeFileSync(preReleasePath, updatedContent);
134+
cli.ok(`Announcement file and banner has been updated. Folder: ${nodejsOrgFolder}`);
135+
}
134136

135-
if (!pathPreRelease || !fs.existsSync(path.resolve(pathPreRelease))) {
136-
return this.promptExistingPreRelease(cli);
137+
findExistingPreRelease(filepath) {
138+
if (!fs.existsSync(filepath)) {
139+
return null;
137140
}
138-
return pathPreRelease;
141+
142+
return fs.readFileSync(filepath, 'utf-8');
139143
}
140144

141145
promptAuthor(cli) {
@@ -146,6 +150,20 @@ export default class SecurityBlog extends SecurityRelease {
146150
});
147151
}
148152

153+
updateWebsiteBanner(siteJsonPath, content) {
154+
const siteJson = JSON.parse(fs.readFileSync(siteJsonPath));
155+
156+
const currentValue = siteJson.websiteBanners.index;
157+
siteJson.websiteBanners.index = {
158+
startDate: content.startDate ?? currentValue.startDate,
159+
endDate: content.endDate ?? currentValue.endDate,
160+
text: content.text ?? currentValue.text,
161+
link: content.link ?? currentValue.link,
162+
type: content.type ?? currentValue.type
163+
};
164+
fs.writeFileSync(siteJsonPath, JSON.stringify(siteJson, null, 2));
165+
}
166+
149167
formatReleaseDate(releaseDate) {
150168
const options = {
151169
weekday: 'long',

0 commit comments

Comments
 (0)