diff --git a/.github/workflows/publish-dev.yml b/.github/workflows/publish-dev.yml index efb3c123fe1d..a2cc43046cb0 100644 --- a/.github/workflows/publish-dev.yml +++ b/.github/workflows/publish-dev.yml @@ -3,37 +3,13 @@ on: schedule: - cron: '0 */12 * * *' workflow_dispatch: + inputs: + dry_run: + type: boolean + default: false jobs: npm-publish: name: npm publish - strategy: - fail-fast: false - matrix: - include: - - package: '@discordjs/brokers' - folder: 'brokers' - - package: '@discordjs/builders' - folder: 'builders' - - package: '@discordjs/collection' - folder: 'collection' - - package: '@discordjs/core' - folder: 'core' - - package: '@discordjs/formatters' - folder: 'formatters' - - package: 'discord.js' - folder: 'discord.js' - - package: '@discordjs/next' - folder: 'next' - - package: '@discordjs/proxy' - folder: 'proxy' - - package: '@discordjs/rest' - folder: 'rest' - - package: '@discordjs/util' - folder: 'util' - - package: '@discordjs/voice' - folder: 'voice' - - package: '@discordjs/ws' - folder: 'ws' runs-on: ubuntu-latest permissions: id-token: write @@ -53,32 +29,18 @@ jobs: node-version: 20 registry-url: https://registry.npmjs.org/ - - name: Check the current development version - id: release-check - run: | - if [[ $(npm view ${{ matrix.package }}@dev version | grep -e "$(git rev-parse --short HEAD)") ]]; \ - then echo "RELEASE=0" >> "$GITHUB_OUTPUT"; \ - else echo "RELEASE=1" >> "$GITHUB_OUTPUT"; \ - fi - - name: Install dependencies - if: steps.release-check.outputs.release == '1' uses: ./packages/actions/src/pnpmCache - name: Build dependencies - if: steps.release-check.outputs.release == '1' run: pnpm run build - - name: Publish package - if: steps.release-check.outputs.release == '1' - run: | - pnpm --filter=${{ matrix.package }} run release --preid "dev.$(date +%s)-$(git rev-parse --short HEAD)" --skip-changelog - pnpm --filter=${{ matrix.package }} publish --provenance --no-git-checks --tag dev || true - env: - NODE_AUTH_TOKEN: ${{ secrets.NPM_PUBLISH_TOKEN }} - - - name: Deprecate prior development releases - if: steps.release-check.outputs.release == '1' - run: pnpm exec npm-deprecate --name "*dev*" --message "This version is deprecated. Please use a newer version." --package ${{ matrix.package }} + - name: Publish packages + uses: ./packages/actions/src/releasePackages + with: + exclude: '@discordjs/docgen' + dry: ${{ inputs.dry_run }} + dev: true env: NODE_AUTH_TOKEN: ${{ secrets.NPM_PUBLISH_TOKEN }} + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml new file mode 100644 index 000000000000..55f5134c16a0 --- /dev/null +++ b/.github/workflows/release.yml @@ -0,0 +1,75 @@ +name: Release +on: + workflow_dispatch: + inputs: + ref: + description: 'The branch, tag or SHA to checkout' + required: true + default: 'main' + package: + description: 'The published name of a single package to release' + type: choice + required: false + options: + - all + - discord.js + - '@discordjs/brokers' + - '@discordjs/builders' + - '@discordjs/collection' + - '@discordjs/core' + - 'create-discord-bot' + - '@discordjs/docgen' + - '@discordjs/formatters' + - '@discordjs/next' + - '@discordjs/proxy' + - '@discordjs/rest' + - '@discordjs/util' + - '@discordjs/voice' + - '@discordjs/ws' + exclude: + description: 'Comma separated list of packages to exclude from release (if not depended upon)' + required: false + type: string + default: '@discordjs/docgen,@discordjs/next' + dry_run: + type: boolean + default: false +jobs: + npm-publish: + name: npm publish + runs-on: ubuntu-latest + permissions: + id-token: write + contents: write + env: + TURBO_TOKEN: ${{ secrets.TURBO_TOKEN }} + TURBO_TEAM: ${{ secrets.TURBO_TEAM }} + if: github.repository_owner == 'discordjs' + steps: + - name: Checkout repository + uses: actions/checkout@v4 + with: + ref: ${{ inputs.ref || '' }} + ssh_key: ${{ secrets.DEPLOY_KEY_CI_RELEASE_TAGS }} + + - name: Install Node.js v20 + uses: actions/setup-node@v4 + with: + node-version: 20 + registry-url: https://registry.npmjs.org/ + + - name: Install dependencies + uses: ./packages/actions/src/pnpmCache + + - name: Build dependencies + run: pnpm run build + + - name: Release packages + uses: ./packages/actions/src/releasePackages + with: + package: ${{ inputs.package }} + exclude: ${{ inputs.exclude }} + dry: ${{ inputs.dry_run }} + env: + NODE_AUTH_TOKEN: ${{ secrets.NPM_PUBLISH_TOKEN }} + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} diff --git a/package.json b/package.json index 7cb9986b48fa..20f4a7cb870b 100644 --- a/package.json +++ b/package.json @@ -22,7 +22,8 @@ "prepare": "is-ci || husky", "update": "pnpm --recursive update --interactive", "update:latest": "pnpm --recursive update --interactive --latest", - "create-package": "turbo gen create-package --args" + "create-package": "turbo gen create-package --args", + "release": "bun ./packages/actions/src/releasePackages/index.ts" }, "type": "module", "contributors": [ diff --git a/packages/actions/package.json b/packages/actions/package.json index 8b29657afee7..9f7a50f0b5ae 100644 --- a/packages/actions/package.json +++ b/packages/actions/package.json @@ -42,16 +42,20 @@ "funding": "https://github.com/discordjs/discord.js?sponsor", "dependencies": { "@actions/core": "^1.10.1", + "@actions/github": "^6.0.0", "@actions/glob": "^0.5.0", "@discordjs/scripts": "workspace:^", "@vercel/blob": "^0.23.4", "@vercel/postgres": "^0.9.0", + "commander": "^12.1.0", "meilisearch": "^0.38.0", "p-limit": "^6.1.0", "tslib": "^2.6.3", "undici": "6.19.8" }, "devDependencies": { + "@npm/types": "^1.0.2", + "@types/bun": "^1.1.4", "@types/node": "^18.19.45", "@vitest/coverage-v8": "^2.0.5", "cross-env": "^7.0.3", diff --git a/packages/actions/src/releasePackages/action.yml b/packages/actions/src/releasePackages/action.yml new file mode 100644 index 000000000000..d25bd849bb3b --- /dev/null +++ b/packages/actions/src/releasePackages/action.yml @@ -0,0 +1,24 @@ +name: 'Release Packages' +description: 'Tags and releases any unreleased packages' +inputs: + dev: + description: 'Releases development versions of packages (skips tagging and github releases)' + default: false + dry: + descrption: 'Perform a dry run that skips publishing and outputs logs indicating what would have happened' + default: false + package: + description: 'The published name of a single package to release' + exclude: + description: 'Comma separated list of packages to exclude from release (if not depended upon)' +runs: + using: composite + steps: + - uses: oven-sh/setup-bun@v1 + - run: bun packages/actions/src/releasePackages/index.ts + shell: bash + env: + INPUT_DEV: ${{ inputs.dev }} + INPUT_DRY: ${{ inputs.dry }} + INPUT_PACKAGE: ${{ inputs.package }} + INPUT_EXCLUDE: ${{ inputs.exclude }} diff --git a/packages/actions/src/releasePackages/generateReleaseTree.ts b/packages/actions/src/releasePackages/generateReleaseTree.ts new file mode 100644 index 000000000000..ec55bbe30351 --- /dev/null +++ b/packages/actions/src/releasePackages/generateReleaseTree.ts @@ -0,0 +1,230 @@ +import { info, warning } from '@actions/core'; +import type { PackageJson, PackumentVersion } from '@npm/types'; +import { $, file, write } from 'bun'; + +const nonNodePackages = new Set(['@discordjs/proxy-container']); + +interface pnpmTreeDependency { + from: string; + path: string; + version: string; +} + +interface pnpmTree { + dependencies?: Record; + name?: string; + path: string; + private?: boolean; + unsavedDependencies?: Record; + version?: string; +} + +export interface ReleaseEntry { + changelog?: string; + dependsOn?: string[]; + name: string; + version: string; +} + +async function fetchDevVersion(pkg: string) { + try { + const res = await fetch(`https://registry.npmjs.org/${pkg}/dev`); + if (!res.ok) return null; + const packument = (await res.json()) as PackumentVersion; + return packument.version; + } catch { + return null; + } +} + +async function getReleaseEntries(dev: boolean, dry: boolean) { + const releaseEntries: ReleaseEntry[] = []; + const packageList: pnpmTree[] = + await $`pnpm list --recursive --only-projects --filter {packages/\*} --prod --json`.json(); + + const commitHash = (await $`git rev-parse --short HEAD`.text()).trim(); + + for (const pkg of packageList) { + // Don't release private packages ever (npm will error anyways) + if (pkg.private) continue; + // Just in case + if (!pkg.version || !pkg.name) continue; + if (nonNodePackages.has(pkg.name)) continue; + + const release: ReleaseEntry = { + name: pkg.name, + version: pkg.version, + }; + + if (dev) { + const devVersion = await fetchDevVersion(pkg.name); + if (devVersion?.endsWith(commitHash)) { + // Write the currently released dev version so when pnpm publish runs on dependents they depend on the dev versions + if (dry) { + info(`[DRY] ${pkg.name}@${devVersion} already released. Editing package.json version.`); + } else { + const pkgJson = (await file(`${pkg.path}/package.json`).json()) as PackageJson; + pkgJson.version = devVersion; + await write(`${pkg.path}/package.json`, JSON.stringify(pkgJson, null, '\t')); + } + + release.version = devVersion; + } else if (dry) { + info(`[DRY] Bumping ${pkg.name} via git-cliff.`); + release.version = `${pkg.version}.DRY-dev.${Math.round(Date.now() / 1_000)}-${commitHash}`; + } else { + await $`pnpm --filter=${pkg.name} run release --preid "dev.${Math.round(Date.now() / 1_000)}-${commitHash} --skip-changelog"`; + // Read again instead of parsing the output to be sure we're matching when checking against npm + const pkgJson = (await file(`${pkg.path}/package.json`).json()) as PackageJson; + release.version = pkgJson.version; + } + } + // Only need changelog for releases published to github + else { + try { + // Find and parse changelog to post in github release + const changelogFile = await file(`${pkg.path}/CHANGELOG.md`).text(); + + let changelogLines: string[] = []; + let foundChangelog = false; + + for (const line of changelogFile.split('\n')) { + if (line.startsWith('# [')) { + if (foundChangelog) { + if (changelogLines.at(-1) === '') { + changelogLines = changelogLines.slice(2, -1); + } + + break; + } + + // Check changelog release version and assume no changelog if version does not match + if (!line.startsWith(`# [${release.name === 'discord.js' ? `` : `${release.name}@`}${release.version}]`)) { + break; + } + + foundChangelog = true; + } + + if (foundChangelog) { + changelogLines.push(line); + } + } + + release.changelog = changelogLines.join('\n'); + } catch (error) { + // Probably just no changelog file but log just in case + warning(`Error parsing changelog for ${pkg.name}, will use auto generated: ${error}`); + } + } + + if (pkg.dependencies) { + release.dependsOn = Object.keys(pkg.dependencies); + } + + releaseEntries.push(release); + } + + return releaseEntries; +} + +export async function generateReleaseTree(dev: boolean, dry: boolean, packageName?: string, exclude?: string[]) { + let releaseEntries = await getReleaseEntries(dev, dry); + // Try to early return if the package doesn't have deps + if (packageName && packageName !== 'all') { + const releaseEntry = releaseEntries.find((entry) => entry.name === packageName); + if (!releaseEntry) { + throw new Error(`Package ${packageName} not releaseable`); + } + + if (!releaseEntry.dependsOn) { + return [[releaseEntry]]; + } + } + + // Generate the whole tree first, then prune if specified + const releaseTree: ReleaseEntry[][] = []; + const didRelease = new Set(); + + while (releaseEntries.length) { + const nextBranch: ReleaseEntry[] = []; + const unreleased: ReleaseEntry[] = []; + for (const entry of releaseEntries) { + if (!entry.dependsOn) { + nextBranch.push(entry); + continue; + } + + const allDepsReleased = entry.dependsOn.every((dep) => didRelease.has(dep)); + if (allDepsReleased) { + nextBranch.push(entry); + } else { + unreleased.push(entry); + } + } + + // Update didRelease in a second loop to avoid loop order issues + for (const release of nextBranch) { + didRelease.add(release.name); + } + + if (releaseEntries.length === unreleased.length) { + throw new Error( + `One or more packages have dependents that can't be released: ${unreleased.map((entry) => entry.name).join(',')}`, + ); + } + + releaseTree.push(nextBranch); + releaseEntries = unreleased; + } + + // Prune exclusions + if ((!packageName || packageName === 'all') && Array.isArray(exclude) && exclude.length) { + const neededPackages = new Set(); + const excludedReleaseTree: ReleaseEntry[][] = []; + + for (const releaseBranch of releaseTree.reverse()) { + const newThisBranch: ReleaseEntry[] = []; + + for (const entry of releaseBranch) { + if (exclude.includes(entry.name) && !neededPackages.has(entry.name)) { + continue; + } + + newThisBranch.push(entry); + for (const dep of entry.dependsOn ?? []) { + neededPackages.add(dep); + } + } + + if (newThisBranch.length) excludedReleaseTree.unshift(newThisBranch); + } + + return excludedReleaseTree; + } + + if (!packageName || packageName === 'all') { + return releaseTree; + } + + // Prune the tree for the specified package + const neededPackages = new Set([packageName]); + const packageReleaseTree: ReleaseEntry[][] = []; + + for (const releaseBranch of releaseTree.reverse()) { + const newThisBranch: ReleaseEntry[] = []; + + for (const entry of releaseBranch) { + if (neededPackages.has(entry.name)) { + newThisBranch.push(entry); + for (const dep of entry.dependsOn ?? []) { + neededPackages.add(dep); + } + } + } + + if (newThisBranch.length) packageReleaseTree.unshift(newThisBranch); + } + + return packageReleaseTree; +} diff --git a/packages/actions/src/releasePackages/index.ts b/packages/actions/src/releasePackages/index.ts new file mode 100644 index 000000000000..b16c8127299a --- /dev/null +++ b/packages/actions/src/releasePackages/index.ts @@ -0,0 +1,47 @@ +import { getInput, startGroup, endGroup, getBooleanInput, info } from '@actions/core'; +import { program } from 'commander'; +import { generateReleaseTree } from './generateReleaseTree.js'; +import { releasePackage } from './releasePackage.js'; + +const excludeInput = getInput('exclude'); +let dryInput = false; +let devInput = false; + +try { + devInput = getBooleanInput('dev'); +} catch { + // We're not running in actions +} + +try { + dryInput = getBooleanInput('dry'); +} catch { + // We're not running in actions or the input isn't set (cron) +} + +program + .name('release packages') + .description('releases monorepo packages with proper sequencing') + .argument('[package]', "release a specific package (and it's dependencies)", getInput('package')) + .option( + '-e, --exclude ', + 'exclude specific packages from releasing (will still release if necessary for another package)', + excludeInput ? excludeInput.split(',') : [], + ) + .option('--dry', 'skips actual publishing and outputs logs instead', dryInput) + .option('--dev', 'publishes development versions and skips tagging / github releases', devInput) + .parse(); + +const { exclude, dry, dev } = program.opts<{ dev: boolean; dry: boolean; exclude: string[] }>(); +const packageName = program.args[0]!; + +const tree = await generateReleaseTree(dev, dry, packageName, exclude); +for (const branch of tree) { + startGroup(`Releasing ${branch.map((entry) => `${entry.name}@${entry.version}`).join(', ')}`); + await Promise.all(branch.map(async (release) => releasePackage(release, dev, dry))); + endGroup(); +} + +info( + `Successfully released ${tree.map((branch) => branch.map((entry) => `${entry.name}@${entry.version}`).join(', ')).join(', ')}`, +); diff --git a/packages/actions/src/releasePackages/releasePackage.ts b/packages/actions/src/releasePackages/releasePackage.ts new file mode 100644 index 000000000000..6a1dab232d6f --- /dev/null +++ b/packages/actions/src/releasePackages/releasePackage.ts @@ -0,0 +1,87 @@ +import process from 'node:process'; +import { setInterval, clearInterval } from 'node:timers'; +import { info, warning } from '@actions/core'; +import { getOctokit, context } from '@actions/github'; +import { $ } from 'bun'; +import type { ReleaseEntry } from './generateReleaseTree.js'; + +let octokit: ReturnType | undefined; + +if (process.env.GITHUB_TOKEN) { + octokit = getOctokit(process.env.GITHUB_TOKEN); +} + +async function checkRegistry(release: ReleaseEntry) { + const res = await fetch(`https://registry.npmjs.org/${release.name}/${release.version}`); + return res.ok; +} + +async function gitTagAndRelease(release: ReleaseEntry, dry: boolean) { + const tagName = `${release.name === 'discord.js' ? `` : `${release.name}@`}${release.version}`; + // Don't throw, if this exits non-zero it's probably because the tag already exists + await $`git tag ${tagName}`.nothrow(); + + if (dry) { + info(`[DRY] Tag "${tagName}" created, skipping push and release creation.`); + return; + } + + await $`git push origin ${tagName}`; + + try { + await octokit?.rest.repos.createRelease({ + ...context.repo, + tag_name: tagName, + name: tagName, + body: release.changelog ?? '', + generate_release_notes: release.changelog === undefined, + make_latest: release.name === 'discord.js' ? 'true' : 'false', + }); + } catch (error) { + warning(`Failed to create github release: ${error}`); + } +} + +export async function releasePackage(release: ReleaseEntry, dev: boolean, dry: boolean) { + // Sanity check against the registry first + if (await checkRegistry(release)) { + info(`${release.name}@${release.version} already published, skipping.`); + return; + } + + if (dry) { + info(`[DRY] Releasing ${release.name}@${release.version}`); + } else { + await $`pnpm --filter=${release.name} publish --provenance --no-git-checks ${dev ? '--tag=dev' : ''}`; + } + + if (!dev) await gitTagAndRelease(release, dry); + + if (dry) return; + + const before = performance.now(); + + // Poll registry to ensure next publishes won't fail + await new Promise((resolve, reject) => { + const interval = setInterval(async () => { + if (await checkRegistry(release)) { + clearInterval(interval); + resolve(); + return; + } + + if (performance.now() > before + 5 * 60 * 1_000) { + clearInterval(interval); + reject(new Error(`Release for ${release.name} failed.`)); + } + }, 15_000); + }); + + if (dev) { + // Send and forget, deprecations are less important than releasing other dev versions and can be done manually + void $`pnpm exec npm-deprecate --name "*dev*" --message "This version is deprecated. Please use a newer version." --package ${release.name}` + .nothrow() + // eslint-disable-next-line promise/prefer-await-to-then + .then(() => {}); + } +} diff --git a/packages/actions/tsconfig.json b/packages/actions/tsconfig.json index b6ea137a02c5..7f25511aac5b 100644 --- a/packages/actions/tsconfig.json +++ b/packages/actions/tsconfig.json @@ -1,6 +1,10 @@ { "$schema": "https://json.schemastore.org/tsconfig.json", "extends": "../../tsconfig.json", + "compilerOptions": { + "types": ["node"], + "skipLibCheck": true + }, "include": ["src/**/*.ts", "src/**/*.js", "src/**/*.cjs", "src/**/*.mjs", "bin"], "exclude": ["node_modules"] } diff --git a/packages/actions/tsup.config.ts b/packages/actions/tsup.config.ts index 8e29a04855b6..d1438612c62e 100644 --- a/packages/actions/tsup.config.ts +++ b/packages/actions/tsup.config.ts @@ -4,6 +4,7 @@ export default createTsupConfig({ entry: [ 'src/index.ts', 'src/formatTag/index.ts', + 'src/releasePackages/index.ts', 'src/uploadDocumentation/index.ts', 'src/uploadSearchIndices/index.ts', 'src/uploadSplitDocumentation/index.ts', @@ -11,4 +12,5 @@ export default createTsupConfig({ dts: false, format: 'esm', minify: 'terser', + target: 'esnext', }); diff --git a/packages/ui/package.json b/packages/ui/package.json index fbd6a0ea0d93..0ed705c2ba21 100644 --- a/packages/ui/package.json +++ b/packages/ui/package.json @@ -1,6 +1,7 @@ { "$schema": "https://json.schemastore.org/package.json", "name": "@discordjs/ui", + "private": true, "version": "0.1.0", "description": "", "scripts": { diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 52c2a55ea0bf..40c7504077f9 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -386,6 +386,9 @@ importers: '@actions/core': specifier: ^1.10.1 version: 1.10.1 + '@actions/github': + specifier: ^6.0.0 + version: 6.0.0 '@actions/glob': specifier: ^0.5.0 version: 0.5.0 @@ -398,6 +401,9 @@ importers: '@vercel/postgres': specifier: ^0.9.0 version: 0.9.0 + commander: + specifier: ^12.1.0 + version: 12.1.0 meilisearch: specifier: ^0.38.0 version: 0.38.0(encoding@0.1.13) @@ -411,6 +417,12 @@ importers: specifier: 6.19.8 version: 6.19.8 devDependencies: + '@npm/types': + specifier: ^1.0.2 + version: 1.0.2 + '@types/bun': + specifier: ^1.1.4 + version: 1.1.4 '@types/node': specifier: ^18.19.45 version: 18.19.45 @@ -1773,6 +1785,9 @@ packages: '@actions/core@1.10.1': resolution: {integrity: sha512-3lBR9EDAY+iYIpTnTIXmWcNbX3T2kCkAEQGIQx4NVQ0575nk2k3GRZDTPQG+vVtS2izSLmINlxXf0uLtnrTP+g==} + '@actions/github@6.0.0': + resolution: {integrity: sha512-alScpSVnYmjNEXboZjarjukQEzgCRmjMv6Xj47fsdnqGS73bjJNDpiiXmp8jr0UZLdUB6d9jW63IcmddUP+l0g==} + '@actions/glob@0.5.0': resolution: {integrity: sha512-tST2rjPvJLRZLuT9NMUtyBjvj9Yo0MiJS3ow004slMvm8GFM+Zv9HvMJ7HWzfUyJnGrJvDsYkWBaaG3YKXRtCw==} @@ -3146,11 +3161,6 @@ packages: engines: {node: '>=v18'} hasBin: true - '@favware/cliff-jumper@4.0.3': - resolution: {integrity: sha512-vRFP87hW/UM4ryVxKFlknV7ZeYwFCzMizjBBpIJ51WSLsmxehOKV365n79IY2r6lVmxMgDbOZ0AZkB8AfBzHPw==} - engines: {node: '>=v18'} - hasBin: true - '@favware/colorette-spinner@1.0.1': resolution: {integrity: sha512-PPYtcLzhSafdylp8NBOxMCYIcLqTUMNiQc7ciBoAIvxNG2egM+P7e2nNPui5+Svyk89Q+Tnbrp139ZRIIBw3IA==} engines: {node: '>=v16'} @@ -3641,6 +3651,9 @@ packages: resolution: {integrity: sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==} engines: {node: '>= 8'} + '@npm/types@1.0.2': + resolution: {integrity: sha512-KXZccTDEnWqNrrx6JjpJKU/wJvNeg9BDgjS0XhmlZab7br921HtyVbsYzJr4L+xIvjdJ20Wh9dgxgCI2a5CEQw==} + '@npmcli/config@8.3.4': resolution: {integrity: sha512-01rtHedemDNhUXdicU7s+QYz/3JyV5Naj84cvdXGH4mgCdL+agmSYaLF4LUG4vMCLzhBO8YtS0gPpH1FGvbgAw==} engines: {node: ^16.14.0 || >=18.0.0} @@ -3669,10 +3682,18 @@ packages: resolution: {integrity: sha512-xhfYPXoV5Dy4UkY0D+v2KkwvnDfiA/8Mt3sWCGI/hM03NsYIH8ZaG6QzS9x7pje5vHZBZJ2v6VRFVTWACnqcmQ==} engines: {node: ^16.14.0 || >=18.0.0} + '@octokit/auth-token@4.0.0': + resolution: {integrity: sha512-tY/msAuJo6ARbK6SPIxZrPBms3xPbfwBrulZe0Wtr/DIY9lje2HeV1uoebShn6mx7SjCHif6EjMvoREj+gZ+SA==} + engines: {node: '>= 18'} + '@octokit/auth-token@5.1.1': resolution: {integrity: sha512-rh3G3wDO8J9wSjfI436JUKzHIxq8NaiL0tVeB2aXmG6p/9859aUOAjA9pmSPNGGZxfwmaJ9ozOJImuNVJdpvbA==} engines: {node: '>= 18'} + '@octokit/core@5.2.0': + resolution: {integrity: sha512-1LFfa/qnMQvEOAdzlQymH0ulepxbxnCYAKJZfMci/5XJyIHWgEYnDmgnKakbTh7CH2tFQ5O60oYDvns4i9RAIg==} + engines: {node: '>= 18'} + '@octokit/core@6.1.2': resolution: {integrity: sha512-hEb7Ma4cGJGEUNOAVmyfdB/3WirWMg5hDuNFVejGEDFqupeOysLc2sG6HJxY2etBp5YQu5Wtxwi020jS9xlUwg==} engines: {node: '>= 18'} @@ -3681,27 +3702,61 @@ packages: resolution: {integrity: sha512-JYjh5rMOwXMJyUpj028cu0Gbp7qe/ihxfJMLc8VZBMMqSwLgOxDI1911gV4Enl1QSavAQNJcwmwBF9M0VvLh6Q==} engines: {node: '>= 18'} + '@octokit/endpoint@9.0.5': + resolution: {integrity: sha512-ekqR4/+PCLkEBF6qgj8WqJfvDq65RH85OAgrtnVp1mSxaXF03u2xW/hUdweGS5654IlC0wkNYC18Z50tSYTAFw==} + engines: {node: '>= 18'} + + '@octokit/graphql@7.1.0': + resolution: {integrity: sha512-r+oZUH7aMFui1ypZnAvZmn0KSqAUgE1/tUXIWaqUCa1758ts/Jio84GZuzsvUkme98kv0WFY8//n0J1Z+vsIsQ==} + engines: {node: '>= 18'} + '@octokit/graphql@8.1.1': resolution: {integrity: sha512-ukiRmuHTi6ebQx/HFRCXKbDlOh/7xEV6QUXaE7MJEKGNAncGI/STSbOkl12qVXZrfZdpXctx5O9X1AIaebiDBg==} engines: {node: '>= 18'} + '@octokit/openapi-types@20.0.0': + resolution: {integrity: sha512-EtqRBEjp1dL/15V7WiX5LJMIxxkdiGJnabzYx5Apx4FkQIFgAfKumXeYAqqJCj1s+BMX4cPFIFC4OLCR6stlnA==} + '@octokit/openapi-types@22.2.0': resolution: {integrity: sha512-QBhVjcUa9W7Wwhm6DBFu6ZZ+1/t/oYxqc2tp81Pi41YNuJinbFRx8B133qVOrAaBbF7D/m0Et6f9/pZt9Rc+tg==} + '@octokit/plugin-paginate-rest@9.2.1': + resolution: {integrity: sha512-wfGhE/TAkXZRLjksFXuDZdmGnJQHvtU/joFQdweXUgzo1XwvBCD4o4+75NtFfjfLK5IwLf9vHTfSiU3sLRYpRw==} + engines: {node: '>= 18'} + peerDependencies: + '@octokit/core': '5' + + '@octokit/plugin-rest-endpoint-methods@10.4.1': + resolution: {integrity: sha512-xV1b+ceKV9KytQe3zCVqjg+8GTGfDYwaT1ATU5isiUyVtlVAO3HNdzpS4sr4GBx4hxQ46s7ITtZrAsxG22+rVg==} + engines: {node: '>= 18'} + peerDependencies: + '@octokit/core': '5' + '@octokit/plugin-retry@7.1.1': resolution: {integrity: sha512-G9Ue+x2odcb8E1XIPhaFBnTTIrrUDfXN05iFXiqhR+SeeeDMMILcAnysOsxUpEWcQp2e5Ft397FCXTcPkiPkLw==} engines: {node: '>= 18'} peerDependencies: '@octokit/core': '>=6' + '@octokit/request-error@5.1.0': + resolution: {integrity: sha512-GETXfE05J0+7H2STzekpKObFe765O5dlAKUTLNGeH+x47z7JjXHfsHKo5z21D/o/IOZTUEI6nyWyR+bZVP/n5Q==} + engines: {node: '>= 18'} + '@octokit/request-error@6.1.4': resolution: {integrity: sha512-VpAhIUxwhWZQImo/dWAN/NpPqqojR6PSLgLYAituLM6U+ddx9hCioFGwBr5Mi+oi5CLeJkcAs3gJ0PYYzU6wUg==} engines: {node: '>= 18'} + '@octokit/request@8.4.0': + resolution: {integrity: sha512-9Bb014e+m2TgBeEJGEbdplMVWwPmL1FPtggHQRkV+WVsMggPtEkLKPlcVYm/o8xKLkpJ7B+6N8WfQMtDLX2Dpw==} + engines: {node: '>= 18'} + '@octokit/request@9.1.3': resolution: {integrity: sha512-V+TFhu5fdF3K58rs1pGUJIDH5RZLbZm5BI+MNF+6o/ssFNT4vWlCh/tVpF3NxGtP15HUxTTMUbsG5llAuU2CZA==} engines: {node: '>= 18'} + '@octokit/types@12.6.0': + resolution: {integrity: sha512-1rhSOfRa6H9w4YwK0yrf5faDaDTb+yLyBUKOCV4xtCDB5VmIPqd/v9yr9o6SAzOAlRxMiRiCic6JVM1/kunVkw==} + '@octokit/types@13.5.0': resolution: {integrity: sha512-HdqWTf5Z3qwDVlzCrP8UJquMwunpDiMPt5er+QjGzL4hqr/vBVY/MauQgS1xWxCDT1oMx1EULyqxncdCY/NVSQ==} @@ -5543,6 +5598,9 @@ packages: '@types/body-parser@1.19.5': resolution: {integrity: sha512-fB3Zu92ucau0iQ0JMCFQE7b/dv8Ot07NI3KaZIkIUNXq82k4eBAqUaneXfleGY9JWskeS9y+u0nXMyspcuQrCg==} + '@types/bun@1.1.4': + resolution: {integrity: sha512-ejSuv/3s0hTHj/nkkLzBlHxm4JxOPygbLNi0kzM6ooq8rOiQvIUCv7RRErTaWSfb+QVnKz6x7qlp8N86bGDiIg==} + '@types/concat-stream@2.0.3': resolution: {integrity: sha512-3qe4oQAPNwVNwK4C9c8u+VJqv9kez+2MR4qJpoPFfXtgxxif1QbFusvXzK0/Wra2VX07smostI2VMmJNSpZjuQ==} @@ -5693,6 +5751,9 @@ packages: '@types/node@18.19.45': resolution: {integrity: sha512-VZxPKNNhjKmaC1SUYowuXSRSMGyQGmQjvvA1xE4QZ0xce2kLtEhPDS+kqpCPBZYgqblCLQ2DAjSzmgCM5auvhA==} + '@types/node@20.12.14': + resolution: {integrity: sha512-scnD59RpYD91xngrQQLGkE+6UrHUPzeKZWhhjBSa3HSkwjbQc38+q3RoIVEwxQGRw3M+j5hpNAM+lgV3cVormg==} + '@types/node@20.16.1': resolution: {integrity: sha512-zJDo7wEadFtSyNz5QITDfRcrhqDvQI1xQNQ0VoizPjM/dVAODqqIUWbJPkvsxmTI0MYRGRikcdjMPhOssnPejQ==} @@ -6680,6 +6741,9 @@ packages: bcrypt-pbkdf@1.0.2: resolution: {integrity: sha512-qeFIXtP4MSoi6NLqO12WfqARWWuCKi2Rn/9hJLEmtB5yTNr9DqFWkJRCf2qShWzPeAMRnOgCrq0sg/KLv5ES9w==} + before-after-hook@2.2.3: + resolution: {integrity: sha512-NzUnlZexiaH/46WDhANlyR2bXRopNg4F/zuSA3OpZnllCUgRaOF2znDioDWrmbNVsuZk6l9pMquQB38cfBZwkQ==} + before-after-hook@3.0.2: resolution: {integrity: sha512-Nik3Sc0ncrMK4UUdXQmAnRtzmNQTAAXmXIopizwZ1W1t8QmfJj+zL4OA2I7XPTPW5z5TDqv4hRo/JzouDJnX3A==} @@ -6760,6 +6824,9 @@ packages: builtins@5.1.0: resolution: {integrity: sha512-SW9lzGTLvWTP1AY8xeAMZimqDrIaSdLQUcVr9DMef51niJ022Ri87SwRRKYm4A6iHfkPaiVUu/Duw2Wc4J7kKg==} + bun-types@1.1.13: + resolution: {integrity: sha512-G/TqF0SsMQGLr4g7K3B2BK8BrPEA1EqCNwxZbyRdj5M4t54zvwyaqvRJOW34kuPqc2IvNNalRU3swc8B4oc4FA==} + bundle-require@5.0.0: resolution: {integrity: sha512-GuziW3fSSmopcx4KRymQEJVbZUfqlCqcq7dvs6TYwKRZiegK/2buMxQTPs6MGlNv50wms1699qYO54R8XfRX4w==} engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} @@ -7570,6 +7637,9 @@ packages: resolution: {integrity: sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==} engines: {node: '>= 0.8'} + deprecation@2.3.1: + resolution: {integrity: sha512-xmHIy4F3scKVwMsQ4WnVaS8bHOx0DmVwRywosKhaILI0ywMDWPtBSku2HNxRvF7jtwDRsoEwYQSfbxj8b7RlJQ==} + dequal@2.0.3: resolution: {integrity: sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA==} engines: {node: '>=6'} @@ -13135,6 +13205,9 @@ packages: unist-util-visit@5.0.0: resolution: {integrity: sha512-MR04uvD+07cwl/yhVuVWAtw+3GOR/knlL55Nd/wAdblk27GCVt3lqpTivy/tkJcZoNPzTwS1Y+KMojlLDhoTzg==} + universal-user-agent@6.0.1: + resolution: {integrity: sha512-yCzhz6FN2wU1NiiQRogkTQszlQSlpWaw8SvVegAc+bDxbzHgh1vX8uIe8OYyMH6DwH+sdTJsgMl36+mSMdRJIQ==} + universal-user-agent@7.0.2: resolution: {integrity: sha512-0JCqzSKnStlRRQfCdowvqy3cy0Dvtlb8xecj/H8JFZuCze4rwjPZQOgvFvn0Ws/usCHQFGpyr+pB9adaGwXn4Q==} @@ -13666,6 +13739,13 @@ snapshots: '@actions/http-client': 2.2.2 uuid: 8.3.2 + '@actions/github@6.0.0': + dependencies: + '@actions/http-client': 2.2.2 + '@octokit/core': 5.2.0 + '@octokit/plugin-paginate-rest': 9.2.1(@octokit/core@5.2.0) + '@octokit/plugin-rest-endpoint-methods': 10.4.1(@octokit/core@5.2.0) + '@actions/glob@0.5.0': dependencies: '@actions/core': 1.10.1 @@ -15180,23 +15260,6 @@ snapshots: semver: 7.6.3 smol-toml: 1.3.0 - '@favware/cliff-jumper@4.0.3': - dependencies: - '@favware/colorette-spinner': 1.0.1 - '@octokit/auth-token': 5.1.1 - '@octokit/core': 6.1.2 - '@octokit/plugin-retry': 7.1.1(@octokit/core@6.1.2) - '@sapphire/result': 2.6.6 - '@sapphire/utilities': 3.16.2 - colorette: 2.0.20 - commander: 12.1.0 - conventional-recommended-bump: 10.0.0 - execa: 9.3.1 - git-cliff: 2.4.0 - js-yaml: 4.1.0 - semver: 7.6.3 - smol-toml: 1.3.0 - '@favware/colorette-spinner@1.0.1': dependencies: colorette: 2.0.20 @@ -15947,6 +16010,8 @@ snapshots: '@nodelib/fs.scandir': 2.1.5 fastq: 1.17.1 + '@npm/types@1.0.2': {} + '@npmcli/config@8.3.4': dependencies: '@npmcli/map-workspaces': 3.0.6 @@ -16003,8 +16068,20 @@ snapshots: dependencies: which: 4.0.0 + '@octokit/auth-token@4.0.0': {} + '@octokit/auth-token@5.1.1': {} + '@octokit/core@5.2.0': + dependencies: + '@octokit/auth-token': 4.0.0 + '@octokit/graphql': 7.1.0 + '@octokit/request': 8.4.0 + '@octokit/request-error': 5.1.0 + '@octokit/types': 13.5.0 + before-after-hook: 2.2.3 + universal-user-agent: 6.0.1 + '@octokit/core@6.1.2': dependencies: '@octokit/auth-token': 5.1.1 @@ -16020,14 +16097,37 @@ snapshots: '@octokit/types': 13.5.0 universal-user-agent: 7.0.2 + '@octokit/endpoint@9.0.5': + dependencies: + '@octokit/types': 13.5.0 + universal-user-agent: 6.0.1 + + '@octokit/graphql@7.1.0': + dependencies: + '@octokit/request': 8.4.0 + '@octokit/types': 13.5.0 + universal-user-agent: 6.0.1 + '@octokit/graphql@8.1.1': dependencies: '@octokit/request': 9.1.3 '@octokit/types': 13.5.0 universal-user-agent: 7.0.2 + '@octokit/openapi-types@20.0.0': {} + '@octokit/openapi-types@22.2.0': {} + '@octokit/plugin-paginate-rest@9.2.1(@octokit/core@5.2.0)': + dependencies: + '@octokit/core': 5.2.0 + '@octokit/types': 12.6.0 + + '@octokit/plugin-rest-endpoint-methods@10.4.1(@octokit/core@5.2.0)': + dependencies: + '@octokit/core': 5.2.0 + '@octokit/types': 12.6.0 + '@octokit/plugin-retry@7.1.1(@octokit/core@6.1.2)': dependencies: '@octokit/core': 6.1.2 @@ -16035,10 +16135,23 @@ snapshots: '@octokit/types': 13.5.0 bottleneck: 2.19.5 + '@octokit/request-error@5.1.0': + dependencies: + '@octokit/types': 13.5.0 + deprecation: 2.3.1 + once: 1.4.0 + '@octokit/request-error@6.1.4': dependencies: '@octokit/types': 13.5.0 + '@octokit/request@8.4.0': + dependencies: + '@octokit/endpoint': 9.0.5 + '@octokit/request-error': 5.1.0 + '@octokit/types': 13.5.0 + universal-user-agent: 6.0.1 + '@octokit/request@9.1.3': dependencies: '@octokit/endpoint': 10.1.1 @@ -16046,6 +16159,10 @@ snapshots: '@octokit/types': 13.5.0 universal-user-agent: 7.0.2 + '@octokit/types@12.6.0': + dependencies: + '@octokit/openapi-types': 20.0.0 + '@octokit/types@13.5.0': dependencies: '@octokit/openapi-types': 22.2.0 @@ -18901,6 +19018,10 @@ snapshots: '@types/connect': 3.4.38 '@types/node': 18.19.45 + '@types/bun@1.1.4': + dependencies: + bun-types: 1.1.13 + '@types/concat-stream@2.0.3': dependencies: '@types/node': 18.19.45 @@ -19065,6 +19186,10 @@ snapshots: dependencies: undici-types: 5.26.5 + '@types/node@20.12.14': + dependencies: + undici-types: 5.26.5 + '@types/node@20.16.1': dependencies: undici-types: 6.19.8 @@ -20496,6 +20621,8 @@ snapshots: dependencies: tweetnacl: 0.14.5 + before-after-hook@2.2.3: {} + before-after-hook@3.0.2: {} bent@7.3.12: @@ -20590,6 +20717,11 @@ snapshots: dependencies: semver: 7.5.4 + bun-types@1.1.13: + dependencies: + '@types/node': 20.12.14 + '@types/ws': 8.5.12 + bundle-require@5.0.0(esbuild@0.23.1): dependencies: esbuild: 0.23.1 @@ -21440,6 +21572,8 @@ snapshots: depd@2.0.0: {} + deprecation@2.3.1: {} + dequal@2.0.3: {} destr@2.0.3: {} @@ -28912,6 +29046,8 @@ snapshots: unist-util-is: 6.0.0 unist-util-visit-parents: 6.0.1 + universal-user-agent@6.0.1: {} + universal-user-agent@7.0.2: {} universalify@0.1.2: {}