Skip to content

Commit 156323a

Browse files
committed
feat: support nodejs org folder on post-release
1 parent d944670 commit 156323a

File tree

3 files changed

+61
-30
lines changed

3 files changed

+61
-30
lines changed

components/git/security.js

Lines changed: 6 additions & 5 deletions
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

Lines changed: 9 additions & 0 deletions
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

Lines changed: 46 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,7 @@ export default class SecurityBlog extends SecurityRelease {
7171
cli.ok(`Announcement file created and banner has been updated. Folder: ${nodejsOrgFolder}`);
7272
}
7373

74-
async createPostRelease() {
74+
async createPostRelease(nodejsOrgFolder) {
7575
const { cli } = this;
7676
const credentials = await auth({
7777
github: true,
@@ -84,7 +84,7 @@ export default class SecurityBlog extends SecurityRelease {
8484
checkoutOnSecurityReleaseBranch(cli, this.repository);
8585

8686
// read vulnerabilities JSON file
87-
const content = this.readVulnerabilitiesJSON(cli);
87+
const content = this.readVulnerabilitiesJSON();
8888
if (!content.releaseDate) {
8989
cli.error('Release date is not set in vulnerabilities.json,' +
9090
' run `git node security --update-date=YYYY/MM/DD` to set the release date.');
@@ -95,47 +95,54 @@ export default class SecurityBlog extends SecurityRelease {
9595
const releaseDate = new Date(content.releaseDate);
9696
const template = this.getSecurityPostReleaseTemplate();
9797
const data = {
98-
// TODO: read from pre-sec-release
99-
annoucementDate: await this.getAnnouncementDate(cli),
98+
annoucementDate: releaseDate.toISOString(),
10099
releaseDate: this.formatReleaseDate(releaseDate),
101100
affectedVersions: this.getAffectedVersions(content),
102101
vulnerabilities: this.getVulnerabilities(content),
103102
slug: this.getSlug(releaseDate),
104-
author: await this.promptAuthor(cli),
103+
author: 'The Node.js Project',
105104
dependencyUpdates: content.dependencies
106105
};
107-
const postReleaseContent = await this.buildPostRelease(template, data, content);
108106

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

120-
fs.writeFileSync(pathPreRelease, updatedContent);
121-
cli.ok(`Post-release announcement file updated at ${pathPreRelease}`);
125+
const endDate = new Date(data.annoucementDate);
126+
endDate.setDate(endDate.getDate() + 7);
127+
const month = releaseDate.toLocaleString('en-US', { month: 'long' });
128+
const capitalizedMonth = month[0].toUpperCase() + month.slice(1);
129+
130+
this.updateWebsiteBanner(pathToBannerJson, {
131+
startDate: releaseDate,
132+
endDate,
133+
text: `${capitalizedMonth} Security Release is available`
134+
});
122135

123-
// if the vulnerabilities.json has been changed, update the file
124-
if (!content[kChanged]) return;
125-
this.updateVulnerabilitiesJSON(content);
136+
fs.writeFileSync(preReleasePath, updatedContent);
137+
cli.ok(`Announcement file and banner has been updated. Folder: ${nodejsOrgFolder}`);
126138
}
127139

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-
});
134-
135-
if (!pathPreRelease || !fs.existsSync(path.resolve(pathPreRelease))) {
136-
return this.promptExistingPreRelease(cli);
140+
findExistingPreRelease(filepath) {
141+
if (!fs.existsSync(filepath)) {
142+
return null;
137143
}
138-
return pathPreRelease;
144+
145+
return fs.readFileSync(filepath, 'utf-8');
139146
}
140147

141148
promptAuthor(cli) {
@@ -146,6 +153,20 @@ export default class SecurityBlog extends SecurityRelease {
146153
});
147154
}
148155

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

0 commit comments

Comments
 (0)