Skip to content

Commit

Permalink
Add release-npm-packages script
Browse files Browse the repository at this point in the history
  • Loading branch information
jdalton committed Oct 9, 2024
1 parent f9bdc31 commit 066b0a6
Show file tree
Hide file tree
Showing 6 changed files with 176 additions and 93 deletions.
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@
"test-pre-commit": "cross-env-shell PRE_COMMIT=1 npm test",
"test-ci": "run-s test:*",
"make:npm-package": "node ./scripts/make-npm-package.js",
"release:npm": "node ./scripts/release-npm-packages.js",
"setup": "run-p --aggregate-output update:package-lock update:tap-config",
"update": "run-p --aggregate-output update:* update:npm:* && run-s update:longtask:**",
"update:browserslist-db": "node ./scripts/update-browserslist-db.js",
Expand Down
16 changes: 7 additions & 9 deletions scripts/make-npm-package.js
Original file line number Diff line number Diff line change
Expand Up @@ -422,15 +422,13 @@ function toChoice(value) {
cwd: rootPath,
stdio: 'inherit'
}
await Promise.all([
runScript('update:manifest', [], spawnOptions),
runScript('update:package-json', [], spawnOptions),
runScript(
'update:longtask:test:npm:package-json',
['--', '--add', origPkgName],
spawnOptions
)
])
await runScript('update:manifest', [], spawnOptions)
await runScript('update:package-json', [], spawnOptions)
await runScript(
'update:longtask:test:npm:package-json',
['--', '--quiet', '--add', origPkgName],
spawnOptions
)
} catch (e) {
console.log('✘ Package override finalization encountered an error:', e)
}
Expand Down
48 changes: 48 additions & 0 deletions scripts/release-npm-packages.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
'use strict'

const path = require('node:path')

const semver = require('semver')

const constants = require('@socketregistry/scripts/constants')
const { npmPackagesPath, relNpmPackagesPath, rootPath } = constants
const { runScript } = require('@socketregistry/scripts/utils/npm')
const {
fetchPackageManifest,
readPackageJson
} = require('@socketregistry/scripts/utils/packages')
const { pEach } = require('@socketregistry/scripts/utils/promises')
const { Spinner } = require('@socketregistry/scripts/utils/spinner')

;(async () => {
const spinner = new Spinner(
`Bumping ${relNpmPackagesPath} versions (semver patch)...`
).start()
// Chunk package names to process them in parallel 3 at a time.
// Lazily access constants.ecosystems.
await pEach(constants.npmPackageNames, 3, async regPkgName => {
const pkgPath = path.join(npmPackagesPath, regPkgName)
if (await fetchPackageManifest(regPkgName)) {
const editablePkgJson = await readPackageJson(pkgPath, {
editable: true
})
editablePkgJson.update({
version: semver.inc(editablePkgJson.content.version, 'patch')
})
await editablePkgJson.save()
}
})
spinner.stop()

const spawnOptions = {
cwd: rootPath,
stdio: 'inherit'
}
await runScript('update:manifest', [], spawnOptions)
await runScript('update:package-json', [], spawnOptions)
await runScript(
'update:longtask:test:npm:package-json',
['--', '--quiet', '--force'],
spawnOptions
)
})()
128 changes: 68 additions & 60 deletions scripts/update-manifest.js
Original file line number Diff line number Diff line change
Expand Up @@ -29,12 +29,77 @@ const {
resolveOriginalPackageName,
resolvePackageJsonEntryExports
} = require('@socketregistry/scripts/utils/packages')
const { pEach } = require('@socketregistry/scripts/utils/promises')
const { localeCompare } = require('@socketregistry/scripts/utils/sorts')
const { Spinner } = require('@socketregistry/scripts/utils/spinner')
const { prettierFormat } = require('@socketregistry/scripts/utils/strings')

const { values: cliArgs } = util.parseArgs(parseArgsConfig)

