diff --git a/.github/workflows/process-release.yml b/.github/workflows/process-release.yml new file mode 100644 index 0000000000..1d25c16aec --- /dev/null +++ b/.github/workflows/process-release.yml @@ -0,0 +1,23 @@ +name: Process release +on: + issues: + types: + - closed +jobs: + build: + name: Release + runs-on: ubuntu-20.04 + if: "startsWith(github.event.issue.title, 'chore: release')" + steps: + - uses: actions/checkout@v2 + with: + fetch-depth: 0 + + - name: Setup + id: setup + uses: ./.github/actions/setup + + - run: ./scripts/release/process-release.js + env: + EVENT_NUMBER: ${{ github.event.issue.number }} + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} diff --git a/doc/changelogs/java.md b/doc/changelogs/java.md new file mode 100644 index 0000000000..e69de29bb2 diff --git a/doc/changelogs/javascript.md b/doc/changelogs/javascript.md new file mode 100644 index 0000000000..e69de29bb2 diff --git a/doc/changelogs/php.md b/doc/changelogs/php.md new file mode 100644 index 0000000000..e69de29bb2 diff --git a/package.json b/package.json index 46398a5651..d7d49ba08e 100644 --- a/package.json +++ b/package.json @@ -27,7 +27,8 @@ "playground": "./scripts/multiplexer.sh ${2:-nonverbose} ./scripts/playground.sh ${0:-javascript} ${1:-search}", "specs:fix": "eslint --ext=yml specs/ --fix", "specs:lint": "eslint --ext=yml specs/$0", - "github-actions:lint": "eslint --ext=yml .github/" + "github-actions:lint": "eslint --ext=yml .github/", + "release": "yarn workspace scripts release" }, "devDependencies": { "@openapitools/openapi-generator-cli": "2.4.26", diff --git a/release.config.json b/release.config.json new file mode 100644 index 0000000000..c37c9064e6 --- /dev/null +++ b/release.config.json @@ -0,0 +1,6 @@ +{ + "releasedTag": "released", + "mainBranch": "main", + "owner": "algolia", + "repo": "api-clients-automation" +} diff --git a/scripts/package.json b/scripts/package.json index 61fcdc1a56..46c9110d79 100644 --- a/scripts/package.json +++ b/scripts/package.json @@ -3,12 +3,17 @@ "version": "1.0.0", "scripts": { "build": "tsc", - "setHostsOptions": "yarn build && node dist/setHostsOptions.js" + "release": "yarn build && node dist/scripts/release/create-release-issue.js", + "setHostsOptions": "yarn build && node dist/scripts/pre-gen/setHostsOptions.js" }, "devDependencies": { + "@octokit/rest": "18.12.0", "@types/js-yaml": "4.0.5", "@types/node": "16.11.11", + "dotenv": "16.0.0", + "execa": "5.1.1", "js-yaml": "4.1.0", + "semver": "7.3.5", "typescript": "4.5.4" } } diff --git a/scripts/release/common.ts b/scripts/release/common.ts new file mode 100644 index 0000000000..248b94e422 --- /dev/null +++ b/scripts/release/common.ts @@ -0,0 +1,38 @@ +import execa from 'execa'; // https://github.com/sindresorhus/execa/tree/v5.1.1 + +import openapitools from '../../openapitools.json'; +import config from '../../release.config.json'; + +export const RELEASED_TAG = config.releasedTag; +export const MAIN_BRANCH = config.mainBranch; +export const OWNER = config.owner; +export const REPO = config.repo; + +type Run = ( + command: string, + options?: Partial<{ + errorMessage: string; + }> +) => execa.ExecaReturnBase['stdout']; + +export const run: Run = (command, { errorMessage = undefined } = {}) => { + let result: execa.ExecaSyncReturnValue; + try { + result = execa.commandSync(command); + } catch (err) { + if (errorMessage) { + throw new Error(`[ERROR] ${errorMessage}`); + } else { + throw err; + } + } + return result.stdout; +}; + +export const LANGS = [ + ...new Set( + Object.keys(openapitools['generator-cli'].generators).map( + (key) => key.split('-')[0] + ) + ), +]; diff --git a/scripts/release/create-release-issue.ts b/scripts/release/create-release-issue.ts new file mode 100755 index 0000000000..1e316d72a2 --- /dev/null +++ b/scripts/release/create-release-issue.ts @@ -0,0 +1,225 @@ +/* eslint-disable no-console */ +import { Octokit } from '@octokit/rest'; +import dotenv from 'dotenv'; +import semver from 'semver'; + +import openapitools from '../../openapitools.json'; + +import { RELEASED_TAG, MAIN_BRANCH, OWNER, REPO, LANGS, run } from './common'; +import TEXT from './text'; + +dotenv.config(); + +type Version = { + current: string; + langName: string; + next?: string; + noCommit?: boolean; + skipRelease?: boolean; +}; + +type Versions = { + [lang: string]: Version; +}; + +function readVersions(): Versions { + const versions = {}; + + const generators = openapitools['generator-cli'].generators; + + Object.keys(generators).forEach((generator) => { + const lang = generator.split('-')[0]; + if (!versions[lang]) { + versions[lang] = { + current: generators[generator].additionalProperties.packageVersion, + langName: lang, + next: undefined, + }; + } + }); + return versions; +} + +if (!process.env.GITHUB_TOKEN) { + throw new Error('Environment variable `GITHUB_TOKEN` does not exist.'); +} + +if (run('git rev-parse --abbrev-ref HEAD') !== MAIN_BRANCH) { + throw new Error( + `You can run this script only from \`${MAIN_BRANCH}\` branch.` + ); +} + +if (run('git status --porcelain')) { + throw new Error( + 'Working directory is not clean. Commit all the changes first.' + ); +} + +run(`git rev-parse --verify refs/tags/${RELEASED_TAG}`, { + errorMessage: '`released` tag is missing in this repository.', +}); + +// Reading versions from `openapitools.json` +const versions = readVersions(); + +console.log('Pulling from origin...'); +run(`git pull origin ${MAIN_BRANCH}`); + +console.log('Pushing to origin...'); +run(`git push origin ${MAIN_BRANCH}`); + +const commitsWithoutScope: string[] = []; +const commitsWithNonLanguageScope: string[] = []; + +// Reading commits since last release +type LatestCommit = { + hash: string; + type: string; + lang: string; + message: string; + raw: string; +}; +const latestCommits = run(`git log --oneline ${RELEASED_TAG}..${MAIN_BRANCH}`) + .split('\n') + .filter(Boolean) + .map((commit) => { + const hash = commit.slice(0, 7); + let message = commit.slice(8); + let type = message.slice(0, message.indexOf(':')); + const matchResult = type.match(/(.+)\((.+)\)/); + if (!matchResult) { + commitsWithoutScope.push(commit); + return undefined; + } + message = message.slice(message.indexOf(':') + 1).trim(); + type = matchResult[1]; + const lang = matchResult[2]; + + if (!LANGS.includes(lang)) { + commitsWithNonLanguageScope.push(commit); + return undefined; + } + + return { + hash, + type, // `fix` | `feat` | `chore` | ... + lang, // `javascript` | `php` | `java` | ... + message, + raw: commit, + }; + }) + .filter(Boolean) as LatestCommit[]; + +console.log('[INFO] Skipping these commits due to lack of language scope:'); +console.log(commitsWithoutScope.map((commit) => ` ${commit}`).join('\n')); + +console.log(''); +console.log('[INFO] Skipping these commits due to wrong scopes:'); +console.log( + commitsWithNonLanguageScope.map((commit) => ` ${commit}`).join('\n') +); + +LANGS.forEach((lang) => { + const commits = latestCommits.filter( + (lastestCommit) => lastestCommit.lang === lang + ); + const currentVersion = versions[lang].current; + + if (commits.length === 0) { + versions[lang].next = currentVersion; + versions[lang].noCommit = true; + return; + } + + if (semver.prerelease(currentVersion)) { + // if version is like 0.1.2-beta.1, it increases to 0.1.2-beta.2, even if there's a breaking change. + versions[lang].next = semver.inc(currentVersion, 'prerelease'); + return; + } + + if (commits.some((commit) => commit.message.includes('BREAKING CHANGE'))) { + versions[lang].next = semver.inc(currentVersion, 'major'); + return; + } + + const commitTypes = new Set(commits.map(({ type }) => type)); + if (commitTypes.has('feat')) { + versions[lang].next = semver.inc(currentVersion, 'minor'); + return; + } + + versions[lang].next = semver.inc(currentVersion, 'patch'); + if (!commitTypes.has('fix')) { + versions[lang].skipRelease = true; + } +}); + +const versionChanges = LANGS.map((lang) => { + const { current, next, noCommit, skipRelease, langName } = versions[lang]; + + if (noCommit) { + return `- ~${langName}: v${current} (${TEXT.noCommit})~`; + } + + if (!current) { + return `- ~${langName}: (${TEXT.currentVersionNotFound})~`; + } + + const checked = skipRelease ? ' ' : 'x'; + return [ + `- [${checked}] ${langName}: v${current} -> v${next}`, + skipRelease && TEXT.descriptionForSkippedLang(langName), + ] + .filter(Boolean) + .join('\n'); +}).join('\n'); + +const changelogs = LANGS.filter( + (lang) => !versions[lang].noCommit && versions[lang].current +) + .flatMap((lang) => { + if (versions[lang].noCommit) { + return []; + } + + return [ + `### ${versions[lang].langName}`, + ...latestCommits + .filter((commit) => commit.lang === lang) + .map((commit) => `- ${commit.raw}`), + ]; + }) + .join('\n'); + +const body = [ + TEXT.header, + TEXT.versionChangeHeader, + versionChanges, + TEXT.changelogHeader, + TEXT.changelogDescription, + changelogs, + TEXT.approvalHeader, + TEXT.approval, +].join('\n\n'); + +const octokit = new Octokit({ + auth: `token ${process.env.GITHUB_TOKEN}`, +}); + +octokit.rest.issues + .create({ + owner: OWNER, + repo: REPO, + title: `chore: release ${new Date().toISOString().split('T')[0]}`, + body, + }) + .then((result) => { + const { + data: { number, html_url: url }, + } = result; + + console.log(''); + console.log(`Release issue #${number} is ready for review.`); + console.log(` > ${url}`); + }); diff --git a/scripts/release/process-release.ts b/scripts/release/process-release.ts new file mode 100755 index 0000000000..669c115c56 --- /dev/null +++ b/scripts/release/process-release.ts @@ -0,0 +1,127 @@ +/* eslint-disable no-console */ +import fs from 'fs'; + +import dotenv from 'dotenv'; +import execa from 'execa'; + +import openapitools from '../../openapitools.json'; + +import { MAIN_BRANCH, OWNER, REPO, run } from './common'; +import TEXT from './text'; + +dotenv.config(); + +function getMarkdownSection(markdown: string, title: string): string { + const levelIndicator = title.split(' ')[0]; // e.g. `##` + const lines = markdown.slice(markdown.indexOf(title)).split('\n'); + let endIndex = lines.length; + for (let i = 1; i < lines.length; i++) { + if (lines[i].startsWith(`${levelIndicator} `)) { + endIndex = i; + break; + } + } + return lines.slice(0, endIndex).join('\n'); +} + +if (!process.env.GITHUB_TOKEN) { + throw new Error('Environment variable `GITHUB_TOKEN` does not exist.'); +} + +if (!process.env.EVENT_NUMBER) { + throw new Error('Environment variable `EVENT_NUMBER` does not exist.'); +} + +const issueBody = JSON.parse( + execa.sync('curl', [ + '-H', + `Authorization: token ${process.env.GITHUB_TOKEN}`, + `https://api.github.com/repos/${OWNER}/${REPO}/issues/${process.env.EVENT_NUMBER}`, + ]).stdout +).body; + +if ( + !getMarkdownSection(issueBody, TEXT.approvalHeader) + .split('\n') + .find((line) => line.startsWith(`- [x] ${TEXT.approved}`)) +) { + throw new Error('The issue was not approved.'); +} + +const versionsToRelease = {}; +getMarkdownSection(issueBody, TEXT.versionChangeHeader) + .split('\n') + .forEach((line) => { + const result = line.match(/- \[x\] (.+): v(.+) -> v(.+)/); + if (!result) { + return; + } + const [, lang, current, next] = result; + versionsToRelease[lang] = { + current, + next, + }; + }); + +const langsToUpdateRepo = getMarkdownSection( + issueBody, + TEXT.versionChangeHeader +) + .split('\n') + .map((line) => { + const result = line.match(/- \[ \] (.+): v(.+) -> v(.+)/); + return result?.[1]; + }) + .filter(Boolean); // e.g. ['javascript', 'php'] + +// update versions in `openapitools.json` +Object.keys(openapitools['generator-cli'].generators).forEach((client) => { + const lang = client.split('-')[0]; + if (versionsToRelease[lang]) { + openapitools['generator-cli'].generators[ + client + ].additionalProperties.packageVersion = versionsToRelease[lang].next; + } +}); +fs.writeFileSync('openapitools.json', JSON.stringify(openapitools, null, 2)); + +// update changelogs +new Set([...Object.keys(versionsToRelease), ...langsToUpdateRepo]).forEach( + (lang) => { + const filePath = `doc/changelogs/${lang}.md`; + const header = versionsToRelease[lang!] + ? `## ${versionsToRelease[lang!].next}` + : `## ${new Date().toISOString().split('T')[0]}`; + const newChangelog = getMarkdownSection( + getMarkdownSection(issueBody, TEXT.changelogHeader), + `### ${lang}` + ); + const existingContent = fs.readFileSync(filePath).toString(); + fs.writeFileSync( + filePath, + [header, newChangelog, existingContent].join('\n\n') + ); + } +); + +// commit openapitools and changelogs +run('git config user.name "api-clients-bot"'); +run('git config user.email "bot@algolia.com"'); +run('git add openapitools.json'); +run('git add doc/changelogs/*'); +execa.sync('git', ['commit', '-m', TEXT.commitMessage]); +run(`git push origin ${MAIN_BRANCH}`); + +// generate clients to release +Object.keys(versionsToRelease).forEach((lang) => { + console.log(`Generating ${lang} client(s)...`); + // @ts-expect-error the library `execa` is not typed correctly + run(`yarn generate ${lang}`).pipe(process.stdout); +}); + +// generate clients to just update the repos +langsToUpdateRepo.forEach((lang) => { + console.log(`Generating ${lang} client(s)...`); + // @ts-expect-error the library `execa` is not typed correctly + run(`yarn generate ${lang}`).pipe(process.stdout); +}); diff --git a/scripts/release/text.ts b/scripts/release/text.ts new file mode 100644 index 0000000000..9dfccb3ec5 --- /dev/null +++ b/scripts/release/text.ts @@ -0,0 +1,29 @@ +const APPROVED = `Approved`; + +export default { + header: `## Summary`, + + versionChangeHeader: `## Version Changes`, + noCommit: `no commit`, + currentVersionNotFound: `current version not found`, + descriptionForSkippedLang: (langName: string): string => + [ + ` - No \`feat\` or \`fix\` commit, thus unchecked by default.`, + ` - **Checked** → Update version, update ${langName} repository, and release the library.`, + ` - **Unchecked** → Update ${langName} repository.`, + ` - **Line removed** → Do nothing.`, + ].join('\n'), + + changelogHeader: `## CHANGELOG`, + changelogDescription: `Update the following lines. Once merged, it will be reflected to \`docs/changelogs/*.\``, + + approvalHeader: `## Approval`, + approved: APPROVED, + approval: [ + `To proceed this release, check the box below and close the issue.`, + `To skip this release, just close the issue.`, + `- [ ] ${APPROVED}`, + ].join('\n'), + + commitMessage: `chore: update versions and changelogs`, +}; diff --git a/scripts/tsconfig.json b/scripts/tsconfig.json index b3bc49dad5..20c3f4903a 100644 --- a/scripts/tsconfig.json +++ b/scripts/tsconfig.json @@ -4,6 +4,6 @@ "typeRoots": ["../node_modules/@types"], "outDir": "dist" }, - "include": ["pre-gen/setHostsOptions.ts"], + "include": ["pre-gen/setHostsOptions.ts", "release/*"], "exclude": ["dist", "*.json"] } diff --git a/yarn.lock b/yarn.lock index b884e921d8..69fff3a224 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1008,6 +1008,137 @@ __metadata: languageName: node linkType: hard +"@octokit/auth-token@npm:^2.4.4": + version: 2.5.0 + resolution: "@octokit/auth-token@npm:2.5.0" + dependencies: + "@octokit/types": ^6.0.3 + checksum: 45949296c09abcd6beb4c3f69d45b0c1f265f9581d2a9683cf4d1800c4cf8259c2f58d58e44c16c20bffb85a0282a176c0d51f4af300e428b863f27b910e6297 + languageName: node + linkType: hard + +"@octokit/core@npm:^3.5.1": + version: 3.5.1 + resolution: "@octokit/core@npm:3.5.1" + dependencies: + "@octokit/auth-token": ^2.4.4 + "@octokit/graphql": ^4.5.8 + "@octokit/request": ^5.6.0 + "@octokit/request-error": ^2.0.5 + "@octokit/types": ^6.0.3 + before-after-hook: ^2.2.0 + universal-user-agent: ^6.0.0 + checksum: 67179739fc9712b201f2400f132287a2c56a18506e00900bc9d2a3f742b74f1ba69ad998e42f28f3964c0bd1d5478232c1ec7b485c97702b821fbe22b76afa90 + languageName: node + linkType: hard + +"@octokit/endpoint@npm:^6.0.1": + version: 6.0.12 + resolution: "@octokit/endpoint@npm:6.0.12" + dependencies: + "@octokit/types": ^6.0.3 + is-plain-object: ^5.0.0 + universal-user-agent: ^6.0.0 + checksum: b48b29940af11c4b9bca41cf56809754bb8385d4e3a6122671799d27f0238ba575b3fde86d2d30a84f4dbbc14430940de821e56ecc6a9a92d47fc2b29a31479d + languageName: node + linkType: hard + +"@octokit/graphql@npm:^4.5.8": + version: 4.8.0 + resolution: "@octokit/graphql@npm:4.8.0" + dependencies: + "@octokit/request": ^5.6.0 + "@octokit/types": ^6.0.3 + universal-user-agent: ^6.0.0 + checksum: f68afe53f63900d4a16a0a733f2f500df2695b731f8ed32edb728d50edead7f5011437f71d069c2d2f6d656227703d0c832a3c8af58ecf82bd5dcc051f2d2d74 + languageName: node + linkType: hard + +"@octokit/openapi-types@npm:^11.2.0": + version: 11.2.0 + resolution: "@octokit/openapi-types@npm:11.2.0" + checksum: eb373ea496bc96bf0233505a0916eb38cb193d1829cab935e1cf1fd21839c402a1d835d3c0326290c756c0ed980a64d0ae73ad3c5d5decde9000f0828aa7ff52 + languageName: node + linkType: hard + +"@octokit/plugin-paginate-rest@npm:^2.16.8": + version: 2.17.0 + resolution: "@octokit/plugin-paginate-rest@npm:2.17.0" + dependencies: + "@octokit/types": ^6.34.0 + peerDependencies: + "@octokit/core": ">=2" + checksum: c8753cda6f7ede79d0e9df43a54e56020aa1c9c6887684e0e0d45cb6ee0dcabf460c3e4b8a18edabef711bb269fd826616e99e78dc29fb30d47c210c562603a0 + languageName: node + linkType: hard + +"@octokit/plugin-request-log@npm:^1.0.4": + version: 1.0.4 + resolution: "@octokit/plugin-request-log@npm:1.0.4" + peerDependencies: + "@octokit/core": ">=3" + checksum: 2086db00056aee0f8ebd79797b5b57149ae1014e757ea08985b71eec8c3d85dbb54533f4fd34b6b9ecaa760904ae6a7536be27d71e50a3782ab47809094bfc0c + languageName: node + linkType: hard + +"@octokit/plugin-rest-endpoint-methods@npm:^5.12.0": + version: 5.13.0 + resolution: "@octokit/plugin-rest-endpoint-methods@npm:5.13.0" + dependencies: + "@octokit/types": ^6.34.0 + deprecation: ^2.3.1 + peerDependencies: + "@octokit/core": ">=3" + checksum: f331457e4317130adb456b27df2a99609fb54a4dc2da6f87009e567c7325680c901abf18ad08483535bab4ec1c892e4236f4135a2804603aebb12c0698c678c8 + languageName: node + linkType: hard + +"@octokit/request-error@npm:^2.0.5, @octokit/request-error@npm:^2.1.0": + version: 2.1.0 + resolution: "@octokit/request-error@npm:2.1.0" + dependencies: + "@octokit/types": ^6.0.3 + deprecation: ^2.0.0 + once: ^1.4.0 + checksum: baec2b5700498be01b4d958f9472cb776b3f3b0ea52924323a07e7a88572e24cac2cdf7eb04a0614031ba346043558b47bea2d346e98f0e8385b4261f138ef18 + languageName: node + linkType: hard + +"@octokit/request@npm:^5.6.0": + version: 5.6.3 + resolution: "@octokit/request@npm:5.6.3" + dependencies: + "@octokit/endpoint": ^6.0.1 + "@octokit/request-error": ^2.1.0 + "@octokit/types": ^6.16.1 + is-plain-object: ^5.0.0 + node-fetch: ^2.6.7 + universal-user-agent: ^6.0.0 + checksum: c0b4542eb4baaf880d673c758d3e0b5c4a625a4ae30abf40df5548b35f1ff540edaac74625192b1aff42a79ac661e774da4ab7d5505f1cb4ef81239b1e8510c5 + languageName: node + linkType: hard + +"@octokit/rest@npm:18.12.0": + version: 18.12.0 + resolution: "@octokit/rest@npm:18.12.0" + dependencies: + "@octokit/core": ^3.5.1 + "@octokit/plugin-paginate-rest": ^2.16.8 + "@octokit/plugin-request-log": ^1.0.4 + "@octokit/plugin-rest-endpoint-methods": ^5.12.0 + checksum: c18bd6676a60b66819b016b0f969fcd04d8dfa04d01b7af9af9a7410ff028c621c995185e29454c23c47906da506c1e01620711259989a964ebbfd9106f5b715 + languageName: node + linkType: hard + +"@octokit/types@npm:^6.0.3, @octokit/types@npm:^6.16.1, @octokit/types@npm:^6.34.0": + version: 6.34.0 + resolution: "@octokit/types@npm:6.34.0" + dependencies: + "@octokit/openapi-types": ^11.2.0 + checksum: f122b9aee8f6baddd515e34a0913e73b21d4bc82d6ee59d77a8aaf01b4a02c10867dd013003d087a83dc96db23511893669015af6d30c27cece185e21cf1df89 + languageName: node + linkType: hard + "@openapitools/openapi-generator-cli@npm:2.4.26": version: 2.4.26 resolution: "@openapitools/openapi-generator-cli@npm:2.4.26" @@ -1814,6 +1945,13 @@ __metadata: languageName: node linkType: hard +"before-after-hook@npm:^2.2.0": + version: 2.2.2 + resolution: "before-after-hook@npm:2.2.2" + checksum: dc2e1ffe389e5afbef2a46790b1b5a50247ed57aba67649cfa9ec2552d248cc9278f222e72fb5a8ff59bbb39d78fbaa97e7234ead0c6b5e8418b67a8644ce207 + languageName: node + linkType: hard + "binary-extensions@npm:^2.0.0": version: 2.2.0 resolution: "binary-extensions@npm:2.2.0" @@ -2423,6 +2561,13 @@ __metadata: languageName: node linkType: hard +"deprecation@npm:^2.0.0, deprecation@npm:^2.3.1": + version: 2.3.1 + resolution: "deprecation@npm:2.3.1" + checksum: f56a05e182c2c195071385455956b0c4106fe14e36245b00c689ceef8e8ab639235176a96977ba7c74afb173317fac2e0ec6ec7a1c6d1e6eaa401c586c714132 + languageName: node + linkType: hard + "detect-newline@npm:^3.0.0": version: 3.1.0 resolution: "detect-newline@npm:3.1.0" @@ -2487,6 +2632,13 @@ __metadata: languageName: node linkType: hard +"dotenv@npm:16.0.0": + version: 16.0.0 + resolution: "dotenv@npm:16.0.0" + checksum: 664cebb51f0a9a1d1b930f51f0271e72e26d62feaecc9dc03df39453dd494b4e724809ca480fb3ec3213382b1ed3f791aaeb83569a137f9329ce58efd4853dbf + languageName: node + linkType: hard + "easy-table@npm:1.1.0": version: 1.1.0 resolution: "easy-table@npm:1.1.0" @@ -2951,7 +3103,7 @@ __metadata: languageName: node linkType: hard -"execa@npm:^5.0.0": +"execa@npm:5.1.1, execa@npm:^5.0.0": version: 5.1.1 resolution: "execa@npm:5.1.1" dependencies: @@ -3765,6 +3917,13 @@ __metadata: languageName: node linkType: hard +"is-plain-object@npm:^5.0.0": + version: 5.0.0 + resolution: "is-plain-object@npm:5.0.0" + checksum: e32d27061eef62c0847d303125440a38660517e586f2f3db7c9d179ae5b6674ab0f469d519b2e25c147a1a3bc87156d0d5f4d8821e0ce4a9ee7fe1fcf11ce45c + languageName: node + linkType: hard + "is-potential-custom-element-name@npm:^1.0.1": version: 1.0.1 resolution: "is-potential-custom-element-name@npm:1.0.1" @@ -4981,6 +5140,20 @@ __metadata: languageName: node linkType: hard +"node-fetch@npm:^2.6.7": + version: 2.6.7 + resolution: "node-fetch@npm:2.6.7" + dependencies: + whatwg-url: ^5.0.0 + peerDependencies: + encoding: ^0.1.0 + peerDependenciesMeta: + encoding: + optional: true + checksum: 8d816ffd1ee22cab8301c7756ef04f3437f18dace86a1dae22cf81db8ef29c0bf6655f3215cb0cdb22b420b6fe141e64b26905e7f33f9377a7fa59135ea3e10b + languageName: node + linkType: hard + "node-gyp@npm:latest": version: 8.4.1 resolution: "node-gyp@npm:8.4.1" @@ -5105,7 +5278,7 @@ __metadata: languageName: node linkType: hard -"once@npm:^1.3.0": +"once@npm:^1.3.0, once@npm:^1.4.0": version: 1.4.0 resolution: "once@npm:1.4.0" dependencies: @@ -5709,14 +5882,18 @@ __metadata: version: 0.0.0-use.local resolution: "scripts@workspace:scripts" dependencies: + "@octokit/rest": 18.12.0 "@types/js-yaml": 4.0.5 "@types/node": 16.11.11 + dotenv: 16.0.0 + execa: 5.1.1 js-yaml: 4.1.0 + semver: 7.3.5 typescript: 4.5.4 languageName: unknown linkType: soft -"semver@npm:7.x, semver@npm:^7.2.1, semver@npm:^7.3.2, semver@npm:^7.3.5": +"semver@npm:7.3.5, semver@npm:7.x, semver@npm:^7.2.1, semver@npm:^7.3.2, semver@npm:^7.3.5": version: 7.3.5 resolution: "semver@npm:7.3.5" dependencies: @@ -6463,6 +6640,13 @@ __metadata: languageName: node linkType: hard +"universal-user-agent@npm:^6.0.0": + version: 6.0.0 + resolution: "universal-user-agent@npm:6.0.0" + checksum: 5092bbc80dd0d583cef0b62c17df0043193b74f425112ea6c1f69bc5eda21eeec7a08d8c4f793a277eb2202ffe9b44bec852fa3faff971234cd209874d1b79ef + languageName: node + linkType: hard + "universalify@npm:^0.1.2": version: 0.1.2 resolution: "universalify@npm:0.1.2"