mirror of
https://github.com/atom/atom.git
synced 2026-01-25 23:08:18 -05:00
Finish automated release notes generation
This commit is contained in:
@@ -1,8 +1,9 @@
|
||||
const semver = require('semver')
|
||||
const changelog = require('pr-changelog')
|
||||
const octokit = require('@octokit/rest')()
|
||||
const changelog = require('pr-changelog')
|
||||
const childProcess = require('child_process')
|
||||
|
||||
module.exports.get = async function(releaseVersion, githubToken) {
|
||||
module.exports.get = async function (releaseVersion, githubToken) {
|
||||
if (githubToken) {
|
||||
octokit.authenticate({
|
||||
type: 'oauth',
|
||||
@@ -10,12 +11,12 @@ module.exports.get = async function(releaseVersion, githubToken) {
|
||||
})
|
||||
}
|
||||
|
||||
let releases = await octokit.repos.getReleases({owner: 'atom', repo: 'atom'})
|
||||
let release = releases.data.find(r => semver.eq(r.name, releaseVersion))
|
||||
const releases = await octokit.repos.getReleases({owner: 'atom', repo: 'atom'})
|
||||
const release = releases.data.find(r => semver.eq(r.name, releaseVersion))
|
||||
return release ? release.body : undefined
|
||||
}
|
||||
|
||||
module.exports.generate = async function(releaseVersion, githubToken) {
|
||||
module.exports.generateForVersion = async function (releaseVersion, githubToken, oldReleaseNotes) {
|
||||
let oldVersion = null
|
||||
let oldVersionName = null
|
||||
const parsedVersion = semver.parse(releaseVersion)
|
||||
@@ -36,8 +37,7 @@ module.exports.generate = async function(releaseVersion, githubToken) {
|
||||
oldVersionName = `v${parsedVersion.major}.${parsedVersion.minor - 1}.0`
|
||||
} else {
|
||||
let releases = await octokit.repos.getReleases({owner: 'atom', repo: 'atom'})
|
||||
let versions = releases.data.map(r => r.name)
|
||||
oldVersion = 'v' + getPreviousVersion(releaseVersion, versions)
|
||||
oldVersion = 'v' + getPreviousRelease(releaseVersion, releases.data).name
|
||||
oldVersionName = oldVersion
|
||||
}
|
||||
|
||||
@@ -59,28 +59,61 @@ module.exports.generate = async function(releaseVersion, githubToken) {
|
||||
}
|
||||
})
|
||||
|
||||
return `## Notable Changes\n\n\
|
||||
**TODO**: Pull relevant changes here!\n\n\
|
||||
const writtenReleaseNotes =
|
||||
extractWrittenReleaseNotes(oldReleaseNotes) ||
|
||||
'**TODO**: Pull relevant changes here!'
|
||||
|
||||
return `## Notable Changes\n
|
||||
${writtenReleaseNotes}\n
|
||||
<details>
|
||||
<summary>All Changes</summary>\n\n
|
||||
${allChangesText}\n\n
|
||||
<summary>All Changes</summary>\n
|
||||
${allChangesText}
|
||||
</details>
|
||||
`
|
||||
}
|
||||
|
||||
function getPreviousVersion (version, allVersions) {
|
||||
module.exports.generateForNightly = async function(releaseVersion, githubToken) {
|
||||
const releases = await octokit.repos.getReleases({owner: 'atom', repo: 'atom-nightly-releases'})
|
||||
const previousRelease = getPreviousRelease(releaseVersion, releases.data)
|
||||
const oldReleaseNotes = previousRelease ? previousRelease.body : undefined
|
||||
|
||||
const latestCommitResult = childProcess.spawnSync('git', ['rev-parse', '--short', 'HEAD'])
|
||||
|
||||
if (latestCommitResult && oldReleaseNotes) {
|
||||
const latestCommit = latestCommitResult.stdout.toString().trim()
|
||||
const extractMatch = oldReleaseNotes.match(/atom\/atom\/compare\/([0-9a-f]{5,40})\.\.\.([0-9a-f]{5,40})/)
|
||||
if (extractMatch) {
|
||||
return `### Click [here](https://github.com/atom/atom/compare/${extractMatch[2]}...${latestCommit}) to see the changes included with this release! :atom: :night_with_stars:`
|
||||
}
|
||||
}
|
||||
|
||||
return undefined
|
||||
}
|
||||
|
||||
function extractWrittenReleaseNotes (oldReleaseNotes) {
|
||||
if (oldReleaseNotes) {
|
||||
const extractMatch = oldReleaseNotes.match(/^## Notable Changes\r\n([\s\S]*)<details>/)
|
||||
if (extractMatch && extractMatch[1]) {
|
||||
return extractMatch[1].trim()
|
||||
}
|
||||
}
|
||||
|
||||
return undefined
|
||||
}
|
||||
|
||||
function getPreviousRelease (version, allReleases) {
|
||||
const versionIsStable = semver.prerelease(version) === null
|
||||
|
||||
// Make sure versions are sorted before using them
|
||||
allVersions.sort(semver.rcompare)
|
||||
allReleases.sort((v1, v2) => semver.rcompare(v1.name, v2.name))
|
||||
|
||||
for (let otherVersion of allVersions) {
|
||||
if (versionIsStable && semver.prerelease(otherVersion)) {
|
||||
for (let release of allReleases) {
|
||||
if (versionIsStable && semver.prerelease(release.name)) {
|
||||
continue
|
||||
}
|
||||
|
||||
if (semver.lt(otherVersion, version)) {
|
||||
return otherVersion
|
||||
if (semver.lt(release.name, version)) {
|
||||
return release
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -80,3 +80,12 @@ jobs:
|
||||
ATOM_RELEASES_S3_BUCKET: $(ATOM_RELEASES_S3_BUCKET)
|
||||
displayName: Upload CI Artifacts to S3
|
||||
condition: and(succeeded(), eq(variables['IsSignedZipBranch'], 'true'))
|
||||
|
||||
- task: PublishBuildArtifacts@1
|
||||
inputs:
|
||||
PathtoPublish: $(Build.SourcesDirectory)/out/OLD_RELEASE_NOTES.md
|
||||
ArtifactName: OLD_RELEASE_NOTES.md
|
||||
ArtifactType: Container
|
||||
displayName: Upload OLD_RELEASE_NOTES.md
|
||||
condition: and(succeeded(), eq(variables['IsReleaseBranch'], 'true'), eq(variables['buildArch'], 'x86'))
|
||||
continueOnError: true
|
||||
|
||||
@@ -1,8 +1,10 @@
|
||||
'use strict'
|
||||
|
||||
const fs = require('fs')
|
||||
const path = require('path')
|
||||
const glob = require('glob')
|
||||
const publishRelease = require('publish-release')
|
||||
const releaseNotes = require('./lib/release-notes')
|
||||
const uploadToS3 = require('./lib/upload-to-s3')
|
||||
const uploadLinuxPackages = require('./lib/upload-linux-packages')
|
||||
|
||||
@@ -19,11 +21,12 @@ const argv = yargs
|
||||
.wrap(yargs.terminalWidth())
|
||||
.argv
|
||||
|
||||
const releaseVersion = CONFIG.computedAppVersion
|
||||
const isNightlyRelease = CONFIG.channel === 'nightly'
|
||||
const assetsPath = argv.assetsPath || path.join(CONFIG.repositoryRootPath, 'out')
|
||||
const assetsPath = argv.assetsPath || CONFIG.buildOutputPath
|
||||
const assetsPattern = '/**/*(*.exe|*.zip|*.nupkg|*.tar.gz|*.rpm|*.deb|RELEASES*|atom-api.json)'
|
||||
const assets = glob.sync(assetsPattern, { root: assetsPath, nodir: true })
|
||||
const bucketPath = argv.s3Path || `releases/v${CONFIG.computedAppVersion}/`
|
||||
const bucketPath = argv.s3Path || `releases/v${releaseVersion}/`
|
||||
|
||||
if (!assets || assets.length === 0) {
|
||||
console.error(`No assets found under specified path: ${assetsPath}`)
|
||||
@@ -31,7 +34,7 @@ if (!assets || assets.length === 0) {
|
||||
}
|
||||
|
||||
async function uploadArtifacts() {
|
||||
console.log(`Uploading ${assets.length} release assets for ${CONFIG.computedAppVersion} to S3 under '${bucketPath}'`)
|
||||
console.log(`Uploading ${assets.length} release assets for ${releaseVersion} to S3 under '${bucketPath}'`)
|
||||
|
||||
await uploadToS3(
|
||||
process.env.ATOM_RELEASES_S3_KEY,
|
||||
@@ -44,20 +47,50 @@ async function uploadArtifacts() {
|
||||
await uploadLinuxPackages(
|
||||
argv.linuxRepoName,
|
||||
process.env.PACKAGE_CLOUD_API_KEY,
|
||||
CONFIG.computedAppVersion,
|
||||
releaseVersion,
|
||||
assets)
|
||||
} else {
|
||||
console.log("Skipping upload of Linux packages")
|
||||
console.log("Skipping upload of Linux packages")
|
||||
}
|
||||
|
||||
const oldReleaseNotes =
|
||||
await releaseNotes.get(
|
||||
releaseVersion,
|
||||
process.env.GITHUB_TOKEN)
|
||||
|
||||
if (oldReleaseNotes) {
|
||||
const oldReleaseNotesPath = path.resolve(CONFIG.buildOutputPath, "OLD_RELEASE_NOTES.md")
|
||||
console.log(`Saving existing ${releaseVersion} release notes to ${oldReleaseNotesPath}`)
|
||||
fs.writeFileSync(oldReleaseNotesPath, oldReleaseNotes, 'utf8')
|
||||
}
|
||||
|
||||
if (argv.createGithubRelease) {
|
||||
console.log(`Creating GitHub release v${CONFIG.computedAppVersion}`)
|
||||
console.log(`\nGenerating new release notes for ${releaseVersion}`)
|
||||
let newReleaseNotes = ''
|
||||
if (isNightlyRelease) {
|
||||
newReleaseNotes =
|
||||
await releaseNotes.generateForNightly(
|
||||
releaseVersion,
|
||||
process.env.GITHUB_TOKEN,
|
||||
oldReleaseNotes)
|
||||
} else {
|
||||
newReleaseNotes =
|
||||
await releaseNotes.generateForVersion(
|
||||
releaseVersion,
|
||||
process.env.GITHUB_TOKEN,
|
||||
oldReleaseNotes)
|
||||
}
|
||||
|
||||
console.log(`New release notes:\n\n${newReleaseNotes}`)
|
||||
|
||||
console.log(`Creating GitHub release v${releaseVersion}`)
|
||||
const release =
|
||||
await publishReleaseAsync({
|
||||
token: process.env.GITHUB_TOKEN,
|
||||
owner: 'atom',
|
||||
repo: !isNightlyRelease ? 'atom' : 'atom-nightly-releases',
|
||||
name: CONFIG.computedAppVersion,
|
||||
body: newReleaseNotes,
|
||||
tag: `v${CONFIG.computedAppVersion}`,
|
||||
draft: !isNightlyRelease,
|
||||
prerelease: CONFIG.channel !== 'stable',
|
||||
|
||||
Reference in New Issue
Block a user