async function addNpmManifestData(manifest) {
const eco = 'npm'
const manifestData = []
// Chunk package names to process them in parallel 3 at a time.
// Lazily access constants.npmPackageNames.
await pEach(constants.npmPackageNames, 3, async regPkgName => {
const origPkgName = resolveOriginalPackageName(regPkgName)
const testNpmPkgJson = await readPackageJson(testNpmPkgJsonPath)

const nmPkgSpec = testNpmPkgJson.devDependencies[origPkgName]
const nmPkgManifest = await fetchPackageManifest(
`${origPkgName}@${nmPkgSpec}`
)
const { _id: nmPkgId, deprecated: nmPkgDeprecated } = nmPkgManifest
const { namespace: nmScope } = PackageURL.fromString(
`pkg:${eco}/${nmPkgId}`
)
let nwPkgLicense
await extractPackage(nmPkgId, async nmPkgPath => {
const nmPkgJson = await readPackageJson(nmPkgPath)
nwPkgLicense = nmPkgJson.license
})

const pkgPath = path.join(npmPackagesPath, regPkgName)
const pkgJson = await readPackageJson(pkgPath)
const { engines, name, socket, version } = pkgJson
const entryExports = resolvePackageJsonEntryExports(pkgJson.exports)

const interop = ['cjs']
const isEsm = pkgJson.type === 'module'
if (isEsm) {
interop.push('esm')
}
const isBrowser = !isEsm && !!(entryExports?.node && entryExports?.default)
if (isBrowser) {
interop.push('browserify')
}
const skipTests = skipTestsByEcosystem[eco].has(regPkgName)
const metaEntries = [
['license', nwPkgLicense ?? UNLICENSED],
...(nmPkgDeprecated ? [['deprecated', true]] : []),
...(skipTests ? [['skipTests', true]] : []),
...(engines ? [['engines', toSortedObject(engines)]] : []),
['interop', interop.sort(localeCompare)],
...(nmScope ? [['scope', nmScope]] : []),
...(socket ? Object.entries(socket) : [])
]
const purlObj = PackageURL.fromString(`pkg:${eco}/${name}@${version}`)
const data = [purlObj.toString()]
if (metaEntries.length) {
data[1] = toSortedObjectFromEntries(metaEntries)
}
manifestData.push(data.length === 1 ? data[0] : data)
})
if (manifestData.length) {
manifest[eco] = manifestData.sort((a_, b_) => {
const a = Array.isArray(a_) ? a_[0] : a_
const b = Array.isArray(b_) ? b_[0] : b_
return localeCompare(a, b)
})
}
return manifest
}

