168 lines
5.6 KiB
JavaScript
Executable File
168 lines
5.6 KiB
JavaScript
Executable File
#!/usr/bin/env node
|
|
|
|
require('make-promises-safe')
|
|
require('dotenv-safe').load()
|
|
|
|
const fs = require('fs')
|
|
const path = require('path')
|
|
const semver = require('semver')
|
|
const hubdown = require('hubdown')
|
|
const GitHub = require('github')
|
|
const got = require('got')
|
|
const parseLinkHeader = require('parse-link-header')
|
|
const {getPlatformFromFilename} = require('platform-utils')
|
|
const github = new GitHub()
|
|
|
|
// `electron` was once a different module on npm. prior to 1.3.1 it was
|
|
// published as `electron-prebuilt`
|
|
const firstNpmVersion = '1.3.1'
|
|
|
|
github.authenticate({
|
|
type: 'token',
|
|
token: process.env.GITHUB_AUTH_TOKEN
|
|
})
|
|
|
|
main()
|
|
|
|
async function main () {
|
|
console.log('fetching list of `electron` releases on npm')
|
|
const npmElectronData = await got('https://registry.npmjs.com/electron', {json: true})
|
|
const npmVersions = Object.keys(npmElectronData.body.versions)
|
|
// filter out old versions of `electron` that were actually a different module
|
|
.filter(version => semver.gte(version, firstNpmVersion))
|
|
|
|
console.log('fetching list of `electron-prebuilt` releases on npm')
|
|
const npmElectronPrebuiltData = await got('https://registry.npmjs.com/electron-prebuilt', {json: true})
|
|
|
|
const npmVersionsPrebuilt = Object.keys(npmElectronPrebuiltData.body.versions)
|
|
// filter out `electron-prebuilt` versions that were published in tandem with `electron` for a while.
|
|
.filter(version => semver.lt(version, firstNpmVersion))
|
|
|
|
console.log('fetching npm dist-tags')
|
|
const distTags = npmElectronData.body['dist-tags']
|
|
const npmDistTaggedVersions = Object.keys(distTags)
|
|
.reduce((acc, key) => {
|
|
acc[distTags[key]] = key
|
|
return acc
|
|
}, {})
|
|
|
|
console.log('fetching GitHub Releases page count')
|
|
const countRes = await github.repos.getReleases(ghOpts({per_page: 1}))
|
|
|
|
let pagesToFetch
|
|
try {
|
|
const count = Number(parseLinkHeader(countRes.meta.link).last.page)
|
|
console.log(`found ${count} releases on GitHub`)
|
|
pagesToFetch = Math.ceil(count / 100)
|
|
} catch (err) {
|
|
console.error('problem fetching number of releases')
|
|
console.error(err)
|
|
process.exit(1)
|
|
}
|
|
|
|
console.log('fetching release data from GitHub')
|
|
let releases = []
|
|
for (let i = 1; i <= pagesToFetch; i++) {
|
|
const batch = await github.repos.getReleases(ghOpts({page: i}))
|
|
releases = releases.concat(batch.data)
|
|
}
|
|
|
|
console.log(`found ${releases.length} releases on GitHub`)
|
|
|
|
console.log('fetching version data for deps like V8, Chromium, and Node.js')
|
|
const depDataRes = await got('https://atom.io/download/electron/index.json', {json: true})
|
|
const depData = depDataRes.body
|
|
|
|
releases = releases
|
|
.filter(release => !release.draft)
|
|
.filter(release => semver.valid(release.tag_name.substring(1)))
|
|
.map(release => {
|
|
// derive version from tag_name for semver comparisons
|
|
release.version = release.tag_name.substring(1)
|
|
|
|
// published to npm? electron? electron-prebuilt?
|
|
if (npmVersions.includes(release.version)) release.npm_package_name = 'electron'
|
|
if (npmVersionsPrebuilt.includes(release.version)) release.npm_package_name = 'electron-prebuilt'
|
|
|
|
// weave in version data for V8, Chromium, Node.js, etc
|
|
const deps = depData.find(version => version.version === release.version)
|
|
if (deps) release.deps = deps
|
|
|
|
// apply dist tags from npm (usually `latest` and `beta`)
|
|
const npmDistTag = npmDistTaggedVersions[release.version]
|
|
if (npmDistTag) release.npm_dist_tag = npmDistTag
|
|
|
|
if (release.assets) {
|
|
release.total_downloads = release.assets
|
|
.reduce((acc, asset) => {
|
|
const platform = getPlatformFromFilename(asset.name)
|
|
if (platform) acc += asset.download_count
|
|
return acc
|
|
}, 0)
|
|
}
|
|
|
|
return release
|
|
})
|
|
|
|
// highest versions first
|
|
.sort((a, b) => semver.compare(b.version, a.version))
|
|
|
|
console.log('processing changelogs to HTML')
|
|
releases = await Promise.all(releases.map(processRelease))
|
|
|
|
// Abort the build early if module is already up to date
|
|
const old = require('..')
|
|
const oldLatest = old.find(release => release.npm_dist_tag === 'latest').version
|
|
const newLatest = releases.find(release => release.npm_dist_tag === 'latest').version
|
|
const oldBeta = old.find(release => release.npm_dist_tag === 'beta').version
|
|
const newBeta = releases.find(release => release.npm_dist_tag === 'beta').version
|
|
const oldNpmCount = old.find(release => release.npm_package_name === 'electron').length
|
|
const newNpmCount = releases.find(release => release.npm_package_name === 'electron').length
|
|
|
|
if (
|
|
old.length === releases.length &&
|
|
oldLatest === newLatest &&
|
|
oldBeta === newBeta &&
|
|
oldNpmCount === newNpmCount
|
|
) {
|
|
console.log('module already has up-to-date versions and dist tags. exiting.')
|
|
process.exit()
|
|
}
|
|
|
|
const fullFile = path.join(__dirname, '../index.json')
|
|
fs.writeFileSync(fullFile, JSON.stringify(releases, null, 2))
|
|
console.log(`wrote ${path.relative(process.cwd(), fullFile)}`)
|
|
}
|
|
|
|
// helpers
|
|
|
|
async function processRelease (release) {
|
|
release.version = release.tag_name.substring(1)
|
|
release.body = release.body
|
|
|
|
// turn PR references like #123 into hyperlinks
|
|
.replace(
|
|
/ #(\d+)$/gm,
|
|
' <a href="https://github.com/electron/electron/pull/$1">#$1</a>'
|
|
)
|
|
|
|
// adjust heading levels (h2 becomes h3, etc)
|
|
.replace(/^#### /gm, '##### ')
|
|
.replace(/^### /gm, '#### ')
|
|
.replace(/^## /gm, '### ')
|
|
|
|
const parsed = await hubdown(release.body)
|
|
release.body_html = parsed.content
|
|
|
|
return release
|
|
}
|
|
|
|
function ghOpts (opts) {
|
|
const defaults = {
|
|
owner: 'electron',
|
|
repo: 'electron',
|
|
per_page: 100
|
|
}
|
|
return Object.assign({}, defaults, opts)
|
|
}
|