Skip to content

Commit

Permalink
ci: add --use-new-release functionality (#1633)
Browse files Browse the repository at this point in the history
  • Loading branch information
jmartin4563 authored May 12, 2023
1 parent b2101fd commit d97b421
Show file tree
Hide file tree
Showing 11 changed files with 503 additions and 50 deletions.
6 changes: 5 additions & 1 deletion .github/workflows/prep-release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,10 @@ on:
type: string
required: false
default: NEWS.md
use_new_release:
description: Whether or not to use the new conventional commit release note workflow
required: false
default: false

jobs:
generate-release-notes:
Expand Down Expand Up @@ -41,6 +45,6 @@ jobs:
git config user.name $GITHUB_ACTOR
git config user.email gh-actions-${GITHUB_ACTOR}@github.com
- name: Create Release Notes
run: node ./agent-repo/bin/prepare-release.js --release-type ${{ inputs.release_type }} --branch ${{ github.ref }} --repo ${{ github.repository }} --changelog ${{ inputs.changelog_file }}
run: node ./agent-repo/bin/prepare-release.js --release-type ${{ inputs.release_type }} --branch ${{ github.ref }} --repo ${{ github.repository }} --changelog ${{ inputs.changelog_file }} --use-new-release ${{ inputs.use_new_release }}
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
1 change: 1 addition & 0 deletions .github/workflows/prepare-release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -14,3 +14,4 @@ jobs:
uses: newrelic/node-newrelic/.github/workflows/prep-release.yml@main
with:
release_type: ${{ github.event.inputs.release_type }}
use_new_release: ${{ vars.USE_NEW_RELEASE }}
3 changes: 2 additions & 1 deletion bin/.eslintrc.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
module.exports = {
rules: {
'no-process-exit': 'off',
'no-console': 'off'
'no-console': 'off',
'no-shadow': 'off'
}
}
36 changes: 25 additions & 11 deletions bin/conventional-changelog.js
Original file line number Diff line number Diff line change
Expand Up @@ -113,28 +113,44 @@ class ConventionalChangelog {
}
}