;(async () => {
// Exit early if no relevant files have been modified.
if (
Expand All @@ -44,68 +109,11 @@ const { values: cliArgs } = util.parseArgs(parseArgsConfig)
return
}
const spinner = new Spinner(`Updating ${relManifestJsonPath}...`).start()
const { ecosystems, npmPackageNames } = constants
const manifest = {}
for (const eco of ecosystems) {
// Lazily access constants.ecosystems.
for (const eco of constants.ecosystems) {
if (eco === 'npm') {
const manifestData = []
for await (const regPkgName of npmPackageNames) {
const origPkgName = resolveOriginalPackageName(regPkgName)
const testNpmPkgJson = await readPackageJson(testNpmPkgJsonPath)

const nmPkgSpec = testNpmPkgJson.devDependencies[origPkgName]
const nmPkgManifest = await fetchPackageManifest(
`${origPkgName}@${nmPkgSpec}`
)
const { _id: nmPkgId, deprecated: nmPkgDeprecated } = nmPkgManifest
const { namespace: nmScope } = PackageURL.fromString(
`pkg:${eco}/${nmPkgId}`
)
let nwPkgLicense
await extractPackage(nmPkgId, async nmPkgPath => {
const nmPkgJson = await readPackageJson(nmPkgPath)
nwPkgLicense = nmPkgJson.license
})

const pkgPath = path.join(npmPackagesPath, regPkgName)
const pkgJson = await readPackageJson(pkgPath)
const { engines, name, socket, version } = pkgJson
const entryExports = resolvePackageJsonEntryExports(pkgJson.exports)

const interop = ['cjs']
const isEsm = pkgJson.type === 'module'
if (isEsm) {
interop.push('esm')
}
const isBrowser =
!isEsm && !!(entryExports?.node && entryExports?.default)
if (isBrowser) {
interop.push('browserify')
}
const skipTests = skipTestsByEcosystem[eco].has(regPkgName)
const metaEntries = [
['license', nwPkgLicense ?? UNLICENSED],
...(nmPkgDeprecated ? [['deprecated', true]] : []),
...(skipTests ? [['skipTests', true]] : []),
...(engines ? [['engines', toSortedObject(engines)]] : []),
['interop', interop.sort(localeCompare)],
...(nmScope ? [['scope', nmScope]] : []),
...(socket ? Object.entries(socket) : [])
]
const purlObj = PackageURL.fromString(`pkg:${eco}/${name}@${version}`)
const data = [purlObj.toString()]
if (metaEntries.length) {
data[1] = toSortedObjectFromEntries(metaEntries)
}
manifestData.push(data.length === 1 ? data[0] : data)
}
if (manifestData.length) {
manifest[eco] = manifestData.sort((a_, b_) => {
const a = Array.isArray(a_) ? a_[0] : a_
const b = Array.isArray(b_) ? b_[0] : b_
return localeCompare(a, b)
})
}
await addNpmManifestData(manifest)
}
}
const output = await prettierFormat(JSON.stringify(manifest), {
Expand Down
68 changes: 47 additions & 21 deletions scripts/update-test-npm-package-json.js
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ const {
README_GLOB,
lifecycleScriptNames,
npmPackagesPath,
parseArgsConfig,
relNpmPackagesPath,
relTestNpmNodeModulesPath,
relTestNpmPath,
Expand All @@ -40,6 +41,7 @@ const {
uniqueSync
} = require('@socketregistry/scripts/utils/fs')
const { execNpm } = require('@socketregistry/scripts/utils/npm')
const { merge } = require('@socketregistry/scripts/utils/objects')
const {
isSubpathExports,
readPackageJson,
Expand All @@ -54,18 +56,19 @@ const { localeCompare } = require('@socketregistry/scripts/utils/sorts')
const { Spinner } = require('@socketregistry/scripts/utils/spinner')
const { isNonEmptyString } = require('@socketregistry/scripts/utils/strings')

const { values: cliArgs } = util.parseArgs({
options: {
add: {
type: 'string',
multiple: true
},
force: {
type: 'boolean',
short: 'f'
const { values: cliArgs } = util.parseArgs(
merge(parseArgsConfig, {
options: {
add: {
type: 'string',
multiple: true
},
quiet: {
type: 'boolean'
}
}
}
})
})
)

const testScripts = [
// Order is significant. First in, first tried.
Expand Down Expand Up @@ -162,11 +165,15 @@ async function resolveDevDependencies(packageNames) {
await installTestNpmNodeModules({ clean: true, specs: [origPkgName] })
// Reload testNpmPkgJson because it is now out of date.
testNpmPkgJson = readPackageJsonSync(testNpmPkgJsonPath)
spinner.stop(
devDepExists
? `✔ Refreshed ${origPkgName}`
: `✔ --save-dev ${origPkgName} to package.json`
)
if (cliArgs.quiet) {
spinner.stop()
} else {
spinner.stop(
devDepExists
? `✔ Refreshed ${origPkgName}`
: `✔ --save-dev ${origPkgName} to package.json`
)
}
} catch {
spinner.stop(
devDepExists
Expand Down Expand Up @@ -235,7 +242,11 @@ async function resolveDevDependencies(packageNames) {
spinner.message = `Refreshing ${origPkgName} from tarball...`
try {
await installTestNpmNodeModules({ clean: true, specs: [origPkgName] })
spinner.stop(`✔ Refreshed ${pkgId} from tarball`)
if (cliArgs.quiet) {
spinner.stop()
} else {
spinner.stop(`✔ Refreshed ${pkgId} from tarball`)
}
} catch {
spinner.stop(`✘ Failed to refresh ${origPkgName} from tarball`)
}
Expand Down Expand Up @@ -483,11 +494,16 @@ async function linkPackages(packageNames) {
await fs.ensureSymlink(targetPath, destPath)
})
}
// Chunk actions to process them in parallel 3 at a time.
await pEach([...actions.values()], 3, a => a())
await nmEditablePkgJson.save()
linkedPackageNames.push(regPkgName)
})
spinner.stop('✔ Packages linked')
if (cliArgs.quiet) {
spinner.stop()
} else {
spinner.stop('✔ Packages linked')
}
return linkedPackageNames
}

Expand Down Expand Up @@ -545,7 +561,11 @@ async function cleanupNodeWorkspaces(linkedPackageNames) {
// Move override package from test/npm/node_modules/ to test/npm/node_workspaces/
await fs.move(srcPath, destPath, { overwrite: true })
})
spinner.stop('✔ Workspaces cleaned (so fresh and so clean, clean)')
if (cliArgs.quiet) {
spinner.stop()
} else {
spinner.stop('✔ Workspaces cleaned (so fresh and so clean, clean)')
}
}

async function installNodeWorkspaces() {
Expand Down Expand Up @@ -594,7 +614,11 @@ async function installNodeWorkspaces() {
).start()
try {
await installTestNpmNodeModules()
spinner.stop(`✔ Initialized ${relTestNpmNodeModulesPath}`)
if (cliArgs.quiet) {
spinner.stop()
} else {
spinner.stop(`✔ Initialized ${relTestNpmNodeModulesPath}`)
}
} catch (e) {
spinner.stop(`✘ Initialization encountered an error:`, e)
}
Expand All @@ -611,5 +635,7 @@ async function installNodeWorkspaces() {
await cleanupNodeWorkspaces(linkedPackageNames)
await installNodeWorkspaces()
}
console.log('Finished 🎉')
if (!cliArgs.quiet) {
console.log('Finished 🎉')
}
})()
8 changes: 5 additions & 3 deletions scripts/utils/templates.js
Original file line number Diff line number Diff line change
Expand Up @@ -74,13 +74,14 @@ async function getLicenseActions(pkgPath) {
}

async function getNpmReadmeAction(pkgPath) {
const eco = 'npm'
const pkgJsonPath = path.join(pkgPath, PACKAGE_JSON)
const pkgJson = await readPackageJson(pkgJsonPath)
const pkgPurlObj = PackageURL.fromString(
`pkg:npm/${pkgJson.name}@${pkgJson.version}`
`pkg:${eco}/${pkgJson.name}@${pkgJson.version}`
)
const { name: regPkgName } = pkgPurlObj
const manifestData = getManifestData('npm', regPkgName)
const manifestData = getManifestData(eco, regPkgName)
const categories = manifestData?.categories
return [
path.join(pkgPath, README_MD),
Expand All @@ -107,8 +108,9 @@ async function getNpmReadmeAction(pkgPath) {

async function getPackageJsonAction(pkgPath, options) {
const { engines } = { __proto__: null, ...options }
const eco = 'npm'
const regPkgName = path.basename(pkgPath)
const manifestData = getManifestData('npm', regPkgName)
const manifestData = getManifestData(eco, regPkgName)
const categories = manifestData?.categories
return [
path.join(pkgPath, PACKAGE_JSON),
Expand Down

0 comments on commit 066b0a6

Please sign in to comment.