From ec73824ba13d70538a30a31a11b8430519592079 Mon Sep 17 00:00:00 2001 From: "Gavin Barron (from Dev Box)" Date: Fri, 9 Oct 2026 11:24:09 -0700 Subject: [PATCH 1/4] fix(hidi): automate independent main version PRs Apply exact-file release routing through the pinned release-please plugin API. Keep OData releases unchanged and maintain isolated Hidi version PR checkpoints without creating production tags or releases. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> Copilot-Session: 5aef9099-c268-492f-a58a-b591c916f1bc --- .github/release-please/package-lock.json | 1855 ++++++++++++++++++++++ .github/release-please/package.json | 12 + .github/release-please/run.cjs | 167 ++ .github/release-please/run.test.cjs | 348 ++++ .github/workflows/release-please-gha.yml | 62 +- .github/workflows/sonarcloud.yml | 19 +- CONTRIBUTING.md | 54 +- README.md | 3 + hidi-release-please-config.json | 14 +- release-please-config.json | 3 + src/Microsoft.OpenApi.Hidi/readme.md | 4 +- 11 files changed, 2520 insertions(+), 21 deletions(-) create mode 100644 .github/release-please/package-lock.json create mode 100644 .github/release-please/package.json create mode 100644 .github/release-please/run.cjs create mode 100644 .github/release-please/run.test.cjs diff --git a/.github/release-please/package-lock.json b/.github/release-please/package-lock.json new file mode 100644 index 000000000..ed84c9cb2 --- /dev/null +++ b/.github/release-please/package-lock.json @@ -0,0 +1,1855 @@ +{ + "name": "openapi-odata-release-automation", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "name": "openapi-odata-release-automation", + "dependencies": { + "@actions/core": "1.11.1", + "release-please": "17.6.0" + } + }, + "node_modules/@actions/core": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@actions/core/-/core-1.11.1.tgz", + "integrity": "sha512-hXJCSrkwfA46Vd9Z3q4cpEpHB1rL5NG04+/rbqW9d3+CSvtB1tYe8UTpAlixa1vj0m/ULglfEK2UKxMGxCxv5A==", + "dependencies": { + "@actions/exec": "^1.1.1", + "@actions/http-client": "^2.0.1" + } + }, + "node_modules/@actions/exec": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@actions/exec/-/exec-1.1.1.tgz", + "integrity": "sha512-+sCcHHbVdk93a0XT19ECtO/gIXoxvdsgQLzb2fE2/5sIZmWQuluYyjPQtrtTHdU1YzTZ7bAPN4sITq2xi1679w==", + "dependencies": { + "@actions/io": "^1.0.1" + } + }, + "node_modules/@actions/http-client": { + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/@actions/http-client/-/http-client-2.2.3.tgz", + "integrity": "sha512-mx8hyJi/hjFvbPokCg4uRd4ZX78t+YyRPtnKWwIl+RzNaVuFpQHfmlGVfsKEJN8LwTCvL+DfVgAM04XaHkm6bA==", + "dependencies": { + "tunnel": "^0.0.6", + "undici": "^5.25.4" + } + }, + "node_modules/@actions/io": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/@actions/io/-/io-1.1.3.tgz", + "integrity": "sha512-wi9JjgKLYS7U/z8PPbco+PvTb/nRWjeoFlJ1Qer83k/3C5PHQi28hiVdeE2kHXmIL99mQFawx8qt/JPjZilJ8Q==" + }, + "node_modules/@babel/code-frame": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.29.7.tgz", + "integrity": "sha512-Aup7aUOfpbAUg2ROOJN6Iw5f9DMBlzu0mIkm/malLQFN/YQgO48wCj0Kxa3sEHJvPVFg7siR+qRInwXd2qhQKw==", + "dependencies": { + "@babel/helper-validator-identifier": "^7.29.7", + "js-tokens": "^4.0.0", + "picocolors": "^1.1.1" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-validator-identifier": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.29.7.tgz", + "integrity": "sha512-qehxGkRj55h/ff8EMaJ+cYhyaKlHIxqYDn682wQD7RNp9UujOQsHog2uS0r2vzr4pW+sXf90NeeayjcNaX3fFg==", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@conventional-commits/parser": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/@conventional-commits/parser/-/parser-0.4.1.tgz", + "integrity": "sha512-H2ZmUVt6q+KBccXfMBhbBF14NlANeqHTXL4qCL6QGbMzrc4HDXyzWuxPxPNbz71f/5UkR5DrycP5VO9u7crahg==", + "dependencies": { + "unist-util-visit": "^2.0.3", + "unist-util-visit-parents": "^3.1.1" + } + }, + "node_modules/@fastify/busboy": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/@fastify/busboy/-/busboy-2.1.1.tgz", + "integrity": "sha512-vBZP4NlzfOlerQTnba4aqZoMhE/a9HY7HRqoOPaETQcSQuWEIyZMHGfVu6w9wGtGK5fED5qRs2DteVCjOH60sA==", + "engines": { + "node": ">=14" + } + }, + "node_modules/@google-automations/git-file-utils": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/@google-automations/git-file-utils/-/git-file-utils-3.2.1.tgz", + "integrity": "sha512-LYOjAnGu/xtEkYYh6W3/1RmeK9HB/fV+xMe7nHc+WiDYrnxAJWBfcyUucoJtYS8XAhVUzNWrQvYDPRbxe67DNQ==", + "dependencies": { + "@octokit/rest": "^20.1.1", + "minimatch": "^10.2.4" + }, + "engines": { + "node": ">= 22" + } + }, + "node_modules/@iarna/toml": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@iarna/toml/-/toml-3.0.0.tgz", + "integrity": "sha512-td6ZUkz2oS3VeleBcN+m//Q6HlCFCPrnI0FZhrt/h4XqLEdOyYp2u21nd8MdsR+WJy5r9PTDaHTDDfhf4H4l6Q==" + }, + "node_modules/@jsep-plugin/assignment": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/@jsep-plugin/assignment/-/assignment-1.3.0.tgz", + "integrity": "sha512-VVgV+CXrhbMI3aSusQyclHkenWSAm95WaiKrMxRFam3JSUiIaQjoMIw2sEs/OX4XifnqeQUN4DYbJjlA8EfktQ==", + "engines": { + "node": ">= 10.16.0" + }, + "peerDependencies": { + "jsep": "^0.4.0||^1.0.0" + } + }, + "node_modules/@jsep-plugin/regex": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/@jsep-plugin/regex/-/regex-1.0.4.tgz", + "integrity": "sha512-q7qL4Mgjs1vByCaTnDFcBnV9HS7GVPJX5vyVoCgZHNSC9rjwIlmbXG5sUuorR5ndfHAIlJ8pVStxvjXHbNvtUg==", + "engines": { + "node": ">= 10.16.0" + }, + "peerDependencies": { + "jsep": "^0.4.0||^1.0.0" + } + }, + "node_modules/@octokit/auth-token": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/@octokit/auth-token/-/auth-token-4.0.0.tgz", + "integrity": "sha512-tY/msAuJo6ARbK6SPIxZrPBms3xPbfwBrulZe0Wtr/DIY9lje2HeV1uoebShn6mx7SjCHif6EjMvoREj+gZ+SA==", + "engines": { + "node": ">= 18" + } + }, + "node_modules/@octokit/core": { + "version": "5.2.2", + "resolved": "https://registry.npmjs.org/@octokit/core/-/core-5.2.2.tgz", + "integrity": "sha512-/g2d4sW9nUDJOMz3mabVQvOGhVa4e/BN/Um7yca9Bb2XTzPPnfTWHWQg+IsEYO7M3Vx+EXvaM/I2pJWIMun1bg==", + "dependencies": { + "@octokit/auth-token": "^4.0.0", + "@octokit/graphql": "^7.1.0", + "@octokit/request": "^8.4.1", + "@octokit/request-error": "^5.1.1", + "@octokit/types": "^13.0.0", + "before-after-hook": "^2.2.0", + "universal-user-agent": "^6.0.0" + }, + "engines": { + "node": ">= 18" + } + }, + "node_modules/@octokit/endpoint": { + "version": "9.0.6", + "resolved": "https://registry.npmjs.org/@octokit/endpoint/-/endpoint-9.0.6.tgz", + "integrity": "sha512-H1fNTMA57HbkFESSt3Y9+FBICv+0jFceJFPWDePYlR/iMGrwM5ph+Dd4XRQs+8X+PUFURLQgX9ChPfhJ/1uNQw==", + "dependencies": { + "@octokit/types": "^13.1.0", + "universal-user-agent": "^6.0.0" + }, + "engines": { + "node": ">= 18" + } + }, + "node_modules/@octokit/graphql": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/@octokit/graphql/-/graphql-7.1.1.tgz", + "integrity": "sha512-3mkDltSfcDUoa176nlGoA32RGjeWjl3K7F/BwHwRMJUW/IteSa4bnSV8p2ThNkcIcZU2umkZWxwETSSCJf2Q7g==", + "dependencies": { + "@octokit/request": "^8.4.1", + "@octokit/types": "^13.0.0", + "universal-user-agent": "^6.0.0" + }, + "engines": { + "node": ">= 18" + } + }, + "node_modules/@octokit/openapi-types": { + "version": "24.2.0", + "resolved": "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-24.2.0.tgz", + "integrity": "sha512-9sIH3nSUttelJSXUrmGzl7QUBFul0/mB8HRYl3fOlgHbIWG+WnYDXU3v/2zMtAvuzZ/ed00Ei6on975FhBfzrg==" + }, + "node_modules/@octokit/plugin-paginate-rest": { + "version": "11.4.4-cjs.2", + "resolved": "https://registry.npmjs.org/@octokit/plugin-paginate-rest/-/plugin-paginate-rest-11.4.4-cjs.2.tgz", + "integrity": "sha512-2dK6z8fhs8lla5PaOTgqfCGBxgAv/le+EhPs27KklPhm1bKObpu6lXzwfUEQ16ajXzqNrKMujsFyo9K2eaoISw==", + "dependencies": { + "@octokit/types": "^13.7.0" + }, + "engines": { + "node": ">= 18" + }, + "peerDependencies": { + "@octokit/core": "5" + } + }, + "node_modules/@octokit/plugin-request-log": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/@octokit/plugin-request-log/-/plugin-request-log-4.0.1.tgz", + "integrity": "sha512-GihNqNpGHorUrO7Qa9JbAl0dbLnqJVrV8OXe2Zm5/Y4wFkZQDfTreBzVmiRfJVfE4mClXdihHnbpyyO9FSX4HA==", + "engines": { + "node": ">= 18" + }, + "peerDependencies": { + "@octokit/core": "5" + } + }, + "node_modules/@octokit/plugin-rest-endpoint-methods": { + "version": "13.3.2-cjs.1", + "resolved": "https://registry.npmjs.org/@octokit/plugin-rest-endpoint-methods/-/plugin-rest-endpoint-methods-13.3.2-cjs.1.tgz", + "integrity": "sha512-VUjIjOOvF2oELQmiFpWA1aOPdawpyaCUqcEBc/UOUnj3Xp6DJGrJ1+bjUIIDzdHjnFNO6q57ODMfdEZnoBkCwQ==", + "dependencies": { + "@octokit/types": "^13.8.0" + }, + "engines": { + "node": ">= 18" + }, + "peerDependencies": { + "@octokit/core": "^5" + } + }, + "node_modules/@octokit/request": { + "version": "8.4.1", + "resolved": "https://registry.npmjs.org/@octokit/request/-/request-8.4.1.tgz", + "integrity": "sha512-qnB2+SY3hkCmBxZsR/MPCybNmbJe4KAlfWErXq+rBKkQJlbjdJeS85VI9r8UqeLYLvnAenU8Q1okM/0MBsAGXw==", + "dependencies": { + "@octokit/endpoint": "^9.0.6", + "@octokit/request-error": "^5.1.1", + "@octokit/types": "^13.1.0", + "universal-user-agent": "^6.0.0" + }, + "engines": { + "node": ">= 18" + } + }, + "node_modules/@octokit/request-error": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/@octokit/request-error/-/request-error-5.1.1.tgz", + "integrity": "sha512-v9iyEQJH6ZntoENr9/yXxjuezh4My67CBSu9r6Ve/05Iu5gNgnisNWOsoJHTP6k0Rr0+HQIpnH+kyammu90q/g==", + "dependencies": { + "@octokit/types": "^13.1.0", + "deprecation": "^2.0.0", + "once": "^1.4.0" + }, + "engines": { + "node": ">= 18" + } + }, + "node_modules/@octokit/rest": { + "version": "20.1.2", + "resolved": "https://registry.npmjs.org/@octokit/rest/-/rest-20.1.2.tgz", + "integrity": "sha512-GmYiltypkHHtihFwPRxlaorG5R9VAHuk/vbszVoRTGXnAsY60wYLkh/E2XiFmdZmqrisw+9FaazS1i5SbdWYgA==", + "dependencies": { + "@octokit/core": "^5.0.2", + "@octokit/plugin-paginate-rest": "11.4.4-cjs.2", + "@octokit/plugin-request-log": "^4.0.0", + "@octokit/plugin-rest-endpoint-methods": "13.3.2-cjs.1" + }, + "engines": { + "node": ">= 18" + } + }, + "node_modules/@octokit/types": { + "version": "13.10.0", + "resolved": "https://registry.npmjs.org/@octokit/types/-/types-13.10.0.tgz", + "integrity": "sha512-ifLaO34EbbPj0Xgro4G5lP5asESjwHracYJvVaPIyXMuiuXLlhic3S47cBdTb+jfODkTE5YtGCLt3Ay3+J97sA==", + "dependencies": { + "@octokit/openapi-types": "^24.2.0" + } + }, + "node_modules/@types/minimist": { + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/@types/minimist/-/minimist-1.2.5.tgz", + "integrity": "sha512-hov8bUuiLiyFPGyFPE1lwWhmzYbirOXQNNo40+y3zow8aFVTeyn3VWL0VFFfdNddA8S4Vf0Tc062rzyNr7Paag==" + }, + "node_modules/@types/normalize-package-data": { + "version": "2.4.4", + "resolved": "https://registry.npmjs.org/@types/normalize-package-data/-/normalize-package-data-2.4.4.tgz", + "integrity": "sha512-37i+OaWTh9qeK4LSHPsyRC7NahnGotNuZvjLSgcPzblpHB3rrCJxAOgI5gCdKm7coonsaX1Of0ILiTcnZjbfxA==" + }, + "node_modules/@types/npm-package-arg": { + "version": "6.1.4", + "resolved": "https://registry.npmjs.org/@types/npm-package-arg/-/npm-package-arg-6.1.4.tgz", + "integrity": "sha512-vDgdbMy2QXHnAruzlv68pUtXCjmqUk3WrBAsRboRovsOmxbfn/WiYCjmecyKjGztnMps5dWp4Uq2prp+Ilo17Q==" + }, + "node_modules/@types/unist": { + "version": "2.0.11", + "resolved": "https://registry.npmjs.org/@types/unist/-/unist-2.0.11.tgz", + "integrity": "sha512-CmBKiL6NNo/OqgmMn95Fk9Whlp2mtvIv+KNpQKN2F4SjvrEesubTRWGYSg+BnWZOnlCaSTU1sMpsBOzgbYhnsA==" + }, + "node_modules/@types/yargs": { + "version": "16.0.11", + "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-16.0.11.tgz", + "integrity": "sha512-sbtvk8wDN+JvEdabmZExoW/HNr1cB7D/j4LT08rMiuikfA7m/JNJg7ATQcgzs34zHnoScDkY0ZRSl29Fkmk36g==", + "dependencies": { + "@types/yargs-parser": "*" + } + }, + "node_modules/@types/yargs-parser": { + "version": "21.0.3", + "resolved": "https://registry.npmjs.org/@types/yargs-parser/-/yargs-parser-21.0.3.tgz", + "integrity": "sha512-I4q9QU9MQv4oEOz4tAHJtNz1cwuLxn2F3xcc2iV5WdqLPpUnj30aUuxt1mAxYTG+oe8CZMV/+6rU4S4gRDzqtQ==" + }, + "node_modules/@xmldom/xmldom": { + "version": "0.8.15", + "resolved": "https://registry.npmjs.org/@xmldom/xmldom/-/xmldom-0.8.15.tgz", + "integrity": "sha512-/5NV/vDALVFDXgLmfsy9TRCBlKwO2LNBFzpzvb9iIj+jR+eSc6DLYYvVOdivT/jm7MtU6TebYuRmzEOI7w40UA==", + "engines": { + "node": ">=10.0.0" + } + }, + "node_modules/agent-base": { + "version": "7.1.4", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-7.1.4.tgz", + "integrity": "sha512-MnA+YT8fwfJPgBx3m60MNqakm30XOkyIoH1y6huTQvC0PwZG7ki8NacLBcrPbNoo8vEZy7Jpuk7+jMO+CUovTQ==", + "engines": { + "node": ">= 14" + } + }, + "node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "engines": { + "node": ">=8" + } + }, + "node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/argparse": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==" + }, + "node_modules/array-ify": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/array-ify/-/array-ify-1.0.0.tgz", + "integrity": "sha512-c5AMf34bKdvPhQ7tBGhqkgKNUzMr4WUs+WDtC2ZUGOUncbxKMTvqxYctiseW3+L4bA8ec+GcZ6/A/FW4m8ukng==" + }, + "node_modules/arrify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/arrify/-/arrify-1.0.1.tgz", + "integrity": "sha512-3CYzex9M9FGQjCGMGyi6/31c8GJbgb0qGyrx5HWxPd0aCwh4cB2YjMb2Xf9UuoogrMrlO9cTqnB5rI5GHZTcUA==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/async-retry": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/async-retry/-/async-retry-1.3.3.tgz", + "integrity": "sha512-wfr/jstw9xNi/0teMHrRW7dsz3Lt5ARhYNZ2ewpadnhaIp5mbALhOAP+EAdsC7t4Z6wqsDVv9+W6gm1Dk9mEyw==", + "dependencies": { + "retry": "0.13.1" + } + }, + "node_modules/balanced-match": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-4.0.4.tgz", + "integrity": "sha512-BLrgEcRTwX2o6gGxGOCNyMvGSp35YofuYzw9h1IMTRmKqttAZZVU67bdb9Pr2vUHA8+j3i2tJfjO6C6+4myGTA==", + "engines": { + "node": "18 || 20 || >=22" + } + }, + "node_modules/before-after-hook": { + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/before-after-hook/-/before-after-hook-2.2.3.tgz", + "integrity": "sha512-NzUnlZexiaH/46WDhANlyR2bXRopNg4F/zuSA3OpZnllCUgRaOF2znDioDWrmbNVsuZk6l9pMquQB38cfBZwkQ==" + }, + "node_modules/boolbase": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/boolbase/-/boolbase-1.0.0.tgz", + "integrity": "sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww==" + }, + "node_modules/brace-expansion": { + "version": "5.0.12", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-5.0.12.tgz", + "integrity": "sha512-YovQ3rzhaLMIrDjNDMkNS01tea93qhEhG5xy8f6+R0l+dw3Ki+5sCoIoI942iuLZTHWogWktgwVDhU09iNEimQ==", + "dependencies": { + "balanced-match": "^4.0.2" + }, + "engines": { + "node": "20 || >=22" + } + }, + "node_modules/camelcase": { + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", + "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", + "engines": { + "node": ">=6" + } + }, + "node_modules/camelcase-keys": { + "version": "6.2.2", + "resolved": "https://registry.npmjs.org/camelcase-keys/-/camelcase-keys-6.2.2.tgz", + "integrity": "sha512-YrwaA0vEKazPBkn0ipTiMpSajYDSe+KjQfrjhcBMxJt/znbvlHd8Pw/Vamaz5EB4Wfhs3SUR3Z9mwRu/P3s3Yg==", + "dependencies": { + "camelcase": "^5.3.1", + "map-obj": "^4.0.0", + "quick-lru": "^4.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/cliui": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz", + "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==", + "dependencies": { + "string-width": "^4.2.0", + "strip-ansi": "^6.0.1", + "wrap-ansi": "^7.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/code-suggester": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/code-suggester/-/code-suggester-5.0.1.tgz", + "integrity": "sha512-8qJiiSCfkbPNWvjEFzdG1UW3axL+Bs0ldV1/TdlBKmF9I/a/WooSQZQCi9M44HoXbVTQesn/IQr6+nIWNnVIWA==", + "dependencies": { + "@octokit/rest": "^20.1.2", + "@types/yargs": "^16.0.0", + "async-retry": "^1.3.1", + "diff": "^8.0.3", + "glob": "^7.1.6", + "parse-diff": "^0.11.0", + "yargs": "^16.0.0" + }, + "bin": { + "code-suggester": "build/src/bin/code-suggester.js" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/code-suggester/node_modules/cliui": { + "version": "7.0.4", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-7.0.4.tgz", + "integrity": "sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==", + "dependencies": { + "string-width": "^4.2.0", + "strip-ansi": "^6.0.0", + "wrap-ansi": "^7.0.0" + } + }, + "node_modules/code-suggester/node_modules/yargs": { + "version": "16.2.2", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-16.2.2.tgz", + "integrity": "sha512-Nt9ZJjXTv5R8MHbqby/wXQ6Gi0Bb3TcYZkR1bzuL4yB2OxWPkXknz513gEF0GoA6tn00UpbPvERW8rzCuWCA6w==", + "dependencies": { + "cliui": "^7.0.2", + "escalade": "^3.1.1", + "get-caller-file": "^2.0.5", + "require-directory": "^2.1.1", + "string-width": "^4.2.0", + "y18n": "^5.0.5", + "yargs-parser": "^20.2.2" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" + }, + "node_modules/compare-func": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/compare-func/-/compare-func-2.0.0.tgz", + "integrity": "sha512-zHig5N+tPWARooBnb0Zx1MFcdfpyJrfTJ3Y5L+IFvUm8rM74hHz66z0gw0x4tijh5CorKkKUCnW82R2vmpeCRA==", + "dependencies": { + "array-ify": "^1.0.0", + "dot-prop": "^5.1.0" + } + }, + "node_modules/concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==" + }, + "node_modules/conventional-changelog-conventionalcommits": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/conventional-changelog-conventionalcommits/-/conventional-changelog-conventionalcommits-6.1.0.tgz", + "integrity": "sha512-3cS3GEtR78zTfMzk0AizXKKIdN4OvSh7ibNz6/DPbhWWQu7LqE/8+/GqSodV+sywUR2gpJAdP/1JFf4XtN7Zpw==", + "dependencies": { + "compare-func": "^2.0.0" + }, + "engines": { + "node": ">=14" + } + }, + "node_modules/conventional-changelog-writer": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/conventional-changelog-writer/-/conventional-changelog-writer-6.0.1.tgz", + "integrity": "sha512-359t9aHorPw+U+nHzUXHS5ZnPBOizRxfQsWT5ZDHBfvfxQOAik+yfuhKXG66CN5LEWPpMNnIMHUTCKeYNprvHQ==", + "dependencies": { + "conventional-commits-filter": "^3.0.0", + "dateformat": "^3.0.3", + "handlebars": "^4.7.7", + "json-stringify-safe": "^5.0.1", + "meow": "^8.1.2", + "semver": "^7.0.0", + "split": "^1.0.1" + }, + "bin": { + "conventional-changelog-writer": "cli.js" + }, + "engines": { + "node": ">=14" + } + }, + "node_modules/conventional-commits-filter": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/conventional-commits-filter/-/conventional-commits-filter-3.0.0.tgz", + "integrity": "sha512-1ymej8b5LouPx9Ox0Dw/qAO2dVdfpRFq28e5Y0jJEU8ZrLdy0vOSkkIInwmxErFGhg6SALro60ZrwYFVTUDo4Q==", + "dependencies": { + "lodash.ismatch": "^4.4.0", + "modify-values": "^1.0.1" + }, + "engines": { + "node": ">=14" + } + }, + "node_modules/css-select": { + "version": "5.2.2", + "resolved": "https://registry.npmjs.org/css-select/-/css-select-5.2.2.tgz", + "integrity": "sha512-TizTzUddG/xYLA3NXodFM0fSbNizXjOKhqiQQwvhlspadZokn1KDy0NZFS0wuEubIYAV5/c1/lAr0TaaFXEXzw==", + "dependencies": { + "boolbase": "^1.0.0", + "css-what": "^6.1.0", + "domhandler": "^5.0.2", + "domutils": "^3.0.1", + "nth-check": "^2.0.1" + }, + "funding": { + "url": "https://github.com/sponsors/fb55" + } + }, + "node_modules/css-what": { + "version": "6.2.2", + "resolved": "https://registry.npmjs.org/css-what/-/css-what-6.2.2.tgz", + "integrity": "sha512-u/O3vwbptzhMs3L1fQE82ZSLHQQfto5gyZzwteVIEyeaY5Fc7R4dapF/BvRoSYFeqfBk4m0V1Vafq5Pjv25wvA==", + "engines": { + "node": ">= 6" + }, + "funding": { + "url": "https://github.com/sponsors/fb55" + } + }, + "node_modules/dateformat": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/dateformat/-/dateformat-3.0.3.tgz", + "integrity": "sha512-jyCETtSl3VMZMWeRo7iY1FL19ges1t55hMo5yaam4Jrsm5EPL89UQkoQRyiI+Yf4k8r2ZpdngkV8hr1lIdjb3Q==", + "engines": { + "node": "*" + } + }, + "node_modules/debug": { + "version": "4.4.3", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz", + "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==", + "dependencies": { + "ms": "^2.1.3" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/decamelize": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", + "integrity": "sha512-z2S+W9X73hAUUki+N+9Za2lBlun89zigOyGrsax+KUQ6wKW4ZoWpEYBkGhQjwAjjDCkWxhY0VKEhk8wzY7F5cA==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/decamelize-keys": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/decamelize-keys/-/decamelize-keys-1.1.1.tgz", + "integrity": "sha512-WiPxgEirIV0/eIOMcnFBA3/IJZAZqKnwAwWyvvdi4lsr1WCN22nhdf/3db3DoZcUjTV2SqfzIwNyp6y2xs3nmg==", + "dependencies": { + "decamelize": "^1.1.0", + "map-obj": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/decamelize-keys/node_modules/map-obj": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/map-obj/-/map-obj-1.0.1.tgz", + "integrity": "sha512-7N/q3lyZ+LVCp7PzuxrJr4KMbBE2hW7BT7YNia330OFxIf4d3r5zVpicP2650l7CPN6RM9zOJRl3NGpqSiw3Eg==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/deprecation": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/deprecation/-/deprecation-2.3.1.tgz", + "integrity": "sha512-xmHIy4F3scKVwMsQ4WnVaS8bHOx0DmVwRywosKhaILI0ywMDWPtBSku2HNxRvF7jtwDRsoEwYQSfbxj8b7RlJQ==" + }, + "node_modules/detect-indent": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/detect-indent/-/detect-indent-6.1.0.tgz", + "integrity": "sha512-reYkTUJAZb9gUuZ2RvVCNhVHdg62RHnJ7WJl8ftMi4diZ6NWlciOzQN88pUhSELEwflJht4oQDv0F0BMlwaYtA==", + "engines": { + "node": ">=8" + } + }, + "node_modules/diff": { + "version": "8.0.4", + "resolved": "https://registry.npmjs.org/diff/-/diff-8.0.4.tgz", + "integrity": "sha512-DPi0FmjiSU5EvQV0++GFDOJ9ASQUVFh5kD+OzOnYdi7n3Wpm9hWWGfB/O2blfHcMVTL5WkQXSnRiK9makhrcnw==", + "engines": { + "node": ">=0.3.1" + } + }, + "node_modules/dom-serializer": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-2.0.0.tgz", + "integrity": "sha512-wIkAryiqt/nV5EQKqQpo3SToSOV9J0DnbJqwK7Wv/Trc92zIAYZ4FlMu+JPFW1DfGFt81ZTCGgDEabffXeLyJg==", + "dependencies": { + "domelementtype": "^2.3.0", + "domhandler": "^5.0.2", + "entities": "^4.2.0" + }, + "funding": { + "url": "https://github.com/cheeriojs/dom-serializer?sponsor=1" + } + }, + "node_modules/domelementtype": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-2.3.0.tgz", + "integrity": "sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/fb55" + } + ] + }, + "node_modules/domhandler": { + "version": "5.0.3", + "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-5.0.3.tgz", + "integrity": "sha512-cgwlv/1iFQiFnU96XXgROh8xTeetsnJiDsTc7TYCLFd9+/WNkIqPTxiM/8pSd8VIrhXGTf1Ny1q1hquVqDJB5w==", + "dependencies": { + "domelementtype": "^2.3.0" + }, + "engines": { + "node": ">= 4" + }, + "funding": { + "url": "https://github.com/fb55/domhandler?sponsor=1" + } + }, + "node_modules/domutils": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/domutils/-/domutils-3.2.2.tgz", + "integrity": "sha512-6kZKyUajlDuqlHKVX1w7gyslj9MPIXzIFiz/rGu35uC1wMi+kMhQwGhl4lt9unC9Vb9INnY9Z3/ZA3+FhASLaw==", + "dependencies": { + "dom-serializer": "^2.0.0", + "domelementtype": "^2.3.0", + "domhandler": "^5.0.3" + }, + "funding": { + "url": "https://github.com/fb55/domutils?sponsor=1" + } + }, + "node_modules/dot-prop": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/dot-prop/-/dot-prop-5.3.0.tgz", + "integrity": "sha512-QM8q3zDe58hqUqjraQOmzZ1LIH9SWQJTlEKCH4kJ2oQvLZk7RbQXvtDM2XEq3fwkV9CCvvH4LA0AV+ogFsBM2Q==", + "dependencies": { + "is-obj": "^2.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==" + }, + "node_modules/entities": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/entities/-/entities-4.5.0.tgz", + "integrity": "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==", + "engines": { + "node": ">=0.12" + }, + "funding": { + "url": "https://github.com/fb55/entities?sponsor=1" + } + }, + "node_modules/error-ex": { + "version": "1.3.4", + "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.4.tgz", + "integrity": "sha512-sqQamAnR14VgCr1A618A3sGrygcpK+HEbenA/HiEAkkUwcZIIB/tgWqHFxWgOyDh4nB4JCRimh79dR5Ywc9MDQ==", + "dependencies": { + "is-arrayish": "^0.2.1" + } + }, + "node_modules/es-errors": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz", + "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/escalade": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz", + "integrity": "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==", + "engines": { + "node": ">=6" + } + }, + "node_modules/escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/figures": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/figures/-/figures-3.2.0.tgz", + "integrity": "sha512-yaduQFRKLXYOGgEn6AZau90j3ggSOyiqXU0F9JZfeXYhNa+Jk4X+s45A2zg5jns87GAFa34BBm2kXw4XpNcbdg==", + "dependencies": { + "escape-string-regexp": "^1.0.5" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/find-up": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", + "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", + "dependencies": { + "locate-path": "^5.0.0", + "path-exists": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==" + }, + "node_modules/function-bind": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", + "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/get-caller-file": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", + "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", + "engines": { + "node": "6.* || 8.* || >= 10.*" + } + }, + "node_modules/glob": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "deprecated": "Old versions of glob are not supported, and contain widely publicized security vulnerabilities, which have been fixed in the current version. Please update. Support for old versions may be purchased (at exorbitant rates) by contacting i@izs.me", + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.1.1", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, + "engines": { + "node": "*" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/glob/node_modules/balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==" + }, + "node_modules/glob/node_modules/brace-expansion": { + "version": "1.1.21", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.21.tgz", + "integrity": "sha512-9zeA+KLZNNzglF2TPKRQEDyx6Yby7daAkuy8MiPzpXPsYDWi/DRM8jmwUDxokQjYqBpv5DgPiwD4h4ZZSy1Ujw==", + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/glob/node_modules/minimatch": { + "version": "3.1.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.5.tgz", + "integrity": "sha512-VgjWUsnnT6n+NUk6eZq77zeFdpW2LWDzP6zFGrCbHXiYNul5Dzqk2HHQ5uFH2DNW5Xbp8+jVzaeNt94ssEEl4w==", + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/handlebars": { + "version": "4.7.10", + "resolved": "https://registry.npmjs.org/handlebars/-/handlebars-4.7.10.tgz", + "integrity": "sha512-P5VJMVM7qgBn6vjXMw8WG9uVI+ncf2pi72j4de4yz5ZULLj2RGqLYaKOYGsgyrViQ0tePOVlN1tDCCXXtFqXKg==", + "dependencies": { + "minimist": "^1.2.8", + "neo-async": "^2.6.2", + "source-map": "^0.6.1", + "wordwrap": "^1.0.0" + }, + "bin": { + "handlebars": "bin/handlebars" + }, + "engines": { + "node": ">=0.4.7" + }, + "optionalDependencies": { + "uglify-js": "^3.1.4" + } + }, + "node_modules/hard-rejection": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/hard-rejection/-/hard-rejection-2.1.0.tgz", + "integrity": "sha512-VIZB+ibDhx7ObhAe7OVtoEbuP4h/MuOTHJ+J8h/eBXotJYl0fBgR72xDFCKgIh22OJZIOVNxBMWuhAr10r8HdA==", + "engines": { + "node": ">=6" + } + }, + "node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "engines": { + "node": ">=8" + } + }, + "node_modules/hasown": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.4.tgz", + "integrity": "sha512-T2UbfbBEF32wiepXIsMlTW9+dDYC6wMh/t/vYA4tuOMKqWz/n3vr1NFSxQiyP+zk2mXsoMA/i/7qV6LKut1t1A==", + "dependencies": { + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/he": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/he/-/he-1.2.0.tgz", + "integrity": "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==", + "bin": { + "he": "bin/he" + } + }, + "node_modules/hosted-git-info": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-4.1.0.tgz", + "integrity": "sha512-kyCuEOWjJqZuDbRHzL8V93NzQhwIB71oFWSyzVo+KPZI+pnQPPxucdkrOZvkLRnrf5URsQM+IJ09Dw29cRALIA==", + "dependencies": { + "lru-cache": "^6.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/http-proxy-agent": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-7.0.2.tgz", + "integrity": "sha512-T1gkAiYYDWYx3V5Bmyu7HcfcvL7mUrTWiM6yOfa3PIphViJ/gFPbvidQ+veqSOHci/PxBcDabeUNCzpOODJZig==", + "dependencies": { + "agent-base": "^7.1.0", + "debug": "^4.3.4" + }, + "engines": { + "node": ">= 14" + } + }, + "node_modules/https-proxy-agent": { + "version": "7.0.6", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-7.0.6.tgz", + "integrity": "sha512-vK9P5/iUfdl95AI+JVyUuIcVtd4ofvtrOr3HNtM2yxC9bnMbEdp3x01OhQNnjb8IJYi38VlTE3mBXwcfvywuSw==", + "dependencies": { + "agent-base": "^7.1.2", + "debug": "4" + }, + "engines": { + "node": ">= 14" + } + }, + "node_modules/indent-string": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-4.0.0.tgz", + "integrity": "sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==", + "engines": { + "node": ">=8" + } + }, + "node_modules/inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", + "deprecated": "This module is not supported, and leaks memory. Do not use it. Check out lru-cache if you want a good and tested way to coalesce async requests by a key value, which is much more comprehensive and powerful.", + "dependencies": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "node_modules/inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" + }, + "node_modules/is-arrayish": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", + "integrity": "sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==" + }, + "node_modules/is-core-module": { + "version": "2.17.0", + "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.17.0.tgz", + "integrity": "sha512-J/vG0zBCbIKOQFfufSwyXdMrsohyJIUNkrnmo6WZGzoM7tr/lsbfW5b2BvisL6zsyMzK9UxV9L6c7AoFbyXHOA==", + "dependencies": { + "hasown": "^2.0.4" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "engines": { + "node": ">=8" + } + }, + "node_modules/is-obj": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-obj/-/is-obj-2.0.0.tgz", + "integrity": "sha512-drqDG3cbczxxEJRoOXcOjtdp1J/lyp1mNn0xaznRs8+muBhgQcrnbspox5X5fOw0HnMnbfDzvnEMEtqDEJEo8w==", + "engines": { + "node": ">=8" + } + }, + "node_modules/is-plain-obj": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-1.1.0.tgz", + "integrity": "sha512-yvkRyxmFKEOQ4pNXCmJG5AEQNlXJS5LaONXo5/cLdTZdWvsZ1ioJEonLGAosKlMWE8lwUy/bJzMjcw8az73+Fg==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/js-tokens": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", + "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==" + }, + "node_modules/js-yaml": { + "version": "4.3.2", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.3.2.tgz", + "integrity": "sha512-SFNOvSJ+Dgf/9An904Yx+CgSlIPCkIpao4qo51lpee25TIRejdH3rhR4EZMGoNx3/TP3O+wzWuiTFl4sqbltzA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/puzrin" + }, + { + "type": "github", + "url": "https://github.com/sponsors/nodeca" + } + ], + "dependencies": { + "argparse": "^2.0.1" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, + "node_modules/jsep": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/jsep/-/jsep-1.4.0.tgz", + "integrity": "sha512-B7qPcEVE3NVkmSJbaYxvv4cHkVW7DQsZz13pUMrfS8z8Q/BuShN+gcTXrUlPiGqM2/t/EEaI030bpxMqY8gMlw==", + "engines": { + "node": ">= 10.16.0" + } + }, + "node_modules/json-parse-even-better-errors": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz", + "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==" + }, + "node_modules/json-stringify-safe": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", + "integrity": "sha512-ZClg6AaYvamvYEE82d3Iyd3vSSIjQ+odgjaTzRuO3s7toCdFKczob2i0zCh7JE8kWn17yvAWhUVxvqGwUalsRA==" + }, + "node_modules/jsonpath-plus": { + "version": "10.4.0", + "resolved": "https://registry.npmjs.org/jsonpath-plus/-/jsonpath-plus-10.4.0.tgz", + "integrity": "sha512-T92WWatJXmhBbKsgH/0hl+jxjdXrifi5IKeMY02DWggRxX0UElcbVzPlmgLTbvsPeW1PasQ6xE2Q75stkhGbsA==", + "dependencies": { + "@jsep-plugin/assignment": "^1.3.0", + "@jsep-plugin/regex": "^1.0.4", + "jsep": "^1.4.0" + }, + "bin": { + "jsonpath": "bin/jsonpath-cli.js", + "jsonpath-plus": "bin/jsonpath-cli.js" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/kind-of": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", + "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/lines-and-columns": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz", + "integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==" + }, + "node_modules/locate-path": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", + "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", + "dependencies": { + "p-locate": "^4.1.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/lodash.ismatch": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/lodash.ismatch/-/lodash.ismatch-4.4.0.tgz", + "integrity": "sha512-fPMfXjGQEV9Xsq/8MTSgUf255gawYRbjwMyDbcvDhXgV7enSZA0hynz6vMPnpAb5iONEzBHBPsT+0zes5Z301g==" + }, + "node_modules/lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/map-obj": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/map-obj/-/map-obj-4.3.0.tgz", + "integrity": "sha512-hdN1wVrZbb29eBGiGjJbeP8JbKjq1urkHJ/LIP/NY48MZ1QVXUsQBV1G1zvYFHn1XE06cwjBsOI2K3Ulnj1YXQ==", + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/meow": { + "version": "8.1.2", + "resolved": "https://registry.npmjs.org/meow/-/meow-8.1.2.tgz", + "integrity": "sha512-r85E3NdZ+mpYk1C6RjPFEMSE+s1iZMuHtsHAqY0DT3jZczl0diWUZ8g6oU7h0M9cD2EL+PzaYghhCLzR0ZNn5Q==", + "dependencies": { + "@types/minimist": "^1.2.0", + "camelcase-keys": "^6.2.2", + "decamelize-keys": "^1.1.0", + "hard-rejection": "^2.1.0", + "minimist-options": "4.1.0", + "normalize-package-data": "^3.0.0", + "read-pkg-up": "^7.0.1", + "redent": "^3.0.0", + "trim-newlines": "^3.0.0", + "type-fest": "^0.18.0", + "yargs-parser": "^20.2.3" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/meow/node_modules/type-fest": { + "version": "0.18.1", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.18.1.tgz", + "integrity": "sha512-OIAYXk8+ISY+qTOwkHtKqzAuxchoMiD9Udx+FSGQDuiRR+PJKJHc2NJAXlbhkGwTt/4/nKZxELY1w3ReWOL8mw==", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/min-indent": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/min-indent/-/min-indent-1.0.1.tgz", + "integrity": "sha512-I9jwMn07Sy/IwOj3zVkVik2JTvgpaykDZEigL6Rx6N9LbMywwUSMtxET+7lVoDLLd3O3IXwJwvuuns8UB/HeAg==", + "engines": { + "node": ">=4" + } + }, + "node_modules/minimatch": { + "version": "10.2.6", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-10.2.6.tgz", + "integrity": "sha512-vpLQEs+VLCr1nU0BXS07maYoFwlDAH0gngQuuttxIwutDFEMHq2blX+8vpgxDdK3J1PwjCJiep77OitTZ4Ll1A==", + "dependencies": { + "brace-expansion": "^5.0.8" + }, + "engines": { + "node": "18 || 20 || >=22" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/minimist": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz", + "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/minimist-options": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/minimist-options/-/minimist-options-4.1.0.tgz", + "integrity": "sha512-Q4r8ghd80yhO/0j1O3B2BjweX3fiHg9cdOwjJd2J76Q135c+NDxGCqdYKQ1SKBuFfgWbAUzBfvYjPUEeNgqN1A==", + "dependencies": { + "arrify": "^1.0.1", + "is-plain-obj": "^1.1.0", + "kind-of": "^6.0.3" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/modify-values": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/modify-values/-/modify-values-1.0.1.tgz", + "integrity": "sha512-xV2bxeN6F7oYjZWTe/YPAy6MN2M+sL4u/Rlm2AHCIVGfo2p1yGmBHQ6vHehl4bRTZBdHu3TSkWdYgkwpYzAGSw==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==" + }, + "node_modules/neo-async": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.6.2.tgz", + "integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==" + }, + "node_modules/node-html-parser": { + "version": "6.1.13", + "resolved": "https://registry.npmjs.org/node-html-parser/-/node-html-parser-6.1.13.tgz", + "integrity": "sha512-qIsTMOY4C/dAa5Q5vsobRpOOvPfC4pB61UVW2uSwZNUp0QU/jCekTal1vMmbO0DgdHeLUJpv/ARmDqErVxA3Sg==", + "dependencies": { + "css-select": "^5.1.0", + "he": "1.2.0" + } + }, + "node_modules/normalize-package-data": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-3.0.3.tgz", + "integrity": "sha512-p2W1sgqij3zMMyRC067Dg16bfzVH+w7hyegmpIvZ4JNjqtGOVAIvLmjBx3yP7YTe9vKJgkoNOPjwQGogDoMXFA==", + "dependencies": { + "hosted-git-info": "^4.0.1", + "is-core-module": "^2.5.0", + "semver": "^7.3.4", + "validate-npm-package-license": "^3.0.1" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/nth-check": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/nth-check/-/nth-check-2.1.1.tgz", + "integrity": "sha512-lqjrjmaOoAnWfMmBPL+XNnynZh2+swxiX3WUE0s4yEHI6m+AwrK2UZOimIRl3X/4QctVqS8AiZjFqyOGrMXb/w==", + "dependencies": { + "boolbase": "^1.0.0" + }, + "funding": { + "url": "https://github.com/fb55/nth-check?sponsor=1" + } + }, + "node_modules/once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", + "dependencies": { + "wrappy": "1" + } + }, + "node_modules/p-limit": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", + "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", + "dependencies": { + "p-try": "^2.0.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/p-locate": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", + "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", + "dependencies": { + "p-limit": "^2.2.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/p-try": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", + "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", + "engines": { + "node": ">=6" + } + }, + "node_modules/parse-diff": { + "version": "0.11.1", + "resolved": "https://registry.npmjs.org/parse-diff/-/parse-diff-0.11.1.tgz", + "integrity": "sha512-Oq4j8LAOPOcssanQkIjxosjATBIEJhCxMCxPhMu+Ci4wdNmAEdx0O+a7gzbR2PyKXgKPvRLIN5g224+dJAsKHA==" + }, + "node_modules/parse-github-repo-url": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/parse-github-repo-url/-/parse-github-repo-url-1.4.1.tgz", + "integrity": "sha512-bSWyzBKqcSL4RrncTpGsEKoJ7H8a4L3++ifTAbTFeMHyq2wRV+42DGmQcHIrJIvdcacjIOxEuKH/w4tthF17gg==" + }, + "node_modules/parse-json": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-5.2.0.tgz", + "integrity": "sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==", + "dependencies": { + "@babel/code-frame": "^7.0.0", + "error-ex": "^1.3.1", + "json-parse-even-better-errors": "^2.3.0", + "lines-and-columns": "^1.1.6" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/path-exists": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", + "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", + "engines": { + "node": ">=8" + } + }, + "node_modules/path-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/path-parse": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", + "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==" + }, + "node_modules/picocolors": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", + "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==" + }, + "node_modules/quick-lru": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/quick-lru/-/quick-lru-4.0.1.tgz", + "integrity": "sha512-ARhCpm70fzdcvNQfPoy49IaanKkTlRWF2JMzqhcJbhSFRZv7nPTvZJdcY7301IPmvW+/p0RgIWnQDLJxifsQ7g==", + "engines": { + "node": ">=8" + } + }, + "node_modules/read-pkg": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-5.2.0.tgz", + "integrity": "sha512-Ug69mNOpfvKDAc2Q8DRpMjjzdtrnv9HcSMX+4VsZxD1aZ6ZzrIE7rlzXBtWTyhULSMKg076AW6WR5iZpD0JiOg==", + "dependencies": { + "@types/normalize-package-data": "^2.4.0", + "normalize-package-data": "^2.5.0", + "parse-json": "^5.0.0", + "type-fest": "^0.6.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/read-pkg-up": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-7.0.1.tgz", + "integrity": "sha512-zK0TB7Xd6JpCLmlLmufqykGE+/TlOePD6qKClNW7hHDKFh/J7/7gCWGR7joEQEW1bKq3a3yUZSObOoWLFQ4ohg==", + "dependencies": { + "find-up": "^4.1.0", + "read-pkg": "^5.2.0", + "type-fest": "^0.8.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/read-pkg-up/node_modules/type-fest": { + "version": "0.8.1", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.8.1.tgz", + "integrity": "sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA==", + "engines": { + "node": ">=8" + } + }, + "node_modules/read-pkg/node_modules/hosted-git-info": { + "version": "2.8.9", + "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.8.9.tgz", + "integrity": "sha512-mxIDAb9Lsm6DoOJ7xH+5+X4y1LU/4Hi50L9C5sIswK3JzULS4bwk1FvjdBgvYR4bzT4tuUQiC15FE2f5HbLvYw==" + }, + "node_modules/read-pkg/node_modules/normalize-package-data": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.5.0.tgz", + "integrity": "sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA==", + "dependencies": { + "hosted-git-info": "^2.1.4", + "resolve": "^1.10.0", + "semver": "2 || 3 || 4 || 5", + "validate-npm-package-license": "^3.0.1" + } + }, + "node_modules/read-pkg/node_modules/semver": { + "version": "5.7.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz", + "integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==", + "bin": { + "semver": "bin/semver" + } + }, + "node_modules/read-pkg/node_modules/type-fest": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.6.0.tgz", + "integrity": "sha512-q+MB8nYR1KDLrgr4G5yemftpMC7/QLqVndBmEEdqzmNj5dcFOO4Oo8qlwZE3ULT3+Zim1F8Kq4cBnikNhlCMlg==", + "engines": { + "node": ">=8" + } + }, + "node_modules/redent": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/redent/-/redent-3.0.0.tgz", + "integrity": "sha512-6tDA8g98We0zd0GvVeMT9arEOnTw9qM03L9cJXaCjrip1OO764RDBLBfrB4cwzNGDj5OA5ioymC9GkizgWJDUg==", + "dependencies": { + "indent-string": "^4.0.0", + "strip-indent": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/release-please": { + "version": "17.6.0", + "resolved": "https://registry.npmjs.org/release-please/-/release-please-17.6.0.tgz", + "integrity": "sha512-ItzkkEBeEbKsCrx7N1QlADrCahoONA4WPlsOinSnXTkqUBIWlHC6+S28VJ9PaHy7ZPSJwSQsRuDjI0/HL5G6hw==", + "dependencies": { + "@conventional-commits/parser": "^0.4.1", + "@google-automations/git-file-utils": "^3.0.0", + "@iarna/toml": "^3.0.0", + "@octokit/graphql": "^7.1.0", + "@octokit/request": "^8.3.1", + "@octokit/request-error": "^5.1.0", + "@octokit/rest": "^20.1.1", + "@types/npm-package-arg": "^6.1.0", + "@xmldom/xmldom": "^0.8.4", + "chalk": "^4.0.0", + "code-suggester": "^5.0.0", + "conventional-changelog-conventionalcommits": "^6.0.0", + "conventional-changelog-writer": "^6.0.0", + "conventional-commits-filter": "^3.0.0", + "detect-indent": "^6.1.0", + "diff": "^8.0.3", + "figures": "^3.0.0", + "http-proxy-agent": "^7.0.0", + "https-proxy-agent": "^7.0.0", + "js-yaml": "^4.0.0", + "jsonpath-plus": "^10.0.0", + "node-html-parser": "^6.0.0", + "parse-github-repo-url": "^1.4.1", + "semver": "^7.5.3", + "type-fest": "^3.0.0", + "typescript": "^4.6.4", + "unist-util-visit": "^2.0.3", + "unist-util-visit-parents": "^3.1.1", + "xpath": "^0.0.34", + "yaml": "^2.2.2", + "yargs": "^17.0.0" + }, + "bin": { + "release-please": "build/src/bin/release-please.js" + }, + "engines": { + "node": ">=20.0.0" + } + }, + "node_modules/require-directory": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", + "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/resolve": { + "version": "1.22.13", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.13.tgz", + "integrity": "sha512-Dj/cW9zBV2aRj6XzCxuGIs3ESZKv02jixne3q6jFZYZ3/Tg09gHHviSMDL4kObh9pqSahdRHEnDoaP2gn8YLhA==", + "dependencies": { + "es-errors": "^1.3.0", + "is-core-module": "^2.17.0", + "path-parse": "^1.0.7", + "supports-preserve-symlinks-flag": "^1.0.0" + }, + "bin": { + "resolve": "bin/resolve" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/retry": { + "version": "0.13.1", + "resolved": "https://registry.npmjs.org/retry/-/retry-0.13.1.tgz", + "integrity": "sha512-XQBQ3I8W1Cge0Seh+6gjj03LbmRFWuoszgK9ooCpwYIrhhoO80pfq4cUkU5DkknwfOfFteRwlZ56PYOGYyFWdg==", + "engines": { + "node": ">= 4" + } + }, + "node_modules/semver": { + "version": "7.8.5", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.8.5.tgz", + "integrity": "sha512-Y7/KDsb8LjooZpwaqGyulO6DQlksgCncchHGk+sZIY4SBvUocMBEFH5Ur1fI4dV+Jvl0w6cjvucaIi40puRioA==", + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/spdx-correct": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.2.0.tgz", + "integrity": "sha512-kN9dJbvnySHULIluDHy32WHRUu3Og7B9sbY7tsFLctQkIqnMh3hErYgdMjTYuqmcXX+lK5T1lnUt3G7zNswmZA==", + "dependencies": { + "spdx-expression-parse": "^3.0.0", + "spdx-license-ids": "^3.0.0" + } + }, + "node_modules/spdx-exceptions": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.5.0.tgz", + "integrity": "sha512-PiU42r+xO4UbUS1buo3LPJkjlO7430Xn5SVAhdpzzsPHsjbYVflnnFdATgabnLude+Cqu25p6N+g2lw/PFsa4w==" + }, + "node_modules/spdx-expression-parse": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-3.0.1.tgz", + "integrity": "sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q==", + "dependencies": { + "spdx-exceptions": "^2.1.0", + "spdx-license-ids": "^3.0.0" + } + }, + "node_modules/spdx-license-ids": { + "version": "3.0.24", + "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.24.tgz", + "integrity": "sha512-cLS9TtWkIQFyLkJ3/5aFQAOHOSKTlOs/7WDut/XPSdjom1fJhUdkepeJAKXa9Y05+FabHd0sti+Et559vDtkpQ==" + }, + "node_modules/split": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/split/-/split-1.0.1.tgz", + "integrity": "sha512-mTyOoPbrivtXnwnIxZRFYRrPNtEFKlpB2fvjSnCQUiAA6qAZzqwna5envK4uk6OIeP17CsdF3rSBGYVBsU0Tkg==", + "dependencies": { + "through": "2" + }, + "engines": { + "node": "*" + } + }, + "node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-indent": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/strip-indent/-/strip-indent-3.0.0.tgz", + "integrity": "sha512-laJTa3Jb+VQpaC6DseHhF7dXVqHTfJPCRDaEbid/drOhgitgYku/letMUqOXFoWV0zIIUbjpdH2t+tYj4bQMRQ==", + "dependencies": { + "min-indent": "^1.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/supports-preserve-symlinks-flag": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", + "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/through": { + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", + "integrity": "sha512-w89qg7PI8wAdvX60bMDP+bFoD5Dvhm9oLheFp5O4a2QF0cSBGsBX4qZmadPMvVqlLJBBci+WqGGOAPvcDeNSVg==" + }, + "node_modules/trim-newlines": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/trim-newlines/-/trim-newlines-3.0.1.tgz", + "integrity": "sha512-c1PTsA3tYrIsLGkJkzHF+w9F2EyxfXGo4UyJc4pFL++FMjnq0HJS69T3M7d//gKrFKwy429bouPescbjecU+Zw==", + "engines": { + "node": ">=8" + } + }, + "node_modules/tunnel": { + "version": "0.0.6", + "resolved": "https://registry.npmjs.org/tunnel/-/tunnel-0.0.6.tgz", + "integrity": "sha512-1h/Lnq9yajKY2PEbBadPXj3VxsDDu844OnaAo52UVmIzIvwwtBPIuNvkjuzBlTWpfJyUbG3ez0KSBibQkj4ojg==", + "engines": { + "node": ">=0.6.11 <=0.7.0 || >=0.7.3" + } + }, + "node_modules/type-fest": { + "version": "3.13.1", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-3.13.1.tgz", + "integrity": "sha512-tLq3bSNx+xSpwvAJnzrK0Ep5CLNWjvFTOp71URMaAEWBfRb9nnJiBoUe0tF8bI4ZFO3omgBR6NvnbzVUT3Ly4g==", + "engines": { + "node": ">=14.16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/typescript": { + "version": "4.9.5", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.9.5.tgz", + "integrity": "sha512-1FXk9E2Hm+QzZQ7z+McJiHL4NW1F2EzMu9Nq9i3zAaGqibafqYwCVU6WyWAuyQRRzOlxou8xZSyXLEN8oKj24g==", + "bin": { + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" + }, + "engines": { + "node": ">=4.2.0" + } + }, + "node_modules/uglify-js": { + "version": "3.19.3", + "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.19.3.tgz", + "integrity": "sha512-v3Xu+yuwBXisp6QYTcH4UbH+xYJXqnq2m/LtQVWKWzYc1iehYnLixoQDN9FH6/j9/oybfd6W9Ghwkl8+UMKTKQ==", + "optional": true, + "bin": { + "uglifyjs": "bin/uglifyjs" + }, + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/undici": { + "version": "5.29.0", + "resolved": "https://registry.npmjs.org/undici/-/undici-5.29.0.tgz", + "integrity": "sha512-raqeBD6NQK4SkWhQzeYKd1KmIG6dllBOTt55Rmkt4HtI9mwdWtJljnrXjAFUBLTSN67HWrOIZ3EPF4kjUw80Bg==", + "dependencies": { + "@fastify/busboy": "^2.0.0" + }, + "engines": { + "node": ">=14.0" + } + }, + "node_modules/unist-util-is": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/unist-util-is/-/unist-util-is-4.1.0.tgz", + "integrity": "sha512-ZOQSsnce92GrxSqlnEEseX0gi7GH9zTJZ0p9dtu87WRb/37mMPO2Ilx1s/t9vBHrFhbgweUwb+t7cIn5dxPhZg==", + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/unist-util-visit": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/unist-util-visit/-/unist-util-visit-2.0.3.tgz", + "integrity": "sha512-iJ4/RczbJMkD0712mGktuGpm/U4By4FfDonL7N/9tATGIF4imikjOuagyMY53tnZq3NP6BcmlrHhEKAfGWjh7Q==", + "dependencies": { + "@types/unist": "^2.0.0", + "unist-util-is": "^4.0.0", + "unist-util-visit-parents": "^3.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/unist-util-visit-parents": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/unist-util-visit-parents/-/unist-util-visit-parents-3.1.1.tgz", + "integrity": "sha512-1KROIZWo6bcMrZEwiH2UrXDyalAa0uqzWCxCJj6lPOvTve2WkfgCytoDTPaMnodXh1WrXOq0haVYHj99ynJlsg==", + "dependencies": { + "@types/unist": "^2.0.0", + "unist-util-is": "^4.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/universal-user-agent": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/universal-user-agent/-/universal-user-agent-6.0.1.tgz", + "integrity": "sha512-yCzhz6FN2wU1NiiQRogkTQszlQSlpWaw8SvVegAc+bDxbzHgh1vX8uIe8OYyMH6DwH+sdTJsgMl36+mSMdRJIQ==" + }, + "node_modules/validate-npm-package-license": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz", + "integrity": "sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==", + "dependencies": { + "spdx-correct": "^3.0.0", + "spdx-expression-parse": "^3.0.0" + } + }, + "node_modules/wordwrap": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-1.0.0.tgz", + "integrity": "sha512-gvVzJFlPycKc5dZN4yPkP8w7Dc37BtP1yczEneOb4uq34pXZcvrtRTmWV8W+Ume+XCxKgbjM+nevkyFPMybd4Q==" + }, + "node_modules/wrap-ansi": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "dependencies": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, + "node_modules/wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==" + }, + "node_modules/xpath": { + "version": "0.0.34", + "resolved": "https://registry.npmjs.org/xpath/-/xpath-0.0.34.tgz", + "integrity": "sha512-FxF6+rkr1rNSQrhUNYrAFJpRXNzlDoMxeXN5qI84939ylEv3qqPFKa85Oxr6tDaJKqwW6KKyo2v26TSv3k6LeA==", + "engines": { + "node": ">=0.6.0" + } + }, + "node_modules/y18n": { + "version": "5.0.8", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", + "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", + "engines": { + "node": ">=10" + } + }, + "node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" + }, + "node_modules/yaml": { + "version": "2.9.1", + "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.9.1.tgz", + "integrity": "sha512-3NxN8+78OdzbT7C/WjGsyfPAtJaN3FNDsWxv7Y7mcDsT/oOmgW8BpyQQFFBnvZE3j9Y2Sdz1ULFLezL7Eb2yFw==", + "bin": { + "yaml": "bin.mjs" + }, + "engines": { + "node": ">= 14.6" + }, + "funding": { + "url": "https://github.com/sponsors/eemeli" + } + }, + "node_modules/yargs": { + "version": "17.7.3", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.3.tgz", + "integrity": "sha512-GZtjxm/J/4TSxuL3FNYjCmLktBTnIw/rVmKSIyKeYAZpmJB2ig9VauCC5xsa82GNKVKDAqpOn3KVzNt0zmrU0g==", + "dependencies": { + "cliui": "^8.0.1", + "escalade": "^3.1.1", + "get-caller-file": "^2.0.5", + "require-directory": "^2.1.1", + "string-width": "^4.2.3", + "y18n": "^5.0.5", + "yargs-parser": "^21.1.1" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/yargs-parser": { + "version": "20.2.9", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.9.tgz", + "integrity": "sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w==", + "engines": { + "node": ">=10" + } + }, + "node_modules/yargs/node_modules/yargs-parser": { + "version": "21.1.1", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz", + "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==", + "engines": { + "node": ">=12" + } + } + } +} diff --git a/.github/release-please/package.json b/.github/release-please/package.json new file mode 100644 index 000000000..41a63ea61 --- /dev/null +++ b/.github/release-please/package.json @@ -0,0 +1,12 @@ +{ + "name": "openapi-odata-release-automation", + "private": true, + "scripts": { + "test": "node --test run.test.cjs", + "coverage": "cd ../.. && node --test --experimental-test-coverage --test-coverage-include=.github/release-please/run.cjs --test-coverage-lines=80 --test-coverage-functions=80 --test-reporter=spec --test-reporter=lcov --test-reporter-destination=stdout --test-reporter-destination=artifacts/release-please/lcov.info .github/release-please/run.test.cjs" + }, + "dependencies": { + "@actions/core": "1.11.1", + "release-please": "17.6.0" + } +} diff --git a/.github/release-please/run.cjs b/.github/release-please/run.cjs new file mode 100644 index 000000000..4db731d86 --- /dev/null +++ b/.github/release-please/run.cjs @@ -0,0 +1,167 @@ +const {GitHub, Manifest, registerPlugin} = require('release-please'); +const {ManifestPlugin} = require('release-please/build/src/plugin'); +const {Version} = require('release-please/build/src/version'); +const {buildStrategy} = require('release-please/build/src/factory'); +const {FilePullRequestOverflowHandler} = require('release-please/build/src/util/pull-request-overflow-handler'); + +const HIDI_PENDING = 'autorelease: hidi-pending'; +const HIDI_VERSIONED = 'autorelease: hidi-versioned'; +const HIDI_FLOORS = {'main': '3.10.2', 'support/v2': '2.12.2'}; + +class ExactPathExclusions extends ManifestPlugin { + async preconfigure(strategies, commitsByPath) { + for (const [path, config] of Object.entries(this.repositoryConfig)) { + const excludes = config.excludePaths || []; + commitsByPath[path] = commitsByPath[path].filter(commit => { + if (!Array.isArray(commit.files)) { + throw new Error(`Missing changed files for commit ${commit.sha}`); + } + return commit.files.some(file => + (path === '.' || file.startsWith(`${path}/`)) && + !excludes.some(exclude => file === exclude || file.startsWith(`${exclude}/`)) + ); + }); + } + return strategies; + } + + async run(candidates) { + for (const candidate of candidates) { + if (candidate.config.component !== 'hidi') continue; + const floor = HIDI_FLOORS[this.targetBranch]; + const version = candidate.pullRequest.version; + if (!floor || !version || version.major !== Version.parse(floor).major || + version.preRelease || version.build || version.compare(Version.parse(floor)) <= 0) { + throw new Error('Generated Hidi version is outside the branch major or migration floor'); + } + } + return candidates; + } +} + +registerPlugin('exact-path-exclusions', options => + new ExactPathExclusions(options.github, options.targetBranch, options.repositoryConfig) +); + +async function prepareHidiVersionPrs(github, manifest, branch) { + const floor = HIDI_FLOORS[branch]; + const manifestConfig = await github.getFileJson('hidi-release-please-config.json', branch); + const config = manifest.repositoryConfig['.']; + const version = manifest.releasedVersions['.']; + if (!floor || Object.keys(manifest.repositoryConfig).length !== 1 || + Object.keys(manifest.releasedVersions).length !== 1 || + config?.component !== 'hidi' || config.releaseType !== 'simple' || + !config.includeComponentInTag || !config.includeVInTag || + (config.tagSeparator && config.tagSeparator !== '-') || + config.skipGithubRelease || + !config.separatePullRequests || + manifestConfig.label !== HIDI_PENDING || + !version || version.major !== Version.parse(floor).major || + version.preRelease || version.build || version.compare(Version.parse(floor)) < 0) { + throw new Error('Unsafe Hidi branch, manifest, component, labels or version configuration'); + } + const project = await github.getFileContentsOnBranch('src/Microsoft.OpenApi.Hidi/Microsoft.OpenApi.Hidi.csproj', branch); + const projectVersions = [...project.parsedContent.matchAll(/\s*([^<]+?)\s*<\/Version>/g)]; + if (projectVersions.length !== 1 || projectVersions[0][1] !== version.toString()) { + throw new Error('Hidi project version does not match its manifest'); + } + + const strategy = await buildStrategy({...config, github, path: '.', targetBranch: branch}); + const overflow = new FilePullRequestOverflowHandler(github); + const expectedBranch = `release-please--branches--${branch}--components--hidi`; + const pending = []; + let checkpoint; + for await (const pr of github.pullRequestIterator(branch, 'MERGED', 200, false)) { + if (!pr.labels.some(label => label === HIDI_PENDING || label === HIDI_VERSIONED)) continue; + if (pr.headBranchName !== expectedBranch || !pr.sha) { + throw new Error(`Unsafe Hidi version PR #${pr.number}: unexpected branch or missing merge SHA`); + } + const releases = await strategy.buildReleases(pr); + if (releases.length !== 1 || releases[0].tag.component !== 'hidi') { + throw new Error(`Cannot parse merged Hidi version PR #${pr.number}`); + } + const release = releases[0]; + const body = await overflow.parseOverflow(pr); + if (body?.releaseData.length !== 1 || + (body.releaseData[0].component && body.releaseData[0].component !== 'hidi') || + body.releaseData[0].version?.compare(release.tag.version) !== 0) { + throw new Error(`Hidi version PR #${pr.number} has inconsistent title and body versions`); + } + if (release.tag.version.compare(version) > 0 || + release.tag.version.compare(Version.parse(floor)) <= 0) { + throw new Error(`Merged Hidi PR #${pr.number} disagrees with the current manifest or migration floor`); + } + if (release.tag.version.compare(version) === 0) { + if (checkpoint && checkpoint.sha !== pr.sha) { + throw new Error(`Multiple merged Hidi PRs claim version ${version}`); + } + checkpoint = pr; + } + if (pr.labels.includes(HIDI_PENDING)) pending.push(pr); + } + if (!checkpoint && (version.toString() !== floor || pending.length)) { + throw new Error(`No merged Hidi version PR matches manifest version ${version}`); + } + if (checkpoint) { + // A version PR merge, not a production tag, is the boundary for the next cycle. + let reachable = false; + for await (const commit of github.mergeCommitIterator(branch, { + maxResults: manifest.commitSearchDepth, backfillFiles: false + })) { + if (commit.sha === checkpoint.sha) { + reachable = true; + break; + } + } + if (!reachable) throw new Error(`Hidi checkpoint ${checkpoint.sha} is outside the branch commit search`); + } + for (const pr of pending) { + // Adding first makes an interrupted label transition safe to retry. + await github.addIssueLabels([HIDI_VERSIONED], pr.number); + await github.removeIssueLabels([HIDI_PENDING], pr.number); + } + return checkpoint?.sha; +} + +async function runReleasePlease(github, branch, component) { + if (!['odata', 'hidi'].includes(component)) throw new Error(`Unknown component: ${component}`); + const configFile = component === 'hidi' ? 'hidi-release-please-config.json' : 'release-please-config.json'; + const manifestFile = component === 'hidi' ? '.hidi-release-please-manifest.json' : '.release-please-manifest.json'; + const load = (options = {}) => Manifest.fromManifest(github, branch, configFile, manifestFile, options); + const releases = component === 'odata' ? await (await load()).createReleases() : []; + let manifest = await load(); + if (component === 'hidi') { + const lastReleaseSha = await prepareHidiVersionPrs(github, manifest, branch); + if (lastReleaseSha) manifest = await load({lastReleaseSha}); + } + const prs = await manifest.createPullRequests(); + return {releases, prs}; +} + +async function main() { + const core = require('@actions/core'); + const token = process.env.RELEASE_PLEASE_TOKEN; + const branch = process.env.GITHUB_REF_NAME; + const [owner, repo] = (process.env.GITHUB_REPOSITORY || '').split('/'); + if (!token || !branch || !owner || !repo) throw new Error('Missing release automation environment'); + const github = await GitHub.create({owner, repo, token, defaultBranch: branch}); + const {releases, prs} = await runReleasePlease(github, branch, process.argv[2]); + core.setOutput('releases_created', releases.length > 0); + core.setOutput('prs_created', prs.length > 0); + core.setOutput('prs', JSON.stringify(prs)); + core.setOutput('paths_released', JSON.stringify(releases.map(release => release.path))); + if (prs.length) core.setOutput('pr', prs[0]); + for (const release of releases) { + const prefix = release.path === '.' ? '' : `${release.path}--`; + core.setOutput(`${prefix}release_created`, true); + for (const [name, value] of Object.entries(release)) { + const key = {tagName: 'tag_name', uploadUrl: 'upload_url', notes: 'body', url: 'html_url'}[name] || name; + core.setOutput(`${prefix}${key}`, value); + } + } +} + +module.exports = {ExactPathExclusions, prepareHidiVersionPrs, runReleasePlease, main}; +if (require.main === module) { + main().catch(error => require('@actions/core').setFailed(error.message)); +} diff --git a/.github/release-please/run.test.cjs b/.github/release-please/run.test.cjs new file mode 100644 index 000000000..6058e8701 --- /dev/null +++ b/.github/release-please/run.test.cjs @@ -0,0 +1,348 @@ +const assert = require('node:assert/strict'); +const fs = require('node:fs'); +const path = require('node:path'); +const {test} = require('node:test'); +const {GitHub, Manifest, setLogger} = require('release-please'); +const {runReleasePlease, main, ExactPathExclusions} = require('./run.cjs'); + +setLogger({debug() {}, info() {}, warn() {}, error() {}}); +const root = path.resolve(__dirname, '..', '..'); +const branch = JSON.parse(fs.readFileSync(path.join(root, '.hidi-release-please-manifest.json')))['.'].startsWith('3.') ? 'main' : 'support/v2'; +const hidiProject = 'src/Microsoft.OpenApi.Hidi/Microsoft.OpenApi.Hidi.csproj'; +const hidiReadme = 'src/Microsoft.OpenApi.Hidi/readme.md'; +const hidiChangelog = 'src/Microsoft.OpenApi.Hidi/CHANGELOG.md'; +const hidiManifest = '.hidi-release-please-manifest.json'; +const odataManifest = '.release-please-manifest.json'; +const inputPaths = [ + 'release-please-config.json', 'hidi-release-please-config.json', + hidiManifest, odataManifest, hidiProject, hidiReadme, hidiChangelog, + 'Directory.Build.props', 'CHANGELOG.md' +]; + +class MemoryGitHub { + constructor() { + this.repository = {owner: 'microsoft', repo: 'OpenAPI.NET.OData', defaultBranch: branch}; + this.files = Object.fromEntries(inputPaths.map(file => [file, fs.readFileSync(path.join(root, file), 'utf8')])); + this.commits = ['hidi-release-please-config.json', 'release-please-config.json'].map(file => ({ + sha: JSON.parse(this.files[file])['bootstrap-sha'], message: 'chore: baseline', files: [] + })); + this.prs = []; + this.releases = []; + this.tags = []; + this.labelWrites = []; + this.nextPr = 1; + } + async getFileJson(file) { return JSON.parse(this.files[file]); } + async getFileContentsOnBranch(file) { + assert.ok(Object.hasOwn(this.files, file), `Unexpected read of ${file}`); + return {parsedContent: this.files[file], content: Buffer.from(this.files[file]).toString('base64'), sha: 'file-sha'}; + } + async *releaseIterator() { yield* this.releases; } + async *tagIterator() { yield* this.tags; } + async *mergeCommitIterator() { yield* this.commits; } + async *pullRequestIterator(target, state) { + assert.equal(target, branch); + yield* this.prs.filter(pr => pr.state === state); + } + change(files, message = 'fix: representative change') { + this.commits.unshift({sha: `change-${this.commits.length}`, message, files}); + } + materialize(updates) { + return Object.fromEntries(updates + .filter(update => update.createIfMissing || Object.hasOwn(this.files, update.path)) + .map(update => [update.path, update.updater.updateContent(this.files[update.path] || '')])); + } + async createPullRequest(pr, target, message, updates) { + assert.equal(target, branch); + const created = {...pr, number: this.nextPr++, state: 'OPEN', output: this.materialize(updates)}; + this.prs.unshift(created); + return created; + } + async updatePullRequest(number, plan) { + const pr = this.prs.find(item => item.number === number); + Object.assign(pr, {title: plan.title.toString(), body: plan.body.toString(), output: this.materialize(plan.updates)}); + return pr; + } + async addIssueLabels(labels, number) { + this.labelWrites.push(['add', number, labels]); + const pr = this.prs.find(item => item.number === number); + pr.labels = [...new Set([...pr.labels, ...labels])]; + } + async removeIssueLabels(labels, number) { + this.labelWrites.push(['remove', number, labels]); + const pr = this.prs.find(item => item.number === number); + pr.labels = pr.labels.filter(label => !labels.includes(label)); + } + async commentOnIssue() {} + async createRelease(release) { + const result = {tagName: release.tag.toString(), sha: release.sha, notes: release.notes, url: 'https://example.invalid/release'}; + this.releases.unshift(result); + this.tags.unshift({name: result.tagName, sha: result.sha}); + return result; + } + merge(pr) { + Object.assign(this.files, pr.output); + Object.assign(pr, {state: 'MERGED', sha: `merge-${pr.number}`}); + this.commits.unshift({sha: pr.sha, message: pr.title, files: Object.keys(pr.output), pullRequest: pr}); + } +} + +async function plans(github, component) { + return (await Manifest.fromManifest(github, branch, + component === 'hidi' ? 'hidi-release-please-config.json' : 'release-please-config.json', + component === 'hidi' ? hidiManifest : odataManifest)).buildPullRequests(); +} + +const routingCases = [ + ['src/Microsoft.OpenApi.Hidi/Program.cs', false, true], + ['src/Microsoft.OpenApi.Hidi/CsdlFilter.xslt', false, true], + [hidiProject, false, true], + [hidiReadme, false, true], + [hidiChangelog, false, true], + ['test/Microsoft.OpenApi.Hidi.Tests/StatsVisitorTests.cs', false, true], + ['test/Microsoft.OpenApi.Hidi.Tests/UtilityFiles/SampleOpenApi.yml', false, true], + ['test/Microsoft.OpenApi.Hidi.Tests/check-nuget-package-published.Tests.ps1', false, true], + ['scripts/check-nuget-package-published.ps1', false, true], + ['test/scripts/check-nuget-package-published.Tests.ps1', false, true], + ['Dockerfile', false, true], + ['.dockerignore', false, true], + ['install-tool.ps1', false, true], + ['tool/hidi-local-nuget.config', false, true], + ['tool/Microsoft.OpenApi.Hidi.public.snk', false, true], + ['hidi-release-please-config.json', false, true], + [hidiManifest, false, true], + ['.azure-pipelines/hidi-release.yml', false, true], + ['src/Microsoft.OpenApi.OData.Reader/OpenApiConvertSettings.cs', true, false], + ['test/Microsoft.OpenAPI.OData.Reader.Tests/OpenApiConvertSettingsTests.cs', true, false], + ['src/OoasGui/Program.cs', true, false], + ['src/OoasUtil/Program.cs', true, false], + ['docs/graphSecurityScheme/GraphSchemes.md', true, false], + ['Directory.Build.props', true, false], + ['redocly.yaml', true, false], + ['.redocly.lint-ignore.yaml', true, false], + ['src/AssemblyInfo/AssemblyInfoCommon.cs', true, false], + ['CHANGELOG.md', true, false], + ['release-please-config.json', true, false], + [odataManifest, true, false], + ['tool/Microsoft.OpenApi.OData.snk', true, false], + ['tool/35MSSharedLib1024.snk', true, false], + ['tool/Microsoft.OpenApi.OData.public.snk', false, true], + ['README.md', true, true], + ['CONTRIBUTING.md', true, true], + ['Build.props', true, true], + ['src/Build.props', true, true], + ['build.root', true, true], + ['build.ps1', true, true], + ['build.cmd', true, true], + ['global.json', true, true], + ['Microsoft.OpenApi.OData.sln', true, true], + ['.github/workflows/ci-cd.yml', false, false], + ['.github/release-please/run.cjs', false, false], + ['.azure-pipelines/ci-build.yml', false, false], + ['src/Microsoft.OpenApi.HidiSibling/Program.cs', true, true] +]; + +for (const [file, odata, hidi] of routingCases) { + test(`real engine routing: ${file}`, async () => { + const github = new MemoryGitHub(); + github.change([file]); + assert.equal((await plans(github, 'odata')).length, Number(odata)); + assert.equal((await plans(github, 'hidi')).length, Number(hidi)); + }); +} + +test('mixed changes affect both components; excluded-only and empty changes affect neither', async () => { + const github = new MemoryGitHub(); + github.change(['Dockerfile', 'src/Microsoft.OpenApi.OData.Reader/OpenApiConvertSettings.cs']); + assert.equal((await plans(github, 'odata')).length, 1); + assert.equal((await plans(github, 'hidi')).length, 1); + github.commits.shift(); + github.change(['Dockerfile', 'test/Microsoft.OpenApi.Hidi.Tests/StatsVisitorTests.cs']); + assert.equal((await plans(github, 'odata')).length, 0); + github.commits.shift(); + github.change([]); + assert.equal((await plans(github, 'odata')).length, 0); + assert.equal((await plans(github, 'hidi')).length, 0); +}); + +test('actual Hidi patch output changes only its version, manifest, changelog and install examples', async () => { + const github = new MemoryGitHub(); + const baseline = github.files[hidiProject]; + const oldVersion = JSON.parse(github.files[hidiManifest])['.']; + const next = oldVersion.replace(/\d+$/, patch => Number(patch) + 1); + github.change(['Dockerfile'], 'fix(hidi): independent distribution fix'); + const [pr] = await plans(github, 'hidi'); + const output = github.materialize(pr.updates); + assert.deepEqual(Object.keys(output).sort(), [hidiChangelog, hidiProject, hidiReadme, hidiManifest].sort()); + assert.equal(pr.headRefName, `release-please--branches--${branch}--components--hidi`); + assert.equal(pr.version.toString(), next); + assert.ok(output[hidiProject].includes(`${next}`)); + const dependencies = text => [...text.matchAll(/ match.slice(1)); + assert.deepEqual(dependencies(output[hidiProject]), dependencies(baseline)); + assert.match(output[hidiChangelog], new RegExp(`hidi-v${oldVersion}\\.\\.\\.hidi-v${next}`)); + assert.equal(JSON.parse(output[hidiManifest])['.'], next); + assert.ok(output[hidiReadme].includes(`--version ${next}`)); + assert.ok(output[hidiReadme].includes(`YamlReader\` ${branch === 'main' ? '3.10.2' : '2.12.2'}`)); +}); + +test('actual OData output and componentless tags retain existing behavior', async () => { + const github = new MemoryGitHub(); + const oldVersion = JSON.parse(github.files[odataManifest])['.']; + const next = oldVersion.replace(/\d+$/, patch => Number(patch) + 1); + github.releases.push({tagName: `v${oldVersion}`, sha: github.commits.at(-1).sha, notes: ''}); + github.change(['Directory.Build.props'], 'fix(odata): independent library fix'); + const [pr] = await plans(github, 'odata'); + const output = github.materialize(pr.updates); + assert.deepEqual(Object.keys(output).sort(), ['CHANGELOG.md', 'Directory.Build.props', odataManifest].sort()); + assert.equal(pr.headRefName, `release-please--branches--${branch}--components--Microsoft.OpenApi.OData`); + assert.ok(output['Directory.Build.props'].includes(`${next}`)); + assert.match(output['CHANGELOG.md'], new RegExp(`v${oldVersion}\\.\\.\\.v${next}`)); + const created = await runReleasePlease(github, branch, 'odata'); + github.merge(created.prs[0]); + const released = await runReleasePlease(github, branch, 'odata'); + assert.equal(released.releases[0].tagName, `v${next}`); + assert.equal(released.prs.length, 0); +}); + +test('Hidi feature release increments minor; breaking changes fail before writing a PR or release', async () => { + const github = new MemoryGitHub(); + const [major, minor] = JSON.parse(github.files[hidiManifest])['.'].split('.').map(Number); + github.change(['src/Microsoft.OpenApi.Hidi/Program.cs'], 'feat(hidi): independent feature'); + assert.equal((await plans(github, 'hidi'))[0].version.toString(), `${major}.${minor + 1}.0`); + github.commits.shift(); + github.change(['src/Microsoft.OpenApi.Hidi/Program.cs'], 'feat(hidi)!: incompatible feature'); + await assert.rejects(runReleasePlease(github, branch, 'hidi'), /outside the branch major/); + assert.equal(github.prs.length, 0); + assert.equal(github.releases.length, 0); +}); + +test('two tag-free Hidi version cycles do not replay commits or block OData', async () => { + const github = new MemoryGitHub(); + const baseline = JSON.parse(github.files[hidiManifest])['.']; + github.change(['Dockerfile'], 'fix(hidi): first cycle'); + const first = await runReleasePlease(github, branch, 'hidi'); + assert.deepEqual(first.releases, []); + assert.deepEqual(first.prs[0].labels, ['autorelease: hidi-pending']); + assert.equal((await runReleasePlease(github, branch, 'hidi')).prs.length, 0); + github.merge(first.prs[0]); + assert.equal((await runReleasePlease(github, branch, 'hidi')).prs.length, 0); + assert.deepEqual(first.prs[0].labels, ['autorelease: hidi-versioned']); + assert.deepEqual(github.labelWrites.slice(0, 2).map(write => write[0]), ['add', 'remove']); + github.change(['scripts/check-nuget-package-published.ps1'], 'fix(hidi): second cycle'); + const second = await runReleasePlease(github, branch, 'hidi'); + const patch = Number(baseline.split('.')[2]); + assert.equal(JSON.parse(second.prs[0].output[hidiManifest])['.'], baseline.replace(/\d+$/, String(patch + 2))); + assert.ok(second.prs[0].body.includes('second cycle')); + assert.ok(!second.prs[0].body.includes('first cycle')); + github.merge(second.prs[0]); + assert.equal((await runReleasePlease(github, branch, 'hidi')).prs.length, 0); + github.change(['src/Microsoft.OpenApi.OData.Reader/OpenApiConvertSettings.cs'], 'fix(odata): after Hidi merges'); + assert.equal((await runReleasePlease(github, branch, 'hidi')).prs.length, 0); + assert.equal((await runReleasePlease(github, branch, 'odata')).prs.length, 1); + assert.deepEqual(github.tags, []); + assert.deepEqual(github.releases, []); +}); + +test('open Hidi PR updates with additional commits instead of opening a duplicate', async () => { + const github = new MemoryGitHub(); + github.change(['Dockerfile'], 'fix(hidi): first fix'); + const first = await runReleasePlease(github, branch, 'hidi'); + github.change(['install-tool.ps1'], 'fix(hidi): additional fix'); + const updated = await runReleasePlease(github, branch, 'hidi'); + assert.equal(updated.prs[0].number, first.prs[0].number); + assert.equal(github.prs.length, 1); + assert.ok(updated.prs[0].body.includes('additional fix')); +}); + +test('unsafe manifest and merged PR state fail without label or release writes', async t => { + for (const kind of ['wrong-major', 'project-version-mismatch', 'missing-checkpoint', 'wrong-branch', 'bad-body', 'future-version', 'duplicate-checkpoint', 'unreachable-checkpoint', 'title-body-mismatch']) { + await t.test(kind, async () => { + const github = new MemoryGitHub(); + github.change(['Dockerfile'], 'fix(hidi): cycle'); + const {prs} = await runReleasePlease(github, branch, 'hidi'); + github.merge(prs[0]); + if (kind === 'wrong-major') github.files[hidiManifest] = '{".":"9.0.0"}'; + if (kind === 'project-version-mismatch') github.files[hidiProject] = github.files[hidiProject].replace(/.*?<\/Version>/, '9.0.0'); + if (kind === 'missing-checkpoint') github.prs = []; + if (kind === 'wrong-branch') prs[0].headBranchName = 'unrelated'; + if (kind === 'bad-body') prs[0].body = 'not a release PR'; + if (kind === 'future-version') github.files[hidiManifest] = fs.readFileSync(path.join(root, hidiManifest), 'utf8'); + if (kind === 'duplicate-checkpoint') github.prs.push({...prs[0], number: 99, sha: 'duplicate'}); + if (kind === 'unreachable-checkpoint') github.commits.shift(); + if (kind === 'title-body-mismatch') prs[0].title = 'chore(main): release hidi 9.0.0'; + await assert.rejects(runReleasePlease(github, branch, 'hidi')); + assert.deepEqual(github.labelWrites, []); + assert.deepEqual(github.releases, []); + }); + + } +}); + +test('merged PR body version must agree with its title even when the title matches the manifest', async () => { + const github = new MemoryGitHub(); + github.change(['Dockerfile'], 'fix(hidi): cycle'); + const {prs} = await runReleasePlease(github, branch, 'hidi'); + github.merge(prs[0]); + const current = JSON.parse(github.files[hidiManifest])['.']; + prs[0].body = prs[0].body.replaceAll(current, current.replace(/\d+$/, patch => Number(patch) + 1)); + await assert.rejects(runReleasePlease(github, branch, 'hidi'), /inconsistent title and body/); + assert.deepEqual(github.labelWrites, []); +}); + +test('unknown component is an explicit failure', async () => { + await assert.rejects(runReleasePlease(new MemoryGitHub(), branch, 'unknown'), /Unknown component/); +}); + +test('missing commit files are an explicit plugin failure', async () => { + const plugin = new ExactPathExclusions(new MemoryGitHub(), branch, {'.': {excludePaths: []}}); + await assert.rejects(plugin.preconfigure({}, {'.': [{sha: 'bad'}]}), /Missing changed files/); +}); + +test('Hidi ignores pending OData PRs and interrupted label transitions are retryable', async () => { + const github = new MemoryGitHub(); + github.change(['Directory.Build.props'], 'fix(odata): root cycle'); + const rootPr = (await runReleasePlease(github, branch, 'odata')).prs[0]; + github.merge(rootPr); + github.change(['Dockerfile'], 'fix(hidi): independent cycle'); + const hidiPr = (await runReleasePlease(github, branch, 'hidi')).prs[0]; + assert.ok(hidiPr); + github.merge(hidiPr); + hidiPr.labels.push('autorelease: hidi-versioned'); + assert.equal((await runReleasePlease(github, branch, 'hidi')).prs.length, 0); + assert.deepEqual(hidiPr.labels, ['autorelease: hidi-versioned']); + assert.deepEqual(rootPr.labels, ['autorelease: pending']); +}); + +test('CLI wiring emits real library PR/release outputs and uses the app token', async t => { + const github = new MemoryGitHub(); + const core = require('@actions/core'); + const saved = {...process.env}; + const argv = process.argv; + t.after(() => { process.env = saved; process.argv = argv; }); + Object.assign(process.env, {RELEASE_PLEASE_TOKEN: 'offline-test-token', GITHUB_REF_NAME: branch, GITHUB_REPOSITORY: 'microsoft/OpenAPI.NET.OData'}); + t.mock.method(GitHub, 'create', async options => { + assert.equal(options.token, 'offline-test-token'); + assert.equal(options.defaultBranch, branch); + return github; + }); + const outputs = {}; + t.mock.method(core, 'setOutput', (key, value) => { outputs[key] = value; }); + process.argv = ['node', 'run.cjs', 'hidi']; + github.change(['Dockerfile'], 'fix(hidi): CLI cycle'); + await main(); + assert.equal(outputs.prs_created, true); + assert.equal(outputs.releases_created, false); + assert.equal(JSON.parse(outputs.prs)[0].headBranchName, `release-please--branches--${branch}--components--hidi`); + assert.equal(outputs.paths_released, '[]'); + process.argv[2] = 'odata'; + github.change(['Directory.Build.props'], 'fix(odata): CLI cycle'); + await main(); + github.merge(github.prs.find(pr => pr.labels.includes('autorelease: pending'))); + await main(); + assert.equal(outputs.releases_created, true); + assert.equal(outputs.release_created, true); + assert.ok(outputs.tag_name.startsWith('v')); + assert.ok(outputs.html_url); + delete process.env.RELEASE_PLEASE_TOKEN; + await assert.rejects(main(), /Missing release automation environment/); +}); diff --git a/.github/workflows/release-please-gha.yml b/.github/workflows/release-please-gha.yml index f503b3d48..73b69d2e5 100644 --- a/.github/workflows/release-please-gha.yml +++ b/.github/workflows/release-please-gha.yml @@ -16,12 +16,35 @@ on: - main - support/v1 - support/v2 + pull_request: + paths: + - .github/release-please/** + - .github/workflows/release-please-gha.yml + - release-please-config.json + - hidi-release-please-config.json + - .release-please-manifest.json + - .hidi-release-please-manifest.json + - Directory.Build.props + - src/Microsoft.OpenApi.Hidi/Microsoft.OpenApi.Hidi.csproj + - src/Microsoft.OpenApi.Hidi/readme.md permissions: contents: read jobs: + release-please-tests: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 + - uses: actions/setup-node@249970729cb0ef3589644e2896645e5dc5ba9c38 # v6 + with: + node-version: 24 + - run: npm ci --ignore-scripts --no-audit --no-fund + working-directory: .github/release-please + - run: npm test + working-directory: .github/release-please check-secret: + if: github.event_name == 'push' runs-on: ubuntu-latest outputs: has-token: ${{ steps.check.outputs.has-token }} @@ -29,12 +52,17 @@ jobs: - id: check run: echo "has-token=${{ secrets.RELEASE_PLEASE_TOKEN_PROVIDER_PEM != '' }}" >> $GITHUB_OUTPUT release-please-master: - needs: check-secret - if: needs.check-secret.outputs.has-token == 'true' + needs: [check-secret, release-please-tests] + if: github.event_name == 'push' && needs.check-secret.outputs.has-token == 'true' runs-on: ubuntu-latest steps: - name: Checkout repository uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 + - uses: actions/setup-node@249970729cb0ef3589644e2896645e5dc5ba9c38 # v6 + with: + node-version: 24 + - run: npm ci --ignore-scripts --no-audit --no-fund + working-directory: .github/release-please - name: Generate GitHub App token id: app-token @@ -44,21 +72,25 @@ jobs: private-key: ${{ secrets.RELEASE_PLEASE_TOKEN_PROVIDER_PEM }} - name: Release Please - uses: googleapis/release-please-action@45996ed1f6d02564a971a2fa1b5860e934307cf7 # v5.0.0 - with: - token: ${{ steps.app-token.outputs.token }} - config-file: release-please-config.json - manifest-file: .release-please-manifest.json - target-branch: ${{ github.ref_name }} + id: release + env: + RELEASE_PLEASE_TOKEN: ${{ steps.app-token.outputs.token }} + run: node .github/release-please/run.cjs odata release-please-hidi: - # Enable only after destination merges and source publishing is cut over. - if: ${{ false }} + needs: [check-secret, release-please-tests] + # Version PRs only; production tags and publishing remain gated. + if: github.event_name == 'push' && needs.check-secret.outputs.has-token == 'true' && (github.ref_name == 'main' || github.ref_name == 'support/v2') runs-on: ubuntu-latest permissions: contents: read steps: - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 + - uses: actions/setup-node@249970729cb0ef3589644e2896645e5dc5ba9c38 # v6 + with: + node-version: 24 + - run: npm ci --ignore-scripts --no-audit --no-fund + working-directory: .github/release-please - name: Generate GitHub App token id: app-token uses: actions/create-github-app-token@bcd2ba49218906704ab6c1aa796996da409d3eb1 # v3.2.0 @@ -66,9 +98,7 @@ jobs: client-id: ${{ vars.RELEASE_PLEASE_TOKEN_PROVIDER_APP_ID }} private-key: ${{ secrets.RELEASE_PLEASE_TOKEN_PROVIDER_PEM }} - name: Release Please (independent hidi version) - uses: googleapis/release-please-action@45996ed1f6d02564a971a2fa1b5860e934307cf7 # v5.0.0 - with: - token: ${{ steps.app-token.outputs.token }} - config-file: hidi-release-please-config.json - manifest-file: .hidi-release-please-manifest.json - target-branch: ${{ github.ref_name }} + id: release + env: + RELEASE_PLEASE_TOKEN: ${{ steps.app-token.outputs.token }} + run: node .github/release-please/run.cjs hidi diff --git a/.github/workflows/sonarcloud.yml b/.github/workflows/sonarcloud.yml index 32ce1a34c..00666d676 100644 --- a/.github/workflows/sonarcloud.yml +++ b/.github/workflows/sonarcloud.yml @@ -49,6 +49,23 @@ jobs: - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 with: fetch-depth: 0 # Shallow clones should be disabled for a better relevancy of analysis + - uses: actions/setup-node@249970729cb0ef3589644e2896645e5dc5ba9c38 # v6 + with: + node-version: 24 + - name: Test release automation with measured JavaScript coverage + shell: pwsh + working-directory: .github/release-please + run: | + New-Item -ItemType Directory -Force ..\..\artifacts\release-please | Out-Null + npm ci --ignore-scripts --no-audit --no-fund + if ($LASTEXITCODE -ne 0) { exit $LASTEXITCODE } + npm run coverage + if ($LASTEXITCODE -ne 0) { exit $LASTEXITCODE } + $lcov = Get-Content ..\..\artifacts\release-please\lcov.info + $sources = @($lcov | Where-Object { $_ -like 'SF:*' }) + if ($sources.Count -ne 1 -or $sources[0] -notmatch '^SF:\.github[\\/]release-please[\\/]run\.cjs$') { + throw 'Expected measured LCOV for the repository-relative release runner.' + } - name: Cache SonarCloud packages uses: actions/cache@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6.1.0 with: @@ -120,7 +137,7 @@ jobs: CoverletOutputFormat: 'opencover' # https://github.com/microsoft/vstest/issues/4014#issuecomment-1307913682 shell: pwsh run: | - dotnet tool run dotnet-sonarscanner begin /k:"microsoft_OpenAPI.NET.OData" /o:"microsoft" /d:sonar.token="${{ secrets.SONAR_TOKEN }}" /d:sonar.host.url="https://sonarcloud.io" /d:sonar.cs.opencover.reportsPaths="test/**/coverage.net8.0.opencover.xml,artifacts/hidi/coverage/*opencover*.xml" /d:sonar.coverageReportPaths="artifacts/hidi/powershell-coverage/sonar-coverage.xml" + dotnet tool run dotnet-sonarscanner begin /k:"microsoft_OpenAPI.NET.OData" /o:"microsoft" /d:sonar.token="${{ secrets.SONAR_TOKEN }}" /d:sonar.host.url="https://sonarcloud.io" /d:sonar.cs.opencover.reportsPaths="test/**/coverage.net8.0.opencover.xml,artifacts/hidi/coverage/*opencover*.xml" /d:sonar.coverageReportPaths="artifacts/hidi/powershell-coverage/sonar-coverage.xml" /d:sonar.javascript.lcov.reportPaths="artifacts/release-please/lcov.info" /d:sonar.test.inclusions="test/**,**/run.test.cjs" if ($LASTEXITCODE -ne 0) { exit $LASTEXITCODE } dotnet workload restore if ($LASTEXITCODE -ne 0) { exit $LASTEXITCODE } diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 334509bee..956ee9807 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -47,4 +47,56 @@ The recommended commit types used are: - __ci__ for CI configuration file changes e.g. updating a pipeline - __chore__ for miscallaneous non-sdk changesin the repo e.g. removing an unused file -Adding an exclamation mark after the commit type (`feat!`) or footer with the prefix __BREAKING CHANGE:__ will cause an increment of the _major_ version. \ No newline at end of file +Adding an exclamation mark after the commit type (`feat!`) or footer with the prefix __BREAKING CHANGE:__ will cause an increment of the _major_ version. + +## Independent Hidi version automation + +OData and Hidi retain separate root release-please configs and version manifests. +Hidi's package directory is deliberately `.`: a package rooted at +`src/Microsoft.OpenApi.Hidi` would miss its tests, Dockerfile, installer and +NuGet helper outside that directory. Routing is based on changed files, not the +optional Conventional Commit scope. A mixed commit can affect both components. + +The pinned runner in `.github/release-please` uses release-please's registered +plugin API to apply `exclude-paths` to exact files as well as directories. +The upstream engine's directory-only matching does not exclude a root filename. +Hidi source, tests, readme, Docker distribution, installer, public identity, +local NuGet config, private-feed helper and Hidi release config/pipeline affect +only Hidi. OData source/tests/docs, its release config/manifest/changelog and +`Directory.Build.props` affect only OData. Shared root README, contribution +guidance, solution, SDK and build files can affect both; shared GitHub CI and +the OData CI pipeline do not trigger releases. Existing OData exclusions, +including its public signing key, remain in place. + +The OData job still creates GitHub releases before opening version PRs. +The Hidi job opens **version PRs only**, with separate component branches and +`autorelease: hidi-pending` labels. After a version PR merges, the runner verifies +its parsed version against the Hidi manifest, uses that merge as the next commit +boundary, and changes its label to `autorelease: hidi-versioned`. No Hidi tag or +GitHub release is created, and Hidi labels cannot block OData automation. +Missing, inconsistent or unreachable checkpoints fail rather than replaying +old commits. Production publishing and cutover remain separately gated. + +Hidi starts at the already-published 3.10.2 on `main` and 2.12.2 on `support/v2`. +Fixes increment its patch; features increment its minor. Generated versions must +remain above the migration floor and within that branch's major, matching the +official pipeline's `hidi-v3.*` / `hidi-v2.*` contracts. A breaking-change major +bump fails before opening a version PR; moving to a new major requires a separate +branch/pipeline decision. Hidi PRs update the project ``, its manifest +and changelog, and annotated install examples, not OData's version or Hidi's +upstream package dependency versions. + +Run the offline regression tests with Node 24: + +```powershell +Push-Location .github\release-please +npm ci --ignore-scripts --no-audit --no-fund +npm test +Pop-Location +``` + +These tests exercise the pinned engine's actual plans and XML/changelog updates, +including two merged Hidi version-PR cycles without tags. The release workflow +runs them before any API writes, including on relevant pull requests. Sonar also +runs measured native Node coverage and imports its LCOV report alongside the +existing C# and PowerShell coverage; the runner is not excluded from analysis. \ No newline at end of file diff --git a/README.md b/README.md index e3b392206..054766700 100644 --- a/README.md +++ b/README.md @@ -94,6 +94,9 @@ The NuGet package remains `Microsoft.OpenApi.Hidi` and the command remains `hidi Hidi 3.x is maintained on `main`; Hidi 2.x is maintained on `support/v2`. Both tracks use independent versions and require the .NET 8 runtime. Building this repository, including the Hidi tests, requires the .NET 10 SDK. +Hidi's release-please version PRs update its own project, manifest and changelog; +OData retains separate versioning. See [independent Hidi version automation](CONTRIBUTING.md#independent-hidi-version-automation) +for changed-file routing and the tag-free version-PR lifecycle. Destination Hidi release publishing is disabled during the migration; the source repository remains intact until the destination PRs are completed. diff --git a/hidi-release-please-config.json b/hidi-release-please-config.json index 457dc5244..3bfeb2ac6 100644 --- a/hidi-release-please-config.json +++ b/hidi-release-please-config.json @@ -1,11 +1,14 @@ { "$schema": "https://raw.githubusercontent.com/googleapis/release-please/main/schemas/config.json", "bootstrap-sha": "5574ccc6d8d129d7a49729619fac3e3e36d334fd", + "plugins": ["exact-path-exclusions"], + "separate-pull-requests": true, + "label": "autorelease: hidi-pending", "release-type": "simple", "include-component-in-tag": true, "include-v-in-tag": true, "exclude-paths": [ - ".azure-pipelines", + ".azure-pipelines/ci-build.yml", ".github", ".idea", ".vs", @@ -13,10 +16,15 @@ "src/Microsoft.OpenApi.OData.Reader", "src/OoasGui", "src/OoasUtil", + "src/AssemblyInfo", "test/Microsoft.OpenAPI.OData.Reader.Tests", "docs", "CHANGELOG.md", "Directory.Build.props", + "redocly.yaml", + ".redocly.lint-ignore.yaml", + "tool/Microsoft.OpenApi.OData.snk", + "tool/35MSSharedLib1024.snk", "release-please-config.json", ".release-please-manifest.json" ], @@ -30,6 +38,10 @@ "type": "xml", "path": "src/Microsoft.OpenApi.Hidi/Microsoft.OpenApi.Hidi.csproj", "xpath": "//Project/PropertyGroup/Version" + }, + { + "type": "generic", + "path": "src/Microsoft.OpenApi.Hidi/readme.md" } ] } diff --git a/release-please-config.json b/release-please-config.json index 75e417d68..093f3458c 100644 --- a/release-please-config.json +++ b/release-please-config.json @@ -1,5 +1,6 @@ { "bootstrap-sha": "4f9bad6ea7d25e8596c0ca214975e690d925e6e7", + "plugins": ["exact-path-exclusions"], "exclude-paths": [ ".azure-pipelines", ".github", @@ -18,6 +19,8 @@ "Dockerfile", ".dockerignore", "install-tool.ps1", + "scripts/check-nuget-package-published.ps1", + "test/scripts/check-nuget-package-published.Tests.ps1", "hidi-release-please-config.json", ".hidi-release-please-manifest.json" ], diff --git a/src/Microsoft.OpenApi.Hidi/readme.md b/src/Microsoft.OpenApi.Hidi/readme.md index 249af7bb2..1f2e5e7ed 100644 --- a/src/Microsoft.OpenApi.Hidi/readme.md +++ b/src/Microsoft.OpenApi.Hidi/readme.md @@ -20,14 +20,14 @@ from NuGet. Hidi 3.x is maintained on this repository's `main` branch and requir ### .NET CLI(Global) ```bash -dotnet tool install --global Microsoft.OpenApi.Hidi --version 3.10.2 +dotnet tool install --global Microsoft.OpenApi.Hidi --version 3.10.2 # x-release-please-version ``` ### .NET CLI(local) ```bash dotnet new tool-manifest # if the repository does not have a tool manifest -dotnet tool install --local Microsoft.OpenApi.Hidi --version 3.10.2 +dotnet tool install --local Microsoft.OpenApi.Hidi --version 3.10.2 # x-release-please-version ``` ### Build and install from this repository From 6d21bbecdc813480b2366a67222ce92ca033eb53 Mon Sep 17 00:00:00 2001 From: "Gavin Barron (from Dev Box)" Date: Fri, 9 Oct 2026 11:33:54 -0700 Subject: [PATCH 2/4] fix(hidi): bootstrap version labels and isolate legacy tag history Create only the two verified Hidi lifecycle labels, retain tag-free version cycles after baseline advances, and retire the duplicate unfiltered OData tag writer and its GitHub-release-only consumer. Keep official publishing gates unchanged. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> Copilot-Session: 5aef9099-c268-492f-a58a-b591c916f1bc --- .github/release-please/package.json | 2 +- .github/release-please/run.cjs | 38 ++++++- .github/release-please/run.test.cjs | 154 +++++++++++++++++++++++++++- .github/workflows/ci-cd.yml | 79 +------------- CONTRIBUTING.md | 7 ++ 5 files changed, 195 insertions(+), 85 deletions(-) diff --git a/.github/release-please/package.json b/.github/release-please/package.json index 41a63ea61..2fdafb092 100644 --- a/.github/release-please/package.json +++ b/.github/release-please/package.json @@ -3,7 +3,7 @@ "private": true, "scripts": { "test": "node --test run.test.cjs", - "coverage": "cd ../.. && node --test --experimental-test-coverage --test-coverage-include=.github/release-please/run.cjs --test-coverage-lines=80 --test-coverage-functions=80 --test-reporter=spec --test-reporter=lcov --test-reporter-destination=stdout --test-reporter-destination=artifacts/release-please/lcov.info .github/release-please/run.test.cjs" + "coverage": "node -e \"require('node:fs').mkdirSync('../../artifacts/release-please', {recursive: true})\" && cd ../.. && node --test --experimental-test-coverage --test-coverage-include=.github/release-please/run.cjs --test-coverage-lines=80 --test-coverage-functions=80 --test-reporter=spec --test-reporter=lcov --test-reporter-destination=stdout --test-reporter-destination=artifacts/release-please/lcov.info .github/release-please/run.test.cjs" }, "dependencies": { "@actions/core": "1.11.1", diff --git a/.github/release-please/run.cjs b/.github/release-please/run.cjs index 4db731d86..67a344ae2 100644 --- a/.github/release-please/run.cjs +++ b/.github/release-please/run.cjs @@ -8,6 +8,41 @@ const HIDI_PENDING = 'autorelease: hidi-pending'; const HIDI_VERSIONED = 'autorelease: hidi-versioned'; const HIDI_FLOORS = {'main': '3.10.2', 'support/v2': '2.12.2'}; +async function ensureHidiLabels(token, owner, repo, request = fetch) { + const api = (process.env.GITHUB_API_URL || 'https://api.github.com').replace(/\/$/, ''); + const url = `${api}/repos/${encodeURIComponent(owner)}/${encodeURIComponent(repo)}/labels`; + const headers = { + Authorization: `Bearer ${token}`, + Accept: 'application/vnd.github+json', + 'X-GitHub-Api-Version': '2022-11-28' + }; + for (const label of [ + {name: HIDI_PENDING, color: 'fbca04', description: 'Pending independent Hidi version pull request'}, + {name: HIDI_VERSIONED, color: '0e8a16', description: 'Merged Hidi version pull request; no production release'} + ]) { + const labelUrl = `${url}/${encodeURIComponent(label.name)}`; + let response = await request(labelUrl, {headers}); + let expectedStatus = 200; + if (response.status === 404) { + response = await request(url, { + method: 'POST', headers: {...headers, 'Content-Type': 'application/json'}, + body: JSON.stringify(label) + }); + if (response.status === 422) { + // Another branch job may have created the same label concurrently. + response = await request(labelUrl, {headers}); + } else if (response.status !== 201) { + throw new Error(`Cannot create Hidi lifecycle label '${label.name}': HTTP ${response.status}`); + } else { + expectedStatus = 201; + } + } + if (response.status !== expectedStatus || (await response.json()).name !== label.name) { + throw new Error(`Cannot verify Hidi lifecycle label '${label.name}': HTTP ${response.status}`); + } + } +} + class ExactPathExclusions extends ManifestPlugin { async preconfigure(strategies, commitsByPath) { for (const [path, config] of Object.entries(this.repositoryConfig)) { @@ -144,6 +179,7 @@ async function main() { const branch = process.env.GITHUB_REF_NAME; const [owner, repo] = (process.env.GITHUB_REPOSITORY || '').split('/'); if (!token || !branch || !owner || !repo) throw new Error('Missing release automation environment'); + if (process.argv[2] === 'hidi') await ensureHidiLabels(token, owner, repo); const github = await GitHub.create({owner, repo, token, defaultBranch: branch}); const {releases, prs} = await runReleasePlease(github, branch, process.argv[2]); core.setOutput('releases_created', releases.length > 0); @@ -161,7 +197,7 @@ async function main() { } } -module.exports = {ExactPathExclusions, prepareHidiVersionPrs, runReleasePlease, main}; +module.exports = {ExactPathExclusions, prepareHidiVersionPrs, runReleasePlease, ensureHidiLabels, main}; if (require.main === module) { main().catch(error => require('@actions/core').setFailed(error.message)); } diff --git a/.github/release-please/run.test.cjs b/.github/release-please/run.test.cjs index 6058e8701..3f27f02c8 100644 --- a/.github/release-please/run.test.cjs +++ b/.github/release-please/run.test.cjs @@ -3,7 +3,9 @@ const fs = require('node:fs'); const path = require('node:path'); const {test} = require('node:test'); const {GitHub, Manifest, setLogger} = require('release-please'); -const {runReleasePlease, main, ExactPathExclusions} = require('./run.cjs'); +const {Version} = require('release-please/build/src/version'); +const {PullRequestBody} = require('release-please/build/src/util/pull-request-body'); +const {runReleasePlease, main, ExactPathExclusions, ensureHidiLabels} = require('./run.cjs'); setLogger({debug() {}, info() {}, warn() {}, error() {}}); const root = path.resolve(__dirname, '..', '..'); @@ -20,7 +22,7 @@ const inputPaths = [ ]; class MemoryGitHub { - constructor() { + constructor(hidiVersion) { this.repository = {owner: 'microsoft', repo: 'OpenAPI.NET.OData', defaultBranch: branch}; this.files = Object.fromEntries(inputPaths.map(file => [file, fs.readFileSync(path.join(root, file), 'utf8')])); this.commits = ['hidi-release-please-config.json', 'release-please-config.json'].map(file => ({ @@ -31,6 +33,24 @@ class MemoryGitHub { this.tags = []; this.labelWrites = []; this.nextPr = 1; + if (hidiVersion) { + this.files[hidiManifest] = JSON.stringify({'.': hidiVersion}); + this.files[hidiProject] = this.files[hidiProject].replace(/.*?<\/Version>/, `${hidiVersion}`); + } + const current = JSON.parse(this.files[hidiManifest])['.']; + const floor = branch === 'main' ? '3.10.2' : '2.12.2'; + if (current !== floor) { + const checkpoint = { + number: 0, state: 'MERGED', sha: 'initial-hidi-checkpoint', + headBranchName: `release-please--branches--${branch}--components--hidi`, + baseBranchName: branch, + title: `chore(${branch}): release hidi ${current}`, + body: new PullRequestBody([{component: 'hidi', version: Version.parse(current), notes: 'Previously merged version'}], {useComponents: true}).toString(), + labels: ['autorelease: hidi-versioned'], files: [hidiManifest, hidiProject] + }; + this.prs.push(checkpoint); + this.commits.unshift({sha: checkpoint.sha, message: checkpoint.title, files: checkpoint.files, pullRequest: checkpoint}); + } } async getFileJson(file) { return JSON.parse(this.files[file]); } async getFileContentsOnBranch(file) { @@ -165,6 +185,20 @@ test('mixed changes affect both components; excluded-only and empty changes affe assert.equal((await plans(github, 'hidi')).length, 0); }); +test('an OData fix after Hidi features keeps the OData patch and changelog independent', async () => { + const github = new MemoryGitHub(); + const current = JSON.parse(github.files[odataManifest])['.']; + github.change(['Dockerfile'], 'feat(hidi): independent feature before root fix'); + github.change(['Directory.Build.props'], 'fix(odata): library fix after Hidi'); + const [pr] = await plans(github, 'odata'); + assert.equal(pr.version.toString(), current.replace(/\d+$/, patch => Number(patch) + 1)); + assert.ok(pr.body.toString().includes('library fix after Hidi')); + assert.ok(!pr.body.toString().includes('independent feature')); + const workflow = fs.readFileSync(path.join(root, '.github', 'workflows', 'ci-cd.yml'), 'utf8'); + assert.ok(!workflow.includes('mathieudutour/github-tag-action')); + assert.ok(!workflow.includes('softprops/action-gh-release')); +}); + test('actual Hidi patch output changes only its version, manifest, changelog and install examples', async () => { const github = new MemoryGitHub(); const baseline = github.files[hidiProject]; @@ -182,7 +216,8 @@ test('actual Hidi patch output changes only its version, manifest, changelog and assert.match(output[hidiChangelog], new RegExp(`hidi-v${oldVersion}\\.\\.\\.hidi-v${next}`)); assert.equal(JSON.parse(output[hidiManifest])['.'], next); assert.ok(output[hidiReadme].includes(`--version ${next}`)); - assert.ok(output[hidiReadme].includes(`YamlReader\` ${branch === 'main' ? '3.10.2' : '2.12.2'}`)); + const unannotatedLines = text => text.split(/\r?\n/).filter(line => !line.includes('x-release-please-version')); + assert.deepEqual(unannotatedLines(output[hidiReadme]), unannotatedLines(github.files[hidiReadme])); }); test('actual OData output and componentless tags retain existing behavior', async () => { @@ -212,10 +247,32 @@ test('Hidi feature release increments minor; breaking changes fail before writin github.commits.shift(); github.change(['src/Microsoft.OpenApi.Hidi/Program.cs'], 'feat(hidi)!: incompatible feature'); await assert.rejects(runReleasePlease(github, branch, 'hidi'), /outside the branch major/); - assert.equal(github.prs.length, 0); + assert.equal(github.prs.filter(pr => pr.state === 'OPEN').length, 0); assert.equal(github.releases.length, 0); }); +test('pure Hidi fix and feature release plans retain the official pipeline tag convention', async () => { + const pipeline = fs.readFileSync(path.join(root, '.azure-pipelines', 'hidi-release.yml'), 'utf8'); + const floor = branch === 'main' ? '3.10.2' : '2.12.2'; + assert.ok(pipeline.includes(`[version]'${floor}'`)); + assert.ok(pipeline.includes(`hidiPublishingEnabled: 'false'`)); + for (const type of ['fix', 'feat']) { + const github = new MemoryGitHub(); + const [major, minor, patch] = JSON.parse(github.files[hidiManifest])['.'].split('.').map(Number); + const next = type === 'fix' ? `${major}.${minor}.${patch + 1}` : `${major}.${minor + 1}.0`; + assert.ok(pipeline.includes(`- hidi-v${major}.*`)); + github.change(['Dockerfile'], `${type}(hidi): tag plan`); + const {prs} = await runReleasePlease(github, branch, 'hidi'); + github.merge(prs[0]); + const manifest = await Manifest.fromManifest(github, branch, 'hidi-release-please-config.json', hidiManifest); + const [release] = await manifest.buildReleases(); + assert.equal(release.tag.toString(), `hidi-v${next}`); + assert.match(release.notes, new RegExp(`hidi-v${major}\\.${minor}\\.${patch}\\.\\.\\.hidi-v${next}`)); + assert.deepEqual(github.tags, []); + assert.deepEqual(github.releases, []); + } +}); + test('two tag-free Hidi version cycles do not replay commits or block OData', async () => { const github = new MemoryGitHub(); const baseline = JSON.parse(github.files[hidiManifest])['.']; @@ -243,6 +300,20 @@ test('two tag-free Hidi version cycles do not replay commits or block OData', as assert.deepEqual(github.releases, []); }); +test('version automation and its fixtures keep working after the repository manifest advances', async () => { + const current = JSON.parse(fs.readFileSync(path.join(root, hidiManifest), 'utf8'))['.']; + const advanced = current.replace(/\d+$/, patch => Number(patch) + 1); + const next = current.replace(/\d+$/, patch => Number(patch) + 2); + const github = new MemoryGitHub(advanced); + github.change(['Dockerfile'], 'fix(hidi): after an existing version checkpoint'); + const {prs, releases} = await runReleasePlease(github, branch, 'hidi'); + assert.equal(JSON.parse(prs[0].output[hidiManifest])['.'], next); + assert.deepEqual(releases, []); + github.merge(prs[0]); + assert.equal((await runReleasePlease(github, branch, 'hidi')).prs.length, 0); + assert.deepEqual(github.tags, []); +}); + test('open Hidi PR updates with additional commits instead of opening a duplicate', async () => { const github = new MemoryGitHub(); github.change(['Dockerfile'], 'fix(hidi): first fix'); @@ -250,7 +321,7 @@ test('open Hidi PR updates with additional commits instead of opening a duplicat github.change(['install-tool.ps1'], 'fix(hidi): additional fix'); const updated = await runReleasePlease(github, branch, 'hidi'); assert.equal(updated.prs[0].number, first.prs[0].number); - assert.equal(github.prs.length, 1); + assert.equal(github.prs.filter(pr => pr.state === 'OPEN').length, 1); assert.ok(updated.prs[0].body.includes('additional fix')); }); @@ -313,6 +384,71 @@ test('Hidi ignores pending OData PRs and interrupted label transitions are retry assert.deepEqual(rootPr.labels, ['autorelease: pending']); }); +test('Hidi lifecycle labels are created using the authenticated GitHub REST API only when missing', async () => { + const calls = []; + const labels = new Set(); + const request = async (url, options) => { + assert.equal(options.headers.Authorization, 'Bearer offline-test-token'); + assert.equal(options.headers['X-GitHub-Api-Version'], '2022-11-28'); + calls.push([url, options.method || 'GET']); + if (options.method === 'POST') { + const label = JSON.parse(options.body); + assert.ok(['autorelease: hidi-pending', 'autorelease: hidi-versioned'].includes(label.name)); + labels.add(label.name); + return Response.json(label, {status: 201}); + } + const name = decodeURIComponent(url.split('/').at(-1)); + return labels.has(name) ? Response.json({name}) : Response.json({}, {status: 404}); + }; + await ensureHidiLabels('offline-test-token', 'microsoft', 'OpenAPI.NET.OData', request); + assert.deepEqual(calls.map(call => call[1]), ['GET', 'POST', 'GET', 'POST']); + assert.ok(calls[0][0].endsWith('/labels/autorelease%3A%20hidi-pending')); + calls.length = 0; + await ensureHidiLabels('offline-test-token', 'microsoft', 'OpenAPI.NET.OData', request); + assert.deepEqual(calls.map(call => call[1]), ['GET', 'GET']); +}); + +test('Hidi label bootstrap fails explicitly on permissions, network errors or invalid responses', async t => { + for (const status of [401, 403, 500]) { + await t.test(`read HTTP ${status}`, async () => { + await assert.rejects(ensureHidiLabels('token', 'owner', 'repo', + async () => Response.json({}, {status})), new RegExp(`HTTP ${status}`)); + }); + } + await t.test('creation permissions', async () => { + await assert.rejects(ensureHidiLabels('token', 'owner', 'repo', + async (url, options) => Response.json({}, {status: options.method === 'POST' ? 403 : 404})), + /Cannot create.*HTTP 403/); + }); + await t.test('network error', async () => { + await assert.rejects(ensureHidiLabels('token', 'owner', 'repo', + async () => { throw new Error('offline connection failed'); }), /offline connection failed/); + }); + await t.test('unexpected label', async () => { + await assert.rejects(ensureHidiLabels('token', 'owner', 'repo', + async () => Response.json({name: 'autorelease: pending'})), /Cannot verify/); + }); + await t.test('invalid JSON', async () => { + await assert.rejects(ensureHidiLabels('token', 'owner', 'repo', + async () => new Response('invalid JSON')), SyntaxError); + }); +}); + +test('concurrent Hidi label creation is accepted only after verifying the exact existing label', async () => { + const existing = new Set(); + await ensureHidiLabels('token', 'owner', 'repo', async (url, options) => { + if (options.method === 'POST') { + existing.add(JSON.parse(options.body).name); + return Response.json({}, {status: 422}); + } + const name = decodeURIComponent(url.split('/').at(-1)); + return existing.has(name) ? Response.json({name}) : Response.json({}, {status: 404}); + }); + await assert.rejects(ensureHidiLabels('token', 'owner', 'repo', + async (url, options) => Response.json({}, {status: options.method === 'POST' ? 422 : 404})), + /Cannot verify.*HTTP 404/); +}); + test('CLI wiring emits real library PR/release outputs and uses the app token', async t => { const github = new MemoryGitHub(); const core = require('@actions/core'); @@ -320,6 +456,13 @@ test('CLI wiring emits real library PR/release outputs and uses the app token', const argv = process.argv; t.after(() => { process.env = saved; process.argv = argv; }); Object.assign(process.env, {RELEASE_PLEASE_TOKEN: 'offline-test-token', GITHUB_REF_NAME: branch, GITHUB_REPOSITORY: 'microsoft/OpenAPI.NET.OData'}); + let labelReads = 0; + t.mock.method(globalThis, 'fetch', async (url, options) => { + labelReads++; + assert.equal(options.headers.Authorization, 'Bearer offline-test-token'); + assert.equal(options.method, undefined); + return Response.json({name: decodeURIComponent(url.split('/').at(-1))}); + }); t.mock.method(GitHub, 'create', async options => { assert.equal(options.token, 'offline-test-token'); assert.equal(options.defaultBranch, branch); @@ -343,6 +486,7 @@ test('CLI wiring emits real library PR/release outputs and uses the app token', assert.equal(outputs.release_created, true); assert.ok(outputs.tag_name.startsWith('v')); assert.ok(outputs.html_url); + assert.equal(labelReads, 2); delete process.env.RELEASE_PLEASE_TOKEN; await assert.rejects(main(), /Missing release automation environment/); }); diff --git a/.github/workflows/ci-cd.yml b/.github/workflows/ci-cd.yml index 05205e8ea..37a019bec 100644 --- a/.github/workflows/ci-cd.yml +++ b/.github/workflows/ci-cd.yml @@ -9,9 +9,6 @@ jobs: ci: name: Continuous Integration runs-on: ubuntu-latest - outputs: - latest_version: ${{ steps.tag_generator.outputs.new_version }} - is_default_branch: ${{ steps.conditionals_handler.outputs.is_default_branch }} env: ARTIFACTS_FOLDER: ${{ github.workspace }}/Artifacts GITHUB_RUN_NUMBER: ${{ github.run_number }} @@ -23,27 +20,6 @@ jobs: 8.0.x 10.0.x - - name: Data gatherer - id: data_gatherer - shell: pwsh - run: | - # Get default branch - $repo = 'microsoft/OpenAPI.NET.OData' - $defaultBranch = Invoke-RestMethod -Method GET -Uri https://api.github.com/repos/$repo | Select-Object -ExpandProperty default_branch - Write-Output "default_branch=$(echo $defaultBranch) >> $GITHUB_OUTPUT" - - - name: Conditionals handler - id: conditionals_handler - shell: pwsh - run: | - $defaultBranch = "${{ steps.data_gatherer.outputs.default_branch }}" - $githubRef = "${{ github.ref }}" - $isDefaultBranch = 'false' - if ( $githubRef -like "*$defaultBranch*" ) { - $isDefaultBranch = 'true' - } - Write-Output "is_default_branch=$(echo $isDefaultBranch) >> $GITHUB_OUTPUT" - - name: Checkout repository id: checkout_repo uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 @@ -51,15 +27,6 @@ jobs: token: ${{ secrets.GITHUB_TOKEN }} fetch-depth: 0 - - if: steps.conditionals_handler.outputs.is_default_branch == 'true' - name: Bump GH tag - id: tag_generator - uses: mathieudutour/github-tag-action@af99e60ce8132224b8e6ebab5023449fe256ed46 # v7.0.0 - with: - github_token: ${{ secrets.GITHUB_TOKEN }} - default_bump: false - release_branches: ${{ steps.data_gatherer.outputs.default_branch }} - - name: Build projects id: build_projects shell: pwsh @@ -67,15 +34,9 @@ jobs: $projectsArray = @( '.\src\Microsoft.OpenApi.OData.Reader\Microsoft.OpenAPI.OData.Reader.csproj' ) - $gitNewVersion = if ("${{ steps.tag_generator.outputs.new_version }}") {"${{ steps.tag_generator.outputs.new_version }}"} else {$null} - $projectCurrentVersion = ([xml](Get-Content .\src\Microsoft.OpenApi.OData.Reader\Microsoft.OpenAPI.OData.Reader.csproj)).Project.PropertyGroup.Version - $projectNewVersion = $gitNewVersion ?? $projectCurrentVersion - $projectsArray | ForEach-Object { dotnet build $PSItem ` - -c Release # ` - # -o $env:ARTIFACTS_FOLDER ` - # /p:Version=$projectNewVersion + -c Release if ($LASTEXITCODE -ne 0) { exit $LASTEXITCODE } } @@ -223,42 +184,4 @@ jobs: throw "Expected OpenAPI 3.0, /Todos paths and schemas in the Docker CSDL YAML output." } - cd: - if: needs.ci.outputs.is_default_branch == 'true' && needs.ci.outputs.latest_version != '' - name: Continuous Deployment - needs: ci - runs-on: ubuntu-latest - steps: - # - name: Download and extract NuGet packages - # id: dl_packages_artifact - # uses: actions/download-artifact@v2 - # with: - # name: NuGet packages - # path: NuGet/ - - # - name: Push NuGet packages to NuGet.org - # id: push_nuget_packages - # continue-on-error: true - # shell: pwsh - # run: | - # Get-ChildItem NuGet/*.nupkg | ForEach-Object { - # nuget push $PSItem ` - # -ApiKey $env:NUGET_API_KEY ` - # -Source https://api.nuget.org/v3/index.json - # } - # env: - # NUGET_API_KEY: ${{ secrets.NUGET_API_KEY }} - - - name: Create and publish release - id: create_release - uses: softprops/action-gh-release@efb35369e0ad2afab669f228072c1b0d510eae64 # v3.0.3 - with: - name: OpenAPI.Net.OData v${{ needs.ci.outputs.latest_version }} - tag_name: v${{ needs.ci.outputs.latest_version }} - # files: | - # NuGet/Microsoft.OpenApi.${{ needs.ci.outputs.latest_version }}.nupkg - # NuGet/Microsoft.OpenApi.Readers.${{ needs.ci.outputs.latest_version }}.nupkg - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - # Built with ❤ by [Pipeline Foundation](https://pipeline.foundation) \ No newline at end of file diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 956ee9807..3eeb22a64 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -69,6 +69,9 @@ the OData CI pipeline do not trigger releases. Existing OData exclusions, including its public signing key, remain in place. The OData job still creates GitHub releases before opening version PRs. +It is the sole authority for OData tags/releases: the duplicate legacy tag writer +and its downstream GitHub-release-only job were retired from CI/CD. Otherwise, +that writer could count Hidi features when a later OData fix arrived. The Hidi job opens **version PRs only**, with separate component branches and `autorelease: hidi-pending` labels. After a version PR merges, the runner verifies its parsed version against the Hidi manifest, uses that merge as the next commit @@ -76,6 +79,10 @@ boundary, and changes its label to `autorelease: hidi-versioned`. No Hidi tag or GitHub release is created, and Hidi labels cannot block OData automation. Missing, inconsistent or unreachable checkpoints fail rather than replaying old commits. Production publishing and cutover remain separately gated. +The Hidi job verifies or creates only `autorelease: hidi-pending` and +`autorelease: hidi-versioned` through the GitHub labels REST API. Permission, +network or unexpected-response failures stop the job; no broader permissions +are requested and the existing OData labels are untouched. Hidi starts at the already-published 3.10.2 on `main` and 2.12.2 on `support/v2`. Fixes increment its patch; features increment its minor. Generated versions must From 6c34176c33645548608544c6e5e3c5133f9567b4 Mon Sep 17 00:00:00 2001 From: "Gavin Barron (from Dev Box)" Date: Fri, 9 Oct 2026 11:57:43 -0700 Subject: [PATCH 3/4] fix(hidi): use standard multi-component release-please config Follow the supplied migration reference with two packages and versions in one config and manifest. Retain separate-pull-requests only as the stock-engine compatibility setting for OData componentless tags; restore accepted workflows and remove the superseded custom runner and duplicated Hidi release scaffolding. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> Copilot-Session: 5aef9099-c268-492f-a58a-b591c916f1bc --- .github/release-please/package-lock.json | 1855 ---------------------- .github/release-please/package.json | 12 - .github/release-please/run.cjs | 203 --- .github/release-please/run.test.cjs | 492 ------ .github/workflows/ci-cd.yml | 79 +- .github/workflows/release-please-gha.yml | 66 +- .github/workflows/sonarcloud.yml | 19 +- .hidi-release-please-manifest.json | 3 - .release-please-manifest.json | 3 +- CONTRIBUTING.md | 77 +- README.md | 3 - hidi-release-please-config.json | 49 - release-please-config.json | 53 +- src/Microsoft.OpenApi.Hidi/readme.md | 4 +- 14 files changed, 144 insertions(+), 2774 deletions(-) delete mode 100644 .github/release-please/package-lock.json delete mode 100644 .github/release-please/package.json delete mode 100644 .github/release-please/run.cjs delete mode 100644 .github/release-please/run.test.cjs delete mode 100644 .hidi-release-please-manifest.json delete mode 100644 hidi-release-please-config.json diff --git a/.github/release-please/package-lock.json b/.github/release-please/package-lock.json deleted file mode 100644 index ed84c9cb2..000000000 --- a/.github/release-please/package-lock.json +++ /dev/null @@ -1,1855 +0,0 @@ -{ - "name": "openapi-odata-release-automation", - "lockfileVersion": 3, - "requires": true, - "packages": { - "": { - "name": "openapi-odata-release-automation", - "dependencies": { - "@actions/core": "1.11.1", - "release-please": "17.6.0" - } - }, - "node_modules/@actions/core": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@actions/core/-/core-1.11.1.tgz", - "integrity": "sha512-hXJCSrkwfA46Vd9Z3q4cpEpHB1rL5NG04+/rbqW9d3+CSvtB1tYe8UTpAlixa1vj0m/ULglfEK2UKxMGxCxv5A==", - "dependencies": { - "@actions/exec": "^1.1.1", - "@actions/http-client": "^2.0.1" - } - }, - "node_modules/@actions/exec": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/@actions/exec/-/exec-1.1.1.tgz", - "integrity": "sha512-+sCcHHbVdk93a0XT19ECtO/gIXoxvdsgQLzb2fE2/5sIZmWQuluYyjPQtrtTHdU1YzTZ7bAPN4sITq2xi1679w==", - "dependencies": { - "@actions/io": "^1.0.1" - } - }, - "node_modules/@actions/http-client": { - "version": "2.2.3", - "resolved": "https://registry.npmjs.org/@actions/http-client/-/http-client-2.2.3.tgz", - "integrity": "sha512-mx8hyJi/hjFvbPokCg4uRd4ZX78t+YyRPtnKWwIl+RzNaVuFpQHfmlGVfsKEJN8LwTCvL+DfVgAM04XaHkm6bA==", - "dependencies": { - "tunnel": "^0.0.6", - "undici": "^5.25.4" - } - }, - "node_modules/@actions/io": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/@actions/io/-/io-1.1.3.tgz", - "integrity": "sha512-wi9JjgKLYS7U/z8PPbco+PvTb/nRWjeoFlJ1Qer83k/3C5PHQi28hiVdeE2kHXmIL99mQFawx8qt/JPjZilJ8Q==" - }, - "node_modules/@babel/code-frame": { - "version": "7.29.7", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.29.7.tgz", - "integrity": "sha512-Aup7aUOfpbAUg2ROOJN6Iw5f9DMBlzu0mIkm/malLQFN/YQgO48wCj0Kxa3sEHJvPVFg7siR+qRInwXd2qhQKw==", - "dependencies": { - "@babel/helper-validator-identifier": "^7.29.7", - "js-tokens": "^4.0.0", - "picocolors": "^1.1.1" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-validator-identifier": { - "version": "7.29.7", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.29.7.tgz", - "integrity": "sha512-qehxGkRj55h/ff8EMaJ+cYhyaKlHIxqYDn682wQD7RNp9UujOQsHog2uS0r2vzr4pW+sXf90NeeayjcNaX3fFg==", - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@conventional-commits/parser": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/@conventional-commits/parser/-/parser-0.4.1.tgz", - "integrity": "sha512-H2ZmUVt6q+KBccXfMBhbBF14NlANeqHTXL4qCL6QGbMzrc4HDXyzWuxPxPNbz71f/5UkR5DrycP5VO9u7crahg==", - "dependencies": { - "unist-util-visit": "^2.0.3", - "unist-util-visit-parents": "^3.1.1" - } - }, - "node_modules/@fastify/busboy": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/@fastify/busboy/-/busboy-2.1.1.tgz", - "integrity": "sha512-vBZP4NlzfOlerQTnba4aqZoMhE/a9HY7HRqoOPaETQcSQuWEIyZMHGfVu6w9wGtGK5fED5qRs2DteVCjOH60sA==", - "engines": { - "node": ">=14" - } - }, - "node_modules/@google-automations/git-file-utils": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/@google-automations/git-file-utils/-/git-file-utils-3.2.1.tgz", - "integrity": "sha512-LYOjAnGu/xtEkYYh6W3/1RmeK9HB/fV+xMe7nHc+WiDYrnxAJWBfcyUucoJtYS8XAhVUzNWrQvYDPRbxe67DNQ==", - "dependencies": { - "@octokit/rest": "^20.1.1", - "minimatch": "^10.2.4" - }, - "engines": { - "node": ">= 22" - } - }, - "node_modules/@iarna/toml": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/@iarna/toml/-/toml-3.0.0.tgz", - "integrity": "sha512-td6ZUkz2oS3VeleBcN+m//Q6HlCFCPrnI0FZhrt/h4XqLEdOyYp2u21nd8MdsR+WJy5r9PTDaHTDDfhf4H4l6Q==" - }, - "node_modules/@jsep-plugin/assignment": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/@jsep-plugin/assignment/-/assignment-1.3.0.tgz", - "integrity": "sha512-VVgV+CXrhbMI3aSusQyclHkenWSAm95WaiKrMxRFam3JSUiIaQjoMIw2sEs/OX4XifnqeQUN4DYbJjlA8EfktQ==", - "engines": { - "node": ">= 10.16.0" - }, - "peerDependencies": { - "jsep": "^0.4.0||^1.0.0" - } - }, - "node_modules/@jsep-plugin/regex": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/@jsep-plugin/regex/-/regex-1.0.4.tgz", - "integrity": "sha512-q7qL4Mgjs1vByCaTnDFcBnV9HS7GVPJX5vyVoCgZHNSC9rjwIlmbXG5sUuorR5ndfHAIlJ8pVStxvjXHbNvtUg==", - "engines": { - "node": ">= 10.16.0" - }, - "peerDependencies": { - "jsep": "^0.4.0||^1.0.0" - } - }, - "node_modules/@octokit/auth-token": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/@octokit/auth-token/-/auth-token-4.0.0.tgz", - "integrity": "sha512-tY/msAuJo6ARbK6SPIxZrPBms3xPbfwBrulZe0Wtr/DIY9lje2HeV1uoebShn6mx7SjCHif6EjMvoREj+gZ+SA==", - "engines": { - "node": ">= 18" - } - }, - "node_modules/@octokit/core": { - "version": "5.2.2", - "resolved": "https://registry.npmjs.org/@octokit/core/-/core-5.2.2.tgz", - "integrity": "sha512-/g2d4sW9nUDJOMz3mabVQvOGhVa4e/BN/Um7yca9Bb2XTzPPnfTWHWQg+IsEYO7M3Vx+EXvaM/I2pJWIMun1bg==", - "dependencies": { - "@octokit/auth-token": "^4.0.0", - "@octokit/graphql": "^7.1.0", - "@octokit/request": "^8.4.1", - "@octokit/request-error": "^5.1.1", - "@octokit/types": "^13.0.0", - "before-after-hook": "^2.2.0", - "universal-user-agent": "^6.0.0" - }, - "engines": { - "node": ">= 18" - } - }, - "node_modules/@octokit/endpoint": { - "version": "9.0.6", - "resolved": "https://registry.npmjs.org/@octokit/endpoint/-/endpoint-9.0.6.tgz", - "integrity": "sha512-H1fNTMA57HbkFESSt3Y9+FBICv+0jFceJFPWDePYlR/iMGrwM5ph+Dd4XRQs+8X+PUFURLQgX9ChPfhJ/1uNQw==", - "dependencies": { - "@octokit/types": "^13.1.0", - "universal-user-agent": "^6.0.0" - }, - "engines": { - "node": ">= 18" - } - }, - "node_modules/@octokit/graphql": { - "version": "7.1.1", - "resolved": "https://registry.npmjs.org/@octokit/graphql/-/graphql-7.1.1.tgz", - "integrity": "sha512-3mkDltSfcDUoa176nlGoA32RGjeWjl3K7F/BwHwRMJUW/IteSa4bnSV8p2ThNkcIcZU2umkZWxwETSSCJf2Q7g==", - "dependencies": { - "@octokit/request": "^8.4.1", - "@octokit/types": "^13.0.0", - "universal-user-agent": "^6.0.0" - }, - "engines": { - "node": ">= 18" - } - }, - "node_modules/@octokit/openapi-types": { - "version": "24.2.0", - "resolved": "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-24.2.0.tgz", - "integrity": "sha512-9sIH3nSUttelJSXUrmGzl7QUBFul0/mB8HRYl3fOlgHbIWG+WnYDXU3v/2zMtAvuzZ/ed00Ei6on975FhBfzrg==" - }, - "node_modules/@octokit/plugin-paginate-rest": { - "version": "11.4.4-cjs.2", - "resolved": "https://registry.npmjs.org/@octokit/plugin-paginate-rest/-/plugin-paginate-rest-11.4.4-cjs.2.tgz", - "integrity": "sha512-2dK6z8fhs8lla5PaOTgqfCGBxgAv/le+EhPs27KklPhm1bKObpu6lXzwfUEQ16ajXzqNrKMujsFyo9K2eaoISw==", - "dependencies": { - "@octokit/types": "^13.7.0" - }, - "engines": { - "node": ">= 18" - }, - "peerDependencies": { - "@octokit/core": "5" - } - }, - "node_modules/@octokit/plugin-request-log": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/@octokit/plugin-request-log/-/plugin-request-log-4.0.1.tgz", - "integrity": "sha512-GihNqNpGHorUrO7Qa9JbAl0dbLnqJVrV8OXe2Zm5/Y4wFkZQDfTreBzVmiRfJVfE4mClXdihHnbpyyO9FSX4HA==", - "engines": { - "node": ">= 18" - }, - "peerDependencies": { - "@octokit/core": "5" - } - }, - "node_modules/@octokit/plugin-rest-endpoint-methods": { - "version": "13.3.2-cjs.1", - "resolved": "https://registry.npmjs.org/@octokit/plugin-rest-endpoint-methods/-/plugin-rest-endpoint-methods-13.3.2-cjs.1.tgz", - "integrity": "sha512-VUjIjOOvF2oELQmiFpWA1aOPdawpyaCUqcEBc/UOUnj3Xp6DJGrJ1+bjUIIDzdHjnFNO6q57ODMfdEZnoBkCwQ==", - "dependencies": { - "@octokit/types": "^13.8.0" - }, - "engines": { - "node": ">= 18" - }, - "peerDependencies": { - "@octokit/core": "^5" - } - }, - "node_modules/@octokit/request": { - "version": "8.4.1", - "resolved": "https://registry.npmjs.org/@octokit/request/-/request-8.4.1.tgz", - "integrity": "sha512-qnB2+SY3hkCmBxZsR/MPCybNmbJe4KAlfWErXq+rBKkQJlbjdJeS85VI9r8UqeLYLvnAenU8Q1okM/0MBsAGXw==", - "dependencies": { - "@octokit/endpoint": "^9.0.6", - "@octokit/request-error": "^5.1.1", - "@octokit/types": "^13.1.0", - "universal-user-agent": "^6.0.0" - }, - "engines": { - "node": ">= 18" - } - }, - "node_modules/@octokit/request-error": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/@octokit/request-error/-/request-error-5.1.1.tgz", - "integrity": "sha512-v9iyEQJH6ZntoENr9/yXxjuezh4My67CBSu9r6Ve/05Iu5gNgnisNWOsoJHTP6k0Rr0+HQIpnH+kyammu90q/g==", - "dependencies": { - "@octokit/types": "^13.1.0", - "deprecation": "^2.0.0", - "once": "^1.4.0" - }, - "engines": { - "node": ">= 18" - } - }, - "node_modules/@octokit/rest": { - "version": "20.1.2", - "resolved": "https://registry.npmjs.org/@octokit/rest/-/rest-20.1.2.tgz", - "integrity": "sha512-GmYiltypkHHtihFwPRxlaorG5R9VAHuk/vbszVoRTGXnAsY60wYLkh/E2XiFmdZmqrisw+9FaazS1i5SbdWYgA==", - "dependencies": { - "@octokit/core": "^5.0.2", - "@octokit/plugin-paginate-rest": "11.4.4-cjs.2", - "@octokit/plugin-request-log": "^4.0.0", - "@octokit/plugin-rest-endpoint-methods": "13.3.2-cjs.1" - }, - "engines": { - "node": ">= 18" - } - }, - "node_modules/@octokit/types": { - "version": "13.10.0", - "resolved": "https://registry.npmjs.org/@octokit/types/-/types-13.10.0.tgz", - "integrity": "sha512-ifLaO34EbbPj0Xgro4G5lP5asESjwHracYJvVaPIyXMuiuXLlhic3S47cBdTb+jfODkTE5YtGCLt3Ay3+J97sA==", - "dependencies": { - "@octokit/openapi-types": "^24.2.0" - } - }, - "node_modules/@types/minimist": { - "version": "1.2.5", - "resolved": "https://registry.npmjs.org/@types/minimist/-/minimist-1.2.5.tgz", - "integrity": "sha512-hov8bUuiLiyFPGyFPE1lwWhmzYbirOXQNNo40+y3zow8aFVTeyn3VWL0VFFfdNddA8S4Vf0Tc062rzyNr7Paag==" - }, - "node_modules/@types/normalize-package-data": { - "version": "2.4.4", - "resolved": "https://registry.npmjs.org/@types/normalize-package-data/-/normalize-package-data-2.4.4.tgz", - "integrity": "sha512-37i+OaWTh9qeK4LSHPsyRC7NahnGotNuZvjLSgcPzblpHB3rrCJxAOgI5gCdKm7coonsaX1Of0ILiTcnZjbfxA==" - }, - "node_modules/@types/npm-package-arg": { - "version": "6.1.4", - "resolved": "https://registry.npmjs.org/@types/npm-package-arg/-/npm-package-arg-6.1.4.tgz", - "integrity": "sha512-vDgdbMy2QXHnAruzlv68pUtXCjmqUk3WrBAsRboRovsOmxbfn/WiYCjmecyKjGztnMps5dWp4Uq2prp+Ilo17Q==" - }, - "node_modules/@types/unist": { - "version": "2.0.11", - "resolved": "https://registry.npmjs.org/@types/unist/-/unist-2.0.11.tgz", - "integrity": "sha512-CmBKiL6NNo/OqgmMn95Fk9Whlp2mtvIv+KNpQKN2F4SjvrEesubTRWGYSg+BnWZOnlCaSTU1sMpsBOzgbYhnsA==" - }, - "node_modules/@types/yargs": { - "version": "16.0.11", - "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-16.0.11.tgz", - "integrity": "sha512-sbtvk8wDN+JvEdabmZExoW/HNr1cB7D/j4LT08rMiuikfA7m/JNJg7ATQcgzs34zHnoScDkY0ZRSl29Fkmk36g==", - "dependencies": { - "@types/yargs-parser": "*" - } - }, - "node_modules/@types/yargs-parser": { - "version": "21.0.3", - "resolved": "https://registry.npmjs.org/@types/yargs-parser/-/yargs-parser-21.0.3.tgz", - "integrity": "sha512-I4q9QU9MQv4oEOz4tAHJtNz1cwuLxn2F3xcc2iV5WdqLPpUnj30aUuxt1mAxYTG+oe8CZMV/+6rU4S4gRDzqtQ==" - }, - "node_modules/@xmldom/xmldom": { - "version": "0.8.15", - "resolved": "https://registry.npmjs.org/@xmldom/xmldom/-/xmldom-0.8.15.tgz", - "integrity": "sha512-/5NV/vDALVFDXgLmfsy9TRCBlKwO2LNBFzpzvb9iIj+jR+eSc6DLYYvVOdivT/jm7MtU6TebYuRmzEOI7w40UA==", - "engines": { - "node": ">=10.0.0" - } - }, - "node_modules/agent-base": { - "version": "7.1.4", - "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-7.1.4.tgz", - "integrity": "sha512-MnA+YT8fwfJPgBx3m60MNqakm30XOkyIoH1y6huTQvC0PwZG7ki8NacLBcrPbNoo8vEZy7Jpuk7+jMO+CUovTQ==", - "engines": { - "node": ">= 14" - } - }, - "node_modules/ansi-regex": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", - "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", - "engines": { - "node": ">=8" - } - }, - "node_modules/ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dependencies": { - "color-convert": "^2.0.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/argparse": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", - "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==" - }, - "node_modules/array-ify": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/array-ify/-/array-ify-1.0.0.tgz", - "integrity": "sha512-c5AMf34bKdvPhQ7tBGhqkgKNUzMr4WUs+WDtC2ZUGOUncbxKMTvqxYctiseW3+L4bA8ec+GcZ6/A/FW4m8ukng==" - }, - "node_modules/arrify": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/arrify/-/arrify-1.0.1.tgz", - "integrity": "sha512-3CYzex9M9FGQjCGMGyi6/31c8GJbgb0qGyrx5HWxPd0aCwh4cB2YjMb2Xf9UuoogrMrlO9cTqnB5rI5GHZTcUA==", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/async-retry": { - "version": "1.3.3", - "resolved": "https://registry.npmjs.org/async-retry/-/async-retry-1.3.3.tgz", - "integrity": "sha512-wfr/jstw9xNi/0teMHrRW7dsz3Lt5ARhYNZ2ewpadnhaIp5mbALhOAP+EAdsC7t4Z6wqsDVv9+W6gm1Dk9mEyw==", - "dependencies": { - "retry": "0.13.1" - } - }, - "node_modules/balanced-match": { - "version": "4.0.4", - "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-4.0.4.tgz", - "integrity": "sha512-BLrgEcRTwX2o6gGxGOCNyMvGSp35YofuYzw9h1IMTRmKqttAZZVU67bdb9Pr2vUHA8+j3i2tJfjO6C6+4myGTA==", - "engines": { - "node": "18 || 20 || >=22" - } - }, - "node_modules/before-after-hook": { - "version": "2.2.3", - "resolved": "https://registry.npmjs.org/before-after-hook/-/before-after-hook-2.2.3.tgz", - "integrity": "sha512-NzUnlZexiaH/46WDhANlyR2bXRopNg4F/zuSA3OpZnllCUgRaOF2znDioDWrmbNVsuZk6l9pMquQB38cfBZwkQ==" - }, - "node_modules/boolbase": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/boolbase/-/boolbase-1.0.0.tgz", - "integrity": "sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww==" - }, - "node_modules/brace-expansion": { - "version": "5.0.12", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-5.0.12.tgz", - "integrity": "sha512-YovQ3rzhaLMIrDjNDMkNS01tea93qhEhG5xy8f6+R0l+dw3Ki+5sCoIoI942iuLZTHWogWktgwVDhU09iNEimQ==", - "dependencies": { - "balanced-match": "^4.0.2" - }, - "engines": { - "node": "20 || >=22" - } - }, - "node_modules/camelcase": { - "version": "5.3.1", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", - "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", - "engines": { - "node": ">=6" - } - }, - "node_modules/camelcase-keys": { - "version": "6.2.2", - "resolved": "https://registry.npmjs.org/camelcase-keys/-/camelcase-keys-6.2.2.tgz", - "integrity": "sha512-YrwaA0vEKazPBkn0ipTiMpSajYDSe+KjQfrjhcBMxJt/znbvlHd8Pw/Vamaz5EB4Wfhs3SUR3Z9mwRu/P3s3Yg==", - "dependencies": { - "camelcase": "^5.3.1", - "map-obj": "^4.0.0", - "quick-lru": "^4.0.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" - } - }, - "node_modules/cliui": { - "version": "8.0.1", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz", - "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==", - "dependencies": { - "string-width": "^4.2.0", - "strip-ansi": "^6.0.1", - "wrap-ansi": "^7.0.0" - }, - "engines": { - "node": ">=12" - } - }, - "node_modules/code-suggester": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/code-suggester/-/code-suggester-5.0.1.tgz", - "integrity": "sha512-8qJiiSCfkbPNWvjEFzdG1UW3axL+Bs0ldV1/TdlBKmF9I/a/WooSQZQCi9M44HoXbVTQesn/IQr6+nIWNnVIWA==", - "dependencies": { - "@octokit/rest": "^20.1.2", - "@types/yargs": "^16.0.0", - "async-retry": "^1.3.1", - "diff": "^8.0.3", - "glob": "^7.1.6", - "parse-diff": "^0.11.0", - "yargs": "^16.0.0" - }, - "bin": { - "code-suggester": "build/src/bin/code-suggester.js" - }, - "engines": { - "node": ">=18.0.0" - } - }, - "node_modules/code-suggester/node_modules/cliui": { - "version": "7.0.4", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-7.0.4.tgz", - "integrity": "sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==", - "dependencies": { - "string-width": "^4.2.0", - "strip-ansi": "^6.0.0", - "wrap-ansi": "^7.0.0" - } - }, - "node_modules/code-suggester/node_modules/yargs": { - "version": "16.2.2", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-16.2.2.tgz", - "integrity": "sha512-Nt9ZJjXTv5R8MHbqby/wXQ6Gi0Bb3TcYZkR1bzuL4yB2OxWPkXknz513gEF0GoA6tn00UpbPvERW8rzCuWCA6w==", - "dependencies": { - "cliui": "^7.0.2", - "escalade": "^3.1.1", - "get-caller-file": "^2.0.5", - "require-directory": "^2.1.1", - "string-width": "^4.2.0", - "y18n": "^5.0.5", - "yargs-parser": "^20.2.2" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dependencies": { - "color-name": "~1.1.4" - }, - "engines": { - "node": ">=7.0.0" - } - }, - "node_modules/color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" - }, - "node_modules/compare-func": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/compare-func/-/compare-func-2.0.0.tgz", - "integrity": "sha512-zHig5N+tPWARooBnb0Zx1MFcdfpyJrfTJ3Y5L+IFvUm8rM74hHz66z0gw0x4tijh5CorKkKUCnW82R2vmpeCRA==", - "dependencies": { - "array-ify": "^1.0.0", - "dot-prop": "^5.1.0" - } - }, - "node_modules/concat-map": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", - "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==" - }, - "node_modules/conventional-changelog-conventionalcommits": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/conventional-changelog-conventionalcommits/-/conventional-changelog-conventionalcommits-6.1.0.tgz", - "integrity": "sha512-3cS3GEtR78zTfMzk0AizXKKIdN4OvSh7ibNz6/DPbhWWQu7LqE/8+/GqSodV+sywUR2gpJAdP/1JFf4XtN7Zpw==", - "dependencies": { - "compare-func": "^2.0.0" - }, - "engines": { - "node": ">=14" - } - }, - "node_modules/conventional-changelog-writer": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/conventional-changelog-writer/-/conventional-changelog-writer-6.0.1.tgz", - "integrity": "sha512-359t9aHorPw+U+nHzUXHS5ZnPBOizRxfQsWT5ZDHBfvfxQOAik+yfuhKXG66CN5LEWPpMNnIMHUTCKeYNprvHQ==", - "dependencies": { - "conventional-commits-filter": "^3.0.0", - "dateformat": "^3.0.3", - "handlebars": "^4.7.7", - "json-stringify-safe": "^5.0.1", - "meow": "^8.1.2", - "semver": "^7.0.0", - "split": "^1.0.1" - }, - "bin": { - "conventional-changelog-writer": "cli.js" - }, - "engines": { - "node": ">=14" - } - }, - "node_modules/conventional-commits-filter": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/conventional-commits-filter/-/conventional-commits-filter-3.0.0.tgz", - "integrity": "sha512-1ymej8b5LouPx9Ox0Dw/qAO2dVdfpRFq28e5Y0jJEU8ZrLdy0vOSkkIInwmxErFGhg6SALro60ZrwYFVTUDo4Q==", - "dependencies": { - "lodash.ismatch": "^4.4.0", - "modify-values": "^1.0.1" - }, - "engines": { - "node": ">=14" - } - }, - "node_modules/css-select": { - "version": "5.2.2", - "resolved": "https://registry.npmjs.org/css-select/-/css-select-5.2.2.tgz", - "integrity": "sha512-TizTzUddG/xYLA3NXodFM0fSbNizXjOKhqiQQwvhlspadZokn1KDy0NZFS0wuEubIYAV5/c1/lAr0TaaFXEXzw==", - "dependencies": { - "boolbase": "^1.0.0", - "css-what": "^6.1.0", - "domhandler": "^5.0.2", - "domutils": "^3.0.1", - "nth-check": "^2.0.1" - }, - "funding": { - "url": "https://github.com/sponsors/fb55" - } - }, - "node_modules/css-what": { - "version": "6.2.2", - "resolved": "https://registry.npmjs.org/css-what/-/css-what-6.2.2.tgz", - "integrity": "sha512-u/O3vwbptzhMs3L1fQE82ZSLHQQfto5gyZzwteVIEyeaY5Fc7R4dapF/BvRoSYFeqfBk4m0V1Vafq5Pjv25wvA==", - "engines": { - "node": ">= 6" - }, - "funding": { - "url": "https://github.com/sponsors/fb55" - } - }, - "node_modules/dateformat": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/dateformat/-/dateformat-3.0.3.tgz", - "integrity": "sha512-jyCETtSl3VMZMWeRo7iY1FL19ges1t55hMo5yaam4Jrsm5EPL89UQkoQRyiI+Yf4k8r2ZpdngkV8hr1lIdjb3Q==", - "engines": { - "node": "*" - } - }, - "node_modules/debug": { - "version": "4.4.3", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz", - "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==", - "dependencies": { - "ms": "^2.1.3" - }, - "engines": { - "node": ">=6.0" - }, - "peerDependenciesMeta": { - "supports-color": { - "optional": true - } - } - }, - "node_modules/decamelize": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", - "integrity": "sha512-z2S+W9X73hAUUki+N+9Za2lBlun89zigOyGrsax+KUQ6wKW4ZoWpEYBkGhQjwAjjDCkWxhY0VKEhk8wzY7F5cA==", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/decamelize-keys": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/decamelize-keys/-/decamelize-keys-1.1.1.tgz", - "integrity": "sha512-WiPxgEirIV0/eIOMcnFBA3/IJZAZqKnwAwWyvvdi4lsr1WCN22nhdf/3db3DoZcUjTV2SqfzIwNyp6y2xs3nmg==", - "dependencies": { - "decamelize": "^1.1.0", - "map-obj": "^1.0.0" - }, - "engines": { - "node": ">=0.10.0" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/decamelize-keys/node_modules/map-obj": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/map-obj/-/map-obj-1.0.1.tgz", - "integrity": "sha512-7N/q3lyZ+LVCp7PzuxrJr4KMbBE2hW7BT7YNia330OFxIf4d3r5zVpicP2650l7CPN6RM9zOJRl3NGpqSiw3Eg==", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/deprecation": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/deprecation/-/deprecation-2.3.1.tgz", - "integrity": "sha512-xmHIy4F3scKVwMsQ4WnVaS8bHOx0DmVwRywosKhaILI0ywMDWPtBSku2HNxRvF7jtwDRsoEwYQSfbxj8b7RlJQ==" - }, - "node_modules/detect-indent": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/detect-indent/-/detect-indent-6.1.0.tgz", - "integrity": "sha512-reYkTUJAZb9gUuZ2RvVCNhVHdg62RHnJ7WJl8ftMi4diZ6NWlciOzQN88pUhSELEwflJht4oQDv0F0BMlwaYtA==", - "engines": { - "node": ">=8" - } - }, - "node_modules/diff": { - "version": "8.0.4", - "resolved": "https://registry.npmjs.org/diff/-/diff-8.0.4.tgz", - "integrity": "sha512-DPi0FmjiSU5EvQV0++GFDOJ9ASQUVFh5kD+OzOnYdi7n3Wpm9hWWGfB/O2blfHcMVTL5WkQXSnRiK9makhrcnw==", - "engines": { - "node": ">=0.3.1" - } - }, - "node_modules/dom-serializer": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-2.0.0.tgz", - "integrity": "sha512-wIkAryiqt/nV5EQKqQpo3SToSOV9J0DnbJqwK7Wv/Trc92zIAYZ4FlMu+JPFW1DfGFt81ZTCGgDEabffXeLyJg==", - "dependencies": { - "domelementtype": "^2.3.0", - "domhandler": "^5.0.2", - "entities": "^4.2.0" - }, - "funding": { - "url": "https://github.com/cheeriojs/dom-serializer?sponsor=1" - } - }, - "node_modules/domelementtype": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-2.3.0.tgz", - "integrity": "sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/fb55" - } - ] - }, - "node_modules/domhandler": { - "version": "5.0.3", - "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-5.0.3.tgz", - "integrity": "sha512-cgwlv/1iFQiFnU96XXgROh8xTeetsnJiDsTc7TYCLFd9+/WNkIqPTxiM/8pSd8VIrhXGTf1Ny1q1hquVqDJB5w==", - "dependencies": { - "domelementtype": "^2.3.0" - }, - "engines": { - "node": ">= 4" - }, - "funding": { - "url": "https://github.com/fb55/domhandler?sponsor=1" - } - }, - "node_modules/domutils": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/domutils/-/domutils-3.2.2.tgz", - "integrity": "sha512-6kZKyUajlDuqlHKVX1w7gyslj9MPIXzIFiz/rGu35uC1wMi+kMhQwGhl4lt9unC9Vb9INnY9Z3/ZA3+FhASLaw==", - "dependencies": { - "dom-serializer": "^2.0.0", - "domelementtype": "^2.3.0", - "domhandler": "^5.0.3" - }, - "funding": { - "url": "https://github.com/fb55/domutils?sponsor=1" - } - }, - "node_modules/dot-prop": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/dot-prop/-/dot-prop-5.3.0.tgz", - "integrity": "sha512-QM8q3zDe58hqUqjraQOmzZ1LIH9SWQJTlEKCH4kJ2oQvLZk7RbQXvtDM2XEq3fwkV9CCvvH4LA0AV+ogFsBM2Q==", - "dependencies": { - "is-obj": "^2.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/emoji-regex": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==" - }, - "node_modules/entities": { - "version": "4.5.0", - "resolved": "https://registry.npmjs.org/entities/-/entities-4.5.0.tgz", - "integrity": "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==", - "engines": { - "node": ">=0.12" - }, - "funding": { - "url": "https://github.com/fb55/entities?sponsor=1" - } - }, - "node_modules/error-ex": { - "version": "1.3.4", - "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.4.tgz", - "integrity": "sha512-sqQamAnR14VgCr1A618A3sGrygcpK+HEbenA/HiEAkkUwcZIIB/tgWqHFxWgOyDh4nB4JCRimh79dR5Ywc9MDQ==", - "dependencies": { - "is-arrayish": "^0.2.1" - } - }, - "node_modules/es-errors": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz", - "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==", - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/escalade": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz", - "integrity": "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==", - "engines": { - "node": ">=6" - } - }, - "node_modules/escape-string-regexp": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", - "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", - "engines": { - "node": ">=0.8.0" - } - }, - "node_modules/figures": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/figures/-/figures-3.2.0.tgz", - "integrity": "sha512-yaduQFRKLXYOGgEn6AZau90j3ggSOyiqXU0F9JZfeXYhNa+Jk4X+s45A2zg5jns87GAFa34BBm2kXw4XpNcbdg==", - "dependencies": { - "escape-string-regexp": "^1.0.5" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/find-up": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", - "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", - "dependencies": { - "locate-path": "^5.0.0", - "path-exists": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/fs.realpath": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", - "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==" - }, - "node_modules/function-bind": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", - "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/get-caller-file": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", - "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", - "engines": { - "node": "6.* || 8.* || >= 10.*" - } - }, - "node_modules/glob": { - "version": "7.2.3", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", - "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", - "deprecated": "Old versions of glob are not supported, and contain widely publicized security vulnerabilities, which have been fixed in the current version. Please update. Support for old versions may be purchased (at exorbitant rates) by contacting i@izs.me", - "dependencies": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.1.1", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - }, - "engines": { - "node": "*" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/glob/node_modules/balanced-match": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", - "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==" - }, - "node_modules/glob/node_modules/brace-expansion": { - "version": "1.1.21", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.21.tgz", - "integrity": "sha512-9zeA+KLZNNzglF2TPKRQEDyx6Yby7daAkuy8MiPzpXPsYDWi/DRM8jmwUDxokQjYqBpv5DgPiwD4h4ZZSy1Ujw==", - "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } - }, - "node_modules/glob/node_modules/minimatch": { - "version": "3.1.5", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.5.tgz", - "integrity": "sha512-VgjWUsnnT6n+NUk6eZq77zeFdpW2LWDzP6zFGrCbHXiYNul5Dzqk2HHQ5uFH2DNW5Xbp8+jVzaeNt94ssEEl4w==", - "dependencies": { - "brace-expansion": "^1.1.7" - }, - "engines": { - "node": "*" - } - }, - "node_modules/handlebars": { - "version": "4.7.10", - "resolved": "https://registry.npmjs.org/handlebars/-/handlebars-4.7.10.tgz", - "integrity": "sha512-P5VJMVM7qgBn6vjXMw8WG9uVI+ncf2pi72j4de4yz5ZULLj2RGqLYaKOYGsgyrViQ0tePOVlN1tDCCXXtFqXKg==", - "dependencies": { - "minimist": "^1.2.8", - "neo-async": "^2.6.2", - "source-map": "^0.6.1", - "wordwrap": "^1.0.0" - }, - "bin": { - "handlebars": "bin/handlebars" - }, - "engines": { - "node": ">=0.4.7" - }, - "optionalDependencies": { - "uglify-js": "^3.1.4" - } - }, - "node_modules/hard-rejection": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/hard-rejection/-/hard-rejection-2.1.0.tgz", - "integrity": "sha512-VIZB+ibDhx7ObhAe7OVtoEbuP4h/MuOTHJ+J8h/eBXotJYl0fBgR72xDFCKgIh22OJZIOVNxBMWuhAr10r8HdA==", - "engines": { - "node": ">=6" - } - }, - "node_modules/has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "engines": { - "node": ">=8" - } - }, - "node_modules/hasown": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.4.tgz", - "integrity": "sha512-T2UbfbBEF32wiepXIsMlTW9+dDYC6wMh/t/vYA4tuOMKqWz/n3vr1NFSxQiyP+zk2mXsoMA/i/7qV6LKut1t1A==", - "dependencies": { - "function-bind": "^1.1.2" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/he": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/he/-/he-1.2.0.tgz", - "integrity": "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==", - "bin": { - "he": "bin/he" - } - }, - "node_modules/hosted-git-info": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-4.1.0.tgz", - "integrity": "sha512-kyCuEOWjJqZuDbRHzL8V93NzQhwIB71oFWSyzVo+KPZI+pnQPPxucdkrOZvkLRnrf5URsQM+IJ09Dw29cRALIA==", - "dependencies": { - "lru-cache": "^6.0.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/http-proxy-agent": { - "version": "7.0.2", - "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-7.0.2.tgz", - "integrity": "sha512-T1gkAiYYDWYx3V5Bmyu7HcfcvL7mUrTWiM6yOfa3PIphViJ/gFPbvidQ+veqSOHci/PxBcDabeUNCzpOODJZig==", - "dependencies": { - "agent-base": "^7.1.0", - "debug": "^4.3.4" - }, - "engines": { - "node": ">= 14" - } - }, - "node_modules/https-proxy-agent": { - "version": "7.0.6", - "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-7.0.6.tgz", - "integrity": "sha512-vK9P5/iUfdl95AI+JVyUuIcVtd4ofvtrOr3HNtM2yxC9bnMbEdp3x01OhQNnjb8IJYi38VlTE3mBXwcfvywuSw==", - "dependencies": { - "agent-base": "^7.1.2", - "debug": "4" - }, - "engines": { - "node": ">= 14" - } - }, - "node_modules/indent-string": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-4.0.0.tgz", - "integrity": "sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==", - "engines": { - "node": ">=8" - } - }, - "node_modules/inflight": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", - "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", - "deprecated": "This module is not supported, and leaks memory. Do not use it. Check out lru-cache if you want a good and tested way to coalesce async requests by a key value, which is much more comprehensive and powerful.", - "dependencies": { - "once": "^1.3.0", - "wrappy": "1" - } - }, - "node_modules/inherits": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", - "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" - }, - "node_modules/is-arrayish": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", - "integrity": "sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==" - }, - "node_modules/is-core-module": { - "version": "2.17.0", - "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.17.0.tgz", - "integrity": "sha512-J/vG0zBCbIKOQFfufSwyXdMrsohyJIUNkrnmo6WZGzoM7tr/lsbfW5b2BvisL6zsyMzK9UxV9L6c7AoFbyXHOA==", - "dependencies": { - "hasown": "^2.0.4" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-fullwidth-code-point": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", - "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", - "engines": { - "node": ">=8" - } - }, - "node_modules/is-obj": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/is-obj/-/is-obj-2.0.0.tgz", - "integrity": "sha512-drqDG3cbczxxEJRoOXcOjtdp1J/lyp1mNn0xaznRs8+muBhgQcrnbspox5X5fOw0HnMnbfDzvnEMEtqDEJEo8w==", - "engines": { - "node": ">=8" - } - }, - "node_modules/is-plain-obj": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-1.1.0.tgz", - "integrity": "sha512-yvkRyxmFKEOQ4pNXCmJG5AEQNlXJS5LaONXo5/cLdTZdWvsZ1ioJEonLGAosKlMWE8lwUy/bJzMjcw8az73+Fg==", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/js-tokens": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", - "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==" - }, - "node_modules/js-yaml": { - "version": "4.3.2", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.3.2.tgz", - "integrity": "sha512-SFNOvSJ+Dgf/9An904Yx+CgSlIPCkIpao4qo51lpee25TIRejdH3rhR4EZMGoNx3/TP3O+wzWuiTFl4sqbltzA==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/puzrin" - }, - { - "type": "github", - "url": "https://github.com/sponsors/nodeca" - } - ], - "dependencies": { - "argparse": "^2.0.1" - }, - "bin": { - "js-yaml": "bin/js-yaml.js" - } - }, - "node_modules/jsep": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/jsep/-/jsep-1.4.0.tgz", - "integrity": "sha512-B7qPcEVE3NVkmSJbaYxvv4cHkVW7DQsZz13pUMrfS8z8Q/BuShN+gcTXrUlPiGqM2/t/EEaI030bpxMqY8gMlw==", - "engines": { - "node": ">= 10.16.0" - } - }, - "node_modules/json-parse-even-better-errors": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz", - "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==" - }, - "node_modules/json-stringify-safe": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", - "integrity": "sha512-ZClg6AaYvamvYEE82d3Iyd3vSSIjQ+odgjaTzRuO3s7toCdFKczob2i0zCh7JE8kWn17yvAWhUVxvqGwUalsRA==" - }, - "node_modules/jsonpath-plus": { - "version": "10.4.0", - "resolved": "https://registry.npmjs.org/jsonpath-plus/-/jsonpath-plus-10.4.0.tgz", - "integrity": "sha512-T92WWatJXmhBbKsgH/0hl+jxjdXrifi5IKeMY02DWggRxX0UElcbVzPlmgLTbvsPeW1PasQ6xE2Q75stkhGbsA==", - "dependencies": { - "@jsep-plugin/assignment": "^1.3.0", - "@jsep-plugin/regex": "^1.0.4", - "jsep": "^1.4.0" - }, - "bin": { - "jsonpath": "bin/jsonpath-cli.js", - "jsonpath-plus": "bin/jsonpath-cli.js" - }, - "engines": { - "node": ">=18.0.0" - } - }, - "node_modules/kind-of": { - "version": "6.0.3", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", - "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/lines-and-columns": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz", - "integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==" - }, - "node_modules/locate-path": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", - "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", - "dependencies": { - "p-locate": "^4.1.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/lodash.ismatch": { - "version": "4.4.0", - "resolved": "https://registry.npmjs.org/lodash.ismatch/-/lodash.ismatch-4.4.0.tgz", - "integrity": "sha512-fPMfXjGQEV9Xsq/8MTSgUf255gawYRbjwMyDbcvDhXgV7enSZA0hynz6vMPnpAb5iONEzBHBPsT+0zes5Z301g==" - }, - "node_modules/lru-cache": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", - "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", - "dependencies": { - "yallist": "^4.0.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/map-obj": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/map-obj/-/map-obj-4.3.0.tgz", - "integrity": "sha512-hdN1wVrZbb29eBGiGjJbeP8JbKjq1urkHJ/LIP/NY48MZ1QVXUsQBV1G1zvYFHn1XE06cwjBsOI2K3Ulnj1YXQ==", - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/meow": { - "version": "8.1.2", - "resolved": "https://registry.npmjs.org/meow/-/meow-8.1.2.tgz", - "integrity": "sha512-r85E3NdZ+mpYk1C6RjPFEMSE+s1iZMuHtsHAqY0DT3jZczl0diWUZ8g6oU7h0M9cD2EL+PzaYghhCLzR0ZNn5Q==", - "dependencies": { - "@types/minimist": "^1.2.0", - "camelcase-keys": "^6.2.2", - "decamelize-keys": "^1.1.0", - "hard-rejection": "^2.1.0", - "minimist-options": "4.1.0", - "normalize-package-data": "^3.0.0", - "read-pkg-up": "^7.0.1", - "redent": "^3.0.0", - "trim-newlines": "^3.0.0", - "type-fest": "^0.18.0", - "yargs-parser": "^20.2.3" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/meow/node_modules/type-fest": { - "version": "0.18.1", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.18.1.tgz", - "integrity": "sha512-OIAYXk8+ISY+qTOwkHtKqzAuxchoMiD9Udx+FSGQDuiRR+PJKJHc2NJAXlbhkGwTt/4/nKZxELY1w3ReWOL8mw==", - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/min-indent": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/min-indent/-/min-indent-1.0.1.tgz", - "integrity": "sha512-I9jwMn07Sy/IwOj3zVkVik2JTvgpaykDZEigL6Rx6N9LbMywwUSMtxET+7lVoDLLd3O3IXwJwvuuns8UB/HeAg==", - "engines": { - "node": ">=4" - } - }, - "node_modules/minimatch": { - "version": "10.2.6", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-10.2.6.tgz", - "integrity": "sha512-vpLQEs+VLCr1nU0BXS07maYoFwlDAH0gngQuuttxIwutDFEMHq2blX+8vpgxDdK3J1PwjCJiep77OitTZ4Ll1A==", - "dependencies": { - "brace-expansion": "^5.0.8" - }, - "engines": { - "node": "18 || 20 || >=22" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/minimist": { - "version": "1.2.8", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz", - "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==", - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/minimist-options": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/minimist-options/-/minimist-options-4.1.0.tgz", - "integrity": "sha512-Q4r8ghd80yhO/0j1O3B2BjweX3fiHg9cdOwjJd2J76Q135c+NDxGCqdYKQ1SKBuFfgWbAUzBfvYjPUEeNgqN1A==", - "dependencies": { - "arrify": "^1.0.1", - "is-plain-obj": "^1.1.0", - "kind-of": "^6.0.3" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/modify-values": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/modify-values/-/modify-values-1.0.1.tgz", - "integrity": "sha512-xV2bxeN6F7oYjZWTe/YPAy6MN2M+sL4u/Rlm2AHCIVGfo2p1yGmBHQ6vHehl4bRTZBdHu3TSkWdYgkwpYzAGSw==", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/ms": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", - "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==" - }, - "node_modules/neo-async": { - "version": "2.6.2", - "resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.6.2.tgz", - "integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==" - }, - "node_modules/node-html-parser": { - "version": "6.1.13", - "resolved": "https://registry.npmjs.org/node-html-parser/-/node-html-parser-6.1.13.tgz", - "integrity": "sha512-qIsTMOY4C/dAa5Q5vsobRpOOvPfC4pB61UVW2uSwZNUp0QU/jCekTal1vMmbO0DgdHeLUJpv/ARmDqErVxA3Sg==", - "dependencies": { - "css-select": "^5.1.0", - "he": "1.2.0" - } - }, - "node_modules/normalize-package-data": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-3.0.3.tgz", - "integrity": "sha512-p2W1sgqij3zMMyRC067Dg16bfzVH+w7hyegmpIvZ4JNjqtGOVAIvLmjBx3yP7YTe9vKJgkoNOPjwQGogDoMXFA==", - "dependencies": { - "hosted-git-info": "^4.0.1", - "is-core-module": "^2.5.0", - "semver": "^7.3.4", - "validate-npm-package-license": "^3.0.1" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/nth-check": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/nth-check/-/nth-check-2.1.1.tgz", - "integrity": "sha512-lqjrjmaOoAnWfMmBPL+XNnynZh2+swxiX3WUE0s4yEHI6m+AwrK2UZOimIRl3X/4QctVqS8AiZjFqyOGrMXb/w==", - "dependencies": { - "boolbase": "^1.0.0" - }, - "funding": { - "url": "https://github.com/fb55/nth-check?sponsor=1" - } - }, - "node_modules/once": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", - "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", - "dependencies": { - "wrappy": "1" - } - }, - "node_modules/p-limit": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", - "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", - "dependencies": { - "p-try": "^2.0.0" - }, - "engines": { - "node": ">=6" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/p-locate": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", - "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", - "dependencies": { - "p-limit": "^2.2.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/p-try": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", - "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", - "engines": { - "node": ">=6" - } - }, - "node_modules/parse-diff": { - "version": "0.11.1", - "resolved": "https://registry.npmjs.org/parse-diff/-/parse-diff-0.11.1.tgz", - "integrity": "sha512-Oq4j8LAOPOcssanQkIjxosjATBIEJhCxMCxPhMu+Ci4wdNmAEdx0O+a7gzbR2PyKXgKPvRLIN5g224+dJAsKHA==" - }, - "node_modules/parse-github-repo-url": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/parse-github-repo-url/-/parse-github-repo-url-1.4.1.tgz", - "integrity": "sha512-bSWyzBKqcSL4RrncTpGsEKoJ7H8a4L3++ifTAbTFeMHyq2wRV+42DGmQcHIrJIvdcacjIOxEuKH/w4tthF17gg==" - }, - "node_modules/parse-json": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-5.2.0.tgz", - "integrity": "sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==", - "dependencies": { - "@babel/code-frame": "^7.0.0", - "error-ex": "^1.3.1", - "json-parse-even-better-errors": "^2.3.0", - "lines-and-columns": "^1.1.6" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/path-exists": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", - "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", - "engines": { - "node": ">=8" - } - }, - "node_modules/path-is-absolute": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", - "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/path-parse": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", - "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==" - }, - "node_modules/picocolors": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", - "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==" - }, - "node_modules/quick-lru": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/quick-lru/-/quick-lru-4.0.1.tgz", - "integrity": "sha512-ARhCpm70fzdcvNQfPoy49IaanKkTlRWF2JMzqhcJbhSFRZv7nPTvZJdcY7301IPmvW+/p0RgIWnQDLJxifsQ7g==", - "engines": { - "node": ">=8" - } - }, - "node_modules/read-pkg": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-5.2.0.tgz", - "integrity": "sha512-Ug69mNOpfvKDAc2Q8DRpMjjzdtrnv9HcSMX+4VsZxD1aZ6ZzrIE7rlzXBtWTyhULSMKg076AW6WR5iZpD0JiOg==", - "dependencies": { - "@types/normalize-package-data": "^2.4.0", - "normalize-package-data": "^2.5.0", - "parse-json": "^5.0.0", - "type-fest": "^0.6.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/read-pkg-up": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-7.0.1.tgz", - "integrity": "sha512-zK0TB7Xd6JpCLmlLmufqykGE+/TlOePD6qKClNW7hHDKFh/J7/7gCWGR7joEQEW1bKq3a3yUZSObOoWLFQ4ohg==", - "dependencies": { - "find-up": "^4.1.0", - "read-pkg": "^5.2.0", - "type-fest": "^0.8.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/read-pkg-up/node_modules/type-fest": { - "version": "0.8.1", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.8.1.tgz", - "integrity": "sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA==", - "engines": { - "node": ">=8" - } - }, - "node_modules/read-pkg/node_modules/hosted-git-info": { - "version": "2.8.9", - "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.8.9.tgz", - "integrity": "sha512-mxIDAb9Lsm6DoOJ7xH+5+X4y1LU/4Hi50L9C5sIswK3JzULS4bwk1FvjdBgvYR4bzT4tuUQiC15FE2f5HbLvYw==" - }, - "node_modules/read-pkg/node_modules/normalize-package-data": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.5.0.tgz", - "integrity": "sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA==", - "dependencies": { - "hosted-git-info": "^2.1.4", - "resolve": "^1.10.0", - "semver": "2 || 3 || 4 || 5", - "validate-npm-package-license": "^3.0.1" - } - }, - "node_modules/read-pkg/node_modules/semver": { - "version": "5.7.2", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz", - "integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==", - "bin": { - "semver": "bin/semver" - } - }, - "node_modules/read-pkg/node_modules/type-fest": { - "version": "0.6.0", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.6.0.tgz", - "integrity": "sha512-q+MB8nYR1KDLrgr4G5yemftpMC7/QLqVndBmEEdqzmNj5dcFOO4Oo8qlwZE3ULT3+Zim1F8Kq4cBnikNhlCMlg==", - "engines": { - "node": ">=8" - } - }, - "node_modules/redent": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/redent/-/redent-3.0.0.tgz", - "integrity": "sha512-6tDA8g98We0zd0GvVeMT9arEOnTw9qM03L9cJXaCjrip1OO764RDBLBfrB4cwzNGDj5OA5ioymC9GkizgWJDUg==", - "dependencies": { - "indent-string": "^4.0.0", - "strip-indent": "^3.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/release-please": { - "version": "17.6.0", - "resolved": "https://registry.npmjs.org/release-please/-/release-please-17.6.0.tgz", - "integrity": "sha512-ItzkkEBeEbKsCrx7N1QlADrCahoONA4WPlsOinSnXTkqUBIWlHC6+S28VJ9PaHy7ZPSJwSQsRuDjI0/HL5G6hw==", - "dependencies": { - "@conventional-commits/parser": "^0.4.1", - "@google-automations/git-file-utils": "^3.0.0", - "@iarna/toml": "^3.0.0", - "@octokit/graphql": "^7.1.0", - "@octokit/request": "^8.3.1", - "@octokit/request-error": "^5.1.0", - "@octokit/rest": "^20.1.1", - "@types/npm-package-arg": "^6.1.0", - "@xmldom/xmldom": "^0.8.4", - "chalk": "^4.0.0", - "code-suggester": "^5.0.0", - "conventional-changelog-conventionalcommits": "^6.0.0", - "conventional-changelog-writer": "^6.0.0", - "conventional-commits-filter": "^3.0.0", - "detect-indent": "^6.1.0", - "diff": "^8.0.3", - "figures": "^3.0.0", - "http-proxy-agent": "^7.0.0", - "https-proxy-agent": "^7.0.0", - "js-yaml": "^4.0.0", - "jsonpath-plus": "^10.0.0", - "node-html-parser": "^6.0.0", - "parse-github-repo-url": "^1.4.1", - "semver": "^7.5.3", - "type-fest": "^3.0.0", - "typescript": "^4.6.4", - "unist-util-visit": "^2.0.3", - "unist-util-visit-parents": "^3.1.1", - "xpath": "^0.0.34", - "yaml": "^2.2.2", - "yargs": "^17.0.0" - }, - "bin": { - "release-please": "build/src/bin/release-please.js" - }, - "engines": { - "node": ">=20.0.0" - } - }, - "node_modules/require-directory": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", - "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/resolve": { - "version": "1.22.13", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.13.tgz", - "integrity": "sha512-Dj/cW9zBV2aRj6XzCxuGIs3ESZKv02jixne3q6jFZYZ3/Tg09gHHviSMDL4kObh9pqSahdRHEnDoaP2gn8YLhA==", - "dependencies": { - "es-errors": "^1.3.0", - "is-core-module": "^2.17.0", - "path-parse": "^1.0.7", - "supports-preserve-symlinks-flag": "^1.0.0" - }, - "bin": { - "resolve": "bin/resolve" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/retry": { - "version": "0.13.1", - "resolved": "https://registry.npmjs.org/retry/-/retry-0.13.1.tgz", - "integrity": "sha512-XQBQ3I8W1Cge0Seh+6gjj03LbmRFWuoszgK9ooCpwYIrhhoO80pfq4cUkU5DkknwfOfFteRwlZ56PYOGYyFWdg==", - "engines": { - "node": ">= 4" - } - }, - "node_modules/semver": { - "version": "7.8.5", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.8.5.tgz", - "integrity": "sha512-Y7/KDsb8LjooZpwaqGyulO6DQlksgCncchHGk+sZIY4SBvUocMBEFH5Ur1fI4dV+Jvl0w6cjvucaIi40puRioA==", - "bin": { - "semver": "bin/semver.js" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/spdx-correct": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.2.0.tgz", - "integrity": "sha512-kN9dJbvnySHULIluDHy32WHRUu3Og7B9sbY7tsFLctQkIqnMh3hErYgdMjTYuqmcXX+lK5T1lnUt3G7zNswmZA==", - "dependencies": { - "spdx-expression-parse": "^3.0.0", - "spdx-license-ids": "^3.0.0" - } - }, - "node_modules/spdx-exceptions": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.5.0.tgz", - "integrity": "sha512-PiU42r+xO4UbUS1buo3LPJkjlO7430Xn5SVAhdpzzsPHsjbYVflnnFdATgabnLude+Cqu25p6N+g2lw/PFsa4w==" - }, - "node_modules/spdx-expression-parse": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-3.0.1.tgz", - "integrity": "sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q==", - "dependencies": { - "spdx-exceptions": "^2.1.0", - "spdx-license-ids": "^3.0.0" - } - }, - "node_modules/spdx-license-ids": { - "version": "3.0.24", - "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.24.tgz", - "integrity": "sha512-cLS9TtWkIQFyLkJ3/5aFQAOHOSKTlOs/7WDut/XPSdjom1fJhUdkepeJAKXa9Y05+FabHd0sti+Et559vDtkpQ==" - }, - "node_modules/split": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/split/-/split-1.0.1.tgz", - "integrity": "sha512-mTyOoPbrivtXnwnIxZRFYRrPNtEFKlpB2fvjSnCQUiAA6qAZzqwna5envK4uk6OIeP17CsdF3rSBGYVBsU0Tkg==", - "dependencies": { - "through": "2" - }, - "engines": { - "node": "*" - } - }, - "node_modules/string-width": { - "version": "4.2.3", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", - "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", - "dependencies": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/strip-ansi": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", - "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", - "dependencies": { - "ansi-regex": "^5.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/strip-indent": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/strip-indent/-/strip-indent-3.0.0.tgz", - "integrity": "sha512-laJTa3Jb+VQpaC6DseHhF7dXVqHTfJPCRDaEbid/drOhgitgYku/letMUqOXFoWV0zIIUbjpdH2t+tYj4bQMRQ==", - "dependencies": { - "min-indent": "^1.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dependencies": { - "has-flag": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/supports-preserve-symlinks-flag": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", - "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==", - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/through": { - "version": "2.3.8", - "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", - "integrity": "sha512-w89qg7PI8wAdvX60bMDP+bFoD5Dvhm9oLheFp5O4a2QF0cSBGsBX4qZmadPMvVqlLJBBci+WqGGOAPvcDeNSVg==" - }, - "node_modules/trim-newlines": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/trim-newlines/-/trim-newlines-3.0.1.tgz", - "integrity": "sha512-c1PTsA3tYrIsLGkJkzHF+w9F2EyxfXGo4UyJc4pFL++FMjnq0HJS69T3M7d//gKrFKwy429bouPescbjecU+Zw==", - "engines": { - "node": ">=8" - } - }, - "node_modules/tunnel": { - "version": "0.0.6", - "resolved": "https://registry.npmjs.org/tunnel/-/tunnel-0.0.6.tgz", - "integrity": "sha512-1h/Lnq9yajKY2PEbBadPXj3VxsDDu844OnaAo52UVmIzIvwwtBPIuNvkjuzBlTWpfJyUbG3ez0KSBibQkj4ojg==", - "engines": { - "node": ">=0.6.11 <=0.7.0 || >=0.7.3" - } - }, - "node_modules/type-fest": { - "version": "3.13.1", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-3.13.1.tgz", - "integrity": "sha512-tLq3bSNx+xSpwvAJnzrK0Ep5CLNWjvFTOp71URMaAEWBfRb9nnJiBoUe0tF8bI4ZFO3omgBR6NvnbzVUT3Ly4g==", - "engines": { - "node": ">=14.16" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/typescript": { - "version": "4.9.5", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.9.5.tgz", - "integrity": "sha512-1FXk9E2Hm+QzZQ7z+McJiHL4NW1F2EzMu9Nq9i3zAaGqibafqYwCVU6WyWAuyQRRzOlxou8xZSyXLEN8oKj24g==", - "bin": { - "tsc": "bin/tsc", - "tsserver": "bin/tsserver" - }, - "engines": { - "node": ">=4.2.0" - } - }, - "node_modules/uglify-js": { - "version": "3.19.3", - "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.19.3.tgz", - "integrity": "sha512-v3Xu+yuwBXisp6QYTcH4UbH+xYJXqnq2m/LtQVWKWzYc1iehYnLixoQDN9FH6/j9/oybfd6W9Ghwkl8+UMKTKQ==", - "optional": true, - "bin": { - "uglifyjs": "bin/uglifyjs" - }, - "engines": { - "node": ">=0.8.0" - } - }, - "node_modules/undici": { - "version": "5.29.0", - "resolved": "https://registry.npmjs.org/undici/-/undici-5.29.0.tgz", - "integrity": "sha512-raqeBD6NQK4SkWhQzeYKd1KmIG6dllBOTt55Rmkt4HtI9mwdWtJljnrXjAFUBLTSN67HWrOIZ3EPF4kjUw80Bg==", - "dependencies": { - "@fastify/busboy": "^2.0.0" - }, - "engines": { - "node": ">=14.0" - } - }, - "node_modules/unist-util-is": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/unist-util-is/-/unist-util-is-4.1.0.tgz", - "integrity": "sha512-ZOQSsnce92GrxSqlnEEseX0gi7GH9zTJZ0p9dtu87WRb/37mMPO2Ilx1s/t9vBHrFhbgweUwb+t7cIn5dxPhZg==", - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/unist-util-visit": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/unist-util-visit/-/unist-util-visit-2.0.3.tgz", - "integrity": "sha512-iJ4/RczbJMkD0712mGktuGpm/U4By4FfDonL7N/9tATGIF4imikjOuagyMY53tnZq3NP6BcmlrHhEKAfGWjh7Q==", - "dependencies": { - "@types/unist": "^2.0.0", - "unist-util-is": "^4.0.0", - "unist-util-visit-parents": "^3.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/unist-util-visit-parents": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/unist-util-visit-parents/-/unist-util-visit-parents-3.1.1.tgz", - "integrity": "sha512-1KROIZWo6bcMrZEwiH2UrXDyalAa0uqzWCxCJj6lPOvTve2WkfgCytoDTPaMnodXh1WrXOq0haVYHj99ynJlsg==", - "dependencies": { - "@types/unist": "^2.0.0", - "unist-util-is": "^4.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/universal-user-agent": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/universal-user-agent/-/universal-user-agent-6.0.1.tgz", - "integrity": "sha512-yCzhz6FN2wU1NiiQRogkTQszlQSlpWaw8SvVegAc+bDxbzHgh1vX8uIe8OYyMH6DwH+sdTJsgMl36+mSMdRJIQ==" - }, - "node_modules/validate-npm-package-license": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz", - "integrity": "sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==", - "dependencies": { - "spdx-correct": "^3.0.0", - "spdx-expression-parse": "^3.0.0" - } - }, - "node_modules/wordwrap": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-1.0.0.tgz", - "integrity": "sha512-gvVzJFlPycKc5dZN4yPkP8w7Dc37BtP1yczEneOb4uq34pXZcvrtRTmWV8W+Ume+XCxKgbjM+nevkyFPMybd4Q==" - }, - "node_modules/wrap-ansi": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", - "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", - "dependencies": { - "ansi-styles": "^4.0.0", - "string-width": "^4.1.0", - "strip-ansi": "^6.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/wrap-ansi?sponsor=1" - } - }, - "node_modules/wrappy": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", - "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==" - }, - "node_modules/xpath": { - "version": "0.0.34", - "resolved": "https://registry.npmjs.org/xpath/-/xpath-0.0.34.tgz", - "integrity": "sha512-FxF6+rkr1rNSQrhUNYrAFJpRXNzlDoMxeXN5qI84939ylEv3qqPFKa85Oxr6tDaJKqwW6KKyo2v26TSv3k6LeA==", - "engines": { - "node": ">=0.6.0" - } - }, - "node_modules/y18n": { - "version": "5.0.8", - "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", - "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", - "engines": { - "node": ">=10" - } - }, - "node_modules/yallist": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" - }, - "node_modules/yaml": { - "version": "2.9.1", - "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.9.1.tgz", - "integrity": "sha512-3NxN8+78OdzbT7C/WjGsyfPAtJaN3FNDsWxv7Y7mcDsT/oOmgW8BpyQQFFBnvZE3j9Y2Sdz1ULFLezL7Eb2yFw==", - "bin": { - "yaml": "bin.mjs" - }, - "engines": { - "node": ">= 14.6" - }, - "funding": { - "url": "https://github.com/sponsors/eemeli" - } - }, - "node_modules/yargs": { - "version": "17.7.3", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.3.tgz", - "integrity": "sha512-GZtjxm/J/4TSxuL3FNYjCmLktBTnIw/rVmKSIyKeYAZpmJB2ig9VauCC5xsa82GNKVKDAqpOn3KVzNt0zmrU0g==", - "dependencies": { - "cliui": "^8.0.1", - "escalade": "^3.1.1", - "get-caller-file": "^2.0.5", - "require-directory": "^2.1.1", - "string-width": "^4.2.3", - "y18n": "^5.0.5", - "yargs-parser": "^21.1.1" - }, - "engines": { - "node": ">=12" - } - }, - "node_modules/yargs-parser": { - "version": "20.2.9", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.9.tgz", - "integrity": "sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w==", - "engines": { - "node": ">=10" - } - }, - "node_modules/yargs/node_modules/yargs-parser": { - "version": "21.1.1", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz", - "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==", - "engines": { - "node": ">=12" - } - } - } -} diff --git a/.github/release-please/package.json b/.github/release-please/package.json deleted file mode 100644 index 2fdafb092..000000000 --- a/.github/release-please/package.json +++ /dev/null @@ -1,12 +0,0 @@ -{ - "name": "openapi-odata-release-automation", - "private": true, - "scripts": { - "test": "node --test run.test.cjs", - "coverage": "node -e \"require('node:fs').mkdirSync('../../artifacts/release-please', {recursive: true})\" && cd ../.. && node --test --experimental-test-coverage --test-coverage-include=.github/release-please/run.cjs --test-coverage-lines=80 --test-coverage-functions=80 --test-reporter=spec --test-reporter=lcov --test-reporter-destination=stdout --test-reporter-destination=artifacts/release-please/lcov.info .github/release-please/run.test.cjs" - }, - "dependencies": { - "@actions/core": "1.11.1", - "release-please": "17.6.0" - } -} diff --git a/.github/release-please/run.cjs b/.github/release-please/run.cjs deleted file mode 100644 index 67a344ae2..000000000 --- a/.github/release-please/run.cjs +++ /dev/null @@ -1,203 +0,0 @@ -const {GitHub, Manifest, registerPlugin} = require('release-please'); -const {ManifestPlugin} = require('release-please/build/src/plugin'); -const {Version} = require('release-please/build/src/version'); -const {buildStrategy} = require('release-please/build/src/factory'); -const {FilePullRequestOverflowHandler} = require('release-please/build/src/util/pull-request-overflow-handler'); - -const HIDI_PENDING = 'autorelease: hidi-pending'; -const HIDI_VERSIONED = 'autorelease: hidi-versioned'; -const HIDI_FLOORS = {'main': '3.10.2', 'support/v2': '2.12.2'}; - -async function ensureHidiLabels(token, owner, repo, request = fetch) { - const api = (process.env.GITHUB_API_URL || 'https://api.github.com').replace(/\/$/, ''); - const url = `${api}/repos/${encodeURIComponent(owner)}/${encodeURIComponent(repo)}/labels`; - const headers = { - Authorization: `Bearer ${token}`, - Accept: 'application/vnd.github+json', - 'X-GitHub-Api-Version': '2022-11-28' - }; - for (const label of [ - {name: HIDI_PENDING, color: 'fbca04', description: 'Pending independent Hidi version pull request'}, - {name: HIDI_VERSIONED, color: '0e8a16', description: 'Merged Hidi version pull request; no production release'} - ]) { - const labelUrl = `${url}/${encodeURIComponent(label.name)}`; - let response = await request(labelUrl, {headers}); - let expectedStatus = 200; - if (response.status === 404) { - response = await request(url, { - method: 'POST', headers: {...headers, 'Content-Type': 'application/json'}, - body: JSON.stringify(label) - }); - if (response.status === 422) { - // Another branch job may have created the same label concurrently. - response = await request(labelUrl, {headers}); - } else if (response.status !== 201) { - throw new Error(`Cannot create Hidi lifecycle label '${label.name}': HTTP ${response.status}`); - } else { - expectedStatus = 201; - } - } - if (response.status !== expectedStatus || (await response.json()).name !== label.name) { - throw new Error(`Cannot verify Hidi lifecycle label '${label.name}': HTTP ${response.status}`); - } - } -} - -class ExactPathExclusions extends ManifestPlugin { - async preconfigure(strategies, commitsByPath) { - for (const [path, config] of Object.entries(this.repositoryConfig)) { - const excludes = config.excludePaths || []; - commitsByPath[path] = commitsByPath[path].filter(commit => { - if (!Array.isArray(commit.files)) { - throw new Error(`Missing changed files for commit ${commit.sha}`); - } - return commit.files.some(file => - (path === '.' || file.startsWith(`${path}/`)) && - !excludes.some(exclude => file === exclude || file.startsWith(`${exclude}/`)) - ); - }); - } - return strategies; - } - - async run(candidates) { - for (const candidate of candidates) { - if (candidate.config.component !== 'hidi') continue; - const floor = HIDI_FLOORS[this.targetBranch]; - const version = candidate.pullRequest.version; - if (!floor || !version || version.major !== Version.parse(floor).major || - version.preRelease || version.build || version.compare(Version.parse(floor)) <= 0) { - throw new Error('Generated Hidi version is outside the branch major or migration floor'); - } - } - return candidates; - } -} - -registerPlugin('exact-path-exclusions', options => - new ExactPathExclusions(options.github, options.targetBranch, options.repositoryConfig) -); - -async function prepareHidiVersionPrs(github, manifest, branch) { - const floor = HIDI_FLOORS[branch]; - const manifestConfig = await github.getFileJson('hidi-release-please-config.json', branch); - const config = manifest.repositoryConfig['.']; - const version = manifest.releasedVersions['.']; - if (!floor || Object.keys(manifest.repositoryConfig).length !== 1 || - Object.keys(manifest.releasedVersions).length !== 1 || - config?.component !== 'hidi' || config.releaseType !== 'simple' || - !config.includeComponentInTag || !config.includeVInTag || - (config.tagSeparator && config.tagSeparator !== '-') || - config.skipGithubRelease || - !config.separatePullRequests || - manifestConfig.label !== HIDI_PENDING || - !version || version.major !== Version.parse(floor).major || - version.preRelease || version.build || version.compare(Version.parse(floor)) < 0) { - throw new Error('Unsafe Hidi branch, manifest, component, labels or version configuration'); - } - const project = await github.getFileContentsOnBranch('src/Microsoft.OpenApi.Hidi/Microsoft.OpenApi.Hidi.csproj', branch); - const projectVersions = [...project.parsedContent.matchAll(/\s*([^<]+?)\s*<\/Version>/g)]; - if (projectVersions.length !== 1 || projectVersions[0][1] !== version.toString()) { - throw new Error('Hidi project version does not match its manifest'); - } - - const strategy = await buildStrategy({...config, github, path: '.', targetBranch: branch}); - const overflow = new FilePullRequestOverflowHandler(github); - const expectedBranch = `release-please--branches--${branch}--components--hidi`; - const pending = []; - let checkpoint; - for await (const pr of github.pullRequestIterator(branch, 'MERGED', 200, false)) { - if (!pr.labels.some(label => label === HIDI_PENDING || label === HIDI_VERSIONED)) continue; - if (pr.headBranchName !== expectedBranch || !pr.sha) { - throw new Error(`Unsafe Hidi version PR #${pr.number}: unexpected branch or missing merge SHA`); - } - const releases = await strategy.buildReleases(pr); - if (releases.length !== 1 || releases[0].tag.component !== 'hidi') { - throw new Error(`Cannot parse merged Hidi version PR #${pr.number}`); - } - const release = releases[0]; - const body = await overflow.parseOverflow(pr); - if (body?.releaseData.length !== 1 || - (body.releaseData[0].component && body.releaseData[0].component !== 'hidi') || - body.releaseData[0].version?.compare(release.tag.version) !== 0) { - throw new Error(`Hidi version PR #${pr.number} has inconsistent title and body versions`); - } - if (release.tag.version.compare(version) > 0 || - release.tag.version.compare(Version.parse(floor)) <= 0) { - throw new Error(`Merged Hidi PR #${pr.number} disagrees with the current manifest or migration floor`); - } - if (release.tag.version.compare(version) === 0) { - if (checkpoint && checkpoint.sha !== pr.sha) { - throw new Error(`Multiple merged Hidi PRs claim version ${version}`); - } - checkpoint = pr; - } - if (pr.labels.includes(HIDI_PENDING)) pending.push(pr); - } - if (!checkpoint && (version.toString() !== floor || pending.length)) { - throw new Error(`No merged Hidi version PR matches manifest version ${version}`); - } - if (checkpoint) { - // A version PR merge, not a production tag, is the boundary for the next cycle. - let reachable = false; - for await (const commit of github.mergeCommitIterator(branch, { - maxResults: manifest.commitSearchDepth, backfillFiles: false - })) { - if (commit.sha === checkpoint.sha) { - reachable = true; - break; - } - } - if (!reachable) throw new Error(`Hidi checkpoint ${checkpoint.sha} is outside the branch commit search`); - } - for (const pr of pending) { - // Adding first makes an interrupted label transition safe to retry. - await github.addIssueLabels([HIDI_VERSIONED], pr.number); - await github.removeIssueLabels([HIDI_PENDING], pr.number); - } - return checkpoint?.sha; -} - -async function runReleasePlease(github, branch, component) { - if (!['odata', 'hidi'].includes(component)) throw new Error(`Unknown component: ${component}`); - const configFile = component === 'hidi' ? 'hidi-release-please-config.json' : 'release-please-config.json'; - const manifestFile = component === 'hidi' ? '.hidi-release-please-manifest.json' : '.release-please-manifest.json'; - const load = (options = {}) => Manifest.fromManifest(github, branch, configFile, manifestFile, options); - const releases = component === 'odata' ? await (await load()).createReleases() : []; - let manifest = await load(); - if (component === 'hidi') { - const lastReleaseSha = await prepareHidiVersionPrs(github, manifest, branch); - if (lastReleaseSha) manifest = await load({lastReleaseSha}); - } - const prs = await manifest.createPullRequests(); - return {releases, prs}; -} - -async function main() { - const core = require('@actions/core'); - const token = process.env.RELEASE_PLEASE_TOKEN; - const branch = process.env.GITHUB_REF_NAME; - const [owner, repo] = (process.env.GITHUB_REPOSITORY || '').split('/'); - if (!token || !branch || !owner || !repo) throw new Error('Missing release automation environment'); - if (process.argv[2] === 'hidi') await ensureHidiLabels(token, owner, repo); - const github = await GitHub.create({owner, repo, token, defaultBranch: branch}); - const {releases, prs} = await runReleasePlease(github, branch, process.argv[2]); - core.setOutput('releases_created', releases.length > 0); - core.setOutput('prs_created', prs.length > 0); - core.setOutput('prs', JSON.stringify(prs)); - core.setOutput('paths_released', JSON.stringify(releases.map(release => release.path))); - if (prs.length) core.setOutput('pr', prs[0]); - for (const release of releases) { - const prefix = release.path === '.' ? '' : `${release.path}--`; - core.setOutput(`${prefix}release_created`, true); - for (const [name, value] of Object.entries(release)) { - const key = {tagName: 'tag_name', uploadUrl: 'upload_url', notes: 'body', url: 'html_url'}[name] || name; - core.setOutput(`${prefix}${key}`, value); - } - } -} - -module.exports = {ExactPathExclusions, prepareHidiVersionPrs, runReleasePlease, ensureHidiLabels, main}; -if (require.main === module) { - main().catch(error => require('@actions/core').setFailed(error.message)); -} diff --git a/.github/release-please/run.test.cjs b/.github/release-please/run.test.cjs deleted file mode 100644 index 3f27f02c8..000000000 --- a/.github/release-please/run.test.cjs +++ /dev/null @@ -1,492 +0,0 @@ -const assert = require('node:assert/strict'); -const fs = require('node:fs'); -const path = require('node:path'); -const {test} = require('node:test'); -const {GitHub, Manifest, setLogger} = require('release-please'); -const {Version} = require('release-please/build/src/version'); -const {PullRequestBody} = require('release-please/build/src/util/pull-request-body'); -const {runReleasePlease, main, ExactPathExclusions, ensureHidiLabels} = require('./run.cjs'); - -setLogger({debug() {}, info() {}, warn() {}, error() {}}); -const root = path.resolve(__dirname, '..', '..'); -const branch = JSON.parse(fs.readFileSync(path.join(root, '.hidi-release-please-manifest.json')))['.'].startsWith('3.') ? 'main' : 'support/v2'; -const hidiProject = 'src/Microsoft.OpenApi.Hidi/Microsoft.OpenApi.Hidi.csproj'; -const hidiReadme = 'src/Microsoft.OpenApi.Hidi/readme.md'; -const hidiChangelog = 'src/Microsoft.OpenApi.Hidi/CHANGELOG.md'; -const hidiManifest = '.hidi-release-please-manifest.json'; -const odataManifest = '.release-please-manifest.json'; -const inputPaths = [ - 'release-please-config.json', 'hidi-release-please-config.json', - hidiManifest, odataManifest, hidiProject, hidiReadme, hidiChangelog, - 'Directory.Build.props', 'CHANGELOG.md' -]; - -class MemoryGitHub { - constructor(hidiVersion) { - this.repository = {owner: 'microsoft', repo: 'OpenAPI.NET.OData', defaultBranch: branch}; - this.files = Object.fromEntries(inputPaths.map(file => [file, fs.readFileSync(path.join(root, file), 'utf8')])); - this.commits = ['hidi-release-please-config.json', 'release-please-config.json'].map(file => ({ - sha: JSON.parse(this.files[file])['bootstrap-sha'], message: 'chore: baseline', files: [] - })); - this.prs = []; - this.releases = []; - this.tags = []; - this.labelWrites = []; - this.nextPr = 1; - if (hidiVersion) { - this.files[hidiManifest] = JSON.stringify({'.': hidiVersion}); - this.files[hidiProject] = this.files[hidiProject].replace(/.*?<\/Version>/, `${hidiVersion}`); - } - const current = JSON.parse(this.files[hidiManifest])['.']; - const floor = branch === 'main' ? '3.10.2' : '2.12.2'; - if (current !== floor) { - const checkpoint = { - number: 0, state: 'MERGED', sha: 'initial-hidi-checkpoint', - headBranchName: `release-please--branches--${branch}--components--hidi`, - baseBranchName: branch, - title: `chore(${branch}): release hidi ${current}`, - body: new PullRequestBody([{component: 'hidi', version: Version.parse(current), notes: 'Previously merged version'}], {useComponents: true}).toString(), - labels: ['autorelease: hidi-versioned'], files: [hidiManifest, hidiProject] - }; - this.prs.push(checkpoint); - this.commits.unshift({sha: checkpoint.sha, message: checkpoint.title, files: checkpoint.files, pullRequest: checkpoint}); - } - } - async getFileJson(file) { return JSON.parse(this.files[file]); } - async getFileContentsOnBranch(file) { - assert.ok(Object.hasOwn(this.files, file), `Unexpected read of ${file}`); - return {parsedContent: this.files[file], content: Buffer.from(this.files[file]).toString('base64'), sha: 'file-sha'}; - } - async *releaseIterator() { yield* this.releases; } - async *tagIterator() { yield* this.tags; } - async *mergeCommitIterator() { yield* this.commits; } - async *pullRequestIterator(target, state) { - assert.equal(target, branch); - yield* this.prs.filter(pr => pr.state === state); - } - change(files, message = 'fix: representative change') { - this.commits.unshift({sha: `change-${this.commits.length}`, message, files}); - } - materialize(updates) { - return Object.fromEntries(updates - .filter(update => update.createIfMissing || Object.hasOwn(this.files, update.path)) - .map(update => [update.path, update.updater.updateContent(this.files[update.path] || '')])); - } - async createPullRequest(pr, target, message, updates) { - assert.equal(target, branch); - const created = {...pr, number: this.nextPr++, state: 'OPEN', output: this.materialize(updates)}; - this.prs.unshift(created); - return created; - } - async updatePullRequest(number, plan) { - const pr = this.prs.find(item => item.number === number); - Object.assign(pr, {title: plan.title.toString(), body: plan.body.toString(), output: this.materialize(plan.updates)}); - return pr; - } - async addIssueLabels(labels, number) { - this.labelWrites.push(['add', number, labels]); - const pr = this.prs.find(item => item.number === number); - pr.labels = [...new Set([...pr.labels, ...labels])]; - } - async removeIssueLabels(labels, number) { - this.labelWrites.push(['remove', number, labels]); - const pr = this.prs.find(item => item.number === number); - pr.labels = pr.labels.filter(label => !labels.includes(label)); - } - async commentOnIssue() {} - async createRelease(release) { - const result = {tagName: release.tag.toString(), sha: release.sha, notes: release.notes, url: 'https://example.invalid/release'}; - this.releases.unshift(result); - this.tags.unshift({name: result.tagName, sha: result.sha}); - return result; - } - merge(pr) { - Object.assign(this.files, pr.output); - Object.assign(pr, {state: 'MERGED', sha: `merge-${pr.number}`}); - this.commits.unshift({sha: pr.sha, message: pr.title, files: Object.keys(pr.output), pullRequest: pr}); - } -} - -async function plans(github, component) { - return (await Manifest.fromManifest(github, branch, - component === 'hidi' ? 'hidi-release-please-config.json' : 'release-please-config.json', - component === 'hidi' ? hidiManifest : odataManifest)).buildPullRequests(); -} - -const routingCases = [ - ['src/Microsoft.OpenApi.Hidi/Program.cs', false, true], - ['src/Microsoft.OpenApi.Hidi/CsdlFilter.xslt', false, true], - [hidiProject, false, true], - [hidiReadme, false, true], - [hidiChangelog, false, true], - ['test/Microsoft.OpenApi.Hidi.Tests/StatsVisitorTests.cs', false, true], - ['test/Microsoft.OpenApi.Hidi.Tests/UtilityFiles/SampleOpenApi.yml', false, true], - ['test/Microsoft.OpenApi.Hidi.Tests/check-nuget-package-published.Tests.ps1', false, true], - ['scripts/check-nuget-package-published.ps1', false, true], - ['test/scripts/check-nuget-package-published.Tests.ps1', false, true], - ['Dockerfile', false, true], - ['.dockerignore', false, true], - ['install-tool.ps1', false, true], - ['tool/hidi-local-nuget.config', false, true], - ['tool/Microsoft.OpenApi.Hidi.public.snk', false, true], - ['hidi-release-please-config.json', false, true], - [hidiManifest, false, true], - ['.azure-pipelines/hidi-release.yml', false, true], - ['src/Microsoft.OpenApi.OData.Reader/OpenApiConvertSettings.cs', true, false], - ['test/Microsoft.OpenAPI.OData.Reader.Tests/OpenApiConvertSettingsTests.cs', true, false], - ['src/OoasGui/Program.cs', true, false], - ['src/OoasUtil/Program.cs', true, false], - ['docs/graphSecurityScheme/GraphSchemes.md', true, false], - ['Directory.Build.props', true, false], - ['redocly.yaml', true, false], - ['.redocly.lint-ignore.yaml', true, false], - ['src/AssemblyInfo/AssemblyInfoCommon.cs', true, false], - ['CHANGELOG.md', true, false], - ['release-please-config.json', true, false], - [odataManifest, true, false], - ['tool/Microsoft.OpenApi.OData.snk', true, false], - ['tool/35MSSharedLib1024.snk', true, false], - ['tool/Microsoft.OpenApi.OData.public.snk', false, true], - ['README.md', true, true], - ['CONTRIBUTING.md', true, true], - ['Build.props', true, true], - ['src/Build.props', true, true], - ['build.root', true, true], - ['build.ps1', true, true], - ['build.cmd', true, true], - ['global.json', true, true], - ['Microsoft.OpenApi.OData.sln', true, true], - ['.github/workflows/ci-cd.yml', false, false], - ['.github/release-please/run.cjs', false, false], - ['.azure-pipelines/ci-build.yml', false, false], - ['src/Microsoft.OpenApi.HidiSibling/Program.cs', true, true] -]; - -for (const [file, odata, hidi] of routingCases) { - test(`real engine routing: ${file}`, async () => { - const github = new MemoryGitHub(); - github.change([file]); - assert.equal((await plans(github, 'odata')).length, Number(odata)); - assert.equal((await plans(github, 'hidi')).length, Number(hidi)); - }); -} - -test('mixed changes affect both components; excluded-only and empty changes affect neither', async () => { - const github = new MemoryGitHub(); - github.change(['Dockerfile', 'src/Microsoft.OpenApi.OData.Reader/OpenApiConvertSettings.cs']); - assert.equal((await plans(github, 'odata')).length, 1); - assert.equal((await plans(github, 'hidi')).length, 1); - github.commits.shift(); - github.change(['Dockerfile', 'test/Microsoft.OpenApi.Hidi.Tests/StatsVisitorTests.cs']); - assert.equal((await plans(github, 'odata')).length, 0); - github.commits.shift(); - github.change([]); - assert.equal((await plans(github, 'odata')).length, 0); - assert.equal((await plans(github, 'hidi')).length, 0); -}); - -test('an OData fix after Hidi features keeps the OData patch and changelog independent', async () => { - const github = new MemoryGitHub(); - const current = JSON.parse(github.files[odataManifest])['.']; - github.change(['Dockerfile'], 'feat(hidi): independent feature before root fix'); - github.change(['Directory.Build.props'], 'fix(odata): library fix after Hidi'); - const [pr] = await plans(github, 'odata'); - assert.equal(pr.version.toString(), current.replace(/\d+$/, patch => Number(patch) + 1)); - assert.ok(pr.body.toString().includes('library fix after Hidi')); - assert.ok(!pr.body.toString().includes('independent feature')); - const workflow = fs.readFileSync(path.join(root, '.github', 'workflows', 'ci-cd.yml'), 'utf8'); - assert.ok(!workflow.includes('mathieudutour/github-tag-action')); - assert.ok(!workflow.includes('softprops/action-gh-release')); -}); - -test('actual Hidi patch output changes only its version, manifest, changelog and install examples', async () => { - const github = new MemoryGitHub(); - const baseline = github.files[hidiProject]; - const oldVersion = JSON.parse(github.files[hidiManifest])['.']; - const next = oldVersion.replace(/\d+$/, patch => Number(patch) + 1); - github.change(['Dockerfile'], 'fix(hidi): independent distribution fix'); - const [pr] = await plans(github, 'hidi'); - const output = github.materialize(pr.updates); - assert.deepEqual(Object.keys(output).sort(), [hidiChangelog, hidiProject, hidiReadme, hidiManifest].sort()); - assert.equal(pr.headRefName, `release-please--branches--${branch}--components--hidi`); - assert.equal(pr.version.toString(), next); - assert.ok(output[hidiProject].includes(`${next}`)); - const dependencies = text => [...text.matchAll(/ match.slice(1)); - assert.deepEqual(dependencies(output[hidiProject]), dependencies(baseline)); - assert.match(output[hidiChangelog], new RegExp(`hidi-v${oldVersion}\\.\\.\\.hidi-v${next}`)); - assert.equal(JSON.parse(output[hidiManifest])['.'], next); - assert.ok(output[hidiReadme].includes(`--version ${next}`)); - const unannotatedLines = text => text.split(/\r?\n/).filter(line => !line.includes('x-release-please-version')); - assert.deepEqual(unannotatedLines(output[hidiReadme]), unannotatedLines(github.files[hidiReadme])); -}); - -test('actual OData output and componentless tags retain existing behavior', async () => { - const github = new MemoryGitHub(); - const oldVersion = JSON.parse(github.files[odataManifest])['.']; - const next = oldVersion.replace(/\d+$/, patch => Number(patch) + 1); - github.releases.push({tagName: `v${oldVersion}`, sha: github.commits.at(-1).sha, notes: ''}); - github.change(['Directory.Build.props'], 'fix(odata): independent library fix'); - const [pr] = await plans(github, 'odata'); - const output = github.materialize(pr.updates); - assert.deepEqual(Object.keys(output).sort(), ['CHANGELOG.md', 'Directory.Build.props', odataManifest].sort()); - assert.equal(pr.headRefName, `release-please--branches--${branch}--components--Microsoft.OpenApi.OData`); - assert.ok(output['Directory.Build.props'].includes(`${next}`)); - assert.match(output['CHANGELOG.md'], new RegExp(`v${oldVersion}\\.\\.\\.v${next}`)); - const created = await runReleasePlease(github, branch, 'odata'); - github.merge(created.prs[0]); - const released = await runReleasePlease(github, branch, 'odata'); - assert.equal(released.releases[0].tagName, `v${next}`); - assert.equal(released.prs.length, 0); -}); - -test('Hidi feature release increments minor; breaking changes fail before writing a PR or release', async () => { - const github = new MemoryGitHub(); - const [major, minor] = JSON.parse(github.files[hidiManifest])['.'].split('.').map(Number); - github.change(['src/Microsoft.OpenApi.Hidi/Program.cs'], 'feat(hidi): independent feature'); - assert.equal((await plans(github, 'hidi'))[0].version.toString(), `${major}.${minor + 1}.0`); - github.commits.shift(); - github.change(['src/Microsoft.OpenApi.Hidi/Program.cs'], 'feat(hidi)!: incompatible feature'); - await assert.rejects(runReleasePlease(github, branch, 'hidi'), /outside the branch major/); - assert.equal(github.prs.filter(pr => pr.state === 'OPEN').length, 0); - assert.equal(github.releases.length, 0); -}); - -test('pure Hidi fix and feature release plans retain the official pipeline tag convention', async () => { - const pipeline = fs.readFileSync(path.join(root, '.azure-pipelines', 'hidi-release.yml'), 'utf8'); - const floor = branch === 'main' ? '3.10.2' : '2.12.2'; - assert.ok(pipeline.includes(`[version]'${floor}'`)); - assert.ok(pipeline.includes(`hidiPublishingEnabled: 'false'`)); - for (const type of ['fix', 'feat']) { - const github = new MemoryGitHub(); - const [major, minor, patch] = JSON.parse(github.files[hidiManifest])['.'].split('.').map(Number); - const next = type === 'fix' ? `${major}.${minor}.${patch + 1}` : `${major}.${minor + 1}.0`; - assert.ok(pipeline.includes(`- hidi-v${major}.*`)); - github.change(['Dockerfile'], `${type}(hidi): tag plan`); - const {prs} = await runReleasePlease(github, branch, 'hidi'); - github.merge(prs[0]); - const manifest = await Manifest.fromManifest(github, branch, 'hidi-release-please-config.json', hidiManifest); - const [release] = await manifest.buildReleases(); - assert.equal(release.tag.toString(), `hidi-v${next}`); - assert.match(release.notes, new RegExp(`hidi-v${major}\\.${minor}\\.${patch}\\.\\.\\.hidi-v${next}`)); - assert.deepEqual(github.tags, []); - assert.deepEqual(github.releases, []); - } -}); - -test('two tag-free Hidi version cycles do not replay commits or block OData', async () => { - const github = new MemoryGitHub(); - const baseline = JSON.parse(github.files[hidiManifest])['.']; - github.change(['Dockerfile'], 'fix(hidi): first cycle'); - const first = await runReleasePlease(github, branch, 'hidi'); - assert.deepEqual(first.releases, []); - assert.deepEqual(first.prs[0].labels, ['autorelease: hidi-pending']); - assert.equal((await runReleasePlease(github, branch, 'hidi')).prs.length, 0); - github.merge(first.prs[0]); - assert.equal((await runReleasePlease(github, branch, 'hidi')).prs.length, 0); - assert.deepEqual(first.prs[0].labels, ['autorelease: hidi-versioned']); - assert.deepEqual(github.labelWrites.slice(0, 2).map(write => write[0]), ['add', 'remove']); - github.change(['scripts/check-nuget-package-published.ps1'], 'fix(hidi): second cycle'); - const second = await runReleasePlease(github, branch, 'hidi'); - const patch = Number(baseline.split('.')[2]); - assert.equal(JSON.parse(second.prs[0].output[hidiManifest])['.'], baseline.replace(/\d+$/, String(patch + 2))); - assert.ok(second.prs[0].body.includes('second cycle')); - assert.ok(!second.prs[0].body.includes('first cycle')); - github.merge(second.prs[0]); - assert.equal((await runReleasePlease(github, branch, 'hidi')).prs.length, 0); - github.change(['src/Microsoft.OpenApi.OData.Reader/OpenApiConvertSettings.cs'], 'fix(odata): after Hidi merges'); - assert.equal((await runReleasePlease(github, branch, 'hidi')).prs.length, 0); - assert.equal((await runReleasePlease(github, branch, 'odata')).prs.length, 1); - assert.deepEqual(github.tags, []); - assert.deepEqual(github.releases, []); -}); - -test('version automation and its fixtures keep working after the repository manifest advances', async () => { - const current = JSON.parse(fs.readFileSync(path.join(root, hidiManifest), 'utf8'))['.']; - const advanced = current.replace(/\d+$/, patch => Number(patch) + 1); - const next = current.replace(/\d+$/, patch => Number(patch) + 2); - const github = new MemoryGitHub(advanced); - github.change(['Dockerfile'], 'fix(hidi): after an existing version checkpoint'); - const {prs, releases} = await runReleasePlease(github, branch, 'hidi'); - assert.equal(JSON.parse(prs[0].output[hidiManifest])['.'], next); - assert.deepEqual(releases, []); - github.merge(prs[0]); - assert.equal((await runReleasePlease(github, branch, 'hidi')).prs.length, 0); - assert.deepEqual(github.tags, []); -}); - -test('open Hidi PR updates with additional commits instead of opening a duplicate', async () => { - const github = new MemoryGitHub(); - github.change(['Dockerfile'], 'fix(hidi): first fix'); - const first = await runReleasePlease(github, branch, 'hidi'); - github.change(['install-tool.ps1'], 'fix(hidi): additional fix'); - const updated = await runReleasePlease(github, branch, 'hidi'); - assert.equal(updated.prs[0].number, first.prs[0].number); - assert.equal(github.prs.filter(pr => pr.state === 'OPEN').length, 1); - assert.ok(updated.prs[0].body.includes('additional fix')); -}); - -test('unsafe manifest and merged PR state fail without label or release writes', async t => { - for (const kind of ['wrong-major', 'project-version-mismatch', 'missing-checkpoint', 'wrong-branch', 'bad-body', 'future-version', 'duplicate-checkpoint', 'unreachable-checkpoint', 'title-body-mismatch']) { - await t.test(kind, async () => { - const github = new MemoryGitHub(); - github.change(['Dockerfile'], 'fix(hidi): cycle'); - const {prs} = await runReleasePlease(github, branch, 'hidi'); - github.merge(prs[0]); - if (kind === 'wrong-major') github.files[hidiManifest] = '{".":"9.0.0"}'; - if (kind === 'project-version-mismatch') github.files[hidiProject] = github.files[hidiProject].replace(/.*?<\/Version>/, '9.0.0'); - if (kind === 'missing-checkpoint') github.prs = []; - if (kind === 'wrong-branch') prs[0].headBranchName = 'unrelated'; - if (kind === 'bad-body') prs[0].body = 'not a release PR'; - if (kind === 'future-version') github.files[hidiManifest] = fs.readFileSync(path.join(root, hidiManifest), 'utf8'); - if (kind === 'duplicate-checkpoint') github.prs.push({...prs[0], number: 99, sha: 'duplicate'}); - if (kind === 'unreachable-checkpoint') github.commits.shift(); - if (kind === 'title-body-mismatch') prs[0].title = 'chore(main): release hidi 9.0.0'; - await assert.rejects(runReleasePlease(github, branch, 'hidi')); - assert.deepEqual(github.labelWrites, []); - assert.deepEqual(github.releases, []); - }); - - } -}); - -test('merged PR body version must agree with its title even when the title matches the manifest', async () => { - const github = new MemoryGitHub(); - github.change(['Dockerfile'], 'fix(hidi): cycle'); - const {prs} = await runReleasePlease(github, branch, 'hidi'); - github.merge(prs[0]); - const current = JSON.parse(github.files[hidiManifest])['.']; - prs[0].body = prs[0].body.replaceAll(current, current.replace(/\d+$/, patch => Number(patch) + 1)); - await assert.rejects(runReleasePlease(github, branch, 'hidi'), /inconsistent title and body/); - assert.deepEqual(github.labelWrites, []); -}); - -test('unknown component is an explicit failure', async () => { - await assert.rejects(runReleasePlease(new MemoryGitHub(), branch, 'unknown'), /Unknown component/); -}); - -test('missing commit files are an explicit plugin failure', async () => { - const plugin = new ExactPathExclusions(new MemoryGitHub(), branch, {'.': {excludePaths: []}}); - await assert.rejects(plugin.preconfigure({}, {'.': [{sha: 'bad'}]}), /Missing changed files/); -}); - -test('Hidi ignores pending OData PRs and interrupted label transitions are retryable', async () => { - const github = new MemoryGitHub(); - github.change(['Directory.Build.props'], 'fix(odata): root cycle'); - const rootPr = (await runReleasePlease(github, branch, 'odata')).prs[0]; - github.merge(rootPr); - github.change(['Dockerfile'], 'fix(hidi): independent cycle'); - const hidiPr = (await runReleasePlease(github, branch, 'hidi')).prs[0]; - assert.ok(hidiPr); - github.merge(hidiPr); - hidiPr.labels.push('autorelease: hidi-versioned'); - assert.equal((await runReleasePlease(github, branch, 'hidi')).prs.length, 0); - assert.deepEqual(hidiPr.labels, ['autorelease: hidi-versioned']); - assert.deepEqual(rootPr.labels, ['autorelease: pending']); -}); - -test('Hidi lifecycle labels are created using the authenticated GitHub REST API only when missing', async () => { - const calls = []; - const labels = new Set(); - const request = async (url, options) => { - assert.equal(options.headers.Authorization, 'Bearer offline-test-token'); - assert.equal(options.headers['X-GitHub-Api-Version'], '2022-11-28'); - calls.push([url, options.method || 'GET']); - if (options.method === 'POST') { - const label = JSON.parse(options.body); - assert.ok(['autorelease: hidi-pending', 'autorelease: hidi-versioned'].includes(label.name)); - labels.add(label.name); - return Response.json(label, {status: 201}); - } - const name = decodeURIComponent(url.split('/').at(-1)); - return labels.has(name) ? Response.json({name}) : Response.json({}, {status: 404}); - }; - await ensureHidiLabels('offline-test-token', 'microsoft', 'OpenAPI.NET.OData', request); - assert.deepEqual(calls.map(call => call[1]), ['GET', 'POST', 'GET', 'POST']); - assert.ok(calls[0][0].endsWith('/labels/autorelease%3A%20hidi-pending')); - calls.length = 0; - await ensureHidiLabels('offline-test-token', 'microsoft', 'OpenAPI.NET.OData', request); - assert.deepEqual(calls.map(call => call[1]), ['GET', 'GET']); -}); - -test('Hidi label bootstrap fails explicitly on permissions, network errors or invalid responses', async t => { - for (const status of [401, 403, 500]) { - await t.test(`read HTTP ${status}`, async () => { - await assert.rejects(ensureHidiLabels('token', 'owner', 'repo', - async () => Response.json({}, {status})), new RegExp(`HTTP ${status}`)); - }); - } - await t.test('creation permissions', async () => { - await assert.rejects(ensureHidiLabels('token', 'owner', 'repo', - async (url, options) => Response.json({}, {status: options.method === 'POST' ? 403 : 404})), - /Cannot create.*HTTP 403/); - }); - await t.test('network error', async () => { - await assert.rejects(ensureHidiLabels('token', 'owner', 'repo', - async () => { throw new Error('offline connection failed'); }), /offline connection failed/); - }); - await t.test('unexpected label', async () => { - await assert.rejects(ensureHidiLabels('token', 'owner', 'repo', - async () => Response.json({name: 'autorelease: pending'})), /Cannot verify/); - }); - await t.test('invalid JSON', async () => { - await assert.rejects(ensureHidiLabels('token', 'owner', 'repo', - async () => new Response('invalid JSON')), SyntaxError); - }); -}); - -test('concurrent Hidi label creation is accepted only after verifying the exact existing label', async () => { - const existing = new Set(); - await ensureHidiLabels('token', 'owner', 'repo', async (url, options) => { - if (options.method === 'POST') { - existing.add(JSON.parse(options.body).name); - return Response.json({}, {status: 422}); - } - const name = decodeURIComponent(url.split('/').at(-1)); - return existing.has(name) ? Response.json({name}) : Response.json({}, {status: 404}); - }); - await assert.rejects(ensureHidiLabels('token', 'owner', 'repo', - async (url, options) => Response.json({}, {status: options.method === 'POST' ? 422 : 404})), - /Cannot verify.*HTTP 404/); -}); - -test('CLI wiring emits real library PR/release outputs and uses the app token', async t => { - const github = new MemoryGitHub(); - const core = require('@actions/core'); - const saved = {...process.env}; - const argv = process.argv; - t.after(() => { process.env = saved; process.argv = argv; }); - Object.assign(process.env, {RELEASE_PLEASE_TOKEN: 'offline-test-token', GITHUB_REF_NAME: branch, GITHUB_REPOSITORY: 'microsoft/OpenAPI.NET.OData'}); - let labelReads = 0; - t.mock.method(globalThis, 'fetch', async (url, options) => { - labelReads++; - assert.equal(options.headers.Authorization, 'Bearer offline-test-token'); - assert.equal(options.method, undefined); - return Response.json({name: decodeURIComponent(url.split('/').at(-1))}); - }); - t.mock.method(GitHub, 'create', async options => { - assert.equal(options.token, 'offline-test-token'); - assert.equal(options.defaultBranch, branch); - return github; - }); - const outputs = {}; - t.mock.method(core, 'setOutput', (key, value) => { outputs[key] = value; }); - process.argv = ['node', 'run.cjs', 'hidi']; - github.change(['Dockerfile'], 'fix(hidi): CLI cycle'); - await main(); - assert.equal(outputs.prs_created, true); - assert.equal(outputs.releases_created, false); - assert.equal(JSON.parse(outputs.prs)[0].headBranchName, `release-please--branches--${branch}--components--hidi`); - assert.equal(outputs.paths_released, '[]'); - process.argv[2] = 'odata'; - github.change(['Directory.Build.props'], 'fix(odata): CLI cycle'); - await main(); - github.merge(github.prs.find(pr => pr.labels.includes('autorelease: pending'))); - await main(); - assert.equal(outputs.releases_created, true); - assert.equal(outputs.release_created, true); - assert.ok(outputs.tag_name.startsWith('v')); - assert.ok(outputs.html_url); - assert.equal(labelReads, 2); - delete process.env.RELEASE_PLEASE_TOKEN; - await assert.rejects(main(), /Missing release automation environment/); -}); diff --git a/.github/workflows/ci-cd.yml b/.github/workflows/ci-cd.yml index 37a019bec..05205e8ea 100644 --- a/.github/workflows/ci-cd.yml +++ b/.github/workflows/ci-cd.yml @@ -9,6 +9,9 @@ jobs: ci: name: Continuous Integration runs-on: ubuntu-latest + outputs: + latest_version: ${{ steps.tag_generator.outputs.new_version }} + is_default_branch: ${{ steps.conditionals_handler.outputs.is_default_branch }} env: ARTIFACTS_FOLDER: ${{ github.workspace }}/Artifacts GITHUB_RUN_NUMBER: ${{ github.run_number }} @@ -20,6 +23,27 @@ jobs: 8.0.x 10.0.x + - name: Data gatherer + id: data_gatherer + shell: pwsh + run: | + # Get default branch + $repo = 'microsoft/OpenAPI.NET.OData' + $defaultBranch = Invoke-RestMethod -Method GET -Uri https://api.github.com/repos/$repo | Select-Object -ExpandProperty default_branch + Write-Output "default_branch=$(echo $defaultBranch) >> $GITHUB_OUTPUT" + + - name: Conditionals handler + id: conditionals_handler + shell: pwsh + run: | + $defaultBranch = "${{ steps.data_gatherer.outputs.default_branch }}" + $githubRef = "${{ github.ref }}" + $isDefaultBranch = 'false' + if ( $githubRef -like "*$defaultBranch*" ) { + $isDefaultBranch = 'true' + } + Write-Output "is_default_branch=$(echo $isDefaultBranch) >> $GITHUB_OUTPUT" + - name: Checkout repository id: checkout_repo uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 @@ -27,6 +51,15 @@ jobs: token: ${{ secrets.GITHUB_TOKEN }} fetch-depth: 0 + - if: steps.conditionals_handler.outputs.is_default_branch == 'true' + name: Bump GH tag + id: tag_generator + uses: mathieudutour/github-tag-action@af99e60ce8132224b8e6ebab5023449fe256ed46 # v7.0.0 + with: + github_token: ${{ secrets.GITHUB_TOKEN }} + default_bump: false + release_branches: ${{ steps.data_gatherer.outputs.default_branch }} + - name: Build projects id: build_projects shell: pwsh @@ -34,9 +67,15 @@ jobs: $projectsArray = @( '.\src\Microsoft.OpenApi.OData.Reader\Microsoft.OpenAPI.OData.Reader.csproj' ) + $gitNewVersion = if ("${{ steps.tag_generator.outputs.new_version }}") {"${{ steps.tag_generator.outputs.new_version }}"} else {$null} + $projectCurrentVersion = ([xml](Get-Content .\src\Microsoft.OpenApi.OData.Reader\Microsoft.OpenAPI.OData.Reader.csproj)).Project.PropertyGroup.Version + $projectNewVersion = $gitNewVersion ?? $projectCurrentVersion + $projectsArray | ForEach-Object { dotnet build $PSItem ` - -c Release + -c Release # ` + # -o $env:ARTIFACTS_FOLDER ` + # /p:Version=$projectNewVersion if ($LASTEXITCODE -ne 0) { exit $LASTEXITCODE } } @@ -184,4 +223,42 @@ jobs: throw "Expected OpenAPI 3.0, /Todos paths and schemas in the Docker CSDL YAML output." } + cd: + if: needs.ci.outputs.is_default_branch == 'true' && needs.ci.outputs.latest_version != '' + name: Continuous Deployment + needs: ci + runs-on: ubuntu-latest + steps: + # - name: Download and extract NuGet packages + # id: dl_packages_artifact + # uses: actions/download-artifact@v2 + # with: + # name: NuGet packages + # path: NuGet/ + + # - name: Push NuGet packages to NuGet.org + # id: push_nuget_packages + # continue-on-error: true + # shell: pwsh + # run: | + # Get-ChildItem NuGet/*.nupkg | ForEach-Object { + # nuget push $PSItem ` + # -ApiKey $env:NUGET_API_KEY ` + # -Source https://api.nuget.org/v3/index.json + # } + # env: + # NUGET_API_KEY: ${{ secrets.NUGET_API_KEY }} + + - name: Create and publish release + id: create_release + uses: softprops/action-gh-release@efb35369e0ad2afab669f228072c1b0d510eae64 # v3.0.3 + with: + name: OpenAPI.Net.OData v${{ needs.ci.outputs.latest_version }} + tag_name: v${{ needs.ci.outputs.latest_version }} + # files: | + # NuGet/Microsoft.OpenApi.${{ needs.ci.outputs.latest_version }}.nupkg + # NuGet/Microsoft.OpenApi.Readers.${{ needs.ci.outputs.latest_version }}.nupkg + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + # Built with ❤ by [Pipeline Foundation](https://pipeline.foundation) \ No newline at end of file diff --git a/.github/workflows/release-please-gha.yml b/.github/workflows/release-please-gha.yml index 73b69d2e5..31b2ea292 100644 --- a/.github/workflows/release-please-gha.yml +++ b/.github/workflows/release-please-gha.yml @@ -16,35 +16,12 @@ on: - main - support/v1 - support/v2 - pull_request: - paths: - - .github/release-please/** - - .github/workflows/release-please-gha.yml - - release-please-config.json - - hidi-release-please-config.json - - .release-please-manifest.json - - .hidi-release-please-manifest.json - - Directory.Build.props - - src/Microsoft.OpenApi.Hidi/Microsoft.OpenApi.Hidi.csproj - - src/Microsoft.OpenApi.Hidi/readme.md permissions: contents: read jobs: - release-please-tests: - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 - - uses: actions/setup-node@249970729cb0ef3589644e2896645e5dc5ba9c38 # v6 - with: - node-version: 24 - - run: npm ci --ignore-scripts --no-audit --no-fund - working-directory: .github/release-please - - run: npm test - working-directory: .github/release-please check-secret: - if: github.event_name == 'push' runs-on: ubuntu-latest outputs: has-token: ${{ steps.check.outputs.has-token }} @@ -52,17 +29,12 @@ jobs: - id: check run: echo "has-token=${{ secrets.RELEASE_PLEASE_TOKEN_PROVIDER_PEM != '' }}" >> $GITHUB_OUTPUT release-please-master: - needs: [check-secret, release-please-tests] - if: github.event_name == 'push' && needs.check-secret.outputs.has-token == 'true' + needs: check-secret + if: needs.check-secret.outputs.has-token == 'true' runs-on: ubuntu-latest steps: - name: Checkout repository uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 - - uses: actions/setup-node@249970729cb0ef3589644e2896645e5dc5ba9c38 # v6 - with: - node-version: 24 - - run: npm ci --ignore-scripts --no-audit --no-fund - working-directory: .github/release-please - name: Generate GitHub App token id: app-token @@ -72,33 +44,9 @@ jobs: private-key: ${{ secrets.RELEASE_PLEASE_TOKEN_PROVIDER_PEM }} - name: Release Please - id: release - env: - RELEASE_PLEASE_TOKEN: ${{ steps.app-token.outputs.token }} - run: node .github/release-please/run.cjs odata - - release-please-hidi: - needs: [check-secret, release-please-tests] - # Version PRs only; production tags and publishing remain gated. - if: github.event_name == 'push' && needs.check-secret.outputs.has-token == 'true' && (github.ref_name == 'main' || github.ref_name == 'support/v2') - runs-on: ubuntu-latest - permissions: - contents: read - steps: - - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 - - uses: actions/setup-node@249970729cb0ef3589644e2896645e5dc5ba9c38 # v6 + uses: googleapis/release-please-action@45996ed1f6d02564a971a2fa1b5860e934307cf7 # v5.0.0 with: - node-version: 24 - - run: npm ci --ignore-scripts --no-audit --no-fund - working-directory: .github/release-please - - name: Generate GitHub App token - id: app-token - uses: actions/create-github-app-token@bcd2ba49218906704ab6c1aa796996da409d3eb1 # v3.2.0 - with: - client-id: ${{ vars.RELEASE_PLEASE_TOKEN_PROVIDER_APP_ID }} - private-key: ${{ secrets.RELEASE_PLEASE_TOKEN_PROVIDER_PEM }} - - name: Release Please (independent hidi version) - id: release - env: - RELEASE_PLEASE_TOKEN: ${{ steps.app-token.outputs.token }} - run: node .github/release-please/run.cjs hidi + token: ${{ steps.app-token.outputs.token }} + config-file: release-please-config.json + manifest-file: .release-please-manifest.json + target-branch: ${{ github.ref_name }} diff --git a/.github/workflows/sonarcloud.yml b/.github/workflows/sonarcloud.yml index 00666d676..32ce1a34c 100644 --- a/.github/workflows/sonarcloud.yml +++ b/.github/workflows/sonarcloud.yml @@ -49,23 +49,6 @@ jobs: - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 with: fetch-depth: 0 # Shallow clones should be disabled for a better relevancy of analysis - - uses: actions/setup-node@249970729cb0ef3589644e2896645e5dc5ba9c38 # v6 - with: - node-version: 24 - - name: Test release automation with measured JavaScript coverage - shell: pwsh - working-directory: .github/release-please - run: | - New-Item -ItemType Directory -Force ..\..\artifacts\release-please | Out-Null - npm ci --ignore-scripts --no-audit --no-fund - if ($LASTEXITCODE -ne 0) { exit $LASTEXITCODE } - npm run coverage - if ($LASTEXITCODE -ne 0) { exit $LASTEXITCODE } - $lcov = Get-Content ..\..\artifacts\release-please\lcov.info - $sources = @($lcov | Where-Object { $_ -like 'SF:*' }) - if ($sources.Count -ne 1 -or $sources[0] -notmatch '^SF:\.github[\\/]release-please[\\/]run\.cjs$') { - throw 'Expected measured LCOV for the repository-relative release runner.' - } - name: Cache SonarCloud packages uses: actions/cache@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6.1.0 with: @@ -137,7 +120,7 @@ jobs: CoverletOutputFormat: 'opencover' # https://github.com/microsoft/vstest/issues/4014#issuecomment-1307913682 shell: pwsh run: | - dotnet tool run dotnet-sonarscanner begin /k:"microsoft_OpenAPI.NET.OData" /o:"microsoft" /d:sonar.token="${{ secrets.SONAR_TOKEN }}" /d:sonar.host.url="https://sonarcloud.io" /d:sonar.cs.opencover.reportsPaths="test/**/coverage.net8.0.opencover.xml,artifacts/hidi/coverage/*opencover*.xml" /d:sonar.coverageReportPaths="artifacts/hidi/powershell-coverage/sonar-coverage.xml" /d:sonar.javascript.lcov.reportPaths="artifacts/release-please/lcov.info" /d:sonar.test.inclusions="test/**,**/run.test.cjs" + dotnet tool run dotnet-sonarscanner begin /k:"microsoft_OpenAPI.NET.OData" /o:"microsoft" /d:sonar.token="${{ secrets.SONAR_TOKEN }}" /d:sonar.host.url="https://sonarcloud.io" /d:sonar.cs.opencover.reportsPaths="test/**/coverage.net8.0.opencover.xml,artifacts/hidi/coverage/*opencover*.xml" /d:sonar.coverageReportPaths="artifacts/hidi/powershell-coverage/sonar-coverage.xml" if ($LASTEXITCODE -ne 0) { exit $LASTEXITCODE } dotnet workload restore if ($LASTEXITCODE -ne 0) { exit $LASTEXITCODE } diff --git a/.hidi-release-please-manifest.json b/.hidi-release-please-manifest.json deleted file mode 100644 index 0ddfa5e48..000000000 --- a/.hidi-release-please-manifest.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - ".": "3.10.2" -} diff --git a/.release-please-manifest.json b/.release-please-manifest.json index a9e40ee00..2899cedb8 100644 --- a/.release-please-manifest.json +++ b/.release-please-manifest.json @@ -1,3 +1,4 @@ { - ".": "3.2.1" + ".": "3.2.1", + "src/Microsoft.OpenApi.Hidi": "3.10.2" } \ No newline at end of file diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 3eeb22a64..f2dacff41 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -49,61 +49,22 @@ The recommended commit types used are: Adding an exclamation mark after the commit type (`feat!`) or footer with the prefix __BREAKING CHANGE:__ will cause an increment of the _major_ version. -## Independent Hidi version automation - -OData and Hidi retain separate root release-please configs and version manifests. -Hidi's package directory is deliberately `.`: a package rooted at -`src/Microsoft.OpenApi.Hidi` would miss its tests, Dockerfile, installer and -NuGet helper outside that directory. Routing is based on changed files, not the -optional Conventional Commit scope. A mixed commit can affect both components. - -The pinned runner in `.github/release-please` uses release-please's registered -plugin API to apply `exclude-paths` to exact files as well as directories. -The upstream engine's directory-only matching does not exclude a root filename. -Hidi source, tests, readme, Docker distribution, installer, public identity, -local NuGet config, private-feed helper and Hidi release config/pipeline affect -only Hidi. OData source/tests/docs, its release config/manifest/changelog and -`Directory.Build.props` affect only OData. Shared root README, contribution -guidance, solution, SDK and build files can affect both; shared GitHub CI and -the OData CI pipeline do not trigger releases. Existing OData exclusions, -including its public signing key, remain in place. - -The OData job still creates GitHub releases before opening version PRs. -It is the sole authority for OData tags/releases: the duplicate legacy tag writer -and its downstream GitHub-release-only job were retired from CI/CD. Otherwise, -that writer could count Hidi features when a later OData fix arrived. -The Hidi job opens **version PRs only**, with separate component branches and -`autorelease: hidi-pending` labels. After a version PR merges, the runner verifies -its parsed version against the Hidi manifest, uses that merge as the next commit -boundary, and changes its label to `autorelease: hidi-versioned`. No Hidi tag or -GitHub release is created, and Hidi labels cannot block OData automation. -Missing, inconsistent or unreachable checkpoints fail rather than replaying -old commits. Production publishing and cutover remain separately gated. -The Hidi job verifies or creates only `autorelease: hidi-pending` and -`autorelease: hidi-versioned` through the GitHub labels REST API. Permission, -network or unexpected-response failures stop the job; no broader permissions -are requested and the existing OData labels are untouched. - -Hidi starts at the already-published 3.10.2 on `main` and 2.12.2 on `support/v2`. -Fixes increment its patch; features increment its minor. Generated versions must -remain above the migration floor and within that branch's major, matching the -official pipeline's `hidi-v3.*` / `hidi-v2.*` contracts. A breaking-change major -bump fails before opening a version PR; moving to a new major requires a separate -branch/pipeline decision. Hidi PRs update the project ``, its manifest -and changelog, and annotated install examples, not OData's version or Hidi's -upstream package dependency versions. - -Run the offline regression tests with Node 24: - -```powershell -Push-Location .github\release-please -npm ci --ignore-scripts --no-audit --no-fund -npm test -Pop-Location -``` - -These tests exercise the pinned engine's actual plans and XML/changelog updates, -including two merged Hidi version-PR cycles without tags. The release workflow -runs them before any API writes, including on relevant pull requests. Sonar also -runs measured native Node coverage and imports its LCOV report alongside the -existing C# and PowerShell coverage; the runner is not excluded from analysis. \ No newline at end of file +## Independent component versions + +`release-please-config.json` defines OData at `.` and Hidi at +`src/Microsoft.OpenApi.Hidi`; `.release-please-manifest.json` tracks their versions +independently. The standard release-please action manages both components. +The standard `separate-pull-requests` setting retains component-specific PR +branches so the pinned engine can parse OData-only releases with componentless +tags; the default combined PR format cannot produce those release candidates. +Hidi uses `hidi-v3.*` tags on `main`, its own changelog and the project +`` property. OData retains its root changelog, `Directory.Build.props` +version and componentless `v*` tags. A Hidi source change does not bump OData; +an OData-only change does not bump Hidi. + +Routing follows package directories, not commit scopes. Hidi tests outside the +source package are excluded from OData releases and do not independently trigger +a Hidi release. Root distribution/helper files remain outside the Hidi component; +they follow the root package's standard routing, not custom Hidi routing. +Existing root OData exclusions remain configured. The official Hidi +package/container publishing gates remain disabled during migration. \ No newline at end of file diff --git a/README.md b/README.md index 054766700..e3b392206 100644 --- a/README.md +++ b/README.md @@ -94,9 +94,6 @@ The NuGet package remains `Microsoft.OpenApi.Hidi` and the command remains `hidi Hidi 3.x is maintained on `main`; Hidi 2.x is maintained on `support/v2`. Both tracks use independent versions and require the .NET 8 runtime. Building this repository, including the Hidi tests, requires the .NET 10 SDK. -Hidi's release-please version PRs update its own project, manifest and changelog; -OData retains separate versioning. See [independent Hidi version automation](CONTRIBUTING.md#independent-hidi-version-automation) -for changed-file routing and the tag-free version-PR lifecycle. Destination Hidi release publishing is disabled during the migration; the source repository remains intact until the destination PRs are completed. diff --git a/hidi-release-please-config.json b/hidi-release-please-config.json deleted file mode 100644 index 3bfeb2ac6..000000000 --- a/hidi-release-please-config.json +++ /dev/null @@ -1,49 +0,0 @@ -{ - "$schema": "https://raw.githubusercontent.com/googleapis/release-please/main/schemas/config.json", - "bootstrap-sha": "5574ccc6d8d129d7a49729619fac3e3e36d334fd", - "plugins": ["exact-path-exclusions"], - "separate-pull-requests": true, - "label": "autorelease: hidi-pending", - "release-type": "simple", - "include-component-in-tag": true, - "include-v-in-tag": true, - "exclude-paths": [ - ".azure-pipelines/ci-build.yml", - ".github", - ".idea", - ".vs", - ".vscode", - "src/Microsoft.OpenApi.OData.Reader", - "src/OoasGui", - "src/OoasUtil", - "src/AssemblyInfo", - "test/Microsoft.OpenAPI.OData.Reader.Tests", - "docs", - "CHANGELOG.md", - "Directory.Build.props", - "redocly.yaml", - ".redocly.lint-ignore.yaml", - "tool/Microsoft.OpenApi.OData.snk", - "tool/35MSSharedLib1024.snk", - "release-please-config.json", - ".release-please-manifest.json" - ], - "packages": { - ".": { - "package-name": "Microsoft.OpenApi.Hidi", - "component": "hidi", - "changelog-path": "src/Microsoft.OpenApi.Hidi/CHANGELOG.md", - "extra-files": [ - { - "type": "xml", - "path": "src/Microsoft.OpenApi.Hidi/Microsoft.OpenApi.Hidi.csproj", - "xpath": "//Project/PropertyGroup/Version" - }, - { - "type": "generic", - "path": "src/Microsoft.OpenApi.Hidi/readme.md" - } - ] - } - } -} diff --git a/release-please-config.json b/release-please-config.json index 093f3458c..694094968 100644 --- a/release-please-config.json +++ b/release-please-config.json @@ -1,28 +1,11 @@ { "bootstrap-sha": "4f9bad6ea7d25e8596c0ca214975e690d925e6e7", - "plugins": ["exact-path-exclusions"], "exclude-paths": [ ".azure-pipelines", ".github", ".idea", ".vs", - ".vscode", - "src/Microsoft.OpenApi.Hidi", - "src/Microsoft.OpenApi.Tool", - "src/Microsoft.Hidi", - "Microsoft.OpenApi.Hidi.Tests", - "test/Microsoft.OpenApi.Hidi.Tests", - "test/Microsoft.OpenApi.Tests", - "tool/Microsoft.OpenApi.Hidi.public.snk", - "tool/Microsoft.OpenApi.OData.public.snk", - "tool/hidi-local-nuget.config", - "Dockerfile", - ".dockerignore", - "install-tool.ps1", - "scripts/check-nuget-package-published.ps1", - "test/scripts/check-nuget-package-published.Tests.ps1", - "hidi-release-please-config.json", - ".hidi-release-please-manifest.json" + ".vscode" ], "release-type": "simple", "bump-minor-pre-major": true, @@ -30,10 +13,30 @@ "include-component-in-tag": false, "include-v-in-tag": true, "draft": false, + "separate-pull-requests": true, "packages": { ".": { "package-name": "Microsoft.OpenApi.OData", "changelog-path": "CHANGELOG.md", + "exclude-paths": [ + ".azure-pipelines", + ".github", + ".idea", + ".vs", + ".vscode", + "src/Microsoft.OpenApi.Hidi", + "src/Microsoft.OpenApi.Tool", + "src/Microsoft.Hidi", + "Microsoft.OpenApi.Hidi.Tests", + "test/Microsoft.OpenApi.Hidi.Tests", + "test/Microsoft.OpenApi.Tests", + "tool/Microsoft.OpenApi.Hidi.public.snk", + "tool/Microsoft.OpenApi.OData.public.snk", + "tool/hidi-local-nuget.config", + "Dockerfile", + ".dockerignore", + "install-tool.ps1" + ], "extra-files": [ { "type": "xml", @@ -41,6 +44,20 @@ "xpath": "//Project/PropertyGroup/Version" } ] + }, + "src/Microsoft.OpenApi.Hidi": { + "package-name": "Microsoft.OpenApi.Hidi", + "component": "hidi", + "changelog-path": "CHANGELOG.md", + "include-component-in-tag": true, + "include-v-in-tag": true, + "extra-files": [ + { + "type": "xml", + "path": "Microsoft.OpenApi.Hidi.csproj", + "xpath": "//Project/PropertyGroup/Version" + } + ] } }, "$schema": "https://raw.githubusercontent.com/googleapis/release-please/main/schemas/config.json" diff --git a/src/Microsoft.OpenApi.Hidi/readme.md b/src/Microsoft.OpenApi.Hidi/readme.md index 1f2e5e7ed..249af7bb2 100644 --- a/src/Microsoft.OpenApi.Hidi/readme.md +++ b/src/Microsoft.OpenApi.Hidi/readme.md @@ -20,14 +20,14 @@ from NuGet. Hidi 3.x is maintained on this repository's `main` branch and requir ### .NET CLI(Global) ```bash -dotnet tool install --global Microsoft.OpenApi.Hidi --version 3.10.2 # x-release-please-version +dotnet tool install --global Microsoft.OpenApi.Hidi --version 3.10.2 ``` ### .NET CLI(local) ```bash dotnet new tool-manifest # if the repository does not have a tool manifest -dotnet tool install --local Microsoft.OpenApi.Hidi --version 3.10.2 # x-release-please-version +dotnet tool install --local Microsoft.OpenApi.Hidi --version 3.10.2 ``` ### Build and install from this repository From e686e8c6730ad9ddc8ee2e8931e71c695b39fe38 Mon Sep 17 00:00:00 2001 From: "Gavin Barron (from Dev Box)" Date: Fri, 9 Oct 2026 12:14:21 -0700 Subject: [PATCH 4/4] fix(release): publish only the component selected by its tag Restrict main OData releases to v3 tags and dedicated Hidi releases to hidi-v3 tags. Validate tag/project versions before staging, use supported OData-only pack inputs with no rebuild, and select exact tag-version packages and assets. Preserve branch validation, Hidi publishing flags, signing and protected environments. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> Copilot-Session: 5aef9099-c268-492f-a58a-b591c916f1bc --- .azure-pipelines/ci-build.yml | 63 +++++++++++++++++++++++-------- .azure-pipelines/hidi-release.yml | 33 +++++++++++----- CONTRIBUTING.md | 10 ++++- 3 files changed, 79 insertions(+), 27 deletions(-) diff --git a/.azure-pipelines/ci-build.yml b/.azure-pipelines/ci-build.yml index 9521826fe..125618185 100644 --- a/.azure-pipelines/ci-build.yml +++ b/.azure-pipelines/ci-build.yml @@ -11,7 +11,7 @@ trigger: - support/v2 tags: include: - - 'v*' + - 'v3.*' pr: branches: include: @@ -56,6 +56,18 @@ extends: targetPath: '$(Build.ArtifactStagingDirectory)' steps: + - pwsh: | + $ErrorActionPreference = 'Stop' + $version = ([xml](Get-Content Directory.Build.props)).Project.PropertyGroup.Version + if ($env:BUILD_SOURCEBRANCH -like 'refs/tags/*') { + if ($env:BUILD_SOURCEBRANCH -cnotmatch '^refs/tags/v(3\.\d+\.\d+(?:-[0-9A-Za-z]+(?:[.-][0-9A-Za-z]+)*)?)$') { + throw "Expected an OData v3.x release tag, got $env:BUILD_SOURCEBRANCH." + } + if ($Matches[1] -cne $version) { throw "OData tag must exactly match Directory.Build.props version $version." } + } + Write-Host "##vso[task.setvariable variable=ODataVersion]$version" + displayName: 'Validate OData component tag and project version' + - task: UseDotNet@2 displayName: 'Use .NET 6' # needed for ESRP signing inputs: @@ -173,8 +185,13 @@ extends: displayName: 'pack' inputs: command: pack - projects: src/Microsoft.OpenApi.OData.Reader/Microsoft.OpenAPI.OData.Reader.csproj - arguments: '-o $(Build.ArtifactStagingDirectory) --configuration $(BuildConfiguration) --no-build --include-symbols --include-source /p:SymbolPackageFormat=snupkg' + packagesToPack: src/Microsoft.OpenApi.OData.Reader/Microsoft.OpenAPI.OData.Reader.csproj + configuration: '$(BuildConfiguration)' + packDirectory: '$(Build.ArtifactStagingDirectory)' + nobuild: true + includesymbols: true + includesource: true + buildProperties: 'SymbolPackageFormat=snupkg' - task: EsrpCodeSigning@6 displayName: 'ESRP CodeSigning Nuget Packages' @@ -186,7 +203,7 @@ extends: AuthAKVName: 'akv-prod-eastus' AuthCertName: 'ReferenceLibraryPrivateCert' AuthSignCertName: 'ReferencePackagePublisherCertificate' - Pattern: '*.nupkg' + Pattern: 'Microsoft.OpenApi.OData.$(ODataVersion).nupkg' signConfigType: inlineSignParams inlineOperation: | [ @@ -211,7 +228,7 @@ extends: PendingAnalysisWaitTimeoutMinutes: '5' - stage: deploy - condition: and(contains(variables['build.sourceBranch'], 'refs/tags/v'), succeeded()) + condition: and(succeeded(), startsWith(variables['Build.SourceBranch'], 'refs/tags/v3.')) dependsOn: build jobs: - deployment: deploy @@ -229,10 +246,20 @@ extends: pool: vmImage: ubuntu-latest steps: + - pwsh: | + $ErrorActionPreference = 'Stop' + if ($env:BUILD_SOURCEBRANCH -cnotmatch '^refs/tags/v(3\.\d+\.\d+(?:-[0-9A-Za-z]+(?:[.-][0-9A-Za-z]+)*)?)$') { + throw "Expected an OData v3.x release tag, got $env:BUILD_SOURCEBRANCH." + } + $version = $Matches[1] + $packages = @(Get-ChildItem -LiteralPath '$(Pipeline.Workspace)' -Recurse -File -Filter "Microsoft.OpenApi.OData.$version.nupkg") + if ($packages.Count -ne 1) { throw "Expected exactly one OData package matching tag version $version." } + Write-Host "##vso[task.setvariable variable=ODataPackagePath]$($packages[0].FullName)" + displayName: 'Verify exact OData release package' - task: 1ES.PublishNuget@1 displayName: 'NuGet push' inputs: - packagesToPush: '$(Pipeline.Workspace)/Microsoft.OpenApi.OData.*.nupkg' + packagesToPush: '$(ODataPackagePath)' nuGetFeedType: external publishFeedCredentials: 'OpenAPI Nuget Connection' packageParentPath: '$(Pipeline.Workspace)' @@ -254,21 +281,25 @@ extends: vmImage: ubuntu-latest steps: - pwsh: | - $artifactName = Get-ChildItem -Path $(Pipeline.Workspace) -Filter Microsoft.OpenApi.OData.*.nupkg -recurse | select -First 1 - $artifactVersion= $artifactName.Name -replace "Microsoft.OpenApi.OData.", "" -replace ".nupkg", "" - #Set Variable $artifactName and $artifactVersion - Write-Host "##vso[task.setvariable variable=artifactVersion; isSecret=false;]$artifactVersion" - echo "$artifactVersion" - displayName: 'Fetch Artifact Name' + $ErrorActionPreference = 'Stop' + if ($env:BUILD_SOURCEBRANCH -cnotmatch '^refs/tags/v(3\.\d+\.\d+(?:-[0-9A-Za-z]+(?:[.-][0-9A-Za-z]+)*)?)$') { + throw "Expected an OData v3.x release tag, got $env:BUILD_SOURCEBRANCH." + } + $version = $Matches[1] + $packages = @(Get-ChildItem -LiteralPath '$(Pipeline.Workspace)' -Recurse -File -Filter "Microsoft.OpenApi.OData.$version.nupkg") + if ($packages.Count -ne 1) { throw "Expected exactly one OData package matching tag version $version." } + Write-Host "##vso[task.setvariable variable=ODataReleaseVersion]$version" + Write-Host "##vso[task.setvariable variable=ODataPackagePath]$($packages[0].FullName)" + displayName: 'Verify OData tag and exact GitHub release asset' - task: GitHubRelease@1 displayName: 'GitHub release' - condition: succeededOrFailed() + condition: succeeded() inputs: gitHubConnection: 'Github-MaggieKimani1' action: edit tagSource: userSpecifiedTag - tag: 'v$(artifactVersion)' - title: 'v$(artifactVersion)' + tag: 'v$(ODataReleaseVersion)' + title: 'v$(ODataReleaseVersion)' releaseNotesSource: inline - assets: '$(Pipeline.Workspace)\**\Microsoft.OpenApi.OData.*.nupkg' + assets: '$(ODataPackagePath)' addChangeLog: false diff --git a/.azure-pipelines/hidi-release.yml b/.azure-pipelines/hidi-release.yml index 9094e5ddf..5329000fb 100644 --- a/.azure-pipelines/hidi-release.yml +++ b/.azure-pipelines/hidi-release.yml @@ -50,6 +50,15 @@ extends: artifactName: HidiDockerContext targetPath: '$(Build.ArtifactStagingDirectory)\hidi-docker-context' steps: + - pwsh: | + $ErrorActionPreference = 'Stop' + $version = ([xml](Get-Content src\Microsoft.OpenApi.Hidi\Microsoft.OpenApi.Hidi.csproj)).Project.PropertyGroup.Version + if ($version -cnotmatch '^3\.\d+\.\d+(?:-[0-9A-Za-z]+(?:[.-][0-9A-Za-z]+)*)?$') { throw "Expected a hidi 3.x version, got $version." } + if ($env:BUILD_SOURCEBRANCH -like 'refs/tags/*' -and $env:BUILD_SOURCEBRANCH -cne "refs/tags/hidi-v$version") { + throw "Hidi tag must exactly match the hidi project version." + } + Write-Host "##vso[task.setvariable variable=HidiVersion]$version" + displayName: Validate Hidi component tag and project version - task: UseDotNet@2 displayName: Use .NET 6 for ESRP inputs: @@ -123,12 +132,7 @@ extends: } displayName: Stage public-only hidi Docker context - pwsh: | - $version = ([xml](Get-Content src\Microsoft.OpenApi.Hidi\Microsoft.OpenApi.Hidi.csproj)).Project.PropertyGroup.Version - if ($version -notmatch '^3\.\d+\.\d+(-[0-9A-Za-z.-]+)?$') { throw "Expected a hidi 3.x version, got $version." } - if ('$(Build.SourceBranch)' -like 'refs/tags/*' -and '$(Build.SourceBranch)' -ne "refs/tags/hidi-v$version") { - throw "Hidi tag must exactly match the hidi project version." - } - Write-Host "##vso[task.setvariable variable=HidiVersion]$version" + $ErrorActionPreference = 'Stop' dotnet build src\Microsoft.OpenApi.Hidi\Microsoft.OpenApi.Hidi.csproj -c $(buildConfiguration) -p:GeneratePackageOnBuild=false if ($LASTEXITCODE -ne 0) { exit $LASTEXITCODE } dotnet run --project test\Microsoft.OpenApi.Hidi.Tests\Microsoft.OpenApi.Hidi.Tests.csproj -c $(buildConfiguration) -- --minimum-expected-tests 1 @@ -246,12 +250,19 @@ extends: deploy: steps: - pwsh: | - $tag = '$(Build.SourceBranch)' -replace '^refs/tags/hidi-v', '' + $ErrorActionPreference = 'Stop' + if ($env:BUILD_SOURCEBRANCH -cnotmatch '^refs/tags/hidi-v(3\.\d+\.\d+(?:-[0-9A-Za-z]+(?:[.-][0-9A-Za-z]+)*)?)$') { + throw "Expected a hidi-v3.x release tag, got $env:BUILD_SOURCEBRANCH." + } + $tag = $Matches[1] if ([version]($tag -split '-')[0] -le [version]'3.10.2') { throw "Never republish the source migration baseline or an older hidi version." } $package = "$(Pipeline.Workspace)\hidi\Microsoft.OpenApi.Hidi.$tag.nupkg" - if (-not (Test-Path $package)) { throw "Missing exact hidi package: $package" } + if (-not (Test-Path -LiteralPath $package -PathType Leaf)) { throw "Missing exact hidi package: $package" } $symbols = "$(Pipeline.Workspace)\hidi\Microsoft.OpenApi.Hidi.$tag.snupkg" - if (-not (Test-Path $symbols)) { throw "Missing exact hidi symbols: $symbols" } + if (-not (Test-Path -LiteralPath $symbols -PathType Leaf)) { throw "Missing exact hidi symbols: $symbols" } + foreach ($asset in @("$(Pipeline.Workspace)\hidi\Microsoft.OpenApi.Hidi.exe", "$(Pipeline.Workspace)\hidi\hidi-win-x64-$tag.zip")) { + if (-not (Test-Path -LiteralPath $asset -PathType Leaf)) { throw "Missing exact hidi release asset: $asset" } + } Write-Host "##vso[task.setvariable variable=HidiReleaseVersion]$tag" displayName: Verify new hidi release version and exact package - task: PowerShell@2 @@ -323,8 +334,10 @@ extends: vmImage: ubuntu-latest steps: - pwsh: | + $ErrorActionPreference = 'Stop' $version = ([xml](Get-Content src/Microsoft.OpenApi.Hidi/Microsoft.OpenApi.Hidi.csproj)).Project.PropertyGroup.Version - if ('$(Build.SourceBranch)' -ne "refs/tags/hidi-v$version") { throw "Hidi tag does not match project version." } + if ($version -cnotmatch '^3\.\d+\.\d+(?:-[0-9A-Za-z]+(?:[.-][0-9A-Za-z]+)*)?$') { throw "Expected a hidi 3.x version, got $version." } + if ($env:BUILD_SOURCEBRANCH -cne "refs/tags/hidi-v$version") { throw "Hidi tag does not match project version." } if ([version]($version -split '-')[0] -le [version]'3.10.2') { throw "Do not republish the migration baseline or an older hidi version." } Write-Host "##vso[task.setvariable variable=HidiReleaseVersion]$version" displayName: Read independent hidi version diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index f2dacff41..f87b51b71 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -67,4 +67,12 @@ source package are excluded from OData releases and do not independently trigger a Hidi release. Root distribution/helper files remain outside the Hidi component; they follow the root package's standard routing, not custom Hidi routing. Existing root OData exclusions remain configured. The official Hidi -package/container publishing gates remain disabled during migration. \ No newline at end of file +package/container publishing gates remain disabled during migration. + +The ADO OData pipeline accepts `v3.*` tags and deploys only the exact OData +package matching that tag and `Directory.Build.props`. The dedicated Hidi +pipeline accepts `hidi-v3.*` tags; its package, symbols, executable, ZIP and +container version must match the Hidi tag/project version. Malformed, +other-component or mismatched tags fail validation rather than publishing a +different component. With publishing disabled, branch/PR builds remain validation-only; the existing +Hidi publishing flags, migration floor and protected environments are unchanged. \ No newline at end of file