/**
* Helper method to strip out the PR links that Github
* likes to add to the end of commit messages when
* using squash and merge
*
* Also since we're already manipulating the string,
* use .trim() to strip any trailing or leading whitespace
*
* @param {string} subject commit message header
* @returns {string} the commit message header with any PR links removed and whitespace trimmed
*/
removePrLinks(subject) {
return subject.replace(/\(\#\d+\)$/, '').trim()
}

/**
* Function for generating our front-matter content in a machine readable format
*
* @param {object[]} commits list of conventional commits
* @returns {object} the entry to add to the JSON changelog
*/
generateJsonChangelog(commits) {
const self = this
const securityChanges = []
const bugfixChanges = []
const featureChanges = []

commits.forEach((commit) => {
if (commit.type === 'security') {
securityChanges.push(commit.subject)
securityChanges.push(self.removePrLinks(commit.subject))
}

if (commit.type === 'fix') {
bugfixChanges.push(commit.subject)
bugfixChanges.push(self.removePrLinks(commit.subject))
}

if (commit.type === 'feat') {
featureChanges.push(commit.subject)
featureChanges.push(self.removePrLinks(commit.subject))
}
})

Expand Down Expand Up @@ -214,9 +230,8 @@ class ConventionalChangelog {
* @param {string} markdownFile path to the markdown file to update, defaults to NEWS.md
* @returns {void}
*/
async writeMarkdownChangelog(newEntry, markdownFile = '../NEWS.md') {
const filename = path.resolve(__dirname, markdownFile)
const changelog = await readFile(filename, 'utf-8')
async writeMarkdownChangelog(newEntry, markdownFile = 'NEWS.md') {
const changelog = await readFile(markdownFile, 'utf-8')

const heading = `### v${this.newVersion}`

Expand All @@ -225,7 +240,7 @@ class ConventionalChangelog {
return
}

await writeFile(filename, `${newEntry}\n${changelog}`, 'utf-8')
await writeFile(markdownFile, `${newEntry}\n${changelog}`, 'utf-8')
}

/**
Expand All @@ -237,9 +252,8 @@ class ConventionalChangelog {
* @param {string} jsonFile path to the markdown file to update, defaults to changelog.json
* @returns {void}
*/
async writeJsonChangelog(newEntry, jsonFile = '../changelog.json') {
const filename = path.resolve(__dirname, jsonFile)
const rawChangelog = await readFile(filename, 'utf-8')
async writeJsonChangelog(newEntry, jsonFile = 'changelog.json') {
const rawChangelog = await readFile(jsonFile, 'utf-8')
const changelog = JSON.parse(rawChangelog)

if (changelog.entries.find((entry) => entry.version === this.newVersion)) {
Expand All @@ -248,7 +262,7 @@ class ConventionalChangelog {
}

changelog.entries.unshift(newEntry)
await writeFile(filename, JSON.stringify(changelog, null, 2), 'utf-8')
await writeFile(jsonFile, JSON.stringify(changelog, null, 2), 'utf-8')
}
}

Expand Down
69 changes: 61 additions & 8 deletions bin/create-docs-pr.js
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,11 @@ program.option(
'Path to the docs-website fork on local machine',
'/tmp/docs-website'
)
program.option(
'--front-matter-file <json file>',
'Name of changelog(defaults to changelog.json)',
'changelog.json'
)

program.option('--repo-owner <owner>', 'Owner of the target repo', 'newrelic')

Expand Down Expand Up @@ -66,6 +71,7 @@ async function createReleaseNotesPr() {
validateTag(version, options.force)
logStep('Get Release Notes from File')
const { body, releaseDate } = await getReleaseNotes(version, options.changelog)
const frontmatter = await getFrontMatter(version, options.frontMatterFile)

if (!fs.existsSync(options.repoPath)) {
logStep('Clone docs repo')
Expand All @@ -75,7 +81,7 @@ async function createReleaseNotesPr() {
logStep('Branch Creation')
const branchName = await createBranch(options.repoPath, version, options.dryRun)
logStep('Format release notes file')
const releaseNotesBody = formatReleaseNotes(releaseDate, version, body)
const releaseNotesBody = formatReleaseNotes(releaseDate, version, body, frontmatter)
logStep('Create Release Notes')
await addReleaseNotesFile(releaseNotesBody, version)
logStep('Commit Release Notes')
Expand Down Expand Up @@ -124,7 +130,7 @@ async function getReleaseNotes(version, releaseNotesFile) {

const data = await readReleaseNoteFile(releaseNotesFile)

const sections = data.split('### ')
const sections = data.split(/^### /m)
// Iterate over all past releases to find the version we want
const versionChangeLog = sections.find((section) => section.startsWith(version))
// e.g. v7.1.2 (2021-02-24)\n\n
Expand All @@ -135,6 +141,33 @@ async function getReleaseNotes(version, releaseNotesFile) {
return { body, releaseDate }
}

/**
* Pulls the necessary frontmatter content for the given version
* from our JSON based changelog
*
* @param {string} tagName version tag name
* @param {string} frontMatterFile JSON changelog file
* @returns {object} frontmatter hash containing security, bugfix and feature lists
*/
async function getFrontMatter(tagName, frontMatterFile) {
console.log(`Retrieving release notes from file: ${frontMatterFile}`)

const version = tagName.replace('v', '')
const data = await readReleaseNoteFile(frontMatterFile)
const changelog = JSON.parse(data)
const frontmatter = changelog.entries.find((entry) => entry.version === version)

if (!frontmatter) {
throw new Error(`Unable to find ${version} entry in ${frontMatterFile}`)
}

return {
security: JSON.stringify(frontmatter.changes.security),
bugfixes: JSON.stringify(frontmatter.changes.bugfixes),
features: JSON.stringify(frontmatter.changes.features)
}
}

/**
* Reads the contents of NEWS.md
*
Expand All @@ -155,8 +188,8 @@ async function readReleaseNoteFile(file) {
/**
* Clones docs repo
*
* @param repoPath
* @param repoOwner
* @param {string} repoPath where to checkout the repo
* @param {string} repoOwner Github organization/owner name
* @returns {boolean} success or failure
*/
async function cloneDocsRepo(repoPath, repoOwner) {
Expand Down Expand Up @@ -198,15 +231,19 @@ async function createBranch(filePath, version, dryRun) {
* @param {string} releaseDate date the release was created
* @param {string} version version number
* @param {string} body list of changes
* @param {object} frontmatter agent version metadata information about the release
* @returns {string} appropriately formatted release notes
*/
function formatReleaseNotes(releaseDate, version, body) {
function formatReleaseNotes(releaseDate, version, body, frontmatter) {
const releaseNotesBody = [
'---',
'subject: Node.js agent',
`releaseDate: '${releaseDate}'`,
`version: ${version.substr(1)}`, // remove the `v` from start of version
`downloadLink: 'https://www.npmjs.com/package/newrelic'`,
`security: ${frontmatter.security}`,
`bugs: ${frontmatter.bugfixes}`,
`features: ${frontmatter.features}`,
'---',
'',
'## Notes',
Expand Down Expand Up @@ -284,13 +321,16 @@ async function createPR(version, branch, dryRun, repoOwner) {
}

const github = new Github(repoOwner, 'docs-website')
const title = `Node.js Agent ${version} Release Notes`
const title = `chore: add Node.js Agent ${version} Release Notes`
const head = repoOwner === `newrelic` ? branch : `${repoOwner}:${branch}`
const body =
'This is an automated PR generated when the Node.js agent is released. Please merge as soon as possible.'

const prOptions = {
head,
base: BASE_BRANCH,
title,
body: title
body
}

console.log(`Creating PR with following options: ${JSON.stringify(prOptions)}\n\n`)
Expand Down Expand Up @@ -326,4 +366,17 @@ function logStep(step) {
console.log(`\n ----- [Step]: ${step} -----\n`)
}

createReleaseNotesPr()
/*
* Exports slightly differ for tests vs. Github Actions
* this allows us to require the function without it executing for tests,
* and executing via `node` cli in GHA
*/
if (require.main === module) {
createReleaseNotesPr()
} else {
module.exports = {
getReleaseNotes,
getFrontMatter,
formatReleaseNotes
}
}
Loading

0 comments on commit d97b421

Please sign in to comment.