From c0a18ab8514e12182eb78739b6e8611ee5629b18 Mon Sep 17 00:00:00 2001 From: Edward Faulkner Date: Thu, 11 May 2023 12:28:06 -0400 Subject: [PATCH 01/16] starting some release infra work --- package.json | 12 +- pnpm-lock.yaml | 550 +++++++++++++++++++++++++-- test-packages/release/.gitignore | 5 + test-packages/release/package.json | 15 + test-packages/release/src/prepare.ts | 13 + tsconfig.json | 1 + 6 files changed, 571 insertions(+), 25 deletions(-) create mode 100644 test-packages/release/.gitignore create mode 100644 test-packages/release/package.json create mode 100755 test-packages/release/src/prepare.ts diff --git a/package.json b/package.json index 0634bd884..2d0d89162 100644 --- a/package.json +++ b/package.json @@ -64,5 +64,15 @@ "node": "16.20.0", "pnpm": "8.4.0" }, - "version": "1.8.3" + "changelog": { + "wildcardLabel": "unlabeled", + "labels": { + "breaking": ":boom: Breaking Change", + "enhancement": ":rocket: Enhancement", + "bug": ":bug: Bug Fix", + "documentation": ":memo: Documentation", + "internal": ":house: Internal", + "unlabeled": ":question: Unlabeled" + } + } } diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index b7a6ea319..55f178050 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -988,6 +988,15 @@ importers: specifier: ^5.38.1 version: 5.78.0 + test-packages/release: + dependencies: + '@ef4/lerna-changelog': + specifier: ^1.0.2 + version: 1.0.2 + execa: + specifier: ^7.0.0 + version: 7.0.0 + test-packages/sample-transforms: dependencies: ember-cli-babel: @@ -4374,6 +4383,24 @@ packages: postcss-selector-parser: 6.0.12 dev: true + /@ef4/lerna-changelog@1.0.2: + resolution: {integrity: sha512-dP5phiSfnd1scK7XkblKCLIB4TQSXFNuW0BgpBZHe721HiDok6jRgRHg3M5d6hHlDP4WogLdN3kRAZF3Sbce3Q==} + engines: {node: '>=6'} + hasBin: true + dependencies: + chalk: 2.4.2 + cli-highlight: 2.1.11 + execa: 0.10.0 + make-fetch-happen: 4.0.2 + normalize-git-url: 3.0.2 + p-map: 1.2.0 + progress: 2.0.3 + string.prototype.padend: 3.1.4 + yargs: 11.1.1 + transitivePeerDependencies: + - supports-color + dev: false + /@ember-data/adapter@3.28.0(@babel/core@7.19.6): resolution: {integrity: sha512-nt9DcoXBzDvBeAw411h3Nu7D90GTfzdCJYUVQVpc0MqQLv0pqC3h4UKrqzq9bDZD8LqKd6spWKo0iP8MaZJPSQ==} engines: {node: 12.* || >= 14.*} @@ -5053,7 +5080,7 @@ packages: ember-cli-babel: 7.26.11 find-up: 5.0.0 lodash: 4.17.21 - resolve: 1.20.0 + resolve: 1.22.2 semver: 7.3.8 transitivePeerDependencies: - supports-color @@ -5765,7 +5792,7 @@ packages: lru-cache: 7.18.3 npm-pick-manifest: 8.0.1 proc-log: 3.0.0 - promise-inflight: 1.0.1 + promise-inflight: 1.0.1(bluebird@3.7.2) promise-retry: 2.0.1 semver: 7.3.8 which: 3.0.1 @@ -6924,6 +6951,20 @@ packages: engines: {node: '>=0.4.0'} hasBin: true + /agent-base@4.2.1: + resolution: {integrity: sha512-JVwXMr9nHYTUXsBFKUqhJwvlcYU/blreOEUkhNR2eXZIvwd+c+o5V4MgDPKWnMS/56awN3TRzIP+KoPn+roQtg==} + engines: {node: '>= 4.0.0'} + dependencies: + es6-promisify: 5.0.0 + dev: false + + /agent-base@4.3.0: + resolution: {integrity: sha512-salcGninV0nPrwpGNn4VTXBb1SOuXQBiqbrNXoeizJsHrsL6ERFM2Ne3JUSBWRE6aeNJI2ROP/WEEIDUiDe3cg==} + engines: {node: '>= 4.0.0'} + dependencies: + es6-promisify: 5.0.0 + dev: false + /agent-base@6.0.2(supports-color@8.1.0): resolution: {integrity: sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==} engines: {node: '>= 6.0.0'} @@ -6932,6 +6973,13 @@ packages: transitivePeerDependencies: - supports-color + /agentkeepalive@3.5.2: + resolution: {integrity: sha512-e0L/HNe6qkQ7H19kTlRRqUibEAwDK5AFk6y3PtMsuut2VAH6+Q4xZml1tNDJD7kSAyqmbG/K08K5WEJYtUrSlQ==} + engines: {node: '>= 4.0.0'} + dependencies: + humanize-ms: 1.2.1 + dev: false + /agentkeepalive@4.3.0: resolution: {integrity: sha512-7Epl1Blf4Sy37j4v9f9FjICCh4+KAQOyXgHEwlyBiAQLbhKdq/i2QQU3amQalS/wPhdPzDXPL5DMR5bkn+YeWg==} engines: {node: '>= 8.0.0'} @@ -7091,6 +7139,10 @@ packages: /ansicolors@0.2.1: resolution: {integrity: sha512-tOIuy1/SK/dr94ZA0ckDohKXNeBNqZ4us6PjMVLs5h1w2GBB6uPtOknp2+VF4F/zcy9LI70W+Z+pE2Soajky1w==} + /any-promise@1.3.0: + resolution: {integrity: sha512-7UvmKalWRt1wgjL1RrGxoSJW/0QZFIegpeGvZG9kjp8vrRu55XTHbwnqq2GpXm9uLbcuhxm3IqX9OB4MZR1b2A==} + dev: false + /anymatch@2.0.0: resolution: {integrity: sha512-5teOsQWABXHHBFP9y3skS5P3d/WfWXpv3FUpy+LorMrNYaT9pI4oLMQX7jzQ2KklNpGpWHzdCXTDT2Y3XGlZBw==} dependencies: @@ -7113,6 +7165,10 @@ packages: jsesc: 2.5.2 dev: true + /aproba@1.2.0: + resolution: {integrity: sha512-Y9J6ZjXtoYh8RnXVCMOU/ttDmk1aBjunq9vO0ta5x85WDQiQfUF9sIPBITdbiiIVcBo03Hi3jMxigBtsddlXRw==} + dev: false + /aproba@2.0.0: resolution: {integrity: sha512-lYe4Gx7QT+MKGbDsA+Z+he/Wtef0BiwDOlK/XkBrdfsh9J/jPPXbX0tE9x9cl27Tmu5gg3QUbUrQYa/y+KOHPQ==} @@ -9084,6 +9140,25 @@ packages: resolution: {integrity: sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==} engines: {node: '>= 0.8'} + /cacache@11.3.3: + resolution: {integrity: sha512-p8WcneCytvzPxhDvYp31PD039vi77I12W+/KfR9S8AZbaiARFBCpsPJS+9uhWfeBfeAtW7o/4vt3MUqLkbY6nA==} + dependencies: + bluebird: 3.7.2 + chownr: 1.1.4 + figgy-pudding: 3.5.2 + glob: 7.2.3 + graceful-fs: 4.2.11 + lru-cache: 5.1.1 + mississippi: 3.0.0 + mkdirp: 0.5.6 + move-concurrently: 1.0.1 + promise-inflight: 1.0.1(bluebird@3.7.2) + rimraf: 2.7.1 + ssri: 6.0.2 + unique-filename: 1.1.1 + y18n: 4.0.3 + dev: false + /cacache@16.1.3: resolution: {integrity: sha512-/+Emcj9DAXxX4cwlLmRI9c166RuL3w30zp4R7Joiv2cQTtTtA+jeuCAjH3ZlGnYS3tKENSrKhAzVVP9GVyzeYQ==} engines: {node: ^12.13.0 || ^14.15.0 || >=16.0.0} @@ -9101,7 +9176,7 @@ packages: minipass-pipeline: 1.2.4 mkdirp: 1.0.4 p-map: 4.0.0 - promise-inflight: 1.0.1 + promise-inflight: 1.0.1(bluebird@3.7.2) rimraf: 3.0.2 ssri: 9.0.1 tar: 6.1.14 @@ -9210,6 +9285,11 @@ packages: quick-lru: 4.0.1 dev: true + /camelcase@4.1.0: + resolution: {integrity: sha512-FxAv7HpHrXbh3aPo4o2qxHay2lkLY3x5Mw3KeE4KQE8ysVfziWeRZDwcjauvwBSGEC/nXUPzZy8zeh4HokqOnw==} + engines: {node: '>=4'} + dev: false + /camelcase@5.3.1: resolution: {integrity: sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==} engines: {node: '>=6'} @@ -9334,6 +9414,10 @@ packages: dependencies: inherits: 2.0.4 + /chownr@1.1.4: + resolution: {integrity: sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg==} + dev: false + /chownr@2.0.0: resolution: {integrity: sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ==} engines: {node: '>=10'} @@ -9407,6 +9491,19 @@ packages: restore-cursor: 4.0.0 dev: true + /cli-highlight@2.1.11: + resolution: {integrity: sha512-9KDcoEVwyUXrjcJNvHD0NFc/hiwe/WPVYIleQh2O1N2Zro5gWJZ/K+3DGn8w8P/F6FxOgzyC5bxDyHIgCSPhGg==} + engines: {node: '>=8.0.0', npm: '>=5.0.0'} + hasBin: true + dependencies: + chalk: 4.1.2 + highlight.js: 10.7.3 + mz: 2.7.0 + parse5: 5.1.1 + parse5-htmlparser2-tree-adapter: 6.0.1 + yargs: 16.2.0 + dev: false + /cli-spinners@2.9.0: resolution: {integrity: sha512-4/aL9X3Wh0yiMQlE+eeRhWP6vclO3QRtw1JHKIT0FFUs5FjpFmESqtMvYZ0+lbzBw900b95mS0hohy+qn2VK/g==} engines: {node: '>=6'} @@ -9439,6 +9536,14 @@ packages: engines: {node: '>= 12'} dev: true + /cliui@4.1.0: + resolution: {integrity: sha512-4FG+RSG9DL7uEwRUZXZn3SS34DiDPfzP0VOiEwtUWlE+AR2EIg+hSyvrIgUUfhdgR/UkAeW2QHgeP+hWrXs7jQ==} + dependencies: + string-width: 2.1.1 + strip-ansi: 4.0.0 + wrap-ansi: 2.1.0 + dev: false + /cliui@6.0.0: resolution: {integrity: sha512-t6wbgtoCXvAzst7QgXxJYqPt0usEfbgQdftEPbLL/cvv6HPE5VgvqCuAIDR0NgU52ds6rFwqrgakNLrHEjCbrQ==} dependencies: @@ -9534,6 +9639,11 @@ packages: transitivePeerDependencies: - supports-color + /code-point-at@1.1.0: + resolution: {integrity: sha512-RpAVKQA5T63xEj6/giIbUEtZwJ4UFIc3ZtvEkiaUERylqe8xb5IvqcgOurZLahv93CLKfxcw5YI+DZcUBRyLXA==} + engines: {node: '>=0.10.0'} + dev: false + /collect-v8-coverage@1.0.1: resolution: {integrity: sha512-iBPtljfCNcTKNAto0KEtDfZ3qzjJvqE3aTGZsbhjSBlorqpXJlaWWtPO35D+ZImoC3KWejX64o+yPGxhWSTzfg==} dev: true @@ -9665,6 +9775,16 @@ packages: /concat-map@0.0.1: resolution: {integrity: sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=} + /concat-stream@1.6.2: + resolution: {integrity: sha512-27HBghJxjiZtIk3Ycvn/4kbJk/1uZuJFfuPEns6LaEvpvG1f0hTea8lilrouyo9mVc2GWdcEZ8OLoGmSADlrCw==} + engines: {'0': node >= 0.8} + dependencies: + buffer-from: 1.1.2 + inherits: 2.0.4 + readable-stream: 2.3.8 + typedarray: 0.0.6 + dev: false + /concurrently@7.2.1: resolution: {integrity: sha512-7cab/QyqipqghrVr9qZmoWbidu0nHsmxrpNqQ7r/67vfl1DWJElexehQnTH1p+87tDkihaAjM79xTZyBQh7HLw==} engines: {node: ^12.20.0 || ^14.13.0 || >=16.0.0} @@ -9955,6 +10075,17 @@ packages: resolution: {integrity: sha512-YZ3GUyn/o8gfKJlnlX7g7xq4gyO6OSuhGPKaaGssGB2qgDUS0gPgtTvoyZLTt9Ab6dC4hfc9dV5arkvc/OCmrw==} engines: {node: '>= 0.6'} + /copy-concurrently@1.0.5: + resolution: {integrity: sha512-f2domd9fsVDFtaFcbaRZuYXwtdmnzqbADSwhSWYxYB/Q8zsdUUFMXVRwXGDMWmbEzAn1kdRrtI1T/KTFOL4X2A==} + dependencies: + aproba: 1.2.0 + fs-write-stream-atomic: 1.0.10 + iferr: 0.1.5 + mkdirp: 0.5.6 + rimraf: 2.7.1 + run-queue: 1.0.3 + dev: false + /copy-dereference@1.0.0: resolution: {integrity: sha512-40TSLuhhbiKeszZhK9LfNdazC67Ue4kq/gGwN5sdxEUWPXTIMmKmGmgD9mPfNKVAeecEW+NfEIpBaZoACCQLLw==} dev: true @@ -10192,6 +10323,10 @@ packages: stream-transform: 2.1.3 dev: true + /cyclist@1.0.1: + resolution: {integrity: sha512-NJGVKPS81XejHcLhaLJS7plab0fK3slPh11mESeeDq2W4ZI5kUKK/LRRdVDvjJseojbPB7ZwjnyOybg3Igea/A==} + dev: false + /dag-map@2.0.2: resolution: {integrity: sha512-xnsprIzYuDeiyu5zSKwilV/ajRHxnoMlAhEREfyfTgTSViMVY2fGP1ZcHJbtwup26oCkofySU/m6oKJ3HrkW7w==} @@ -10238,6 +10373,17 @@ packages: ms: 2.0.0 supports-color: 8.1.0 + /debug@3.1.0: + resolution: {integrity: sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==} + peerDependencies: + supports-color: '*' + peerDependenciesMeta: + supports-color: + optional: true + dependencies: + ms: 2.0.0 + dev: false + /debug@3.2.7: resolution: {integrity: sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==} peerDependencies: @@ -10283,7 +10429,6 @@ packages: /decamelize@1.2.0: resolution: {integrity: sha512-z2S+W9X73hAUUki+N+9Za2lBlun89zigOyGrsax+KUQ6wKW4ZoWpEYBkGhQjwAjjDCkWxhY0VKEhk8wzY7F5cA==} engines: {node: '>=0.10.0'} - dev: true /decimal.js@10.4.3: resolution: {integrity: sha512-VBBaLc1MgL5XpzgIP7ny5Z6Nx3UrRkIViUkPUdtl9aya5amy3De1gsUUSB1g3+3sExYNjCAsAznmukyxCb1GRA==} @@ -10564,6 +10709,15 @@ packages: resolution: {integrity: sha512-1A8za6ws41LQgv9HrE/66jyC5yuSjQ3L/KOpFtoBilsAK2iA2wuS5rTt1OCzIvtS2V7nVmedsUU+DGRcjBmOYA==} dev: true + /duplexify@3.7.1: + resolution: {integrity: sha512-07z8uv2wMyS51kKhD1KsdXJg5WQ6t93RneqRxUHnskXVtlYYkLqM0gqStQZ3pj073g687jPCHrqNfCzawLYh5g==} + dependencies: + end-of-stream: 1.4.4 + inherits: 2.0.4 + readable-stream: 2.3.8 + stream-shift: 1.0.1 + dev: false + /eastasianwidth@0.2.0: resolution: {integrity: sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==} dev: true @@ -13038,8 +13192,6 @@ packages: requiresBuild: true dependencies: iconv-lite: 0.6.3 - dev: true - optional: true /end-of-stream@1.4.4: resolution: {integrity: sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==} @@ -13110,6 +13262,10 @@ packages: engines: {node: '>=6'} dev: true + /err-code@1.1.2: + resolution: {integrity: sha512-CJAN+O0/yA1CKfRn9SXOGctSpEM7DCon/r/5r2eXFMY2zCCJBasFhcM5I+1kh3Ap11FsQCX+vGHceNPvpWKhoA==} + dev: false + /err-code@2.0.3: resolution: {integrity: sha512-2bmlRpNKBxT/CRmPOlyISQpNj+qSeYvcym/uT0Jx2bMOlKLtSy1ZmLuVxSEKKyor/N5yhvp/ZiG1oE3DEYMSFA==} dev: true @@ -13211,6 +13367,16 @@ packages: is-date-object: 1.0.5 is-symbol: 1.0.4 + /es6-promise@4.2.8: + resolution: {integrity: sha512-HJDGx5daxeIvxdBxvG2cb9g4tEvwIk3i8+nhX0yGrYmZUzbkdg8QbDevheDB8gd0//uPj4c1EQua8Q+MViT0/w==} + dev: false + + /es6-promisify@5.0.0: + resolution: {integrity: sha512-C+d6UdsYDk0lMebHNR4S2NybQMMngAOnOwYBQjTOiv0MkoJMP0Myw2mgpDLBcpfCmRLxyFqYhS/CfOENq4SJhQ==} + dependencies: + es6-promise: 4.2.8 + dev: false + /escalade@3.1.1: resolution: {integrity: sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==} engines: {node: '>=6'} @@ -13721,6 +13887,19 @@ packages: /exec-sh@0.3.6: resolution: {integrity: sha512-nQn+hI3yp+oD0huYhKwvYI32+JFeq+XkNcD1GAo3Y/MjxsfVGmrrzrnzjWiNY6f+pUCP440fThsFh5gZrRAU/w==} + /execa@0.10.0: + resolution: {integrity: sha512-7XOMnz8Ynx1gGo/3hyV9loYNPWM94jG3+3T3Y8tsfSstFmETmENCMU/A/zj8Lyaj1lkgEepKepvd6240tBRvlw==} + engines: {node: '>=4'} + dependencies: + cross-spawn: 6.0.5 + get-stream: 3.0.0 + is-stream: 1.1.0 + npm-run-path: 2.0.2 + p-finally: 1.0.0 + signal-exit: 3.0.7 + strip-eof: 1.0.0 + dev: false + /execa@1.0.0: resolution: {integrity: sha512-adbxcyWV46qiHyvSp50TKt05tB4tK3HcmF7/nxfAdhnox83seTDbwnaqKO4sXRy7roHAIFqJP/Rw/AuEbX61LA==} engines: {node: '>=6'} @@ -14085,6 +14264,10 @@ packages: dependencies: bser: 2.1.1 + /figgy-pudding@3.5.2: + resolution: {integrity: sha512-0btnI/H8f2pavGMN8w40mlSKOfTK2SVJmBfBeVIj3kNw0swwgzyRq0d5TJVOwodFmtvpPeWPN/MCcfuWF0Ezbw==} + dev: false + /figures@2.0.0: resolution: {integrity: sha512-Oa2M9atig69ZkfwiApY8F2Yy+tzMbazyvqv21R0NsSC8floSOC09BbT1ITWAdoMGQvJ/aZnR1KMwdx9tvHnTNA==} engines: {node: '>=4'} @@ -14393,6 +14576,13 @@ packages: engines: {node: '>=0.4.0'} dev: true + /flush-write-stream@1.1.1: + resolution: {integrity: sha512-3Z4XhFZ3992uIq0XOqb9AreonueSYphE6oYbpt5+3u06JWklbsPkNv3ZKkP9Bz/r+1MWCaMoSQ28P85+1Yc77w==} + dependencies: + inherits: 2.0.4 + readable-stream: 2.3.8 + dev: false + /focus-trap@6.9.4: resolution: {integrity: sha512-v2NTsZe2FF59Y+sDykKY+XjqZ0cPfhq/hikWVL88BqLivnNiEffAsac6rP6H45ff9wG9LL5ToiDqrLEP9GX9mw==} dependencies: @@ -14467,7 +14657,6 @@ packages: dependencies: inherits: 2.0.4 readable-stream: 2.3.8 - dev: true /fs-extra@0.24.0: resolution: {integrity: sha512-w1RvhdLZdU9V3vQdL+RooGlo6b9R9WVoBanOfoJvosWlqSKvrjFlci2oVhwvLwZXBtM7khyPvZ8r3fwsim3o0A==} @@ -14628,6 +14817,15 @@ packages: transitivePeerDependencies: - supports-color + /fs-write-stream-atomic@1.0.10: + resolution: {integrity: sha512-gehEzmPn2nAwr39eay+x3X34Ra+M2QlVUTLhkXPjWdeO8RF9kszk116avgBJM3ZyNHgHXBNx+VmPaFC36k0PzA==} + dependencies: + graceful-fs: 4.2.11 + iferr: 0.1.5 + imurmurhash: 0.1.4 + readable-stream: 2.3.8 + dev: false + /fs.realpath@1.0.0: resolution: {integrity: sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==} @@ -14679,6 +14877,10 @@ packages: resolution: {integrity: sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==} engines: {node: '>=6.9.0'} + /get-caller-file@1.0.3: + resolution: {integrity: sha512-3t6rVToeoZfYSGd8YoLFR2DJkiQrIiUrGcjvFX2mDw3bn6k2OtwHN0TNCLbBO+w8qTvimhDkv+LSscbJY1vE6w==} + dev: false + /get-caller-file@2.0.5: resolution: {integrity: sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==} engines: {node: 6.* || 8.* || >= 10.*} @@ -14712,7 +14914,6 @@ packages: /get-stream@3.0.0: resolution: {integrity: sha512-GlhdIUuVakc8SJ6kK0zAFbiGzRFzNnY4jUuEbV9UROo4Y+0Ny4fjvcZFVTeDA4odpFyOQzaw6hXukJSq/f28sQ==} engines: {node: '>=4'} - dev: true /get-stream@4.1.0: resolution: {integrity: sha512-GMat4EJ5161kIy2HevLlr4luNjBgvmj413KaQA7jt4V8B4RDsfpHk7WQ9GVqfYyyx8OS/L66Kox+rJRNklLK7w==} @@ -15153,6 +15354,10 @@ packages: engines: {node: '>=10.0.0'} dev: true + /highlight.js@10.7.3: + resolution: {integrity: sha512-tzcUFauisWKNHaRkN4Wjl/ZA07gENAjFl3J/c480dprkGTg5EQstgaNFqBfUqCq54kZRIEcreTsAgF/m2quD7A==} + dev: false + /home-or-tmp@2.0.0: resolution: {integrity: sha512-ycURW7oUxE2sNiPVw1HVEFsW+ecOpJ5zaj7eC0RlwhibhRBod20muUN8qu/gzx956YrLolVvs1MTXwKgC2rVEg==} engines: {node: '>=0.10.0'} @@ -15236,7 +15441,6 @@ packages: /http-cache-semantics@3.8.1: resolution: {integrity: sha512-5ai2iksyV8ZXmnZhHH4rWPoxxistEexSi5936zIQ1bnNTW5VnA85B6P/VpXiRM017IgRvb2kKo1a//y+0wSp3w==} - dev: true /http-cache-semantics@4.1.1: resolution: {integrity: sha512-er295DKPVsV82j5kw1Gjt+ADA/XYHsajl82cGNQG2eyoPkvgUhX+nDIyelzhIWbbsXP39EHcI6l5tYs2FYqYXQ==} @@ -15264,6 +15468,16 @@ packages: /http-parser-js@0.5.8: resolution: {integrity: sha512-SGeBX54F94Wgu5RH3X5jsDtf4eHyRogWX1XGT3b4HuW3tQPM4AaBzoUji/4AAJNXCEOWZ5O0DgZmJw1947gD5Q==} + /http-proxy-agent@2.1.0: + resolution: {integrity: sha512-qwHbBLV7WviBl0rQsOzH6o5lwyOIvwp/BdFnvVxXORldu5TmjFfjzBcWUWS5kWAZhmv+JtiDhSuQCp4sBfbIgg==} + engines: {node: '>= 4.5.0'} + dependencies: + agent-base: 4.3.0 + debug: 3.1.0 + transitivePeerDependencies: + - supports-color + dev: false + /http-proxy-agent@4.0.1(supports-color@8.1.0): resolution: {integrity: sha512-k0zdNgqWTGA6aeIRVpvfVob4fL52dTfaehylg0Y4UvSySvOq/Y+BOyPrgpUrA7HylqvU8vIZGsRuXmspskV0Tg==} engines: {node: '>= 6'} @@ -15304,6 +15518,16 @@ packages: resolve-alpn: 1.2.1 dev: true + /https-proxy-agent@2.2.4: + resolution: {integrity: sha512-OmvfoQ53WLjtA9HeYP9RNrWMJzzAz1JGaSFr1nijg0PVR1JaD/xbJq1mdEIIlxGpXp9eSe/O2LgU9DJmTPd0Eg==} + engines: {node: '>= 4.5.0'} + dependencies: + agent-base: 4.3.0 + debug: 3.2.7 + transitivePeerDependencies: + - supports-color + dev: false + /https-proxy-agent@5.0.1(supports-color@8.1.0): resolution: {integrity: sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==} engines: {node: '>= 6'} @@ -15341,7 +15565,6 @@ packages: resolution: {integrity: sha512-Fl70vYtsAFb/C06PTS9dZBo7ihau+Tu/DNCk/OyHhea07S+aeMWpFFkUaXRa8fI+ScZbEI8dfSxwY7gxZ9SAVQ==} dependencies: ms: 2.1.3 - dev: true /iconv-lite@0.4.24: resolution: {integrity: sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==} @@ -15354,7 +15577,6 @@ packages: engines: {node: '>=0.10.0'} dependencies: safer-buffer: 2.1.2 - dev: true /icss-utils@5.1.0(postcss@8.4.23): resolution: {integrity: sha512-soFhflCVWLfRNOPU3iv5Z9VUdT44xFRbzjLsEzSr5AQmgqPMTHdU3PMT1Cf1ssx8fLNJDA1juftYl+PUcv3MqA==} @@ -15368,6 +15590,10 @@ packages: resolution: {integrity: sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==} dev: true + /iferr@0.1.5: + resolution: {integrity: sha512-DUNFN5j7Tln0D+TxzloUjKB+CtVu6myn0JEFak6dG18mNt9YkQ6lzGCdafwofISZ1lLF3xRHJ98VKy9ynkcFaA==} + dev: false + /ignore-walk@6.0.3: resolution: {integrity: sha512-C7FfFoTA+bI10qfeydT8aZbvr91vAEU+2W5BZUlzPec47oNb07SsOfwYrtxuvOYdUApPP/Qlh4DtAO51Ekk2QA==} engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} @@ -15570,11 +15796,20 @@ packages: dependencies: loose-envify: 1.4.0 + /invert-kv@2.0.0: + resolution: {integrity: sha512-wPVv/y/QQ/Uiirj/vh3oP+1Ww+AWehmi1g5fFWGPF6IpCBCDVrhgHRMvrLfdYcwDh3QJbGXDW4JAuzxElLSqKA==} + engines: {node: '>=4'} + dev: false + /invert-kv@3.0.1: resolution: {integrity: sha512-CYdFeFexxhv/Bcny+Q0BfOV+ltRlJcd4BBZBYFX/O0u4npJrgZtIcjokegtiSMAvlMTJ+Koq0GBCc//3bueQxw==} engines: {node: '>=8'} dev: true + /ip@1.1.5: + resolution: {integrity: sha512-rBtCAQAJm8A110nbwn6YdveUnuZH3WrC36IwkRXxDnq53JvXA2NVQvB7IHyKomxK1MJ4VDNw3UtFDdXQ+AvLYA==} + dev: false + /ip@2.0.0: resolution: {integrity: sha512-WKa+XuLG1A1R0UWhl2+1XQSi+fZWMsYKffMZTTYsiZaUD8k2yDAj5atimTUD2TZkyCkNEeYE5NhFZmupOGtjYQ==} dev: true @@ -15715,6 +15950,13 @@ packages: engines: {node: '>=0.10.0'} dev: true + /is-fullwidth-code-point@1.0.0: + resolution: {integrity: sha512-1pqUqRjkhPJ9miNq9SwMfdvi6lBJcd6eFxvfaivQhaH3SgisfiuudvFntdKOmxuee/77l+FPjKrQjWvmPjWrRw==} + engines: {node: '>=0.10.0'} + dependencies: + number-is-nan: 1.0.1 + dev: false + /is-fullwidth-code-point@2.0.0: resolution: {integrity: sha512-VHskAKYM8RfSFXwee5t5cbN5PZeq1Wrh6qd5bkyiXIf6UQcN6w/A0eXM9r6t8d+GYOh+o6ZhiEnb88LN/Y8m2w==} engines: {node: '>=4'} @@ -16817,6 +17059,13 @@ packages: package-json: 8.1.0 dev: true + /lcid@2.0.0: + resolution: {integrity: sha512-avPEb8P8EGnwXKClwsNUgryVjllcRqtMYa49NTsbQagYuT1DcXnl1915oxWjoyGrXR6zH/Y0Zc96xWsPcoDKeA==} + engines: {node: '>=6'} + dependencies: + invert-kv: 2.0.0 + dev: false + /lcid@3.1.1: resolution: {integrity: sha512-M6T051+5QCGLBQb8id3hdvIW8+zeFV2FyBGFS9IEK5H9Wt4MueD4bW1eWikpHgZp+5xR3l5c8pZUkQsIA0BFZg==} engines: {node: '>=8'} @@ -17274,6 +17523,24 @@ packages: - supports-color dev: true + /make-fetch-happen@4.0.2: + resolution: {integrity: sha512-YMJrAjHSb/BordlsDEcVcPyTbiJKkzqMf48N8dAJZT9Zjctrkb6Yg4TY9Sq2AwSIQJFn5qBBKVTYt3vP5FMIHA==} + dependencies: + agentkeepalive: 3.5.2 + cacache: 11.3.3 + http-cache-semantics: 3.8.1 + http-proxy-agent: 2.1.0 + https-proxy-agent: 2.2.4 + lru-cache: 5.1.1 + mississippi: 3.0.0 + node-fetch-npm: 2.0.4 + promise-retry: 1.1.1 + socks-proxy-agent: 4.0.2 + ssri: 6.0.2 + transitivePeerDependencies: + - supports-color + dev: false + /makeerror@1.0.12: resolution: {integrity: sha512-JmqCvUhmt43madlpFzG4BQzG2Z3m6tvQDNKdClZnO3VbIudJYmxsT0FNJMeiB2+JTSlTQTSbU8QdesVmwJcmLg==} dependencies: @@ -17284,7 +17551,6 @@ packages: engines: {node: '>=6'} dependencies: p-defer: 1.0.0 - dev: true /map-cache@0.2.2: resolution: {integrity: sha512-8y/eV9QQZCiyn1SprXSrCmqJN0yNRATe+PO8ztwqrvrbdRLA3eYJF0yaR0YayLWkMbsQSKWS9N2gPcGEc4UsZg==} @@ -17418,6 +17684,15 @@ packages: resolution: {integrity: sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g=} engines: {node: '>= 0.6'} + /mem@4.3.0: + resolution: {integrity: sha512-qX2bG48pTqYRVmDB37rn/6PT7LcR8T7oAX3bf99u1Tt1nzxYfxkgqDwUwolPlXweM0XzBOBFzSx4kfp7KP1s/w==} + engines: {node: '>=6'} + dependencies: + map-age-cleaner: 0.1.3 + mimic-fn: 2.1.0 + p-is-promise: 2.1.0 + dev: false + /mem@5.1.1: resolution: {integrity: sha512-qvwipnozMohxLXG1pOqoLiZKNkC4r4qqRucSoDwXowsNGDSULiqFTRUF05vcZWnwJSG22qTsynQhxbaMtnX9gw==} engines: {node: '>=8'} @@ -17723,6 +17998,22 @@ packages: yallist: 4.0.0 dev: true + /mississippi@3.0.0: + resolution: {integrity: sha512-x471SsVjUtBRtcvd4BzKE9kFC+/2TeWgKCgw0bZcw1b9l2X3QX5vCWgF+KaZaYm87Ss//rHnWryupDrgLvmSkA==} + engines: {node: '>=4.0.0'} + dependencies: + concat-stream: 1.6.2 + duplexify: 3.7.1 + end-of-stream: 1.4.4 + flush-write-stream: 1.1.1 + from2: 2.3.0 + parallel-transform: 1.2.0 + pump: 3.0.0 + pumpify: 1.5.1 + stream-each: 1.2.3 + through2: 2.0.5 + dev: false + /mixin-deep@1.3.2: resolution: {integrity: sha512-WRoDn//mXBiJ1H40rqa3vH0toePwSsGb45iInWlTySa+Uu4k3tYUSxa2v1KqAiLtvlrSzaExqS1gtk96A9zvEA==} engines: {node: '>=0.10.0'} @@ -17773,6 +18064,17 @@ packages: /mout@1.2.4: resolution: {integrity: sha512-mZb9uOruMWgn/fw28DG4/yE3Kehfk1zKCLhuDU2O3vlKdnBBr4XaOCqVTflJ5aODavGUPqFHZgrFX3NJVuxGhQ==} + /move-concurrently@1.0.1: + resolution: {integrity: sha512-hdrFxZOycD/g6A6SoI2bB5NA/5NEqD0569+S47WZhPvm46sD50ZHdYaFmnua5lndde9rCHGjmfK7Z8BuCt/PcQ==} + dependencies: + aproba: 1.2.0 + copy-concurrently: 1.0.5 + fs-write-stream-atomic: 1.0.10 + mkdirp: 0.5.6 + rimraf: 2.7.1 + run-queue: 1.0.3 + dev: false + /mr-dep-walk@1.4.0: resolution: {integrity: sha512-UaDUqkLsd0ep3jAx2+A7BIpfw8wKxhthDj3yPNLBnevipK1CUFJJiz24jRVLw18q7R2aEiRq13WwUBlnwfbQqQ==} dependencies: @@ -17811,6 +18113,14 @@ packages: engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} dev: true + /mz@2.7.0: + resolution: {integrity: sha512-z81GNO7nnYMEhrGh9LeymoE4+Yr0Wn5McHIZMK5cfQCl+NDX08sCZgUc9/6MHni9IWuFLm1Z3HTCXu2z9fN62Q==} + dependencies: + any-promise: 1.3.0 + object-assign: 4.1.1 + thenify-all: 1.6.0 + dev: false + /nanoid@3.3.6: resolution: {integrity: sha512-BGcqMMJuToF7i1rt+2PWSNVnWIkGCU78jBG3RxO/bZlnZPK2Cmi2QaffxGO/2RvWi9sL+FAiRiXMgsyxQ1DIDA==} engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1} @@ -17868,6 +18178,16 @@ packages: minimatch: 3.1.2 dev: true + /node-fetch-npm@2.0.4: + resolution: {integrity: sha512-iOuIQDWDyjhv9qSDrj9aq/klt6F9z1p2otB3AV7v3zBDcL/x+OfGsvGQZZCcMZbUf4Ujw1xGNQkjvGnVT22cKg==} + engines: {node: '>=4'} + deprecated: This module is not used anymore, npm uses minipass-fetch for its fetch implementation now + dependencies: + encoding: 0.1.13 + json-parse-better-errors: 1.0.2 + safe-buffer: 5.2.1 + dev: false + /node-fetch@2.6.11: resolution: {integrity: sha512-4I6pdBY1EthSqDmJkiNk3JIT8cswwR9nfeW/cPdUagJYEQG7R95WRH74wpz7ma8Gh/9dI9FP+OU+0E4FvtA55w==} engines: {node: 4.x || >=6.0.0} @@ -17936,6 +18256,10 @@ packages: abbrev: 1.1.1 dev: true + /normalize-git-url@3.0.2: + resolution: {integrity: sha512-UEmKT33ssKLLoLCsFJ4Si4fmNQsedNwivXpuNTR4V1I97jU9WZlicTV1xn5QAG5itE5B3Z9zhl8OItP6wIGkRA==} + dev: false + /normalize-package-data@2.5.0: resolution: {integrity: sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA==} dependencies: @@ -18137,6 +18461,11 @@ packages: boolbase: 1.0.0 dev: true + /number-is-nan@1.0.1: + resolution: {integrity: sha512-4jbtZXNAsfZbAHiiqjLPBiCl16dES1zI4Hpzzxw61Tk+loF+sBDBKx1ICKKKwIqQ7M0mFn1TmkN7euSncWgHiQ==} + engines: {node: '>=0.10.0'} + dev: false + /nwsapi@2.2.4: resolution: {integrity: sha512-NHj4rzRo0tQdijE9ZqAx6kYDcoRwYwSYzCA8MY3JzfxlrvEU0jhnhJT9BhqhJs7I/dKcrDm6TyulaRqZPIhN5g==} @@ -18332,6 +18661,15 @@ packages: resolution: {integrity: sha512-B5JU3cabzk8c67mRRd3ECmROafjYMXbuzlwtqdM8IbS8ktlTix8aFGb2bAGKrSRIlnfKwovGUUr72JUPyOb6kQ==} engines: {node: '>=0.10.0'} + /os-locale@3.1.0: + resolution: {integrity: sha512-Z8l3R4wYWM40/52Z+S265okfFj8Kt2cC2MKY+xNi3kFs+XGI7WXu/I309QQQYbRW4ijiZ+yxs9pqEhJh0DqW3Q==} + engines: {node: '>=6'} + dependencies: + execa: 1.0.0 + lcid: 2.0.0 + mem: 4.3.0 + dev: false + /os-locale@5.0.0: resolution: {integrity: sha512-tqZcNEDAIZKBEPnHPlVDvKrp7NzgLi7jRmhKiUoa2NUmhl13FtkAGLUVR+ZsYvApBQdBfYm43A4tXXQ4IrYLBA==} engines: {node: '>=10'} @@ -18373,7 +18711,6 @@ packages: /p-defer@1.0.0: resolution: {integrity: sha512-wB3wfAxZpk2AzOfUMJNL+d36xothRSyj8EXOa4f6GMqYDN9BJaaSISbsk+wS9abmnebVw95C2Kb5t85UmpCxuw==} engines: {node: '>=4'} - dev: true /p-defer@3.0.0: resolution: {integrity: sha512-ugZxsxmtTln604yeYd29EGrNhazN2lywetzpKhfmQjW/VJmhpDmWbiX+h0zL8V91R0UXkhb3KtPmyq9PZw3aYw==} @@ -18402,7 +18739,6 @@ packages: /p-is-promise@2.1.0: resolution: {integrity: sha512-Y3W0wlRPK8ZMRbNq97l4M5otioeA5lm1z7bkNkxCka8HSPjR0xRWmpCmc9utiaLP9Jb1eD8BgeIxTW4AIF45Pg==} engines: {node: '>=6'} - dev: true /p-limit@1.3.0: resolution: {integrity: sha512-vvcXsLAJ9Dr5rQOPk7toZQZJApBl2K4J6dANSsEuh6QI41JYcsS/qhTGa9ErIUUgK3WNQoJYvylxvjqmiqEA9Q==} @@ -18460,6 +18796,11 @@ packages: p-limit: 4.0.0 dev: true + /p-map@1.2.0: + resolution: {integrity: sha512-r6zKACMNhjPJMTl8KcFH4li//gkrXWfbD6feV8l6doRHlzljFWGJ2AP6iKaCJXyZmAUMOPtvbW7EXkbWO/pLEA==} + engines: {node: '>=4'} + dev: false + /p-map@2.1.0: resolution: {integrity: sha512-y3b8Kpd8OAN444hxfBbFfj1FY/RjtTd8tzYwhUqNYXx0fXx2iX4maP4Qr6qhIKbQXI02wTLAda4fYUbDagTUFw==} engines: {node: '>=6'} @@ -18542,6 +18883,14 @@ packages: - supports-color dev: true + /parallel-transform@1.2.0: + resolution: {integrity: sha512-P2vSmIu38uIlvdcU7fDkyrxj33gTUy/ABO5ZUbGowxNCopBq/OoD42bP4UmMrJoPyk4Uqf0mu3mtWBhHCZD8yg==} + dependencies: + cyclist: 1.0.1 + inherits: 2.0.4 + readable-stream: 2.3.8 + dev: false + /parent-module@1.0.1: resolution: {integrity: sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==} engines: {node: '>=6'} @@ -18586,6 +18935,16 @@ packages: /parse-static-imports@1.1.0: resolution: {integrity: sha512-HlxrZcISCblEV0lzXmAHheH/8qEkKgmqkdxyHTPbSqsTUV8GzqmN1L+SSti+VbNPfbBO3bYLPHDiUs2avbAdbA==} + /parse5-htmlparser2-tree-adapter@6.0.1: + resolution: {integrity: sha512-qPuWvbLgvDGilKc5BoicRovlT4MtYT6JfJyBOMDsKoiT+GiuP5qyrPCnR9HcPECIJJmZh5jRndyNThnhhb/vlA==} + dependencies: + parse5: 6.0.1 + dev: false + + /parse5@5.1.1: + resolution: {integrity: sha512-ugq4DFI0Ptb+WWjAdOK16+u/nHfiIrcE+sh8kZMaM0WllQKLI9rOUq6c2b7cwPkXdzfQESqvoqK6ug7U/Yyzug==} + dev: false + /parse5@6.0.1: resolution: {integrity: sha512-Ofn/CTFzRGTTxwpNEs9PP93gXShHcTq255nzRYSKe8AkVpZY7e1fpmTfOyoIvjP5HG7Z2ZM7VS9PPhQGW2pOpw==} @@ -18981,7 +19340,6 @@ packages: /process-nextick-args@2.0.1: resolution: {integrity: sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==} - dev: true /process-relative-require@1.0.0: resolution: {integrity: sha512-r8G5WJPozMJAiv8sDdVWKgJ4In/zBXqwJdMCGAXQt2Kd3HdbAuJVzWYM4JW150hWoaI9DjhtbjcsCCHIMxm8RA==} @@ -18991,16 +19349,16 @@ packages: /progress@2.0.3: resolution: {integrity: sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA==} engines: {node: '>=0.4.0'} - dev: true - /promise-inflight@1.0.1: + /promise-inflight@1.0.1(bluebird@3.7.2): resolution: {integrity: sha512-6zWPyEOFaQBJYcGMHBKTKJ3u6TBsnMFOIZSa6ce1e/ZrrsOlnHRHbabMjLiBYKp+n44X9eUI6VUPaukCXHuG4g==} peerDependencies: bluebird: '*' peerDependenciesMeta: bluebird: optional: true - dev: true + dependencies: + bluebird: 3.7.2 /promise-map-series@0.2.3: resolution: {integrity: sha512-wx9Chrutvqu1N/NHzTayZjE1BgIwt6SJykQoCOic4IZ9yUDjKyVYrpLa/4YCNsV61eRENfs29hrEquVuB13Zlw==} @@ -19011,6 +19369,14 @@ packages: resolution: {integrity: sha512-3npG2NGhTc8BWBolLLf8l/92OxMGaRLbqvIh9wjCHhDXNvk4zsxaTaCpiCunW09qWPrN2zeNSNwRLVBrQQtutA==} engines: {node: 10.* || >= 12.*} + /promise-retry@1.1.1: + resolution: {integrity: sha512-StEy2osPr28o17bIW776GtwO6+Q+M9zPiZkYfosciUUMYqjhU/ffwRAH0zN2+uvGyUsn8/YICIHRzLbPacpZGw==} + engines: {node: '>=0.12'} + dependencies: + err-code: 1.1.2 + retry: 0.10.1 + dev: false + /promise-retry@2.0.1: resolution: {integrity: sha512-y+WKFlBR8BGXnsNlIHFGPZmyDf3DFMoLhaflAnyZgV6rG6xu+JwesTo2Q9R6XwYmtmwAFCkAk3e35jEdoeh/3g==} engines: {node: '>=10'} @@ -19066,12 +19432,27 @@ packages: /psl@1.9.0: resolution: {integrity: sha512-E/ZsdU4HLs/68gYzgGTkMicWTLPdAftJLfJFlLUAAKZGkStNU72sZjT66SnMDVOfOWY/YAoiD7Jxa9iHvngcag==} + /pump@2.0.1: + resolution: {integrity: sha512-ruPMNRkN3MHP1cWJc9OWr+T/xDP0jhXYCLfJcBuX54hhfIBnaQmAUMfDcG4DM5UMWByBbJY69QSphm3jtDKIkA==} + dependencies: + end-of-stream: 1.4.4 + once: 1.4.0 + dev: false + /pump@3.0.0: resolution: {integrity: sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==} dependencies: end-of-stream: 1.4.4 once: 1.4.0 + /pumpify@1.5.1: + resolution: {integrity: sha512-oClZI37HvuUJJxSKKrC17bZ9Cu0ZYhEAGPsPUy9KlMUmv9dKX2o77RUmq7f3XjIxbwyGwYzbzQ1L2Ks8sIradQ==} + dependencies: + duplexify: 3.7.1 + inherits: 2.0.4 + pump: 2.0.1 + dev: false + /punycode@2.3.0: resolution: {integrity: sha512-rRV+zQD8tVFys26lAGR9WUuS4iUAngJScM+ZRSKtvl5tKeZ2t5bvdNFdNHBW9FWR4guGHlgmsZ1G7BSm2wTbuA==} engines: {node: '>=6'} @@ -19296,7 +19677,6 @@ packages: safe-buffer: 5.1.2 string_decoder: 1.1.1 util-deprecate: 1.0.2 - dev: true /readable-stream@3.6.2: resolution: {integrity: sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==} @@ -19518,6 +19898,10 @@ packages: resolution: {integrity: sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==} engines: {node: '>=0.10.0'} + /require-main-filename@1.0.1: + resolution: {integrity: sha512-IqSUtOVP4ksd1C/ej5zeEh/BIP2ajqpn8c5x+q99gvcIG/Qf0cud5raVnE/Dwd0ua9TXYDoDc0RE5hBSdz22Ug==} + dev: false + /require-main-filename@2.0.0: resolution: {integrity: sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg==} dev: true @@ -19671,6 +20055,10 @@ packages: resolution: {integrity: sha512-TTlYpa+OL+vMMNG24xSlQGEJ3B/RzEfUlLct7b5G/ytav+wPrplCpVMFuwzXbkecJrb6IYo1iFb0S9v37754mg==} engines: {node: '>=0.12'} + /retry@0.10.1: + resolution: {integrity: sha512-ZXUSQYTHdl3uS7IuCehYfMzKyIDBNoAuUblvy5oGO5UJSUTmStUUVPXbA9Qxd173Bgre53yCQczQuHgRWAdvJQ==} + dev: false + /retry@0.12.0: resolution: {integrity: sha512-9LkiTwjUh6rT555DtE9rTX+BKByPfrMzEAtnlEtdEwr3Nkffwiihqe2bWADg+OQRjt9gl6ICdmB/ZFDCGAtSow==} engines: {node: '>= 4'} @@ -19832,6 +20220,12 @@ packages: dependencies: queue-microtask: 1.2.3 + /run-queue@1.0.3: + resolution: {integrity: sha512-ntymy489o0/QQplUDnpYAYUsO50K9SBrIVaKCWDOJzYJts0f9WH9RFJkyagebkw5+y1oi00R7ynNW/d12GBumg==} + dependencies: + aproba: 1.2.0 + dev: false + /rx-lite-aggregates@4.0.8: resolution: {integrity: sha512-3xPNZGW93oCjiO7PtKxRK6iOVYBWBvtf9QHDfU23Oc+dLIQmAV//UnyXV/yihv81VS/UqoQPk4NegS8EFi55Hg==} dependencies: @@ -20166,7 +20560,6 @@ packages: /smart-buffer@4.2.0: resolution: {integrity: sha512-94hK0Hh8rPqQl2xXc3HsaBoOXKV20MToPkcXvwbISWLEs+64sBq5kFgn2kJDHb1Pry9yrP0dxrCI9RRci7RXKg==} engines: {node: '>= 6.0.0', npm: '>= 3.0.0'} - dev: true /smartwrap@2.0.2: resolution: {integrity: sha512-vCsKNQxb7PnCNd2wY1WClWifAc2lwqsG8OaswpJkVJsvMGcnEntdTCDajZCkk93Ay1U3t/9puJmb525Rg5MZBA==} @@ -20255,6 +20648,14 @@ packages: - supports-color - utf-8-validate + /socks-proxy-agent@4.0.2: + resolution: {integrity: sha512-NT6syHhI9LmuEMSK6Kd2V7gNv5KFZoLE7V5udWmn0de+3Mkj3UMA/AJPLyeNUVmElCurSHtUdM3ETpR3z770Wg==} + engines: {node: '>= 6'} + dependencies: + agent-base: 4.2.1 + socks: 2.3.3 + dev: false + /socks-proxy-agent@7.0.0: resolution: {integrity: sha512-Fgl0YPZ902wEsAyiQ+idGd1A7rSFx/ayC1CQVMw5P+EQx2V0SgpGtf6OKFhVjPflPUl9YMmEOnmfjCdMUsygww==} engines: {node: '>= 10'} @@ -20266,6 +20667,14 @@ packages: - supports-color dev: true + /socks@2.3.3: + resolution: {integrity: sha512-o5t52PCNtVdiOvzMry7wU4aOqYWL0PeCXRWBEiJow4/i/wr+wpsJQ9awEu1EonLIqsfGd5qSgDdxEOvCdmBEpA==} + engines: {node: '>= 6.0.0', npm: '>= 3.0.0'} + dependencies: + ip: 1.1.5 + smart-buffer: 4.2.0 + dev: false + /socks@2.7.1: resolution: {integrity: sha512-7maUZy1N7uo6+WVEX6psASxtNlKaNVMlGQKkG/63nEDdLOWNbiUMoLK7X4uYoLhQstau72mLgfEWcXcwsaHbYQ==} engines: {node: '>= 10.13.0', npm: '>= 3.0.0'} @@ -20433,6 +20842,12 @@ packages: minipass: 5.0.0 dev: true + /ssri@6.0.2: + resolution: {integrity: sha512-cepbSq/neFK7xB6A50KHN0xHDotYzq58wWCa5LeWqnPrHG8GzfEjO/4O8kpmcGW+oaxkvhEJCWgbgNk4/ZV93Q==} + dependencies: + figgy-pudding: 3.5.2 + dev: false + /ssri@9.0.1: resolution: {integrity: sha512-o57Wcn66jMQvfHG1FlYbWeZWW/dHZhJXjpIcTfXldXEk5nz5lStPo3mK0OJQfGR3RbZUlbISexbljkJzuEj/8Q==} engines: {node: ^12.13.0 || ^14.15.0 || >=16.0.0} @@ -20488,6 +20903,17 @@ packages: internal-slot: 1.0.5 dev: true + /stream-each@1.2.3: + resolution: {integrity: sha512-vlMC2f8I2u/bZGqkdfLQW/13Zihpej/7PmSiMQsbYddxuTsJp8vRe2x2FvVExZg7FaOds43ROAuFJwPR4MTZLw==} + dependencies: + end-of-stream: 1.4.4 + stream-shift: 1.0.1 + dev: false + + /stream-shift@1.0.1: + resolution: {integrity: sha512-AiisoFqQ0vbGcZgQPY1cdP2I76glaVA/RauYR4G4thNFgkTqr90yXTo4LYX60Jl+sIlPNHHdGSwo01AvbKUSVQ==} + dev: false + /stream-transform@2.1.3: resolution: {integrity: sha512-9GHUiM5hMiCi6Y03jD2ARC1ettBXkQBoQAe7nJsPknnI0ow10aXjTnew8QtYQmLjzn974BnmWEAJgCY6ZP1DeQ==} dependencies: @@ -20510,6 +20936,15 @@ packages: /string-template@0.2.1: resolution: {integrity: sha512-Yptehjogou2xm4UJbxJ4CxgZx12HBfeystp0y3x7s4Dj32ltVVG1Gg8YhKjHZkHicuKpZX/ffilA8505VbUbpw==} + /string-width@1.0.2: + resolution: {integrity: sha512-0XsVpQLnVCXHJfyEs8tC0zpTVIr5PKKsQtkT29IwupnPTjtPmQ3xT/4yCREF9hYkV/3M3kzcUTSAZT6a6h81tw==} + engines: {node: '>=0.10.0'} + dependencies: + code-point-at: 1.1.0 + is-fullwidth-code-point: 1.0.0 + strip-ansi: 3.0.1 + dev: false + /string-width@2.1.1: resolution: {integrity: sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==} engines: {node: '>=4'} @@ -20562,7 +20997,6 @@ packages: call-bind: 1.0.2 define-properties: 1.2.0 es-abstract: 1.21.2 - dev: true /string.prototype.trim@1.2.7: resolution: {integrity: sha512-p6TmeT1T3411M8Cgg9wBTMRtY2q9+PNy9EV1i2lIXUN/btt763oIfxwN3RR8VU6wHX8j/1CFy0L+YuThm6bgOg==} @@ -20593,7 +21027,6 @@ packages: resolution: {integrity: sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==} dependencies: safe-buffer: 5.1.2 - dev: true /string_decoder@1.3.0: resolution: {integrity: sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==} @@ -21099,6 +21532,19 @@ packages: resolution: {integrity: sha512-49WtAWS+tcsy93dRt6P0P3AMD2m5PvXRhuEA0kaXos5ZLlujtYmpmFsB+QvWUSxE1ZsstmYXfQ7L40+EcQgpAQ==} engines: {node: '>=0.8'} + /thenify-all@1.6.0: + resolution: {integrity: sha512-RNxQH/qI8/t3thXJDwcstUO4zeqo64+Uy/+sNVRBx4Xn2OX+OZ9oP+iJnNFqplFra2ZUVeKCSa2oVWi3T4uVmA==} + engines: {node: '>=0.8'} + dependencies: + thenify: 3.3.1 + dev: false + + /thenify@3.3.1: + resolution: {integrity: sha512-RVZSIV5IG10Hk3enotrhvz0T9em6cyHBLkH/YAZuKqd8hRkKhSfCGIcP2KUY0EPxndzANBmNllzWPwak+bheSw==} + dependencies: + any-promise: 1.3.0 + dev: false + /thread-loader@3.0.4(webpack@5.78.0): resolution: {integrity: sha512-ByaL2TPb+m6yArpqQUZvP+5S1mZtXsEP7nWKKlAUTm7fCml8kB5s1uI3+eHRP2bk5mVYfRSBI7FFf+tWEyLZwA==} engines: {node: '>= 10.13.0'} @@ -21113,6 +21559,13 @@ packages: webpack: 5.78.0 dev: false + /through2@2.0.5: + resolution: {integrity: sha512-/mrRod8xqpA+IHSLyGCQ2s8SPHiCDEeQJSep1jqLYeEUClOFG2Qsh+4FU6G9VeqpZnGW/Su8LQGc4YKni5rYSQ==} + dependencies: + readable-stream: 2.3.8 + xtend: 4.0.2 + dev: false + /through2@3.0.2: resolution: {integrity: sha512-enaDQ4MUyP2W6ZyT6EsMzqBPZaM/avg8iuo+l2d3QCs0J+6RaqkHV/2/lOwDTueBHeJ/2LG9lrLW3d5rWPucuQ==} dependencies: @@ -21468,6 +21921,10 @@ packages: dependencies: is-typedarray: 1.0.0 + /typedarray@0.0.6: + resolution: {integrity: sha512-/aCDEGatGvZ2BIk+HmLf4ifCJFwvKFNb9/JeZPMulfgFracn9QFcAf5GO8B/mweUjSoblS5In0cWhqpfs/5PQA==} + dev: false + /typescript-memoize@1.0.1: resolution: {integrity: sha512-oJNge1qUrOK37d5Y6Ly2txKeuelYVsFtNF6U9kXIN7juudcQaHJQg2MxLOy0CqtkW65rVDYuTCOjnSIVPd8z3w==} @@ -21547,6 +22004,12 @@ packages: is-extendable: 0.1.1 set-value: 2.0.1 + /unique-filename@1.1.1: + resolution: {integrity: sha512-Vmp0jIp2ln35UTXuryvjzkjGdRyf9b2lTXuSYUiPmzRcl3FDtYqAwOnTJkAngD9SWhnoJzDbTKwaOrZ+STtxNQ==} + dependencies: + unique-slug: 2.0.2 + dev: false + /unique-filename@2.0.1: resolution: {integrity: sha512-ODWHtkkdx3IAR+veKxFV+VBkUMcN+FaqzUUd7IZzt+0zhDZFPFxhlqwPF3YQvMHx1TD0tdgYl+kuPnJ8E6ql7A==} engines: {node: ^12.13.0 || ^14.15.0 || >=16.0.0} @@ -21561,6 +22024,12 @@ packages: unique-slug: 4.0.0 dev: true + /unique-slug@2.0.2: + resolution: {integrity: sha512-zoWr9ObaxALD3DOPfjPSqxt4fnZiWblxHIgeWqW8x7UqDzEtHEQLzji2cuJYQFCU6KmoJikOYAZlrTHHebjx2w==} + dependencies: + imurmurhash: 0.1.4 + dev: false + /unique-slug@3.0.0: resolution: {integrity: sha512-8EyMynh679x/0gqE9fT9oilG+qEt+ibFyqjuVTsZn1+CMxH+XLlpvr2UZx4nVcCwTpx81nICr2JQFkM+HPLq4w==} engines: {node: ^12.13.0 || ^14.15.0 || >=16.0.0} @@ -22025,7 +22494,6 @@ packages: /which-module@2.0.1: resolution: {integrity: sha512-iBdZ57RDvnOR9AGBhML2vFZf7h8vmBjhoaZqODJBFWHVtKkDmKuHai3cx5PgVMrX5YDNp27AofYbAwctSS+vhQ==} - dev: true /which-pm@2.0.0: resolution: {integrity: sha512-Lhs9Pmyph0p5n5Z3mVnN0yWcbQYUAD7rbQUiMsQxOJ3T57k7RFe35SUwWMf7dsbDZks1uOmw4AecB/JMDj3v/w==} @@ -22101,6 +22569,14 @@ packages: /workerpool@6.4.0: resolution: {integrity: sha512-i3KR1mQMNwY2wx20ozq2EjISGtQWDIfV56We+yGJ5yDs8jTwQiLLaqHlkBHITlCuJnYlVRmXegxFxZg7gqI++A==} + /wrap-ansi@2.1.0: + resolution: {integrity: sha512-vAaEaDM946gbNpH5pLVNR+vX2ht6n0Bt3GXwVB1AuAqZosOvHNF3P7wDnh8KLkSqgUh0uh77le7Owgoz+Z9XBw==} + engines: {node: '>=0.10.0'} + dependencies: + string-width: 1.0.2 + strip-ansi: 3.0.1 + dev: false + /wrap-ansi@6.2.0: resolution: {integrity: sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==} engines: {node: '>=8'} @@ -22226,9 +22702,12 @@ packages: resolution: {integrity: sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==} engines: {node: '>=0.4'} + /y18n@3.2.2: + resolution: {integrity: sha512-uGZHXkHnhF0XeeAPgnKfPv1bgKAYyVvmNL1xlKsPYZPaIHxGti2hHqvOCQv71XMsLxu1QjergkqogUnms5D3YQ==} + dev: false + /y18n@4.0.3: resolution: {integrity: sha512-JKhqTOwSrqNA1NY5lSztJ1GrBiUodLMmIZuLiDaMRJ+itFd+ABVE8XBjOvIWL+rSqNDC74LCSFmlb/U4UZ4hJQ==} - dev: true /y18n@5.0.8: resolution: {integrity: sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==} @@ -22273,6 +22752,29 @@ packages: engines: {node: '>=12'} dev: true + /yargs-parser@9.0.2: + resolution: {integrity: sha512-CswCfdOgCr4MMsT1GzbEJ7Z2uYudWyrGX8Bgh/0eyCzj/DXWdKq6a/ADufkzI1WAOIW6jYaXJvRyLhDO0kfqBw==} + dependencies: + camelcase: 4.1.0 + dev: false + + /yargs@11.1.1: + resolution: {integrity: sha512-PRU7gJrJaXv3q3yQZ/+/X6KBswZiaQ+zOmdprZcouPYtQgvNU35i+68M4b1ZHLZtYFT5QObFLV+ZkmJYcwKdiw==} + dependencies: + cliui: 4.1.0 + decamelize: 1.2.0 + find-up: 2.1.0 + get-caller-file: 1.0.3 + os-locale: 3.1.0 + require-directory: 2.1.1 + require-main-filename: 1.0.1 + set-blocking: 2.0.0 + string-width: 2.1.1 + which-module: 2.0.1 + y18n: 3.2.2 + yargs-parser: 9.0.2 + dev: false + /yargs@15.4.1: resolution: {integrity: sha512-aePbxDmcYW++PaqBsJ+HYUFwCdv4LVvdnhBy78E57PIor8/OVvhMrADFFEDh8DHDFRv/O9i3lPhsENjO7QX0+A==} engines: {node: '>=8'} diff --git a/test-packages/release/.gitignore b/test-packages/release/.gitignore new file mode 100644 index 000000000..2e2f15e2e --- /dev/null +++ b/test-packages/release/.gitignore @@ -0,0 +1,5 @@ +/node_modules +/src/**/*.js +/src/**/*.d.ts +/src/**/*.map + diff --git a/test-packages/release/package.json b/test-packages/release/package.json new file mode 100644 index 000000000..9e6ae7b90 --- /dev/null +++ b/test-packages/release/package.json @@ -0,0 +1,15 @@ +{ + "name": "@embroider/release", + "version": "0.0.0", + "private": true, + "scripts": { + "prepare": "node ./src/prepare.js" + }, + "dependencies": { + "@ef4/lerna-changelog": "^1.0.2", + "execa": "^7.0.0" + }, + "volta": { + "extends": "../../package.json" + } +} diff --git a/test-packages/release/src/prepare.ts b/test-packages/release/src/prepare.ts new file mode 100755 index 000000000..0d39849df --- /dev/null +++ b/test-packages/release/src/prepare.ts @@ -0,0 +1,13 @@ +import { execa } from 'execa'; + +async function main() {} + +main().then( + () => { + process.exit(0); + }, + err => { + console.error(err); + process.exit(-1); + } +); diff --git a/tsconfig.json b/tsconfig.json index 0896d4e0b..3ef815899 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -3,6 +3,7 @@ "./packages/*/src/**/*.ts", "./packages/*/tests/**/*.ts", "./test-packages/support/**/*.ts", + "./test-packages/release/src/**/*.ts", "./tests/scenarios/**/*.ts" ], "compilerOptions": { From c296d0bc853455c43393c65eb701021711429548 Mon Sep 17 00:00:00 2001 From: Edward Faulkner Date: Thu, 11 May 2023 14:27:19 -0400 Subject: [PATCH 02/16] generating and parsing lerna-changelog results --- package.json | 5 +- pnpm-lock.yaml | 172 ++++++++------------- test-packages/release/package.json | 6 +- test-packages/release/src/change-parser.ts | 108 +++++++++++++ test-packages/release/src/prepare.ts | 22 ++- 5 files changed, 198 insertions(+), 115 deletions(-) create mode 100644 test-packages/release/src/change-parser.ts diff --git a/package.json b/package.json index 2d0d89162..6b638b344 100644 --- a/package.json +++ b/package.json @@ -65,7 +65,7 @@ "pnpm": "8.4.0" }, "changelog": { - "wildcardLabel": "unlabeled", + "__comment__": "Our release infrastructure relies on these exact labels. Be careful changing them.", "labels": { "breaking": ":boom: Breaking Change", "enhancement": ":rocket: Enhancement", @@ -73,6 +73,7 @@ "documentation": ":memo: Documentation", "internal": ":house: Internal", "unlabeled": ":question: Unlabeled" - } + }, + "wildcardLabel": "unlabeled" } } diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 55f178050..e011c9d3b 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -991,11 +991,11 @@ importers: test-packages/release: dependencies: '@ef4/lerna-changelog': - specifier: ^1.0.2 - version: 1.0.2 + specifier: ^1.0.4 + version: 1.0.4 execa: - specifier: ^7.0.0 - version: 7.0.0 + specifier: ^4.0.3 + version: 4.0.3 test-packages/sample-transforms: dependencies: @@ -2012,7 +2012,6 @@ packages: semver: 6.3.0 transitivePeerDependencies: - supports-color - dev: true /@babel/helper-create-regexp-features-plugin@7.21.8(@babel/core@7.19.6): resolution: {integrity: sha512-zGuSdedkFtsFHGbexAvNuipg1hbtitDLo2XE8/uf6Y9sOQV1xsYX/2pNbtedp/X0eU1pIt+kGvaqHCowkRbS5g==} @@ -2035,7 +2034,6 @@ packages: '@babel/helper-annotate-as-pure': 7.18.6 regexpu-core: 5.3.2 semver: 6.3.0 - dev: true /@babel/helper-define-polyfill-provider@0.3.3(@babel/core@7.19.6): resolution: {integrity: sha512-z5aQKU4IzbqCC1XH0nAqfsFLMVSo22SBKUc0BxGrLkolTdPTructy0ToNnlO2zA4j9Q/7pjMZf0DSY+DSTYzww==} @@ -2066,7 +2064,6 @@ packages: semver: 6.3.0 transitivePeerDependencies: - supports-color - dev: true /@babel/helper-environment-visitor@7.21.5: resolution: {integrity: sha512-IYl4gZ3ETsWocUWgsFZLM5i1BYx9SoemminVEXadgLBa9TdeorzgLKm8wWLA6J1N/kT3Kch8XIk1laNzYoHKvQ==} @@ -2149,7 +2146,6 @@ packages: '@babel/types': 7.21.5 transitivePeerDependencies: - supports-color - dev: true /@babel/helper-replace-supers@7.21.5: resolution: {integrity: sha512-/y7vBgsr9Idu4M6MprbOVUfH3vs7tsIfnVWv/Ml2xgwvyH6LTngdfbf5AdsKwkJy4zgy1X/kuNrEKvhhK28Yrg==} @@ -2254,7 +2250,6 @@ packages: dependencies: '@babel/core': 7.21.8 '@babel/helper-plugin-utils': 7.21.5 - dev: true /@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining@7.20.7(@babel/core@7.19.6): resolution: {integrity: sha512-sbr9+wNE5aXMBBFBICk01tt7sBf2Oc9ikRFEcem/ZORup9IMUdNhW7/wVLEbbtlWOsEubJet46mHAL2C8+2jKQ==} @@ -2277,7 +2272,6 @@ packages: '@babel/helper-plugin-utils': 7.21.5 '@babel/helper-skip-transparent-expression-wrappers': 7.20.0 '@babel/plugin-proposal-optional-chaining': 7.21.0(@babel/core@7.21.8) - dev: true /@babel/plugin-proposal-async-generator-functions@7.20.7(@babel/core@7.19.6): resolution: {integrity: sha512-xMbiLsn/8RK7Wq7VeVytytS2L6qE69bXPB10YCmMdDZbKF4okCqY74pI/jJQ/8U0b/F6NrT2+14b8/P9/3AMGA==} @@ -2306,7 +2300,6 @@ packages: '@babel/plugin-syntax-async-generators': 7.8.4(@babel/core@7.21.8) transitivePeerDependencies: - supports-color - dev: true /@babel/plugin-proposal-class-properties@7.16.7(@babel/core@7.19.6): resolution: {integrity: sha512-IobU0Xme31ewjYOShSIqd/ZGM/r/cuOz2z0MDbNrhF5FW+ZVgi0f2lyeoj9KFPDOAqsYxmLWZte1WOwlvY9aww==} @@ -2331,7 +2324,6 @@ packages: '@babel/helper-plugin-utils': 7.21.5 transitivePeerDependencies: - supports-color - dev: true /@babel/plugin-proposal-class-static-block@7.21.0(@babel/core@7.19.6): resolution: {integrity: sha512-XP5G9MWNUskFuP30IfFSEFB0Z6HzLIUcjYM4bYOPHXl7eiJ9HFv8tWj6TXTN5QODiEhDZAeI4hLok2iHFFV4hw==} @@ -2358,7 +2350,6 @@ packages: '@babel/plugin-syntax-class-static-block': 7.14.5(@babel/core@7.21.8) transitivePeerDependencies: - supports-color - dev: true /@babel/plugin-proposal-decorators@7.21.0(@babel/core@7.19.6): resolution: {integrity: sha512-MfgX49uRrFUTL/HvWtmx3zmpyzMMr4MTj3d527MLlr/4RTT9G/ytFFP7qet2uM2Ve03b+BkpWUpK+lRXnQ+v9w==} @@ -2375,6 +2366,21 @@ packages: transitivePeerDependencies: - supports-color + /@babel/plugin-proposal-decorators@7.21.0(@babel/core@7.21.8): + resolution: {integrity: sha512-MfgX49uRrFUTL/HvWtmx3zmpyzMMr4MTj3d527MLlr/4RTT9G/ytFFP7qet2uM2Ve03b+BkpWUpK+lRXnQ+v9w==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.21.8 + '@babel/helper-create-class-features-plugin': 7.21.8(@babel/core@7.21.8) + '@babel/helper-plugin-utils': 7.21.5 + '@babel/helper-replace-supers': 7.21.5 + '@babel/helper-split-export-declaration': 7.18.6 + '@babel/plugin-syntax-decorators': 7.21.0(@babel/core@7.21.8) + transitivePeerDependencies: + - supports-color + /@babel/plugin-proposal-dynamic-import@7.18.6(@babel/core@7.19.6): resolution: {integrity: sha512-1auuwmK+Rz13SJj36R+jqFPMJWyKEDd7lLSdOj4oJK0UTgGueSAtkrCvz9ewmgyU/P941Rv2fQwZJN8s6QruXw==} engines: {node: '>=6.9.0'} @@ -2394,7 +2400,6 @@ packages: '@babel/core': 7.21.8 '@babel/helper-plugin-utils': 7.21.5 '@babel/plugin-syntax-dynamic-import': 7.8.3(@babel/core@7.21.8) - dev: true /@babel/plugin-proposal-export-namespace-from@7.18.9(@babel/core@7.19.6): resolution: {integrity: sha512-k1NtHyOMvlDDFeb9G5PhUXuGj8m/wiwojgQVEhJ/fsVsMCpLyOP4h0uGEjYJKrRI+EVPlb5Jk+Gt9P97lOGwtA==} @@ -2415,7 +2420,6 @@ packages: '@babel/core': 7.21.8 '@babel/helper-plugin-utils': 7.21.5 '@babel/plugin-syntax-export-namespace-from': 7.8.3(@babel/core@7.21.8) - dev: true /@babel/plugin-proposal-json-strings@7.18.6(@babel/core@7.19.6): resolution: {integrity: sha512-lr1peyn9kOdbYc0xr0OdHTZ5FMqS6Di+H0Fz2I/JwMzGmzJETNeOFq2pBySw6X/KFL5EWDjlJuMsUGRFb8fQgQ==} @@ -2436,7 +2440,6 @@ packages: '@babel/core': 7.21.8 '@babel/helper-plugin-utils': 7.21.5 '@babel/plugin-syntax-json-strings': 7.8.3(@babel/core@7.21.8) - dev: true /@babel/plugin-proposal-logical-assignment-operators@7.20.7(@babel/core@7.19.6): resolution: {integrity: sha512-y7C7cZgpMIjWlKE5T7eJwp+tnRYM89HmRvWM5EQuB5BoHEONjmQ8lSNmBUwOyy/GFRsohJED51YBF79hE1djug==} @@ -2457,7 +2460,6 @@ packages: '@babel/core': 7.21.8 '@babel/helper-plugin-utils': 7.21.5 '@babel/plugin-syntax-logical-assignment-operators': 7.10.4(@babel/core@7.21.8) - dev: true /@babel/plugin-proposal-nullish-coalescing-operator@7.18.6(@babel/core@7.19.6): resolution: {integrity: sha512-wQxQzxYeJqHcfppzBDnm1yAY0jSRkUXR2z8RePZYrKwMKgMlE8+Z6LUno+bd6LvbGh8Gltvy74+9pIYkr+XkKA==} @@ -2478,7 +2480,6 @@ packages: '@babel/core': 7.21.8 '@babel/helper-plugin-utils': 7.21.5 '@babel/plugin-syntax-nullish-coalescing-operator': 7.8.3(@babel/core@7.21.8) - dev: true /@babel/plugin-proposal-numeric-separator@7.18.6(@babel/core@7.19.6): resolution: {integrity: sha512-ozlZFogPqoLm8WBr5Z8UckIoE4YQ5KESVcNudyXOR8uqIkliTEgJ3RoketfG6pmzLdeZF0H/wjE9/cCEitBl7Q==} @@ -2499,7 +2500,6 @@ packages: '@babel/core': 7.21.8 '@babel/helper-plugin-utils': 7.21.5 '@babel/plugin-syntax-numeric-separator': 7.10.4(@babel/core@7.21.8) - dev: true /@babel/plugin-proposal-object-rest-spread@7.20.7(@babel/core@7.19.6): resolution: {integrity: sha512-d2S98yCiLxDVmBmE8UjGcfPvNEUbA1U5q5WxaWFUGRzJSVAZqm5W6MbPct0jxnegUZ0niLeNX+IOzEs7wYg9Dg==} @@ -2526,7 +2526,6 @@ packages: '@babel/helper-plugin-utils': 7.21.5 '@babel/plugin-syntax-object-rest-spread': 7.8.3(@babel/core@7.21.8) '@babel/plugin-transform-parameters': 7.21.3(@babel/core@7.21.8) - dev: true /@babel/plugin-proposal-optional-catch-binding@7.18.6(@babel/core@7.19.6): resolution: {integrity: sha512-Q40HEhs9DJQyaZfUjjn6vE8Cv4GmMHCYuMGIWUnlxH6400VGxOuwWsPt4FxXxJkC/5eOzgn0z21M9gMT4MOhbw==} @@ -2547,7 +2546,6 @@ packages: '@babel/core': 7.21.8 '@babel/helper-plugin-utils': 7.21.5 '@babel/plugin-syntax-optional-catch-binding': 7.8.3(@babel/core@7.21.8) - dev: true /@babel/plugin-proposal-optional-chaining@7.21.0(@babel/core@7.19.6): resolution: {integrity: sha512-p4zeefM72gpmEe2fkUr/OnOXpWEf8nAgk7ZYVqqfFiyIG7oFfVZcCrU64hWn5xp4tQ9LkV4bTIa5rD0KANpKNA==} @@ -2570,7 +2568,6 @@ packages: '@babel/helper-plugin-utils': 7.21.5 '@babel/helper-skip-transparent-expression-wrappers': 7.20.0 '@babel/plugin-syntax-optional-chaining': 7.8.3(@babel/core@7.21.8) - dev: true /@babel/plugin-proposal-private-methods@7.18.6(@babel/core@7.19.6): resolution: {integrity: sha512-nutsvktDItsNn4rpGItSNV2sz1XwS+nfU0Rg8aCx3W3NOKVzdMjJRu0O5OkgDp3ZGICSTbgRpxZoWsxoKRvbeA==} @@ -2595,7 +2592,6 @@ packages: '@babel/helper-plugin-utils': 7.21.5 transitivePeerDependencies: - supports-color - dev: true /@babel/plugin-proposal-private-property-in-object@7.21.0(@babel/core@7.19.6): resolution: {integrity: sha512-ha4zfehbJjc5MmXBlHec1igel5TJXXLDDRbuJ4+XT2TJcyD9/V1919BA8gMvsdHcNMBy4WBUBiRb3nw/EQUtBw==} @@ -2624,7 +2620,6 @@ packages: '@babel/plugin-syntax-private-property-in-object': 7.14.5(@babel/core@7.21.8) transitivePeerDependencies: - supports-color - dev: true /@babel/plugin-proposal-unicode-property-regex@7.18.6(@babel/core@7.19.6): resolution: {integrity: sha512-2BShG/d5yoZyXZfVePH91urL5wTG6ASZU9M4o03lKK8u8UW1y08OMttBSOADTcJrnPMpvDXRG3G8fyLh4ovs8w==} @@ -2645,7 +2640,6 @@ packages: '@babel/core': 7.21.8 '@babel/helper-create-regexp-features-plugin': 7.21.8(@babel/core@7.21.8) '@babel/helper-plugin-utils': 7.21.5 - dev: true /@babel/plugin-syntax-async-generators@7.8.4(@babel/core@7.19.6): resolution: {integrity: sha512-tycmZxkGfZaxhMRbXlPXuVFpdWlXpir2W4AMhSJgRKzk/eDlIXOhb2LHWoLpDF7TEHylV5zNhykX6KAgHJmTNw==} @@ -2662,7 +2656,6 @@ packages: dependencies: '@babel/core': 7.21.8 '@babel/helper-plugin-utils': 7.21.5 - dev: true /@babel/plugin-syntax-bigint@7.8.3(@babel/core@7.21.8): resolution: {integrity: sha512-wnTnFlG+YxQm3vDxpGE57Pj0srRU4sHE/mDkt1qv2YJJSeUAec2ma4WLUnUPeKjyrfntVwe/N6dCXpU+zL3Npg==} @@ -2688,7 +2681,6 @@ packages: dependencies: '@babel/core': 7.21.8 '@babel/helper-plugin-utils': 7.21.5 - dev: true /@babel/plugin-syntax-class-static-block@7.14.5(@babel/core@7.19.6): resolution: {integrity: sha512-b+YyPmr6ldyNnM6sqYeMWE+bgJcJpO6yS4QD7ymxgH34GBPNDM/THBh8iunyvKIZztiwLH4CJZ0RxTk9emgpjw==} @@ -2707,7 +2699,6 @@ packages: dependencies: '@babel/core': 7.21.8 '@babel/helper-plugin-utils': 7.21.5 - dev: true /@babel/plugin-syntax-decorators@7.17.0(@babel/core@7.19.6): resolution: {integrity: sha512-qWe85yCXsvDEluNP0OyeQjH63DlhAR3W7K9BxxU1MvbDb48tgBG+Ao6IJJ6smPDrrVzSQZrbF6donpkFBMcs3A==} @@ -2719,23 +2710,22 @@ packages: '@babel/helper-plugin-utils': 7.21.5 dev: true - /@babel/plugin-syntax-decorators@7.17.0(@babel/core@7.21.8): - resolution: {integrity: sha512-qWe85yCXsvDEluNP0OyeQjH63DlhAR3W7K9BxxU1MvbDb48tgBG+Ao6IJJ6smPDrrVzSQZrbF6donpkFBMcs3A==} + /@babel/plugin-syntax-decorators@7.21.0(@babel/core@7.19.6): + resolution: {integrity: sha512-tIoPpGBR8UuM4++ccWN3gifhVvQu7ZizuR1fklhRJrd5ewgbkUS+0KVFeWWxELtn18NTLoW32XV7zyOgIAiz+w==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: - '@babel/core': 7.21.8 + '@babel/core': 7.19.6(supports-color@8.1.0) '@babel/helper-plugin-utils': 7.21.5 - dev: true - /@babel/plugin-syntax-decorators@7.21.0(@babel/core@7.19.6): + /@babel/plugin-syntax-decorators@7.21.0(@babel/core@7.21.8): resolution: {integrity: sha512-tIoPpGBR8UuM4++ccWN3gifhVvQu7ZizuR1fklhRJrd5ewgbkUS+0KVFeWWxELtn18NTLoW32XV7zyOgIAiz+w==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: - '@babel/core': 7.19.6(supports-color@8.1.0) + '@babel/core': 7.21.8 '@babel/helper-plugin-utils': 7.21.5 /@babel/plugin-syntax-dynamic-import@7.8.3(@babel/core@7.19.6): @@ -2753,7 +2743,6 @@ packages: dependencies: '@babel/core': 7.21.8 '@babel/helper-plugin-utils': 7.21.5 - dev: true /@babel/plugin-syntax-export-namespace-from@7.8.3(@babel/core@7.19.6): resolution: {integrity: sha512-MXf5laXo6c1IbEbegDmzGPwGNTsHZmEy6QGznu5Sh2UCWvueywb2ee+CCE4zQiZstxU9BMoQO9i6zUFSY0Kj0Q==} @@ -2770,7 +2759,6 @@ packages: dependencies: '@babel/core': 7.21.8 '@babel/helper-plugin-utils': 7.21.5 - dev: true /@babel/plugin-syntax-flow@7.21.4(@babel/core@7.21.8): resolution: {integrity: sha512-l9xd3N+XG4fZRxEP3vXdK6RW7vN1Uf5dxzRC/09wV86wqZ/YYQooBIGNsiRdfNR3/q2/5pPzV4B54J/9ctX5jw==} @@ -2806,7 +2794,6 @@ packages: dependencies: '@babel/core': 7.21.8 '@babel/helper-plugin-utils': 7.21.5 - dev: true /@babel/plugin-syntax-jsx@7.21.4(@babel/core@7.21.8): resolution: {integrity: sha512-5hewiLct5OKyh6PLKEYaFclcqtIgCb6bmELouxjF6up5q3Sov7rOayW4RwhbaBL0dit8rA80GNfY+UuDp2mBbQ==} @@ -2833,7 +2820,6 @@ packages: dependencies: '@babel/core': 7.21.8 '@babel/helper-plugin-utils': 7.21.5 - dev: true /@babel/plugin-syntax-nullish-coalescing-operator@7.8.3(@babel/core@7.19.6): resolution: {integrity: sha512-aSff4zPII1u2QD7y+F8oDsz19ew4IGEJg9SVW+bqwpwtfFleiQDMdzA/R+UlWDzfnHFCxxleFT0PMIrR36XLNQ==} @@ -2850,7 +2836,6 @@ packages: dependencies: '@babel/core': 7.21.8 '@babel/helper-plugin-utils': 7.21.5 - dev: true /@babel/plugin-syntax-numeric-separator@7.10.4(@babel/core@7.19.6): resolution: {integrity: sha512-9H6YdfkcK/uOnY/K7/aA2xpzaAgkQn37yzWUMRK7OaPOqOpGS1+n0H5hxT9AUw9EsSjPW8SVyMJwYRtWs3X3ug==} @@ -2867,7 +2852,6 @@ packages: dependencies: '@babel/core': 7.21.8 '@babel/helper-plugin-utils': 7.21.5 - dev: true /@babel/plugin-syntax-object-rest-spread@7.8.3(@babel/core@7.19.6): resolution: {integrity: sha512-XoqMijGZb9y3y2XskN+P1wUGiVwWZ5JmoDRwx5+3GmEplNyVM2s2Dg8ILFQm8rWM48orGy5YpI5Bl8U1y7ydlA==} @@ -2884,7 +2868,6 @@ packages: dependencies: '@babel/core': 7.21.8 '@babel/helper-plugin-utils': 7.21.5 - dev: true /@babel/plugin-syntax-optional-catch-binding@7.8.3(@babel/core@7.19.6): resolution: {integrity: sha512-6VPD0Pc1lpTqw0aKoeRTMiB+kWhAoT24PA+ksWSBrFtl5SIRVpZlwN3NNPQjehA2E/91FV3RjLWoVTglWcSV3Q==} @@ -2901,7 +2884,6 @@ packages: dependencies: '@babel/core': 7.21.8 '@babel/helper-plugin-utils': 7.21.5 - dev: true /@babel/plugin-syntax-optional-chaining@7.8.3(@babel/core@7.19.6): resolution: {integrity: sha512-KoK9ErH1MBlCPxV0VANkXW2/dw4vlbGDrFgz8bmUsBGYkFRcbRwMh6cIJubdPrkxRwuGdtCk0v/wPTKbQgBjkg==} @@ -2918,7 +2900,6 @@ packages: dependencies: '@babel/core': 7.21.8 '@babel/helper-plugin-utils': 7.21.5 - dev: true /@babel/plugin-syntax-private-property-in-object@7.14.5(@babel/core@7.19.6): resolution: {integrity: sha512-0wVnp9dxJ72ZUJDV27ZfbSj6iHLoytYZmh3rFcxNnvsJF3ktkzLDZPy/mA17HGsaQT3/DQsWYX1f1QGWkCoVUg==} @@ -2937,7 +2918,6 @@ packages: dependencies: '@babel/core': 7.21.8 '@babel/helper-plugin-utils': 7.21.5 - dev: true /@babel/plugin-syntax-top-level-await@7.14.5(@babel/core@7.19.6): resolution: {integrity: sha512-hx++upLv5U1rgYfwe1xBQUhRmU41NEvpUvrp8jkrSCdvGSnM5/qdRMtylJ6PG5OFkBaHkbTAKTnd3/YyESRHFw==} @@ -2956,7 +2936,6 @@ packages: dependencies: '@babel/core': 7.21.8 '@babel/helper-plugin-utils': 7.21.5 - dev: true /@babel/plugin-syntax-typescript@7.21.4(@babel/core@7.19.6): resolution: {integrity: sha512-xz0D39NvhQn4t4RNsHmDnnsaQizIlUkdtYvLs8La1BlfjQ6JEwxkJGeqJMW2tAXx+q6H+WFuUTXNdYVpEya0YA==} @@ -2994,7 +2973,6 @@ packages: dependencies: '@babel/core': 7.21.8 '@babel/helper-plugin-utils': 7.21.5 - dev: true /@babel/plugin-transform-async-to-generator@7.20.7(@babel/core@7.19.6): resolution: {integrity: sha512-Uo5gwHPT9vgnSXQxqGtpdufUiWp96gk7yiP4Mp5bm1QMkEmLXBO7PAGYbKoJ6DhAwiNkcHFBol/x5zZZkL/t0Q==} @@ -3021,7 +2999,6 @@ packages: '@babel/helper-remap-async-to-generator': 7.18.9(@babel/core@7.21.8) transitivePeerDependencies: - supports-color - dev: true /@babel/plugin-transform-block-scoped-functions@7.18.6(@babel/core@7.19.6): resolution: {integrity: sha512-ExUcOqpPWnliRcPqves5HJcJOvHvIIWfuS4sroBUenPuMdmW+SMHDakmtS7qOo13sVppmUijqeTv7qqGsvURpQ==} @@ -3040,7 +3017,6 @@ packages: dependencies: '@babel/core': 7.21.8 '@babel/helper-plugin-utils': 7.21.5 - dev: true /@babel/plugin-transform-block-scoping@7.21.0(@babel/core@7.19.6): resolution: {integrity: sha512-Mdrbunoh9SxwFZapeHVrwFmri16+oYotcZysSzhNIVDwIAb1UV+kvnxULSYq9J3/q5MDG+4X6w8QVgD1zhBXNQ==} @@ -3097,7 +3073,6 @@ packages: globals: 11.12.0 transitivePeerDependencies: - supports-color - dev: true /@babel/plugin-transform-computed-properties@7.21.5(@babel/core@7.19.6): resolution: {integrity: sha512-TR653Ki3pAwxBxUe8srfF3e4Pe3FTA46uaNHYyQwIoM4oWKSoOZiDNyHJ0oIoDIUPSRQbQG7jzgVBX3FPVne1Q==} @@ -3118,7 +3093,6 @@ packages: '@babel/core': 7.21.8 '@babel/helper-plugin-utils': 7.21.5 '@babel/template': 7.20.7 - dev: true /@babel/plugin-transform-destructuring@7.21.3(@babel/core@7.19.6): resolution: {integrity: sha512-bp6hwMFzuiE4HqYEyoGJ/V2LeIWn+hLVKc4pnj++E5XQptwhtcGmSayM029d/j2X1bPKGTlsyPwAubuU22KhMA==} @@ -3137,7 +3111,6 @@ packages: dependencies: '@babel/core': 7.21.8 '@babel/helper-plugin-utils': 7.21.5 - dev: true /@babel/plugin-transform-dotall-regex@7.18.6(@babel/core@7.19.6): resolution: {integrity: sha512-6S3jpun1eEbAxq7TdjLotAsl4WpQI9DxfkycRcKrjhQYzU87qpXdknpBg/e+TdcMehqGnLFi7tnFUBR02Vq6wg==} @@ -3158,7 +3131,6 @@ packages: '@babel/core': 7.21.8 '@babel/helper-create-regexp-features-plugin': 7.21.8(@babel/core@7.21.8) '@babel/helper-plugin-utils': 7.21.5 - dev: true /@babel/plugin-transform-duplicate-keys@7.18.9(@babel/core@7.19.6): resolution: {integrity: sha512-d2bmXCtZXYc59/0SanQKbiWINadaJXqtvIQIzd4+hNwkWBgyCd5F/2t1kXoUdvPMrxzPvhK6EMQRROxsue+mfw==} @@ -3177,7 +3149,6 @@ packages: dependencies: '@babel/core': 7.21.8 '@babel/helper-plugin-utils': 7.21.5 - dev: true /@babel/plugin-transform-exponentiation-operator@7.18.6(@babel/core@7.19.6): resolution: {integrity: sha512-wzEtc0+2c88FVR34aQmiz56dxEkxr2g8DQb/KfaFa1JYXOFVsbhvAonFN6PwVWj++fKmku8NP80plJ5Et4wqHw==} @@ -3198,7 +3169,6 @@ packages: '@babel/core': 7.21.8 '@babel/helper-builder-binary-assignment-operator-visitor': 7.21.5 '@babel/helper-plugin-utils': 7.21.5 - dev: true /@babel/plugin-transform-flow-strip-types@7.21.0(@babel/core@7.21.8): resolution: {integrity: sha512-FlFA2Mj87a6sDkW4gfGrQQqwY/dLlBAyJa2dJEZ+FHXUVHBflO2wyKvg+OOEzXfrKYIa4HWl0mgmbCzt0cMb7w==} @@ -3228,7 +3198,6 @@ packages: dependencies: '@babel/core': 7.21.8 '@babel/helper-plugin-utils': 7.21.5 - dev: true /@babel/plugin-transform-function-name@7.18.9(@babel/core@7.19.6): resolution: {integrity: sha512-WvIBoRPaJQ5yVHzcnJFor7oS5Ls0PYixlTYE63lCj2RtdQEl15M68FXQlxnG6wdraJIXRdR7KI+hQ7q/9QjrCQ==} @@ -3251,7 +3220,6 @@ packages: '@babel/helper-compilation-targets': 7.21.5(@babel/core@7.21.8) '@babel/helper-function-name': 7.21.0 '@babel/helper-plugin-utils': 7.21.5 - dev: true /@babel/plugin-transform-literals@7.18.9(@babel/core@7.19.6): resolution: {integrity: sha512-IFQDSRoTPnrAIrI5zoZv73IFeZu2dhu6irxQjY9rNjTT53VmKg9fenjvoiOWOkJ6mm4jKVPtdMzBY98Fp4Z4cg==} @@ -3270,7 +3238,6 @@ packages: dependencies: '@babel/core': 7.21.8 '@babel/helper-plugin-utils': 7.21.5 - dev: true /@babel/plugin-transform-member-expression-literals@7.18.6(@babel/core@7.19.6): resolution: {integrity: sha512-qSF1ihLGO3q+/g48k85tUjD033C29TNTVB2paCwZPVmOsjn9pClvYYrM2VeJpBY2bcNkuny0YUyTNRyRxJ54KA==} @@ -3289,7 +3256,6 @@ packages: dependencies: '@babel/core': 7.21.8 '@babel/helper-plugin-utils': 7.21.5 - dev: true /@babel/plugin-transform-modules-amd@7.19.6(@babel/core@7.19.6): resolution: {integrity: sha512-uG3od2mXvAtIFQIh0xrpLH6r5fpSQN04gIVovl+ODLdUMANokxQLZnPBHcjmv3GxRjnqwLuHvppjjcelqUFZvg==} @@ -3326,7 +3292,6 @@ packages: '@babel/helper-plugin-utils': 7.21.5 transitivePeerDependencies: - supports-color - dev: true /@babel/plugin-transform-modules-commonjs@7.21.5(@babel/core@7.19.6): resolution: {integrity: sha512-OVryBEgKUbtqMoB7eG2rs6UFexJi6Zj6FDXx+esBLPTCxCNxAY9o+8Di7IsUGJ+AVhp5ncK0fxWUBd0/1gPhrQ==} @@ -3353,7 +3318,6 @@ packages: '@babel/helper-simple-access': 7.21.5 transitivePeerDependencies: - supports-color - dev: true /@babel/plugin-transform-modules-commonjs@7.8.3(@babel/core@7.19.6): resolution: {integrity: sha512-JpdMEfA15HZ/1gNuB9XEDlZM1h/gF/YOH7zaZzQu2xCFRfwc01NXBMHHSTT6hRjlXJJs5x/bfODM3LiCk94Sxg==} @@ -3396,7 +3360,6 @@ packages: '@babel/helper-validator-identifier': 7.19.1 transitivePeerDependencies: - supports-color - dev: true /@babel/plugin-transform-modules-umd@7.18.6(@babel/core@7.19.6): resolution: {integrity: sha512-dcegErExVeXcRqNtkRU/z8WlBLnvD4MRnHgNs3MytRO1Mn1sHRyhbcpYbVMGclAqOjdW+9cfkdZno9dFdfKLfQ==} @@ -3421,7 +3384,6 @@ packages: '@babel/helper-plugin-utils': 7.21.5 transitivePeerDependencies: - supports-color - dev: true /@babel/plugin-transform-named-capturing-groups-regex@7.20.5(@babel/core@7.19.6): resolution: {integrity: sha512-mOW4tTzi5iTLnw+78iEq3gr8Aoq4WNRGpmSlrogqaiCBoR1HFhpU4JkpQFOHfeYx3ReVIFWOQJS4aZBRvuZ6mA==} @@ -3442,7 +3404,6 @@ packages: '@babel/core': 7.21.8 '@babel/helper-create-regexp-features-plugin': 7.21.8(@babel/core@7.21.8) '@babel/helper-plugin-utils': 7.21.5 - dev: true /@babel/plugin-transform-new-target@7.18.6(@babel/core@7.19.6): resolution: {integrity: sha512-DjwFA/9Iu3Z+vrAn+8pBUGcjhxKguSMlsFqeCKbhb9BAV756v0krzVK04CRDi/4aqmk8BsHb4a/gFcaA5joXRw==} @@ -3461,7 +3422,6 @@ packages: dependencies: '@babel/core': 7.21.8 '@babel/helper-plugin-utils': 7.21.5 - dev: true /@babel/plugin-transform-object-assign@7.18.6(@babel/core@7.19.6): resolution: {integrity: sha512-mQisZ3JfqWh2gVXvfqYCAAyRs6+7oev+myBsTwW5RnPhYXOTuCEw2oe3YgxlXMViXUS53lG8koulI7mJ+8JE+A==} @@ -3504,7 +3464,6 @@ packages: '@babel/helper-replace-supers': 7.21.5 transitivePeerDependencies: - supports-color - dev: true /@babel/plugin-transform-parameters@7.21.3(@babel/core@7.19.6): resolution: {integrity: sha512-Wxc+TvppQG9xWFYatvCGPvZ6+SIUxQ2ZdiBP+PHYMIjnPXD+uThCshaz4NZOnODAtBjjcVQQ/3OKs9LW28purQ==} @@ -3523,7 +3482,6 @@ packages: dependencies: '@babel/core': 7.21.8 '@babel/helper-plugin-utils': 7.21.5 - dev: true /@babel/plugin-transform-property-literals@7.18.6(@babel/core@7.19.6): resolution: {integrity: sha512-cYcs6qlgafTud3PAzrrRNbQtfpQ8+y/+M5tKmksS9+M1ckbH6kzY8MrexEM9mcA6JDsukE19iIRvAyYl463sMg==} @@ -3542,7 +3500,6 @@ packages: dependencies: '@babel/core': 7.21.8 '@babel/helper-plugin-utils': 7.21.5 - dev: true /@babel/plugin-transform-regenerator@7.21.5(@babel/core@7.19.6): resolution: {integrity: sha512-ZoYBKDb6LyMi5yCsByQ5jmXsHAQDDYeexT1Szvlmui+lADvfSecr5Dxd/PkrTC3pAD182Fcju1VQkB4oCp9M+w==} @@ -3563,7 +3520,6 @@ packages: '@babel/core': 7.21.8 '@babel/helper-plugin-utils': 7.21.5 regenerator-transform: 0.15.1 - dev: true /@babel/plugin-transform-reserved-words@7.18.6(@babel/core@7.19.6): resolution: {integrity: sha512-oX/4MyMoypzHjFrT1CdivfKZ+XvIPMFXwwxHp/r0Ddy2Vuomt4HDFGmft1TAY2yiTKiNSsh3kjBAzcM8kSdsjA==} @@ -3582,7 +3538,6 @@ packages: dependencies: '@babel/core': 7.21.8 '@babel/helper-plugin-utils': 7.21.5 - dev: true /@babel/plugin-transform-runtime@7.18.6(@babel/core@7.19.6): resolution: {integrity: sha512-8uRHk9ZmRSnWqUgyae249EJZ94b0yAGLBIqzZzl+0iEdbno55Pmlt/32JZsHwXD9k/uZj18Aqqk35wBX4CBTXA==} @@ -3617,7 +3572,6 @@ packages: dependencies: '@babel/core': 7.21.8 '@babel/helper-plugin-utils': 7.21.5 - dev: true /@babel/plugin-transform-spread@7.20.7(@babel/core@7.19.6): resolution: {integrity: sha512-ewBbHQ+1U/VnH1fxltbJqDeWBU1oNLG8Dj11uIv3xVf7nrQu0bPGe5Rf716r7K5Qz+SqtAOVswoVunoiBtGhxw==} @@ -3638,7 +3592,6 @@ packages: '@babel/core': 7.21.8 '@babel/helper-plugin-utils': 7.21.5 '@babel/helper-skip-transparent-expression-wrappers': 7.20.0 - dev: true /@babel/plugin-transform-sticky-regex@7.18.6(@babel/core@7.19.6): resolution: {integrity: sha512-kfiDrDQ+PBsQDO85yj1icueWMfGfJFKN1KCkndygtu/C9+XUfydLC8Iv5UYJqRwy4zk8EcplRxEOeLyjq1gm6Q==} @@ -3657,7 +3610,6 @@ packages: dependencies: '@babel/core': 7.21.8 '@babel/helper-plugin-utils': 7.21.5 - dev: true /@babel/plugin-transform-template-literals@7.18.9(@babel/core@7.19.6): resolution: {integrity: sha512-S8cOWfT82gTezpYOiVaGHrCbhlHgKhQt8XH5ES46P2XWmX92yisoZywf5km75wv5sYcXDUCLMmMxOLCtthDgMA==} @@ -3676,7 +3628,6 @@ packages: dependencies: '@babel/core': 7.21.8 '@babel/helper-plugin-utils': 7.21.5 - dev: true /@babel/plugin-transform-typeof-symbol@7.18.9(@babel/core@7.19.6): resolution: {integrity: sha512-SRfwTtF11G2aemAZWivL7PD+C9z52v9EvMqH9BuYbabyPuKUvSWks3oCg6041pT925L4zVFqaVBeECwsmlguEw==} @@ -3695,7 +3646,6 @@ packages: dependencies: '@babel/core': 7.21.8 '@babel/helper-plugin-utils': 7.21.5 - dev: true /@babel/plugin-transform-typescript@7.21.3(@babel/core@7.19.6): resolution: {integrity: sha512-RQxPz6Iqt8T0uw/WsJNReuBpWpBqs/n7mNo18sKLoTbMp+UrEekhH+pKSVC7gWz+DNjo9gryfV8YzCiT45RgMw==} @@ -3788,7 +3738,6 @@ packages: dependencies: '@babel/core': 7.21.8 '@babel/helper-plugin-utils': 7.21.5 - dev: true /@babel/plugin-transform-unicode-regex@7.18.6(@babel/core@7.19.6): resolution: {integrity: sha512-gE7A6Lt7YLnNOL3Pb9BNeZvi+d8l7tcRrG4+pwJjK9hD2xX4mEvjlQW60G9EEmfXVYRPv9VRQcyegIVHCql/AA==} @@ -3809,7 +3758,6 @@ packages: '@babel/core': 7.21.8 '@babel/helper-create-regexp-features-plugin': 7.21.8(@babel/core@7.21.8) '@babel/helper-plugin-utils': 7.21.5 - dev: true /@babel/polyfill@7.12.1: resolution: {integrity: sha512-X0pi0V6gxLi6lFZpGmeNa4zxtwEmCs42isWLNjZZDE0Y8yVfgu0T2OAHlzBbdYlqbW/YXVvoBHpATEM+goCj8g==} @@ -3985,7 +3933,6 @@ packages: semver: 6.3.0 transitivePeerDependencies: - supports-color - dev: true /@babel/preset-flow@7.21.4(@babel/core@7.21.8): resolution: {integrity: sha512-F24cSq4DIBmhq4OzK3dE63NHagb27OPE3eWR+HLekt4Z3Y5MzIIUGF3LlLgV0gN8vzbDViSY7HnrReNVCJXTeA==} @@ -4022,7 +3969,6 @@ packages: '@babel/plugin-transform-dotall-regex': 7.18.6(@babel/core@7.21.8) '@babel/types': 7.21.5 esutils: 2.0.3 - dev: true /@babel/preset-typescript@7.18.6(@babel/core@7.19.6): resolution: {integrity: sha512-s9ik86kXBAnD760aybBucdpnLsAt0jK1xqJn2juOn9lkOvSHV60os5hxoVJsPzMQxvnUJFAlkont2DvvaYEBtQ==} @@ -4383,8 +4329,8 @@ packages: postcss-selector-parser: 6.0.12 dev: true - /@ef4/lerna-changelog@1.0.2: - resolution: {integrity: sha512-dP5phiSfnd1scK7XkblKCLIB4TQSXFNuW0BgpBZHe721HiDok6jRgRHg3M5d6hHlDP4WogLdN3kRAZF3Sbce3Q==} + /@ef4/lerna-changelog@1.0.4: + resolution: {integrity: sha512-xG/w+aOAaBtZVrRQDN7Ina+yjhEEV1WENN119pue3SfFCcPOA00tYNgt5Hg2VMuO8G6+TOW8FQxA3jESTRLy4w==} engines: {node: '>=6'} hasBin: true dependencies: @@ -5737,7 +5683,7 @@ packages: '@changesets/types': 4.1.0 '@manypkg/find-root': 1.1.0 fs-extra: 8.1.0 - globby: 11.0.3 + globby: 11.1.0 read-yaml-file: 1.1.0 dev: true @@ -7583,6 +7529,21 @@ packages: make-dir: 3.1.0 schema-utils: 2.7.1 webpack: 5.78.0 + dev: false + + /babel-loader@8.2.2(@babel/core@7.21.8)(webpack@5.78.0): + resolution: {integrity: sha512-JvTd0/D889PQBtUXJ2PXaKU/pjZDMtHA9V2ecm+eNRmmBCMR09a+fmpGTNwnJtFmFl5Ei7Vy47LjBb+L0wQ99g==} + engines: {node: '>= 8.9'} + peerDependencies: + '@babel/core': ^7.0.0 + webpack: '>=2' + dependencies: + '@babel/core': 7.21.8 + find-cache-dir: 3.3.2 + loader-utils: 1.4.2 + make-dir: 3.1.0 + schema-utils: 2.7.1 + webpack: 5.78.0 /babel-messages@6.23.0: resolution: {integrity: sha512-Bl3ZiA+LjqaMtNYopA9TYE9HP1tQ+E5dLxE0XrAzcIJeK2UqF0/EaqXwBn9esd4UmTfEab+P+UYQ1GnioFIb/w==} @@ -7728,7 +7689,7 @@ packages: glob: 7.2.3 pkg-up: 2.0.0 reselect: 3.0.1 - resolve: 1.20.0 + resolve: 1.22.2 /babel-plugin-module-resolver@4.1.0: resolution: {integrity: sha512-MlX10UDheRr3lb3P0WcaIdtCSRlxdQsB1sBqL7W0raF070bGl1HQQq5K3T2vf2XAYie+ww+5AKC/WrkjRO2knA==} @@ -7763,7 +7724,6 @@ packages: semver: 6.3.0 transitivePeerDependencies: - supports-color - dev: true /babel-plugin-polyfill-corejs3@0.5.3(@babel/core@7.19.6): resolution: {integrity: sha512-zKsXDh0XjnrUEW0mxIHLfjBfnXSMr5Q/goMe/fxpQnLm07mcOZiIZHBNWCMx60HmdvjxfXcalac0tfFg0wqxyw==} @@ -7786,7 +7746,6 @@ packages: core-js-compat: 3.30.2 transitivePeerDependencies: - supports-color - dev: true /babel-plugin-polyfill-regenerator@0.3.1(@babel/core@7.19.6): resolution: {integrity: sha512-Y2B06tvgHYt1x0yz17jGkGeeMr5FeKUu+ASJ+N6nB5lQ8Dapfg42i0OVrf8PNGJ3zKL4A23snMi1IRwrqqND7A==} @@ -7807,7 +7766,6 @@ packages: '@babel/helper-define-polyfill-provider': 0.3.3(@babel/core@7.21.8) transitivePeerDependencies: - supports-color - dev: true /babel-plugin-syntax-async-functions@6.13.0: resolution: {integrity: sha512-4Zp4unmHgw30A1eWI5EpACji2qMocisdXhAftfhXoSV9j0Tvj6nRFE3tOmRY912E0FMRm/L5xWE7MGVT2FoLnw==} @@ -8402,7 +8360,7 @@ packages: resolution: {integrity: sha512-6IXBgfRt7HZ61g67ssBc6lBb3Smw3DPZ9dEYirgtvXWpRZ2A9M22nxy6opEwJDgDJzlu/bB7ToppW33OFkA1gA==} engines: {node: '>= 6'} dependencies: - '@babel/core': 7.19.6(supports-color@8.1.0) + '@babel/core': 7.21.8 '@babel/polyfill': 7.12.1 broccoli-funnel: 2.0.2 broccoli-merge-trees: 3.0.2 @@ -8615,7 +8573,7 @@ packages: fast-ordered-set: 1.0.3 fs-tree-diff: 0.5.9 heimdalljs: 0.2.6 - minimatch: 3.0.4 + minimatch: 3.1.2 mkdirp: 0.5.6 path-posix: 1.0.0 rimraf: 2.7.1 @@ -10785,13 +10743,13 @@ packages: resolution: {integrity: sha512-uLhrRDJYWCRvQ4JQ1e64XlSrqAKSd6PXaJ9ZsZI6Tlms9T4DtQFxNXasqji2ZRJBVrxEoLCRYX3RTldsQ0vNGQ==} engines: {node: 12.* || 14.* || >= 16} dependencies: - '@babel/core': 7.19.6(supports-color@8.1.0) - '@babel/plugin-proposal-class-properties': 7.16.7(@babel/core@7.19.6) - '@babel/plugin-proposal-decorators': 7.21.0(@babel/core@7.19.6) - '@babel/preset-env': 7.16.11(@babel/core@7.19.6) + '@babel/core': 7.21.8 + '@babel/plugin-proposal-class-properties': 7.16.7(@babel/core@7.21.8) + '@babel/plugin-proposal-decorators': 7.21.0(@babel/core@7.21.8) + '@babel/preset-env': 7.16.11(@babel/core@7.21.8) '@embroider/macros': 1.10.0 '@embroider/shared-internals': 2.0.0 - babel-loader: 8.2.2(@babel/core@7.19.6)(webpack@5.78.0) + babel-loader: 8.2.2(@babel/core@7.21.8)(webpack@5.78.0) babel-plugin-ember-modules-api-polyfill: 3.5.0 babel-plugin-ember-template-compilation: 2.0.2 babel-plugin-htmlbars-inline-precompile: 5.3.1 @@ -10803,14 +10761,14 @@ packages: broccoli-source: 3.0.1 css-loader: 5.2.6(webpack@5.78.0) debug: 4.3.2(supports-color@8.1.0) - fs-extra: 10.0.0 + fs-extra: 10.1.0 fs-tree-diff: 2.0.1 handlebars: 4.7.7 js-string-escape: 1.0.1 lodash: 4.17.21 mini-css-extract-plugin: 2.5.3(webpack@5.78.0) parse5: 6.0.1 - resolve: 1.20.0 + resolve: 1.22.2 resolve-package-path: 4.0.3 semver: 7.3.8 style-loader: 2.0.0(webpack@5.78.0) @@ -11221,7 +11179,7 @@ packages: /ember-cli-typescript-blueprint-polyfill@0.1.0: resolution: {integrity: sha512-g0weUTOnHmPGqVZzkQTl3Nbk9fzEdFkEXydCs5mT1qBjXh8eQ6VlmjjGD5/998UXKuA0pLSCVVMbSp/linLzGA==} dependencies: - chalk: 4.1.1 + chalk: 4.1.2 remove-types: 1.0.0 transitivePeerDependencies: - supports-color @@ -11275,7 +11233,7 @@ packages: dependencies: '@babel/plugin-transform-typescript': 7.5.5(@babel/core@7.19.6) ansi-to-html: 0.6.15 - debug: 4.3.2(supports-color@8.1.0) + debug: 4.3.4(supports-color@8.1.0) ember-cli-babel-plugin-helpers: 1.1.1 execa: 2.1.0 fs-extra: 8.1.0 @@ -12738,8 +12696,8 @@ packages: resolution: {integrity: sha512-89oVHVJwmLDvGvAUWgS87KpBoRhy3aZ6U0Ql6HOmU4TrPkyaa8pM0W81wj9cIwjYprcQtN9EwzZMHnq46+oUyw==} engines: {node: 8.* || 10.* || >= 12} dependencies: - '@babel/parser': 7.14.5 - '@babel/traverse': 7.14.5 + '@babel/parser': 7.21.8 + '@babel/traverse': 7.21.5(supports-color@8.1.0) recast: 0.18.10 transitivePeerDependencies: - supports-color @@ -13083,7 +13041,7 @@ packages: async-promise-queue: 1.0.5 colors: 1.4.0 commander: 6.2.1 - globby: 11.0.3 + globby: 11.1.0 ora: 5.4.1 slash: 3.0.0 tmp: 0.2.1 @@ -13103,7 +13061,7 @@ packages: async-promise-queue: 1.0.5 colors: 1.4.0 commander: 8.3.0 - globby: 11.0.3 + globby: 11.1.0 ora: 5.4.1 slash: 3.0.0 tmp: 0.2.1 @@ -14691,7 +14649,6 @@ packages: graceful-fs: 4.2.11 jsonfile: 6.1.0 universalify: 2.0.0 - dev: true /fs-extra@11.1.1: resolution: {integrity: sha512-MGIE4HOvQCeUCzmlHs0vXpih4ysz4wg9qiSAu6cd42lVwPbTM1TjV7RusoyQqMmk/95gdQZX72u+YW+c3eEpFQ==} @@ -15719,7 +15676,7 @@ packages: engines: {node: '>=8.0.0'} dependencies: ansi-escapes: 4.3.2 - chalk: 4.1.1 + chalk: 4.1.2 cli-cursor: 3.1.0 cli-width: 3.0.0 external-editor: 3.1.0 @@ -16697,7 +16654,7 @@ packages: dependencies: '@types/node': 15.12.2 merge-stream: 2.0.0 - supports-color: 8.1.0 + supports-color: 8.1.1 /jest-worker@29.5.0: resolution: {integrity: sha512-NcrQnevGoSp4b5kg+akIpthoAFHxPBcb5P6mYPY0fUNT+sSvmtu6jlkEle3anczUKIKEbMxFimk9oTP/tpIPgA==} @@ -16706,7 +16663,7 @@ packages: '@types/node': 15.12.2 jest-util: 29.5.0 merge-stream: 2.0.0 - supports-color: 8.1.0 + supports-color: 8.1.1 dev: true /jest@29.2.1: @@ -19868,7 +19825,7 @@ packages: resolution: {integrity: sha512-G7Hk1Q+UJ5DvlNAoJZObxANkBZGiGdp589rVcTW/tYqJWJ5rwfraSnKSQaETN8Epaytw8J40nS/zC7bcHGv36w==} dependencies: '@babel/core': 7.21.8 - '@babel/plugin-syntax-decorators': 7.17.0(@babel/core@7.21.8) + '@babel/plugin-syntax-decorators': 7.21.0(@babel/core@7.21.8) '@babel/plugin-transform-typescript': 7.21.3(@babel/core@7.21.8) prettier: 2.8.7 transitivePeerDependencies: @@ -19970,7 +19927,7 @@ packages: engines: {node: 10.* || >= 12} dependencies: path-root: 0.1.1 - resolve: 1.20.0 + resolve: 1.22.2 /resolve-package-path@4.0.1: resolution: {integrity: sha512-2gb/yU2fSfX22pjDYyevzyOKK9q72XKUFqlAsrfPzZArM4JkIH/Qcme4n3EbaZttObWm/fIFLbPxrXIyiL8wdQ==} @@ -21232,7 +21189,6 @@ packages: engines: {node: '>=10'} dependencies: has-flag: 4.0.0 - dev: true /supports-hyperlinks@3.0.0: resolution: {integrity: sha512-QBDPHyPQDRTy9ku4URNGY5Lah8PAaXs6tAAwp55sL5WCsSW7GIfdf6W5ixfziW+t7wh3GVvHyHHyQ1ESsoRvaA==} @@ -22293,7 +22249,7 @@ packages: '@types/minimatch': 3.0.4 ensure-posix-path: 1.1.1 matcher-collection: 2.0.1 - minimatch: 3.0.4 + minimatch: 3.1.2 /walk-sync@3.0.0: resolution: {integrity: sha512-41TvKmDGVpm2iuH7o+DAOt06yyu/cSHpX3uzAwetzASvlNtVddgIjXIb2DfB/Wa20B1Jo86+1Dv1CraSU7hWdw==} diff --git a/test-packages/release/package.json b/test-packages/release/package.json index 9e6ae7b90..5bbb77eaa 100644 --- a/test-packages/release/package.json +++ b/test-packages/release/package.json @@ -3,11 +3,11 @@ "version": "0.0.0", "private": true, "scripts": { - "prepare": "node ./src/prepare.js" + "prepare-release": "node ./src/prepare.js" }, "dependencies": { - "@ef4/lerna-changelog": "^1.0.2", - "execa": "^7.0.0" + "@ef4/lerna-changelog": "^1.0.4", + "execa": "^4.0.3" }, "volta": { "extends": "../../package.json" diff --git a/test-packages/release/src/change-parser.ts b/test-packages/release/src/change-parser.ts new file mode 100644 index 000000000..670c21aa0 --- /dev/null +++ b/test-packages/release/src/change-parser.ts @@ -0,0 +1,108 @@ +export type Impact = 'major' | 'minor' | 'patch'; + +const knownSections: Record = { + ':boom: Breaking Change': { + impact: 'major', + }, + ':rocket: Enhancement': { + impact: 'minor', + }, + ':bug: Bug Fix': { + impact: 'patch', + }, + ':memo: Documentation': { + impact: 'patch', + }, + ':house: Internal': { + impact: 'patch', + }, + ':question: Unlabeled': { + unlabeled: true, + }, +}; + +const ignoredSections = [/Committers: \d+/]; + +function sectionHeading(line: string): string | undefined { + if (line.startsWith('#### ')) { + return line.slice(5); + } +} + +function stillWithinSection(lines: string[]): boolean { + return lines.length > 0 && !sectionHeading(lines[0]); +} + +function consumeSection(lines: string[]) { + let matchedLines = []; + while (stillWithinSection(lines)) { + matchedLines.push(lines.shift()); + } + return matchedLines; +} + +export type Section = { packages: string[]; impact: Impact } | { unlabeled: true; summaryText: string }; + +function parseSection(lines: string[]): Section | undefined { + let line = lines.shift(); + const heading = line ? sectionHeading(line) : undefined; + if (!heading) { + return; + } + + let sectionConfig = knownSections[heading]; + if (!sectionConfig) { + if (ignoredSections.some(pattern => pattern.test(heading))) { + consumeSection(lines); + return; + } + throw new Error(`unexpected section: ${heading}`); + } + + if ('unlabeled' in sectionConfig) { + return { unlabeled: true, summaryText: consumeSection(lines).join('\n') }; + } + + let packages = new Set(); + while (stillWithinSection(lines)) { + let packageList = parsePackageList(lines); + if (packageList) { + for (let pkg of packageList) { + packages.add(pkg); + } + } + } + return { + packages: [...packages], + impact: sectionConfig.impact, + }; +} + +function parsePackageList(lines: string[]): string[] | undefined { + let line = lines.shift(); + if (!line) { + return; + } + if (line === '* Other') { + return; + } + if (line.startsWith('* ')) { + let parts = line.slice(2).split(/,\s*/); + if (!parts.every(p => p.startsWith('`') && p.endsWith('`'))) { + throw new Error(`don't understanding this line: ${line}.`); + } + return parts.map(p => p.slice(1, -1)); + } +} + +export function parseChangeLog(src: string): { sections: Section[] } { + let lines = src.split('\n'); + let sections = []; + while (lines.length > 0) { + let section = parseSection(lines); + if (section) { + sections.push(section); + } + } + return { sections }; +} diff --git a/test-packages/release/src/prepare.ts b/test-packages/release/src/prepare.ts index 0d39849df..4afc13e00 100755 --- a/test-packages/release/src/prepare.ts +++ b/test-packages/release/src/prepare.ts @@ -1,6 +1,24 @@ -import { execa } from 'execa'; +import execa from 'execa'; +import fs from 'node:fs'; +import { parseChangeLog } from './change-parser'; -async function main() {} +async function buildChangelog(): Promise { + let result = await execa('pnpm', ['lerna-changelog', '--next-version', 'Embroider Monorepo Release']); + return result.stdout; +} + +async function main() { + let changelog = fs.readFileSync('/tmp/changelog', 'utf8'); + let parsed; + try { + parsed = parseChangeLog(changelog); + } catch (err) { + console.error(err); + console.error(`the full changelog that failed to parse was:\n${changelog}`); + process.exit(-1); + } + console.log(JSON.stringify(parsed, null, 2)); +} main().then( () => { From dfd06eda24b1eed667d74c1bcf6be2389d7b6cb1 Mon Sep 17 00:00:00 2001 From: Edward Faulkner Date: Thu, 11 May 2023 18:49:50 -0400 Subject: [PATCH 03/16] interdep discovery --- pnpm-lock.yaml | 22 ++++++++-- test-packages/release/package.json | 7 ++- test-packages/release/src/interdep.ts | 54 ++++++++++++++++++++++++ test-packages/release/src/prepare.ts | 14 +++--- tests/fixtures/package.json | 3 +- types/broccoli-file-creator/package.json | 3 +- types/broccoli-merge-trees/package.json | 3 +- types/broccoli/package.json | 3 +- types/console-ui/package.json | 3 +- types/ember-cli/package.json | 3 +- types/fast-sourcemap-concat/package.json | 3 +- types/thread-loader/package.json | 3 +- 12 files changed, 102 insertions(+), 19 deletions(-) create mode 100644 test-packages/release/src/interdep.ts diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 9f4966cc2..cb8f7cbf4 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -993,9 +993,24 @@ importers: '@ef4/lerna-changelog': specifier: ^1.0.4 version: 1.0.4 + '@types/fs-extra': + specifier: ^9.0.12 + version: 9.0.12 + '@types/js-yaml': + specifier: ^4.0.5 + version: 4.0.5 execa: specifier: ^4.0.3 version: 4.0.3 + fs-extra: + specifier: ^10.0.0 + version: 10.0.0 + globby: + specifier: ^11.0.3 + version: 11.0.3 + js-yaml: + specifier: ^4.1.0 + version: 4.1.0 test-packages/sample-transforms: dependencies: @@ -6282,7 +6297,6 @@ packages: resolution: {integrity: sha512-I+bsBr67CurCGnSenZZ7v94gd3tc3+Aj2taxMT4yu4ABLuOgOjeFxX3dokG24ztSRg5tnT00sL8BszO7gSMoIw==} dependencies: '@types/node': 15.12.2 - dev: true /@types/glob@7.2.0: resolution: {integrity: sha512-ZUxbzKl0IfJILTS6t7ip5fQQM/J3TJYubDm3nMbgubNNYS62eXeUpoLUC8/7fJNiFYHTrGPQn7hspDUzIHX3UA==} @@ -6341,7 +6355,6 @@ packages: /@types/js-yaml@4.0.5: resolution: {integrity: sha512-FhpRzf927MNQdRZP0J5DLIdTXhjLYzeUTmLAu69mnVksLH9CJY3IuSeEgbKUki7GQZm0WqDkGzyxju2EZGD2wA==} - dev: true /@types/jsdom@16.2.11: resolution: {integrity: sha512-Dvtx0zFQOJqn06VgjRur7P5CeSNUOaQ5ivSSvdAdA3sBWzL3kl9OWApQRExKnS3XN39OaZdeCHpoYxVmX6FwCQ==} @@ -10869,7 +10882,7 @@ packages: ember-render-helpers: 0.2.0 ember-style-modifier: 0.7.0(@babel/core@7.19.6) findup-sync: 5.0.0 - fs-extra: 10.0.0 + fs-extra: 10.1.0 resolve: 1.20.0 rsvp: 4.8.5 silent-error: 1.1.1 @@ -11100,7 +11113,7 @@ packages: fastboot: 3.2.0 fastboot-express-middleware: 3.2.0 fastboot-transform: 0.1.3 - fs-extra: 10.0.0 + fs-extra: 10.1.0 json-stable-stringify: 1.0.2 md5-hex: 3.0.1 recast: 0.19.1 @@ -14794,6 +14807,7 @@ packages: graceful-fs: 4.2.11 jsonfile: 6.1.0 universalify: 2.0.0 + dev: false /fs-extra@10.1.0: resolution: {integrity: sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==} diff --git a/test-packages/release/package.json b/test-packages/release/package.json index 5bbb77eaa..254767658 100644 --- a/test-packages/release/package.json +++ b/test-packages/release/package.json @@ -7,7 +7,12 @@ }, "dependencies": { "@ef4/lerna-changelog": "^1.0.4", - "execa": "^4.0.3" + "@types/fs-extra": "^9.0.12", + "@types/js-yaml": "^4.0.5", + "execa": "^4.0.3", + "fs-extra": "^10.0.0", + "globby": "^11.0.3", + "js-yaml": "^4.1.0" }, "volta": { "extends": "../../package.json" diff --git a/test-packages/release/src/interdep.ts b/test-packages/release/src/interdep.ts new file mode 100644 index 000000000..73fc2b4bf --- /dev/null +++ b/test-packages/release/src/interdep.ts @@ -0,0 +1,54 @@ +import glob from 'globby'; +import { resolve } from 'path'; +import { readFileSync, readJSONSync } from 'fs-extra'; +import yaml from 'js-yaml'; + +type Range = 'exact' | 'caret'; +interface PkgEntry { + version: string; + deps: Map; +} + +function workspaceRangeType(range: string): Range | undefined { + if (!range.startsWith('workspace:')) { + return; + } + switch (range.slice(10)) { + case '*': + // this is how pnpm interprets workspace:* + return 'exact'; + case '^': + return 'caret'; + default: + throw new Error(`unsupported workspace dependency type ${range}`); + } +} + +export function publishedInterPackageDeps(): Map { + let rootDir = resolve(__dirname, '..', '..', '..'); + let packages: Map = new Map(); + for (let pattern of (yaml.load(readFileSync(resolve(__dirname, '../../../pnpm-workspace.yaml'), 'utf8')) as any) + .packages) { + for (let dir of glob.sync(pattern, { cwd: rootDir, expandDirectories: false, onlyDirectories: true })) { + let pkg = readJSONSync(resolve(rootDir, dir, 'package.json')); + if (pkg.private) { + continue; + } + let entry: PkgEntry = { version: pkg.version, deps: new Map() }; + // no devDeps because changes to devDeps shouldn't ever force us to + // release + for (let section of ['dependencies', 'peerDependencies']) { + if (pkg[section]) { + for (let [depName, depRange] of Object.entries(pkg[section] as Record)) { + let rangeType = workspaceRangeType(depRange); + if (rangeType) { + entry.deps.set(depName, rangeType); + } + } + } + } + packages.set(pkg.name, entry); + } + } + return packages; +} diff --git a/test-packages/release/src/prepare.ts b/test-packages/release/src/prepare.ts index 4afc13e00..819d149f4 100755 --- a/test-packages/release/src/prepare.ts +++ b/test-packages/release/src/prepare.ts @@ -1,11 +1,12 @@ -import execa from 'execa'; -import fs from 'node:fs'; +// import execa from 'execa'; +import fs from 'fs'; import { parseChangeLog } from './change-parser'; +import { publishedInterPackageDeps } from './interdep'; -async function buildChangelog(): Promise { - let result = await execa('pnpm', ['lerna-changelog', '--next-version', 'Embroider Monorepo Release']); - return result.stdout; -} +// async function buildChangelog(): Promise { +// let result = await execa('pnpm', ['lerna-changelog', '--next-version', 'Embroider Monorepo Release']); +// return result.stdout; +// } async function main() { let changelog = fs.readFileSync('/tmp/changelog', 'utf8'); @@ -18,6 +19,7 @@ async function main() { process.exit(-1); } console.log(JSON.stringify(parsed, null, 2)); + console.log(publishedInterPackageDeps()); } main().then( diff --git a/tests/fixtures/package.json b/tests/fixtures/package.json index 3ebf291d2..807cb85d6 100644 --- a/tests/fixtures/package.json +++ b/tests/fixtures/package.json @@ -1,3 +1,4 @@ { - "name": "@embroider/test-fixtures" + "name": "@embroider/test-fixtures", + "private": true } \ No newline at end of file diff --git a/types/broccoli-file-creator/package.json b/types/broccoli-file-creator/package.json index e66dcf365..21e11207f 100644 --- a/types/broccoli-file-creator/package.json +++ b/types/broccoli-file-creator/package.json @@ -1,3 +1,4 @@ { - "name": "@types/broccoli-file-creator" + "name": "@types/broccoli-file-creator", + "private": true } \ No newline at end of file diff --git a/types/broccoli-merge-trees/package.json b/types/broccoli-merge-trees/package.json index fe8d49e09..d28f4d006 100644 --- a/types/broccoli-merge-trees/package.json +++ b/types/broccoli-merge-trees/package.json @@ -1,3 +1,4 @@ { - "name": "@types/broccoli-merge-trees" + "name": "@types/broccoli-merge-trees", + "private": true } \ No newline at end of file diff --git a/types/broccoli/package.json b/types/broccoli/package.json index e38612434..c5aac104c 100644 --- a/types/broccoli/package.json +++ b/types/broccoli/package.json @@ -1,3 +1,4 @@ { - "name": "@types/broccoli" + "name": "@types/broccoli", + "private": true } \ No newline at end of file diff --git a/types/console-ui/package.json b/types/console-ui/package.json index 9b9151fba..67b431156 100644 --- a/types/console-ui/package.json +++ b/types/console-ui/package.json @@ -1,3 +1,4 @@ { - "name": "@types/console-ui" + "name": "@types/console-ui", + "private": true } \ No newline at end of file diff --git a/types/ember-cli/package.json b/types/ember-cli/package.json index cf17ad920..42cdf8724 100644 --- a/types/ember-cli/package.json +++ b/types/ember-cli/package.json @@ -1,3 +1,4 @@ { - "name": "@types/ember-cli" + "name": "@types/ember-cli", + "private": true } \ No newline at end of file diff --git a/types/fast-sourcemap-concat/package.json b/types/fast-sourcemap-concat/package.json index 193f7bd51..03cbac1b7 100644 --- a/types/fast-sourcemap-concat/package.json +++ b/types/fast-sourcemap-concat/package.json @@ -1,3 +1,4 @@ { - "name": "@types/fast-sourcemap-concat" + "name": "@types/fast-sourcemap-concat", + "private": true } \ No newline at end of file diff --git a/types/thread-loader/package.json b/types/thread-loader/package.json index 2dc756cf3..b87abeb23 100644 --- a/types/thread-loader/package.json +++ b/types/thread-loader/package.json @@ -1,3 +1,4 @@ { - "name": "@types/thread-loader" + "name": "@types/thread-loader", + "private": true } \ No newline at end of file From 276848380236fa5962306cceb36f3b64c41a5750 Mon Sep 17 00:00:00 2001 From: Edward Faulkner Date: Fri, 12 May 2023 11:05:48 -0400 Subject: [PATCH 04/16] much release infra --- pnpm-lock.yaml | 9 ++++ test-packages/release/package.json | 5 +- test-packages/release/src/change-parser.ts | 20 +++++-- test-packages/release/src/cli.ts | 59 +++++++++++++++++++++ test-packages/release/src/gather-changes.ts | 6 +++ test-packages/release/src/prepare.ts | 50 ++++++++--------- 6 files changed, 120 insertions(+), 29 deletions(-) create mode 100644 test-packages/release/src/cli.ts create mode 100644 test-packages/release/src/gather-changes.ts mode change 100755 => 100644 test-packages/release/src/prepare.ts diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index cb8f7cbf4..194cfcec8 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -999,6 +999,12 @@ importers: '@types/js-yaml': specifier: ^4.0.5 version: 4.0.5 + '@types/yargs': + specifier: ^17.0.3 + version: 17.0.3 + cli-highlight: + specifier: ^2.1.11 + version: 2.1.11 execa: specifier: ^4.0.3 version: 4.0.3 @@ -1011,6 +1017,9 @@ importers: js-yaml: specifier: ^4.1.0 version: 4.1.0 + yargs: + specifier: ^17.0.1 + version: 17.0.1 test-packages/sample-transforms: dependencies: diff --git a/test-packages/release/package.json b/test-packages/release/package.json index 254767658..a74314285 100644 --- a/test-packages/release/package.json +++ b/test-packages/release/package.json @@ -9,10 +9,13 @@ "@ef4/lerna-changelog": "^1.0.4", "@types/fs-extra": "^9.0.12", "@types/js-yaml": "^4.0.5", + "@types/yargs": "^17.0.3", + "cli-highlight": "^2.1.11", "execa": "^4.0.3", "fs-extra": "^10.0.0", "globby": "^11.0.3", - "js-yaml": "^4.1.0" + "js-yaml": "^4.1.0", + "yargs": "^17.0.1" }, "volta": { "extends": "../../package.json" diff --git a/test-packages/release/src/change-parser.ts b/test-packages/release/src/change-parser.ts index 670c21aa0..fd9c7ba6a 100644 --- a/test-packages/release/src/change-parser.ts +++ b/test-packages/release/src/change-parser.ts @@ -1,4 +1,10 @@ export type Impact = 'major' | 'minor' | 'patch'; +export type UnlabeledSection = { unlabeled: true; summaryText: string }; +export type LabeledSection = { packages: string[]; impact: Impact }; +export type Section = LabeledSection | UnlabeledSection; +export interface ParsedChangelog { + sections: Section[]; +} const knownSections: Record = { ':boom: Breaking Change': { @@ -41,8 +47,6 @@ function consumeSection(lines: string[]) { return matchedLines; } -export type Section = { packages: string[]; impact: Impact } | { unlabeled: true; summaryText: string }; - function parseSection(lines: string[]): Section | undefined { let line = lines.shift(); const heading = line ? sectionHeading(line) : undefined; @@ -95,7 +99,7 @@ function parsePackageList(lines: string[]): string[] | undefined { } } -export function parseChangeLog(src: string): { sections: Section[] } { +export function parseChangeLog(src: string): ParsedChangelog { let lines = src.split('\n'); let sections = []; while (lines.length > 0) { @@ -106,3 +110,13 @@ export function parseChangeLog(src: string): { sections: Section[] } { } return { sections }; } + +export function parseChangeLogOrExit(src: string): ParsedChangelog { + try { + return parseChangeLog(src); + } catch (err) { + console.error(err); + console.error(`the full changelog that failed to parse was:\n${src}`); + process.exit(-1); + } +} diff --git a/test-packages/release/src/cli.ts b/test-packages/release/src/cli.ts new file mode 100644 index 000000000..5a0d8138b --- /dev/null +++ b/test-packages/release/src/cli.ts @@ -0,0 +1,59 @@ +import yargs from 'yargs/yargs'; +import { readFileSync } from 'fs'; + +yargs(process.argv.slice(2)) + .usage( + `Most of the subcommands in here exist so you can easily test parts of the release process by themselves. To do an actual release, see RELEASE.md.` + ) + .scriptName('release') + .command( + 'prepare', + `Edits the package.json and changelog files to prepare for release.`, + yargs => + yargs.option('fromStdin', { + type: 'boolean', + description: 'Read the summary of changes from stdin instead of building them from scratch.', + }), + async function (opts) { + let newChangelogContent: string; + if (opts.fromStdin) { + newChangelogContent = readFileSync(process.stdin.fd, 'utf8'); + } else { + let { gatherChanges } = await import('./gather-changes'); + newChangelogContent = await gatherChanges(); + } + let { prepare } = await import('./prepare'); + await prepare(newChangelogContent); + } + ) + .command( + 'gather-changes', + `Uses lerna-changelog to build a description of all the PRs in the release.`, + yargs => yargs, + async function (/* opts */) { + let { gatherChanges } = await import('./gather-changes'); + process.stdout.write(await gatherChanges()); + } + ) + .command( + 'parse-changes', + `Takes the output of gather-changes and parses it into a structured format`, + yargs => yargs, + async function (/* opts */) { + let { parseChangeLogOrExit } = await import('./change-parser'); + console.log(JSON.stringify(parseChangeLogOrExit(readFileSync(process.stdin.fd, 'utf8')), null, 2)); + } + ) + .command( + 'discover-deps', + `Summarizes how all our published packages relate to each other`, + yargs => yargs, + async function (/* opts */) { + let { publishedInterPackageDeps } = await import('./interdep'); + console.log(publishedInterPackageDeps()); + } + ) + + .demandCommand() + .strictCommands() + .help().argv; diff --git a/test-packages/release/src/gather-changes.ts b/test-packages/release/src/gather-changes.ts new file mode 100644 index 000000000..6a7dbd5af --- /dev/null +++ b/test-packages/release/src/gather-changes.ts @@ -0,0 +1,6 @@ +import execa from 'execa'; + +export async function gatherChanges() { + let result = await execa('pnpm', ['lerna-changelog', '--next-version', 'Release']); + return result.stdout; +} diff --git a/test-packages/release/src/prepare.ts b/test-packages/release/src/prepare.ts old mode 100755 new mode 100644 index 819d149f4..28d153486 --- a/test-packages/release/src/prepare.ts +++ b/test-packages/release/src/prepare.ts @@ -1,33 +1,33 @@ -// import execa from 'execa'; -import fs from 'fs'; -import { parseChangeLog } from './change-parser'; -import { publishedInterPackageDeps } from './interdep'; +import { parseChangeLogOrExit, ParsedChangelog, UnlabeledSection } from './change-parser'; +import highlight from 'cli-highlight'; +import { readFileSync, writeFileSync } from 'fs'; +import { resolve } from 'path'; -// async function buildChangelog(): Promise { -// let result = await execa('pnpm', ['lerna-changelog', '--next-version', 'Embroider Monorepo Release']); -// return result.stdout; -// } +const changelogPreamble = `# Embroider Changelog +`; -async function main() { - let changelog = fs.readFileSync('/tmp/changelog', 'utf8'); - let parsed; - try { - parsed = parseChangeLog(changelog); - } catch (err) { - console.error(err); - console.error(`the full changelog that failed to parse was:\n${changelog}`); +function ensureAllLabeled(changes: ParsedChangelog) { + let unlabeled = changes.sections.find(section => 'unlabeled' in section) as UnlabeledSection; + if (unlabeled) { + process.stderr.write('Cannot release because these PRs are unlabeled:\n'); + process.stderr.write(highlight(unlabeled.summaryText)); process.exit(-1); } - console.log(JSON.stringify(parsed, null, 2)); - console.log(publishedInterPackageDeps()); } -main().then( - () => { - process.exit(0); - }, - err => { - console.error(err); +function updateChangelog(newChangelogContent: string) { + let targetChangelogFile = resolve(__dirname, '..', '..', '..', 'CHANGELOG.md'); + let oldChangelogContent = readFileSync(targetChangelogFile, 'utf8'); + if (!oldChangelogContent.startsWith(changelogPreamble)) { + process.stderr.write(`Cannot parse existing changelog. Expected it to start with:\n${changelogPreamble}`); process.exit(-1); } -); + oldChangelogContent = oldChangelogContent.slice(changelogPreamble.length); + writeFileSync(targetChangelogFile, changelogPreamble + newChangelogContent + '\n' + oldChangelogContent); +} + +export async function prepare(newChangelogContent: string) { + let changes = parseChangeLogOrExit(newChangelogContent); + ensureAllLabeled(changes); + updateChangelog(newChangelogContent); +} From bac2f1497acfca7378ffabb4ccd44cab8b1b1224 Mon Sep 17 00:00:00 2001 From: Edward Faulkner Date: Fri, 12 May 2023 11:33:34 -0400 Subject: [PATCH 05/16] starting planner --- test-packages/release/src/change-parser.ts | 3 +- test-packages/release/src/cli.ts | 11 ++++++ test-packages/release/src/interdep.ts | 17 ++++---- test-packages/release/src/plan.ts | 45 ++++++++++++++++++++++ test-packages/release/src/prepare.ts | 5 +++ 5 files changed, 73 insertions(+), 8 deletions(-) create mode 100644 test-packages/release/src/plan.ts diff --git a/test-packages/release/src/change-parser.ts b/test-packages/release/src/change-parser.ts index fd9c7ba6a..48e87c7e1 100644 --- a/test-packages/release/src/change-parser.ts +++ b/test-packages/release/src/change-parser.ts @@ -1,6 +1,6 @@ export type Impact = 'major' | 'minor' | 'patch'; export type UnlabeledSection = { unlabeled: true; summaryText: string }; -export type LabeledSection = { packages: string[]; impact: Impact }; +export type LabeledSection = { packages: string[]; impact: Impact; heading: string }; export type Section = LabeledSection | UnlabeledSection; export interface ParsedChangelog { sections: Section[]; @@ -79,6 +79,7 @@ function parseSection(lines: string[]): Section | undefined { return { packages: [...packages], impact: sectionConfig.impact, + heading, }; } diff --git a/test-packages/release/src/cli.ts b/test-packages/release/src/cli.ts index 5a0d8138b..cdb6edaa4 100644 --- a/test-packages/release/src/cli.ts +++ b/test-packages/release/src/cli.ts @@ -1,5 +1,6 @@ import yargs from 'yargs/yargs'; import { readFileSync } from 'fs'; +import { parseChangeLogOrExit } from './change-parser'; yargs(process.argv.slice(2)) .usage( @@ -53,6 +54,16 @@ yargs(process.argv.slice(2)) console.log(publishedInterPackageDeps()); } ) + .command( + 'plan-version-bumps', + `Takes the output of gather-changes and explains which packages need to be released at what versions and why.`, + yargs => yargs, + async function (/* opts */) { + let { planVersionBumps } = await import('./plan'); + let newChangelogContent = readFileSync(process.stdin.fd, 'utf8'); + console.log(planVersionBumps(parseChangeLogOrExit(newChangelogContent))); + } + ) .demandCommand() .strictCommands() diff --git a/test-packages/release/src/interdep.ts b/test-packages/release/src/interdep.ts index 73fc2b4bf..ccd1d98e6 100644 --- a/test-packages/release/src/interdep.ts +++ b/test-packages/release/src/interdep.ts @@ -3,10 +3,12 @@ import { resolve } from 'path'; import { readFileSync, readJSONSync } from 'fs-extra'; import yaml from 'js-yaml'; -type Range = 'exact' | 'caret'; -interface PkgEntry { +export type Range = 'exact' | 'caret'; +export interface PkgEntry { version: string; - deps: Map; + pkgJSONPath: string; + dependencies: Map; + peerDependencies: Map; } function workspaceRangeType(range: string): Range | undefined { @@ -30,19 +32,20 @@ export function publishedInterPackageDeps(): Map { for (let pattern of (yaml.load(readFileSync(resolve(__dirname, '../../../pnpm-workspace.yaml'), 'utf8')) as any) .packages) { for (let dir of glob.sync(pattern, { cwd: rootDir, expandDirectories: false, onlyDirectories: true })) { - let pkg = readJSONSync(resolve(rootDir, dir, 'package.json')); + let pkgJSONPath = resolve(rootDir, dir, 'package.json'); + let pkg = readJSONSync(pkgJSONPath); if (pkg.private) { continue; } - let entry: PkgEntry = { version: pkg.version, deps: new Map() }; + let entry: PkgEntry = { version: pkg.version, pkgJSONPath, dependencies: new Map(), peerDependencies: new Map() }; // no devDeps because changes to devDeps shouldn't ever force us to // release - for (let section of ['dependencies', 'peerDependencies']) { + for (let section of ['dependencies', 'peerDependencies'] as const) { if (pkg[section]) { for (let [depName, depRange] of Object.entries(pkg[section] as Record)) { let rangeType = workspaceRangeType(depRange); if (rangeType) { - entry.deps.set(depName, rangeType); + entry[section].set(depName, rangeType); } } } diff --git a/test-packages/release/src/plan.ts b/test-packages/release/src/plan.ts new file mode 100644 index 000000000..445bb18ca --- /dev/null +++ b/test-packages/release/src/plan.ts @@ -0,0 +1,45 @@ +import { Impact, ParsedChangelog } from './change-parser'; +import { publishedInterPackageDeps } from './interdep'; + +class Plan { + constraints: Map; + + constructor() { + let pkgs = publishedInterPackageDeps(); + + // initialize constraints for every published package + let constraints = new Map(); + for (let pkg of pkgs.keys()) { + constraints.set(pkg, []); + } + + this.constraints = constraints; + } + + addConstraint(packageName: string, impact: Impact, reason: string): boolean { + let pkgConstraints = this.constraints.get(packageName); + if (!pkgConstraints) { + let err = new Error(`unknown package "${packageName}"`); + (err as any).unknownPackage = true; + throw err; + } + pkgConstraints.push({ impact, reason }); + return true; + } +} + +export function planVersionBumps(changed: ParsedChangelog) { + let plan = new Plan(); + for (let section of changed.sections) { + if ('unlabeled' in section) { + process.stderr.write(`cannot plan version bumps when there are unlabeled changes\n`); + process.exit(-1); + } + + for (let pkg of section.packages) { + plan.addConstraint(`@embroider/${pkg}`, section.impact, `Appears in changelog section ${section.heading}`); + } + } + + return plan.constraints; +} diff --git a/test-packages/release/src/prepare.ts b/test-packages/release/src/prepare.ts index 28d153486..987ef6f54 100644 --- a/test-packages/release/src/prepare.ts +++ b/test-packages/release/src/prepare.ts @@ -2,6 +2,7 @@ import { parseChangeLogOrExit, ParsedChangelog, UnlabeledSection } from './chang import highlight from 'cli-highlight'; import { readFileSync, writeFileSync } from 'fs'; import { resolve } from 'path'; +import { publishedInterPackageDeps } from './interdep'; const changelogPreamble = `# Embroider Changelog `; @@ -15,6 +16,10 @@ function ensureAllLabeled(changes: ParsedChangelog) { } } +function planVersionBumps(changes: ParsedChangelog) { + let deps = publishedInterPackageDeps(); +} + function updateChangelog(newChangelogContent: string) { let targetChangelogFile = resolve(__dirname, '..', '..', '..', 'CHANGELOG.md'); let oldChangelogContent = readFileSync(targetChangelogFile, 'utf8'); From 73191efd23ea65a7e24b5a04b8bd57223fc781ac Mon Sep 17 00:00:00 2001 From: Edward Faulkner Date: Fri, 12 May 2023 12:43:39 -0400 Subject: [PATCH 06/16] solve all constraints and explain them --- pnpm-lock.yaml | 37 ++++--- test-packages/release/package.json | 3 + test-packages/release/src/cli.ts | 51 +++++----- test-packages/release/src/highlight.ts | 13 +++ test-packages/release/src/interdep.ts | 40 +++++--- test-packages/release/src/plan.ts | 129 ++++++++++++++++++++++--- test-packages/release/src/prepare.ts | 9 +- types/source-map-url/package.json | 3 +- 8 files changed, 219 insertions(+), 66 deletions(-) create mode 100644 test-packages/release/src/highlight.ts diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 194cfcec8..87f6f2314 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -999,9 +999,18 @@ importers: '@types/js-yaml': specifier: ^4.0.5 version: 4.0.5 + '@types/semver': + specifier: ^7.3.6 + version: 7.3.6 '@types/yargs': specifier: ^17.0.3 version: 17.0.3 + assert-never: + specifier: ^1.2.1 + version: 1.2.1 + chalk: + specifier: ^4.1.1 + version: 4.1.2 cli-highlight: specifier: ^2.1.11 version: 2.1.11 @@ -1017,6 +1026,9 @@ importers: js-yaml: specifier: ^4.1.0 version: 4.1.0 + semver: + specifier: ^7.3.5 + version: 7.3.8 yargs: specifier: ^17.0.1 version: 17.0.1 @@ -4934,7 +4946,7 @@ packages: resolution: {integrity: sha512-4gkvuGRYfpAh1nwAz306cmMeC1mG7wxZnbsBZ09mMaMX/W7IyKOKc/38JwrDPUFUalmNEM7q7JEPcmew2M3Dog==} engines: {node: 10.* || 12.* || >= 14} dependencies: - chalk: 4.1.1 + chalk: 4.1.2 ember-cli-version-checker: 5.1.2 glob: 7.2.3 inquirer: 7.3.3 @@ -6500,7 +6512,6 @@ packages: /@types/semver@7.3.6: resolution: {integrity: sha512-0caWDWmpCp0uifxFh+FaqK3CuZ2SkRR/ZRxAV5+zNdC3QVUi6wyOJnefhPvtNt8NQWXB5OA93BUvZsXpWat2Xw==} - dev: true /@types/semver@7.5.0: resolution: {integrity: sha512-G8hZ6XJiHnuhQKR7ZmysCeJWE08o8T0AXtk5darsCaTVsYZhhgUrq53jizaR2FvsoeCwJhlmwTjkXBY5Pn/ZHw==} @@ -9410,6 +9421,7 @@ packages: dependencies: ansi-styles: 4.3.0 supports-color: 7.2.0 + dev: false /chalk@4.1.2: resolution: {integrity: sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==} @@ -9837,7 +9849,7 @@ packages: engines: {node: ^12.20.0 || ^14.13.0 || >=16.0.0} hasBin: true dependencies: - chalk: 4.1.1 + chalk: 4.1.2 date-fns: 2.30.0 lodash: 4.17.21 rxjs: 6.6.7 @@ -10873,7 +10885,7 @@ packages: broccoli-debug: 0.6.5 broccoli-funnel: 3.0.8 broccoli-merge-trees: 4.2.0 - chalk: 4.1.1 + chalk: 4.1.2 ember-auto-import: 2.6.3(webpack@5.78.0) ember-cli-babel: 7.26.11 ember-cli-build-config-editor: 0.5.1 @@ -11439,7 +11451,7 @@ packages: broccoli-stew: 3.0.0 calculate-cache-key-for-tree: 2.0.0 capture-exit: 2.0.0 - chalk: 4.1.1 + chalk: 4.1.2 ci-info: 2.0.0 clean-base-url: 1.0.0 compression: 1.7.4 @@ -12817,7 +12829,7 @@ packages: broccoli-debug: 0.6.5 broccoli-funnel: 2.0.2 broccoli-merge-trees: 4.2.0 - chalk: 4.1.1 + chalk: 4.1.2 ember-cli-babel: 7.26.11 ember-cli-get-component-path-option: 1.0.0 ember-cli-is-package-missing: 1.0.0 @@ -12851,7 +12863,7 @@ packages: broccoli-debug: 0.6.5 broccoli-funnel: 2.0.2 broccoli-merge-trees: 4.2.0 - chalk: 4.1.1 + chalk: 4.1.2 ember-cli-babel: 7.26.11 ember-cli-get-component-path-option: 1.0.0 ember-cli-is-package-missing: 1.0.0 @@ -12885,7 +12897,7 @@ packages: broccoli-file-creator: 2.1.1 broccoli-funnel: 2.0.2 broccoli-merge-trees: 4.2.0 - chalk: 4.1.1 + chalk: 4.1.2 ember-cli-babel: 7.26.11 ember-cli-get-component-path-option: 1.0.0 ember-cli-is-package-missing: 1.0.0 @@ -12922,7 +12934,7 @@ packages: broccoli-file-creator: 2.1.1 broccoli-funnel: 3.0.8 broccoli-merge-trees: 4.2.0 - chalk: 4.1.1 + chalk: 4.1.2 ember-auto-import: 2.6.3(webpack@5.78.0) ember-cli-babel: 7.26.11 ember-cli-get-component-path-option: 1.0.0 @@ -12994,7 +13006,7 @@ packages: broccoli-file-creator: 2.1.1 broccoli-funnel: 3.0.8 broccoli-merge-trees: 4.2.0 - chalk: 4.1.1 + chalk: 4.1.2 ember-auto-import: 2.6.3(webpack@5.78.0) ember-cli-babel: 7.26.11 ember-cli-get-component-path-option: 1.0.0 @@ -13837,7 +13849,7 @@ packages: '@eslint/eslintrc': 0.4.3 '@humanwhocodes/config-array': 0.5.0 ajv: 6.12.6 - chalk: 4.1.1 + chalk: 4.1.2 cross-spawn: 7.0.3 debug: 4.3.2(supports-color@8.1.0) doctrine: 3.0.0 @@ -16837,7 +16849,7 @@ packages: dependencies: '@types/node': 15.12.2 merge-stream: 2.0.0 - supports-color: 8.1.0 + supports-color: 8.1.1 /jest-worker@29.5.0: resolution: {integrity: sha512-NcrQnevGoSp4b5kg+akIpthoAFHxPBcb5P6mYPY0fUNT+sSvmtu6jlkEle3anczUKIKEbMxFimk9oTP/tpIPgA==} @@ -21334,7 +21346,6 @@ packages: engines: {node: '>=10'} dependencies: has-flag: 4.0.0 - dev: true /supports-hyperlinks@3.0.0: resolution: {integrity: sha512-QBDPHyPQDRTy9ku4URNGY5Lah8PAaXs6tAAwp55sL5WCsSW7GIfdf6W5ixfziW+t7wh3GVvHyHHyQ1ESsoRvaA==} diff --git a/test-packages/release/package.json b/test-packages/release/package.json index a74314285..68fffed70 100644 --- a/test-packages/release/package.json +++ b/test-packages/release/package.json @@ -10,11 +10,14 @@ "@types/fs-extra": "^9.0.12", "@types/js-yaml": "^4.0.5", "@types/yargs": "^17.0.3", + "@types/semver": "^7.3.6", + "assert-never": "^1.2.1", "cli-highlight": "^2.1.11", "execa": "^4.0.3", "fs-extra": "^10.0.0", "globby": "^11.0.3", "js-yaml": "^4.1.0", + "semver": "^7.3.5", "yargs": "^17.0.1" }, "volta": { diff --git a/test-packages/release/src/cli.ts b/test-packages/release/src/cli.ts index cdb6edaa4..a76e9d527 100644 --- a/test-packages/release/src/cli.ts +++ b/test-packages/release/src/cli.ts @@ -1,4 +1,6 @@ import yargs from 'yargs/yargs'; +import type { Argv } from 'yargs'; + import { readFileSync } from 'fs'; import { parseChangeLogOrExit } from './change-parser'; @@ -10,21 +12,10 @@ yargs(process.argv.slice(2)) .command( 'prepare', `Edits the package.json and changelog files to prepare for release.`, - yargs => - yargs.option('fromStdin', { - type: 'boolean', - description: 'Read the summary of changes from stdin instead of building them from scratch.', - }), + yargs => fromStdin(yargs), async function (opts) { - let newChangelogContent: string; - if (opts.fromStdin) { - newChangelogContent = readFileSync(process.stdin.fd, 'utf8'); - } else { - let { gatherChanges } = await import('./gather-changes'); - newChangelogContent = await gatherChanges(); - } let { prepare } = await import('./prepare'); - await prepare(newChangelogContent); + await prepare(await newChangelogContent(opts)); } ) .command( @@ -38,11 +29,11 @@ yargs(process.argv.slice(2)) ) .command( 'parse-changes', - `Takes the output of gather-changes and parses it into a structured format`, - yargs => yargs, - async function (/* opts */) { + `Parse the summary of changes into a structured format`, + yargs => fromStdin(yargs), + async function (opts) { let { parseChangeLogOrExit } = await import('./change-parser'); - console.log(JSON.stringify(parseChangeLogOrExit(readFileSync(process.stdin.fd, 'utf8')), null, 2)); + console.log(JSON.stringify(parseChangeLogOrExit(await newChangelogContent(opts)), null, 2)); } ) .command( @@ -57,14 +48,30 @@ yargs(process.argv.slice(2)) .command( 'plan-version-bumps', `Takes the output of gather-changes and explains which packages need to be released at what versions and why.`, - yargs => yargs, - async function (/* opts */) { + yargs => fromStdin(yargs), + async function (opts) { let { planVersionBumps } = await import('./plan'); - let newChangelogContent = readFileSync(process.stdin.fd, 'utf8'); - console.log(planVersionBumps(parseChangeLogOrExit(newChangelogContent))); + console.log(planVersionBumps(parseChangeLogOrExit(await newChangelogContent(opts))).explain()); } ) - .demandCommand() .strictCommands() .help().argv; + +function fromStdin(yargs: Argv) { + return yargs.option('fromStdin', { + type: 'boolean', + description: 'Read the summary of changes from stdin instead of building them from scratch.', + }); +} + +async function newChangelogContent(opts: { fromStdin: boolean | undefined }) { + let content: string; + if (opts.fromStdin) { + content = readFileSync(process.stdin.fd, 'utf8'); + } else { + let { gatherChanges } = await import('./gather-changes'); + content = await gatherChanges(); + } + return content; +} diff --git a/test-packages/release/src/highlight.ts b/test-packages/release/src/highlight.ts new file mode 100644 index 000000000..957314907 --- /dev/null +++ b/test-packages/release/src/highlight.ts @@ -0,0 +1,13 @@ +import highlight from 'cli-highlight'; +import chalk from 'chalk'; + +export function highlightMarkdown(md: string): string { + return highlight(md, { + language: 'Markdown', + theme: { + section: chalk.blueBright, + string: chalk.hex('#0366d6'), + link: chalk.dim, + }, + }); +} diff --git a/test-packages/release/src/interdep.ts b/test-packages/release/src/interdep.ts index ccd1d98e6..f1efc269b 100644 --- a/test-packages/release/src/interdep.ts +++ b/test-packages/release/src/interdep.ts @@ -7,8 +7,8 @@ export type Range = 'exact' | 'caret'; export interface PkgEntry { version: string; pkgJSONPath: string; - dependencies: Map; - peerDependencies: Map; + isDependencyOf: Map; + isPeerDependencyOf: Map; } function workspaceRangeType(range: string): Range | undefined { @@ -29,6 +29,9 @@ function workspaceRangeType(range: string): Range | undefined { export function publishedInterPackageDeps(): Map { let rootDir = resolve(__dirname, '..', '..', '..'); let packages: Map = new Map(); + + let pkgJSONS: Map = new Map(); + for (let pattern of (yaml.load(readFileSync(resolve(__dirname, '../../../pnpm-workspace.yaml'), 'utf8')) as any) .packages) { for (let dir of glob.sync(pattern, { cwd: rootDir, expandDirectories: false, onlyDirectories: true })) { @@ -37,20 +40,33 @@ export function publishedInterPackageDeps(): Map { if (pkg.private) { continue; } - let entry: PkgEntry = { version: pkg.version, pkgJSONPath, dependencies: new Map(), peerDependencies: new Map() }; - // no devDeps because changes to devDeps shouldn't ever force us to - // release - for (let section of ['dependencies', 'peerDependencies'] as const) { - if (pkg[section]) { - for (let [depName, depRange] of Object.entries(pkg[section] as Record)) { - let rangeType = workspaceRangeType(depRange); - if (rangeType) { - entry[section].set(depName, rangeType); + pkgJSONS.set(pkg.name, pkg); + packages.set(pkg.name, { + version: pkg.version, + pkgJSONPath, + isDependencyOf: new Map(), + isPeerDependencyOf: new Map(), + }); + } + } + + for (let [consumerName, consumerPkgJSON] of pkgJSONS) { + // no devDeps because changes to devDeps shouldn't ever force us to + // release + for (let section of ['dependencies', 'peerDependencies'] as const) { + if (consumerPkgJSON[section]) { + for (let [depName, depRange] of Object.entries(consumerPkgJSON[section] as Record)) { + let rangeType = workspaceRangeType(depRange); + if (rangeType) { + let dependency = packages.get(depName); + if (!dependency) { + throw new Error(`broken "workspace:" reference to ${depName} in ${consumerName}`); } + let field = section === 'dependencies' ? ('isDependencyOf' as const) : ('isPeerDependencyOf' as const); + dependency[field].set(consumerName, rangeType); } } } - packages.set(pkg.name, entry); } } return packages; diff --git a/test-packages/release/src/plan.ts b/test-packages/release/src/plan.ts index 445bb18ca..b643d32a0 100644 --- a/test-packages/release/src/plan.ts +++ b/test-packages/release/src/plan.ts @@ -1,30 +1,133 @@ import { Impact, ParsedChangelog } from './change-parser'; import { publishedInterPackageDeps } from './interdep'; +import assertNever from 'assert-never'; +import { inc } from 'semver'; +import { highlightMarkdown } from './highlight'; + +export type Solution = Map< + string, + | { impact: undefined; oldVersion: string } + | { impact: Impact; oldVersion: string; newVersion: string; constraints: { impact: Impact; reason: string }[] } +>; class Plan { - constraints: Map; + #constraints: Map; + #pkgs: ReturnType; constructor() { - let pkgs = publishedInterPackageDeps(); + this.#pkgs = publishedInterPackageDeps(); // initialize constraints for every published package let constraints = new Map(); - for (let pkg of pkgs.keys()) { + for (let pkg of this.#pkgs.keys()) { constraints.set(pkg, []); } - - this.constraints = constraints; + this.#constraints = constraints; } - addConstraint(packageName: string, impact: Impact, reason: string): boolean { - let pkgConstraints = this.constraints.get(packageName); + addConstraint(packageName: string, impact: Impact, reason: string): void { + let pkgConstraints = this.#constraints.get(packageName); if (!pkgConstraints) { let err = new Error(`unknown package "${packageName}"`); (err as any).unknownPackage = true; throw err; } - pkgConstraints.push({ impact, reason }); - return true; + if (!pkgConstraints.some(existing => existing.impact === impact && existing.reason === reason)) { + pkgConstraints.push({ impact, reason }); + this.#propagate(packageName, impact); + } + } + + solve(): Solution { + let solution: Solution = new Map(); + for (let [pkgName, entry] of this.#pkgs) { + let constraints = this.#constraints.get(pkgName)!; + let impact = this.#sumImpact(constraints); + if (!impact) { + solution.set(pkgName, { impact: undefined, oldVersion: entry.version }); + } else { + let newVersion = inc(entry.version, impact)!; + solution.set(pkgName, { impact, oldVersion: entry.version, newVersion, constraints }); + } + } + return solution; + } + + explain() { + let output: string[] = []; + for (let [pkgName, entry] of this.solve()) { + if (!entry.impact) { + output.push(`## ${pkgName} ${entry.oldVersion} does not need to be released.`); + } else { + output.push(`## ${pkgName} needs a ${entry.impact} release from ${entry.oldVersion} to ${entry.newVersion}`); + for (let constraint of entry.constraints) { + if (constraint.impact === entry.impact) { + output.push(` - ${constraint.reason}`); + } + } + } + } + return highlightMarkdown(output.join('\n')); + } + + #propagate(packageName: string, impact: Impact) { + let entry = this.#pkgs.get(packageName)!; + for (let [consumerName, rangeType] of entry.isDependencyOf) { + switch (rangeType) { + case 'exact': + this.addConstraint( + consumerName, + 'patch', + `Has an exact dependency on ${packageName}, which is being released` + ); + break; + case 'caret': + if (impact === 'major') { + this.addConstraint( + consumerName, + 'patch', + `Has a caret dependency on ${packageName}, which needs a major release` + ); + } + break; + default: + throw assertNever(rangeType); + } + } + for (let [consumerName, rangeType] of entry.isPeerDependencyOf) { + switch (rangeType) { + case 'exact': + this.addConstraint( + consumerName, + 'major', + `Has an exact peer dependency on ${packageName}, which is being released` + ); + break; + case 'caret': + if (impact === 'major') { + this.addConstraint( + consumerName, + 'major', + `Has a caret peer dependency on ${packageName}, which needs a major release` + ); + } + break; + default: + throw assertNever(rangeType); + } + } + } + + #sumImpact(impacts: { impact: Impact }[]): Impact | undefined { + if (impacts.some(i => i.impact === 'major')) { + return 'major'; + } + if (impacts.some(i => i.impact === 'minor')) { + return 'minor'; + } + if (impacts.some(i => i.impact === 'patch')) { + return 'patch'; + } } } @@ -32,7 +135,11 @@ export function planVersionBumps(changed: ParsedChangelog) { let plan = new Plan(); for (let section of changed.sections) { if ('unlabeled' in section) { - process.stderr.write(`cannot plan version bumps when there are unlabeled changes\n`); + process.stderr.write( + highlightMarkdown( + `# Unlabeled Changes\n\n${section.summaryText}\n\n*Cannot plan version bumps until the above changes are labeled*.\n` + ) + ); process.exit(-1); } @@ -41,5 +148,5 @@ export function planVersionBumps(changed: ParsedChangelog) { } } - return plan.constraints; + return plan; } diff --git a/test-packages/release/src/prepare.ts b/test-packages/release/src/prepare.ts index 987ef6f54..581e21399 100644 --- a/test-packages/release/src/prepare.ts +++ b/test-packages/release/src/prepare.ts @@ -1,8 +1,7 @@ import { parseChangeLogOrExit, ParsedChangelog, UnlabeledSection } from './change-parser'; -import highlight from 'cli-highlight'; import { readFileSync, writeFileSync } from 'fs'; import { resolve } from 'path'; -import { publishedInterPackageDeps } from './interdep'; +import { highlightMarkdown } from './highlight'; const changelogPreamble = `# Embroider Changelog `; @@ -11,15 +10,11 @@ function ensureAllLabeled(changes: ParsedChangelog) { let unlabeled = changes.sections.find(section => 'unlabeled' in section) as UnlabeledSection; if (unlabeled) { process.stderr.write('Cannot release because these PRs are unlabeled:\n'); - process.stderr.write(highlight(unlabeled.summaryText)); + process.stderr.write(highlightMarkdown(unlabeled.summaryText)); process.exit(-1); } } -function planVersionBumps(changes: ParsedChangelog) { - let deps = publishedInterPackageDeps(); -} - function updateChangelog(newChangelogContent: string) { let targetChangelogFile = resolve(__dirname, '..', '..', '..', 'CHANGELOG.md'); let oldChangelogContent = readFileSync(targetChangelogFile, 'utf8'); diff --git a/types/source-map-url/package.json b/types/source-map-url/package.json index 03db6f81b..b8253e069 100644 --- a/types/source-map-url/package.json +++ b/types/source-map-url/package.json @@ -1,3 +1,4 @@ { - "name": "@types/source-map-url" + "name": "@types/source-map-url", + "private": true } \ No newline at end of file From edf55e18a4b6f2b85ef6d159834b1f9ed52513a8 Mon Sep 17 00:00:00 2001 From: Edward Faulkner Date: Fri, 12 May 2023 13:19:13 -0400 Subject: [PATCH 07/16] improved explain commands and finished changelog output --- test-packages/release/src/cli.ts | 14 ++++--- test-packages/release/src/plan.ts | 56 ++++++++++++++++----------- test-packages/release/src/prepare.ts | 57 ++++++++++++++++++++-------- 3 files changed, 85 insertions(+), 42 deletions(-) diff --git a/test-packages/release/src/cli.ts b/test-packages/release/src/cli.ts index a76e9d527..a9055aa7c 100644 --- a/test-packages/release/src/cli.ts +++ b/test-packages/release/src/cli.ts @@ -15,7 +15,10 @@ yargs(process.argv.slice(2)) yargs => fromStdin(yargs), async function (opts) { let { prepare } = await import('./prepare'); - await prepare(await newChangelogContent(opts)); + let solution = await prepare(await newChangelogContent(opts)); + let { explain } = await import('./plan'); + process.stdout.write(explain(solution)); + process.stdout.write(`\nSuccessfully prepared released\n`); } ) .command( @@ -46,12 +49,13 @@ yargs(process.argv.slice(2)) } ) .command( - 'plan-version-bumps', - `Takes the output of gather-changes and explains which packages need to be released at what versions and why.`, + 'explain-plan', + `Explains which packages need to be released at what versions and why.`, yargs => fromStdin(yargs), async function (opts) { - let { planVersionBumps } = await import('./plan'); - console.log(planVersionBumps(parseChangeLogOrExit(await newChangelogContent(opts))).explain()); + let { planVersionBumps, explain } = await import('./plan'); + let solution = planVersionBumps(parseChangeLogOrExit(await newChangelogContent(opts))); + console.log(explain(solution)); } ) .demandCommand() diff --git a/test-packages/release/src/plan.ts b/test-packages/release/src/plan.ts index b643d32a0..c3b1999e5 100644 --- a/test-packages/release/src/plan.ts +++ b/test-packages/release/src/plan.ts @@ -7,7 +7,13 @@ import { highlightMarkdown } from './highlight'; export type Solution = Map< string, | { impact: undefined; oldVersion: string } - | { impact: Impact; oldVersion: string; newVersion: string; constraints: { impact: Impact; reason: string }[] } + | { + impact: Impact; + oldVersion: string; + newVersion: string; + constraints: { impact: Impact; reason: string }[]; + pkgJSONPath: string; + } >; class Plan { @@ -47,29 +53,18 @@ class Plan { solution.set(pkgName, { impact: undefined, oldVersion: entry.version }); } else { let newVersion = inc(entry.version, impact)!; - solution.set(pkgName, { impact, oldVersion: entry.version, newVersion, constraints }); + solution.set(pkgName, { + impact, + oldVersion: entry.version, + newVersion, + constraints, + pkgJSONPath: entry.pkgJSONPath, + }); } } return solution; } - explain() { - let output: string[] = []; - for (let [pkgName, entry] of this.solve()) { - if (!entry.impact) { - output.push(`## ${pkgName} ${entry.oldVersion} does not need to be released.`); - } else { - output.push(`## ${pkgName} needs a ${entry.impact} release from ${entry.oldVersion} to ${entry.newVersion}`); - for (let constraint of entry.constraints) { - if (constraint.impact === entry.impact) { - output.push(` - ${constraint.reason}`); - } - } - } - } - return highlightMarkdown(output.join('\n')); - } - #propagate(packageName: string, impact: Impact) { let entry = this.#pkgs.get(packageName)!; for (let [consumerName, rangeType] of entry.isDependencyOf) { @@ -131,13 +126,30 @@ class Plan { } } -export function planVersionBumps(changed: ParsedChangelog) { +export function explain(solution: Solution) { + let output: string[] = []; + for (let [pkgName, entry] of solution) { + if (!entry.impact) { + output.push(`## ${pkgName} ${entry.oldVersion} does not need to be released.`); + } else { + output.push(`## ${pkgName} needs a ${entry.impact} release from ${entry.oldVersion} to ${entry.newVersion}`); + for (let constraint of entry.constraints) { + if (constraint.impact === entry.impact) { + output.push(` - ${constraint.reason}`); + } + } + } + } + return highlightMarkdown(output.join('\n')); +} + +export function planVersionBumps(changed: ParsedChangelog): Solution { let plan = new Plan(); for (let section of changed.sections) { if ('unlabeled' in section) { process.stderr.write( highlightMarkdown( - `# Unlabeled Changes\n\n${section.summaryText}\n\n*Cannot plan version bumps until the above changes are labeled*.\n` + `# Unlabeled Changes\n\n${section.summaryText}\n\n*Cannot plan release until the above changes are labeled*.\n` ) ); process.exit(-1); @@ -148,5 +160,5 @@ export function planVersionBumps(changed: ParsedChangelog) { } } - return plan; + return plan.solve(); } diff --git a/test-packages/release/src/prepare.ts b/test-packages/release/src/prepare.ts index 581e21399..31b8e00cb 100644 --- a/test-packages/release/src/prepare.ts +++ b/test-packages/release/src/prepare.ts @@ -1,21 +1,13 @@ -import { parseChangeLogOrExit, ParsedChangelog, UnlabeledSection } from './change-parser'; +import { parseChangeLogOrExit } from './change-parser'; import { readFileSync, writeFileSync } from 'fs'; import { resolve } from 'path'; -import { highlightMarkdown } from './highlight'; +import { planVersionBumps, Solution } from './plan'; +import { readJSONSync, writeJSONSync } from 'fs-extra'; const changelogPreamble = `# Embroider Changelog `; -function ensureAllLabeled(changes: ParsedChangelog) { - let unlabeled = changes.sections.find(section => 'unlabeled' in section) as UnlabeledSection; - if (unlabeled) { - process.stderr.write('Cannot release because these PRs are unlabeled:\n'); - process.stderr.write(highlightMarkdown(unlabeled.summaryText)); - process.exit(-1); - } -} - -function updateChangelog(newChangelogContent: string) { +function updateChangelog(newChangelogContent: string, solution: Solution) { let targetChangelogFile = resolve(__dirname, '..', '..', '..', 'CHANGELOG.md'); let oldChangelogContent = readFileSync(targetChangelogFile, 'utf8'); if (!oldChangelogContent.startsWith(changelogPreamble)) { @@ -23,11 +15,46 @@ function updateChangelog(newChangelogContent: string) { process.exit(-1); } oldChangelogContent = oldChangelogContent.slice(changelogPreamble.length); - writeFileSync(targetChangelogFile, changelogPreamble + newChangelogContent + '\n' + oldChangelogContent); + + let [firstNewLine, ...restNewLines] = newChangelogContent.trim().split('\n'); + + writeFileSync( + targetChangelogFile, + changelogPreamble + + firstNewLine + + '\n\n' + + versionSummary(solution) + + '\n' + + restNewLines.join('\n') + + '\n' + + oldChangelogContent + ); +} + +function versionSummary(solution: Solution): string { + let result: string[] = []; + for (let [pkgName, entry] of solution) { + if (entry.impact) { + result.push(`${pkgName} ${entry.newVersion} (${entry.impact})`); + } + } + return result.join('\n'); +} + +function updateVersions(solution: Solution) { + for (let entry of solution.values()) { + if (entry.impact) { + let pkg = readJSONSync(entry.pkgJSONPath); + pkg.version = entry.newVersion; + writeJSONSync(entry.pkgJSONPath, pkg, { spaces: 2 }); + } + } } export async function prepare(newChangelogContent: string) { let changes = parseChangeLogOrExit(newChangelogContent); - ensureAllLabeled(changes); - updateChangelog(newChangelogContent); + let solution = planVersionBumps(changes); + updateVersions(solution); + updateChangelog(newChangelogContent, solution); + return solution; } From 4884860c5d158d8f6ca809c8a165d22490a35daf Mon Sep 17 00:00:00 2001 From: Edward Faulkner Date: Tue, 16 May 2023 00:30:18 -0400 Subject: [PATCH 08/16] better explain and more flexible range checking in solver --- package.json | 1 + pnpm-lock.yaml | 82 +++++++++--- test-packages/release/package.json | 7 +- test-packages/release/src/gather-changes.ts | 2 +- test-packages/release/src/interdep.ts | 23 +--- test-packages/release/src/plan.ts | 134 +++++++++++++------- 6 files changed, 161 insertions(+), 88 deletions(-) diff --git a/package.json b/package.json index f6824c0e9..4153341a0 100644 --- a/package.json +++ b/package.json @@ -42,6 +42,7 @@ }, "devDependencies": { "@changesets/cli": "^2.25.0", + "@embroider/release": "workspace:*", "@types/jest": "^29.2.0", "@typescript-eslint/eslint-plugin": "^5.59.5", "@typescript-eslint/parser": "^5.59.5", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 87f6f2314..db774a207 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -13,6 +13,9 @@ importers: '@changesets/cli': specifier: ^2.25.0 version: 2.25.0 + '@embroider/release': + specifier: workspace:* + version: link:test-packages/release '@types/jest': specifier: ^29.2.0 version: 29.2.0 @@ -578,7 +581,7 @@ importers: specifier: workspace:^ version: link:../addon-shim '@embroider/core': - specifier: workspace:^ + specifier: workspace:2.x||3.x version: link:../core devDependencies: '@babel/core': @@ -1569,7 +1572,7 @@ importers: version: 7.18.6 '@ember/legacy-built-in-components': specifier: ^0.4.1 - version: 0.4.1(ember-source@5.0.0-beta.3) + version: 0.4.1(ember-source@5.0.0) '@ember/string': specifier: ^3.0.0 version: 3.0.1 @@ -1623,7 +1626,7 @@ importers: version: 3.0.0 ember-bootstrap: specifier: ^5.0.0 - version: 5.0.0(@babel/core@7.19.6)(ember-source@5.0.0-beta.3)(webpack@5.78.0) + version: 5.0.0(@babel/core@7.19.6)(ember-source@5.0.0)(webpack@5.78.0) ember-cli: specifier: ~3.28.0 version: 3.28.0(lodash@4.17.21) @@ -1653,13 +1656,13 @@ importers: version: /ember-data@4.4.1(@babel/core@7.19.6)(webpack@5.78.0) ember-engines: specifier: ^0.8.23 - version: 0.8.23(@ember/legacy-built-in-components@0.4.1)(ember-source@5.0.0-beta.3) + version: 0.8.23(@ember/legacy-built-in-components@0.4.1)(ember-source@5.0.0) ember-inline-svg: specifier: ^0.2.1 version: 0.2.1(@babel/core@7.19.6) ember-modifier: specifier: ^4.0.0 - version: 4.1.0(ember-source@5.0.0-beta.3) + version: 4.1.0(ember-source@5.0.0) ember-source: specifier: ~3.28.11 version: 3.28.11(@babel/core@7.19.6) @@ -1671,7 +1674,7 @@ importers: version: /ember-source@5.0.0-beta.3(@babel/core@7.19.6)(@glimmer/component@1.1.2)(webpack@5.78.0) ember-source-latest: specifier: npm:ember-source@latest - version: /ember-source@4.12.0(@babel/core@7.19.6)(@glimmer/component@1.1.2)(webpack@5.78.0) + version: /ember-source@5.0.0(@babel/core@7.19.6)(@glimmer/component@1.1.2)(webpack@5.78.0) ember-truth-helpers: specifier: ^3.0.0 version: 3.0.0 @@ -4911,7 +4914,7 @@ packages: - supports-color dev: true - /@ember/legacy-built-in-components@0.4.1(ember-source@5.0.0-beta.3): + /@ember/legacy-built-in-components@0.4.1(ember-source@5.0.0): resolution: {integrity: sha512-tLxiU1YR+A+002rkGfwyB4FK8bO5qqU/3c7cZ1z2j3XG+1T28Yg2iZuMxPwFJ0LsE//mhRFkWlGzO3tJUtMHbA==} engines: {node: 12.* || 14.* || >= 16} peerDependencies: @@ -4921,7 +4924,7 @@ packages: ember-cli-babel: 7.26.11 ember-cli-htmlbars: 5.7.2 ember-cli-typescript: 4.2.1 - ember-source: 5.0.0-beta.3(@babel/core@7.19.6)(@glimmer/component@1.1.2)(webpack@5.78.0) + ember-source: 5.0.0(@babel/core@7.19.6)(@glimmer/component@1.1.2)(webpack@5.78.0) transitivePeerDependencies: - supports-color dev: true @@ -4956,7 +4959,7 @@ packages: - supports-color dev: true - /@ember/render-modifiers@2.0.5(@babel/core@7.19.6)(ember-source@5.0.0-beta.3): + /@ember/render-modifiers@2.0.5(@babel/core@7.19.6)(ember-source@5.0.0): resolution: {integrity: sha512-5cJ1niIdOJC6k6KtIn9HGbr1DATJQp4ZqMv1vbi6LKQWbVCQ3byvKONtUEi3H0wcewlrcaWCqXOgm0nACzCOQA==} engines: {node: 12.* || 14.* || >= 16} peerDependencies: @@ -4965,7 +4968,7 @@ packages: '@embroider/macros': 1.10.0 ember-cli-babel: 7.26.11 ember-modifier-manager-polyfill: 1.2.0(@babel/core@7.19.6) - ember-source: 5.0.0-beta.3(@babel/core@7.19.6)(@glimmer/component@1.1.2)(webpack@5.78.0) + ember-source: 5.0.0(@babel/core@7.19.6)(@glimmer/component@1.1.2)(webpack@5.78.0) transitivePeerDependencies: - '@babel/core' - supports-color @@ -10873,11 +10876,11 @@ packages: - supports-color - webpack - /ember-bootstrap@5.0.0(@babel/core@7.19.6)(ember-source@5.0.0-beta.3)(webpack@5.78.0): + /ember-bootstrap@5.0.0(@babel/core@7.19.6)(ember-source@5.0.0)(webpack@5.78.0): resolution: {integrity: sha512-ocH7qJKikxDgLv1prWyYzDaH85of8/l0LeV2bnMCp3/ZdRak/vq4dWqm53hMQ0ifN4llfs1Q1bwlcra/BT7yCA==} engines: {node: 12.* || 14.* || >= 16} dependencies: - '@ember/render-modifiers': 2.0.5(@babel/core@7.19.6)(ember-source@5.0.0-beta.3) + '@ember/render-modifiers': 2.0.5(@babel/core@7.19.6)(ember-source@5.0.0) '@embroider/macros': 1.10.0 '@embroider/util': 1.10.0(@glint/template@1.0.0)(ember-source@4.12.0) '@glimmer/component': 1.1.2(@babel/core@7.19.6) @@ -10893,7 +10896,7 @@ packages: ember-cli-version-checker: 5.1.2 ember-concurrency: 2.3.7(@babel/core@7.19.6) ember-decorators: 6.1.1 - ember-element-helper: 0.6.1(ember-source@5.0.0-beta.3) + ember-element-helper: 0.6.1(ember-source@5.0.0) ember-focus-trap: 1.0.2 ember-in-element-polyfill: 1.0.1 ember-named-blocks-polyfill: 0.2.5 @@ -12342,7 +12345,7 @@ packages: engines: {node: '>= 0.10.0'} dev: true - /ember-element-helper@0.6.1(ember-source@5.0.0-beta.3): + /ember-element-helper@0.6.1(ember-source@5.0.0): resolution: {integrity: sha512-YiOdAMlzYul4ulkIoNp8z7iHDfbT1fbut/9xGFRfxDwU/FmF8HtAUB2f1veu/w50HTeZNopa1OV2PCloZ76XlQ==} engines: {node: 12.* || 14.* || >= 16} peerDependencies: @@ -12351,7 +12354,7 @@ packages: '@embroider/util': 1.10.0(@glint/template@1.0.0)(ember-source@4.12.0) ember-cli-babel: 7.26.11 ember-cli-htmlbars: 6.2.0 - ember-source: 5.0.0-beta.3(@babel/core@7.19.6)(@glimmer/component@1.1.2)(webpack@5.78.0) + ember-source: 5.0.0(@babel/core@7.19.6)(@glimmer/component@1.1.2)(webpack@5.78.0) transitivePeerDependencies: - '@glint/template' - supports-color @@ -12388,14 +12391,14 @@ packages: - supports-color dev: true - /ember-engines@0.8.23(@ember/legacy-built-in-components@0.4.1)(ember-source@5.0.0-beta.3): + /ember-engines@0.8.23(@ember/legacy-built-in-components@0.4.1)(ember-source@5.0.0): resolution: {integrity: sha512-rrvHUkZRNrf+9u/sCw7XYrITStjP/9Ypykk1nYQHoo+6Krp11e81QNVsGTXFpXtMHXbNtH5IcRyZvfSXqUOrUQ==} engines: {node: 10.* || >= 12} peerDependencies: '@ember/legacy-built-in-components': '*' ember-source: ^3.12 || 4 dependencies: - '@ember/legacy-built-in-components': 0.4.1(ember-source@5.0.0-beta.3) + '@ember/legacy-built-in-components': 0.4.1(ember-source@5.0.0) '@embroider/macros': 1.10.0 amd-name-resolver: 1.3.1 babel-plugin-compact-reexports: 1.1.0 @@ -12413,7 +12416,7 @@ packages: ember-cli-preprocess-registry: 3.3.0 ember-cli-string-utils: 1.1.0 ember-cli-version-checker: 5.1.2 - ember-source: 5.0.0-beta.3(@babel/core@7.19.6)(@glimmer/component@1.1.2)(webpack@5.78.0) + ember-source: 5.0.0(@babel/core@7.19.6)(@glimmer/component@1.1.2)(webpack@5.78.0) lodash: 4.17.21 transitivePeerDependencies: - supports-color @@ -12578,7 +12581,7 @@ packages: - supports-color dev: true - /ember-modifier@4.1.0(ember-source@5.0.0-beta.3): + /ember-modifier@4.1.0(ember-source@5.0.0): resolution: {integrity: sha512-YFCNpEYj6jdyy3EjslRb2ehNiDvaOrXTilR9+ngq+iUqSHYto2zKV0rleiA1XJQ27ELM1q8RihT29U6Lq5EyqQ==} peerDependencies: ember-source: '*' @@ -12589,7 +12592,7 @@ packages: '@embroider/addon-shim': 1.8.4 ember-cli-normalize-entity-name: 1.0.0 ember-cli-string-utils: 1.1.0 - ember-source: 5.0.0-beta.3(@babel/core@7.19.6)(@glimmer/component@1.1.2)(webpack@5.78.0) + ember-source: 5.0.0(@babel/core@7.19.6)(@glimmer/component@1.1.2)(webpack@5.78.0) transitivePeerDependencies: - supports-color dev: true @@ -13027,6 +13030,45 @@ packages: - webpack dev: true + /ember-source@5.0.0(@babel/core@7.19.6)(@glimmer/component@1.1.2)(webpack@5.78.0): + resolution: {integrity: sha512-zy0iU3Mf9HZXVQacqWLAfHCbQge8Ysi2EpU6XTgrdf2PX5ILdWTbSPklxuTlkGV7NrG5PkIfGW8hfimwY6I/tw==} + engines: {node: '>= 16.*'} + peerDependencies: + '@glimmer/component': ^1.1.2 + dependencies: + '@babel/helper-module-imports': 7.21.4 + '@babel/plugin-transform-block-scoping': 7.21.0(@babel/core@7.19.6) + '@ember/edition-utils': 1.2.0 + '@glimmer/component': 1.1.2(@babel/core@7.19.6) + '@glimmer/vm-babel-plugins': 0.84.2(@babel/core@7.19.6) + babel-plugin-debug-macros: 0.3.4(@babel/core@7.19.6) + babel-plugin-filter-imports: 4.0.0 + broccoli-concat: 4.2.5 + broccoli-debug: 0.6.5 + broccoli-file-creator: 2.1.1 + broccoli-funnel: 3.0.8 + broccoli-merge-trees: 4.2.0 + chalk: 4.1.2 + ember-auto-import: 2.6.3(webpack@5.78.0) + ember-cli-babel: 7.26.11 + ember-cli-get-component-path-option: 1.0.0 + ember-cli-is-package-missing: 1.0.0 + ember-cli-normalize-entity-name: 1.0.0 + ember-cli-path-utils: 1.0.0 + ember-cli-string-utils: 1.1.0 + ember-cli-typescript-blueprint-polyfill: 0.1.0 + ember-cli-version-checker: 5.1.2 + ember-router-generator: 2.0.0 + inflection: 1.13.4 + resolve: 1.22.2 + semver: 7.3.8 + silent-error: 1.1.1 + transitivePeerDependencies: + - '@babel/core' + - supports-color + - webpack + dev: true + /ember-source@5.0.0-beta.3(@babel/core@7.19.6)(@glimmer/component@1.1.2)(webpack@5.78.0): resolution: {integrity: sha512-NkPWXt7nYEvoSOzjJJ3JxYPGvvHoZ2ouPHqs1/Jf2ZahXY5SKJW3mTJql1zW5gMcUwNIoFx1cvlfHr3CJ6sQog==} engines: {node: '>= 16.*'} diff --git a/test-packages/release/package.json b/test-packages/release/package.json index 68fffed70..8e1a16326 100644 --- a/test-packages/release/package.json +++ b/test-packages/release/package.json @@ -2,16 +2,17 @@ "name": "@embroider/release", "version": "0.0.0", "private": true, - "scripts": { - "prepare-release": "node ./src/prepare.js" + "bin": { + "embroider-release": "./src/cli.js" }, "dependencies": { "@ef4/lerna-changelog": "^1.0.4", "@types/fs-extra": "^9.0.12", "@types/js-yaml": "^4.0.5", - "@types/yargs": "^17.0.3", "@types/semver": "^7.3.6", + "@types/yargs": "^17.0.3", "assert-never": "^1.2.1", + "chalk": "^4.1.1", "cli-highlight": "^2.1.11", "execa": "^4.0.3", "fs-extra": "^10.0.0", diff --git a/test-packages/release/src/gather-changes.ts b/test-packages/release/src/gather-changes.ts index 6a7dbd5af..06c2d3f34 100644 --- a/test-packages/release/src/gather-changes.ts +++ b/test-packages/release/src/gather-changes.ts @@ -1,6 +1,6 @@ import execa from 'execa'; export async function gatherChanges() { - let result = await execa('pnpm', ['lerna-changelog', '--next-version', 'Release']); + let result = await execa('pnpm', ['lerna-changelog', '--next-version', 'Release'], { cwd: __dirname }); return result.stdout; } diff --git a/test-packages/release/src/interdep.ts b/test-packages/release/src/interdep.ts index f1efc269b..bade2de48 100644 --- a/test-packages/release/src/interdep.ts +++ b/test-packages/release/src/interdep.ts @@ -3,7 +3,8 @@ import { resolve } from 'path'; import { readFileSync, readJSONSync } from 'fs-extra'; import yaml from 'js-yaml'; -export type Range = 'exact' | 'caret'; +export type Range = `workspace:${string}`; + export interface PkgEntry { version: string; pkgJSONPath: string; @@ -11,21 +12,6 @@ export interface PkgEntry { isPeerDependencyOf: Map; } -function workspaceRangeType(range: string): Range | undefined { - if (!range.startsWith('workspace:')) { - return; - } - switch (range.slice(10)) { - case '*': - // this is how pnpm interprets workspace:* - return 'exact'; - case '^': - return 'caret'; - default: - throw new Error(`unsupported workspace dependency type ${range}`); - } -} - export function publishedInterPackageDeps(): Map { let rootDir = resolve(__dirname, '..', '..', '..'); let packages: Map = new Map(); @@ -56,14 +42,13 @@ export function publishedInterPackageDeps(): Map { for (let section of ['dependencies', 'peerDependencies'] as const) { if (consumerPkgJSON[section]) { for (let [depName, depRange] of Object.entries(consumerPkgJSON[section] as Record)) { - let rangeType = workspaceRangeType(depRange); - if (rangeType) { + if (depRange.startsWith('workspace:')) { let dependency = packages.get(depName); if (!dependency) { throw new Error(`broken "workspace:" reference to ${depName} in ${consumerName}`); } let field = section === 'dependencies' ? ('isDependencyOf' as const) : ('isPeerDependencyOf' as const); - dependency[field].set(consumerName, rangeType); + dependency[field].set(consumerName, depRange as Range); } } } diff --git a/test-packages/release/src/plan.ts b/test-packages/release/src/plan.ts index c3b1999e5..c355a92f9 100644 --- a/test-packages/release/src/plan.ts +++ b/test-packages/release/src/plan.ts @@ -1,8 +1,9 @@ import { Impact, ParsedChangelog } from './change-parser'; import { publishedInterPackageDeps } from './interdep'; import assertNever from 'assert-never'; -import { inc } from 'semver'; +import { inc, satisfies } from 'semver'; import { highlightMarkdown } from './highlight'; +import chalk from 'chalk'; export type Solution = Map< string, @@ -65,50 +66,56 @@ class Plan { return solution; } + #expandWorkspaceRange(range: `workspace:${string}`, availableVersion: string): string { + // this implements PNPM's rules for how workspace: protocol dependencies get + // expanded into proper semver ranges. + switch (range) { + case 'workspace:*': + return availableVersion; + case 'workspace:~': + return `~${availableVersion}`; + case 'workspace:^': + return `^${availableVersion}`; + default: + return range.slice(10); + } + } + #propagate(packageName: string, impact: Impact) { let entry = this.#pkgs.get(packageName)!; - for (let [consumerName, rangeType] of entry.isDependencyOf) { - switch (rangeType) { - case 'exact': - this.addConstraint( - consumerName, - 'patch', - `Has an exact dependency on ${packageName}, which is being released` - ); - break; - case 'caret': - if (impact === 'major') { - this.addConstraint( - consumerName, - 'patch', - `Has a caret dependency on ${packageName}, which needs a major release` - ); - } - break; - default: - throw assertNever(rangeType); - } + let minNewVersion = inc(entry.version, impact)!; + for (let [consumerName, workspaceRange] of entry.isDependencyOf) { + this.#propagateDep(packageName, minNewVersion, 'dependencies', consumerName, workspaceRange); + } + for (let [consumerName, workspaceRange] of entry.isPeerDependencyOf) { + this.#propagateDep(packageName, minNewVersion, 'peerDependencies', consumerName, workspaceRange); } - for (let [consumerName, rangeType] of entry.isPeerDependencyOf) { - switch (rangeType) { - case 'exact': + } + + #propagateDep( + packageName: string, + minNewVersion: string, + section: 'dependencies' | 'peerDependencies', + consumerName: string, + workspaceRange: `workspace:${string}` + ) { + let entry = this.#pkgs.get(packageName)!; + + let oldRange = this.#expandWorkspaceRange(workspaceRange, entry.version); + if (!satisfies(minNewVersion, oldRange)) { + switch (section) { + case 'dependencies': + this.addConstraint(consumerName, 'patch', `Has dependency ${'`'}${workspaceRange}${'`'} on ${packageName}`); + break; + case 'peerDependencies': this.addConstraint( consumerName, 'major', - `Has an exact peer dependency on ${packageName}, which is being released` + `Has peer dependency ${'`'}${workspaceRange}${'`'} on ${packageName}` ); break; - case 'caret': - if (impact === 'major') { - this.addConstraint( - consumerName, - 'major', - `Has a caret peer dependency on ${packageName}, which needs a major release` - ); - } - break; default: - throw assertNever(rangeType); + throw assertNever(section); } } } @@ -126,21 +133,58 @@ class Plan { } } +function impactLabel(impact: Impact | undefined, text?: string) { + switch (impact) { + case undefined: + return chalk.gray(text); + case 'patch': + return chalk.blueBright(text); + case 'minor': + return chalk.greenBright(text); + case 'major': + return chalk.redBright(text); + } +} + +function capitalize(s: string): string { + return s[0].toUpperCase() + s.slice(1); +} + export function explain(solution: Solution) { let output: string[] = []; - for (let [pkgName, entry] of solution) { - if (!entry.impact) { - output.push(`## ${pkgName} ${entry.oldVersion} does not need to be released.`); - } else { - output.push(`## ${pkgName} needs a ${entry.impact} release from ${entry.oldVersion} to ${entry.newVersion}`); - for (let constraint of entry.constraints) { - if (constraint.impact === entry.impact) { - output.push(` - ${constraint.reason}`); + + for (let priority of ['major', 'minor', 'patch'] as const) { + if ([...solution].some(entry => entry[1].impact === priority)) { + output.push(impactLabel(priority, capitalize(priority))); + output.push(''); + + for (let [pkgName, entry] of solution) { + if (entry.impact === priority) { + output.push(` ${impactLabel(entry.impact, pkgName)} from ${entry.oldVersion} to ${entry.newVersion}`); + for (let constraint of entry.constraints) { + if (constraint.impact === entry.impact) { + output.push(` - ${constraint.reason}`); + } + } } } + output.push(''); + } + } + + if ([...solution].some(entry => entry[1].impact === undefined)) { + output.push(impactLabel(undefined, 'Unreleased')); + output.push(''); + for (let [pkgName, entry] of solution) { + if (entry.impact === undefined) { + output.push(`## ${pkgName}`); + output.push(` ${impactLabel(entry.impact, pkgName)} unchanged`); + } } + output.push(''); } - return highlightMarkdown(output.join('\n')); + + return output.join('\n'); } export function planVersionBumps(changed: ParsedChangelog): Solution { From 374d8973c199dc597b060896f030c8f9d683ec4f Mon Sep 17 00:00:00 2001 From: Edward Faulkner Date: Tue, 16 May 2023 00:47:26 -0400 Subject: [PATCH 09/16] expanding router peerdep in anticipation of release --- packages/router/package.json | 2 +- pnpm-lock.yaml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/router/package.json b/packages/router/package.json index fe13ff88a..d517f70d5 100644 --- a/packages/router/package.json +++ b/packages/router/package.json @@ -59,7 +59,7 @@ "typescript": "^4.9.0" }, "peerDependencies": { - "@embroider/core": "workspace:^" + "@embroider/core": "workspace:^2.0.0||^3.0.0" }, "peerDependenciesMeta": { "@embroider/core": { diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index db774a207..5e027cf55 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -581,7 +581,7 @@ importers: specifier: workspace:^ version: link:../addon-shim '@embroider/core': - specifier: workspace:2.x||3.x + specifier: workspace:^2.0.0||^3.0.0 version: link:../core devDependencies: '@babel/core': From a109a16132e523cc3b348d569e28effac73041b1 Mon Sep 17 00:00:00 2001 From: Edward Faulkner Date: Tue, 16 May 2023 01:02:06 -0400 Subject: [PATCH 10/16] some docs --- RELEASE.md | 31 ++++++++++++++----------------- 1 file changed, 14 insertions(+), 17 deletions(-) diff --git a/RELEASE.md b/RELEASE.md index 84d38abe7..4287d5c88 100644 --- a/RELEASE.md +++ b/RELEASE.md @@ -1,25 +1,22 @@ # Release Process -Release process is currently switching from release-it to https://github.com/changesets/changesets +1. You need a github token as `GITHUB_AUTH` environment variable. -## Notes +2. Run `pnpm embroider-release explain-plan`. If there are unlabeled PRs that need to be released it will complain and show you a list of them. Each PR needs to be labeled with one of: + - breaking + - enhancement + - bug + - documentation + - internal -Used `changesets` to do release-2022-10-6.0. Didn't go smoothly. +3. Once all the PRs are labeled, it will instead show you the release plain, explaining which packages are getting released, at which versions, and why. -1. Generated a changeset file describing everything since last release. +4. If you disagree with the plan, you can modify the list of changes before using it to `explain-plan` or `prepare` a release: - Scan for which packages were touched so nothing gets missed: + - `pnpm embroider-release gather-changes > /tmp/changelog` + - edit `/tmp/changelog` + - `pnpm embroider-release explain-plan --from-stdin < /tmp/changelog` - git diff --stat v1.8.3..HEAD + For example, this can be necessary if a PR that's labeled `breaking` touches multiple packages and only one of those packages is actually a breaking change. In that case you can take the other package names out of the description of the PR. - Find all PRs since previous release to summarize them - - git log v1.8.3..HEAD - - And search for "Merge pull" - -2. Used `changeset version`, manually moved all readme content from changeset into our top-level readme (because the defaults in `changesets` want to create per-package ones). - -3. Tried using `changeset publish` but that started publishing lots of unintended packages. Followed up by manually releasing the others. - -4. Noticed that `changeset version` bumped a dependency version in `@embroider/util` but didn't bump `@embroider/util`'s version. Had to update and release it manually. + \ No newline at end of file From f9ce923c967a2f464c24c90b0884c280c2a07f35 Mon Sep 17 00:00:00 2001 From: Edward Faulkner Date: Wed, 17 May 2023 15:32:44 -0400 Subject: [PATCH 11/16] working on publish step --- test-packages/release/src/cli.ts | 10 ++++++++++ test-packages/release/src/plan.ts | 8 ++++++++ test-packages/release/src/prepare.ts | 3 ++- test-packages/release/src/publish.ts | 15 +++++++++++++++ 4 files changed, 35 insertions(+), 1 deletion(-) create mode 100644 test-packages/release/src/publish.ts diff --git a/test-packages/release/src/cli.ts b/test-packages/release/src/cli.ts index a9055aa7c..c0c959d45 100644 --- a/test-packages/release/src/cli.ts +++ b/test-packages/release/src/cli.ts @@ -3,6 +3,7 @@ import type { Argv } from 'yargs'; import { readFileSync } from 'fs'; import { parseChangeLogOrExit } from './change-parser'; +import { publish } from './publish'; yargs(process.argv.slice(2)) .usage( @@ -21,6 +22,15 @@ yargs(process.argv.slice(2)) process.stdout.write(`\nSuccessfully prepared released\n`); } ) + .command( + 'publish', + `Publishes an already-prepared released by tagging, pushing tags, creating GitHub release, and publishing to NPM.`, + yargs => yargs, + async function () { + await publish(); + process.stdout.write(`\nSuccessfully published released\n`); + } + ) .command( 'gather-changes', `Uses lerna-changelog to build a description of all the PRs in the release.`, diff --git a/test-packages/release/src/plan.ts b/test-packages/release/src/plan.ts index c355a92f9..af745ff90 100644 --- a/test-packages/release/src/plan.ts +++ b/test-packages/release/src/plan.ts @@ -206,3 +206,11 @@ export function planVersionBumps(changed: ParsedChangelog): Solution { return plan.solve(); } + +export function serializeSolution(solution: Solution): string { + return JSON.stringify(Object.fromEntries(solution), null, 2); +} + +export function loadSolution(serialized: string): Solution { + return new Map(Object.entries(JSON.parse(serialized))); +} diff --git a/test-packages/release/src/prepare.ts b/test-packages/release/src/prepare.ts index 31b8e00cb..f96e6ffa9 100644 --- a/test-packages/release/src/prepare.ts +++ b/test-packages/release/src/prepare.ts @@ -1,7 +1,7 @@ import { parseChangeLogOrExit } from './change-parser'; import { readFileSync, writeFileSync } from 'fs'; import { resolve } from 'path'; -import { planVersionBumps, Solution } from './plan'; +import { planVersionBumps, serializeSolution, Solution } from './plan'; import { readJSONSync, writeJSONSync } from 'fs-extra'; const changelogPreamble = `# Embroider Changelog @@ -56,5 +56,6 @@ export async function prepare(newChangelogContent: string) { let solution = planVersionBumps(changes); updateVersions(solution); updateChangelog(newChangelogContent, solution); + writeFileSync(resolve(__dirname, '..', '..', '..', '.release-plan.json'), serializeSolution(solution)); return solution; } diff --git a/test-packages/release/src/publish.ts b/test-packages/release/src/publish.ts new file mode 100644 index 000000000..ae0adcf9e --- /dev/null +++ b/test-packages/release/src/publish.ts @@ -0,0 +1,15 @@ +import execa from 'execa'; + +async function hasCleanRepo(): Promise { + let result = await execa('git', ['status', '--porcelain=v1'], { cwd: __dirname }); + return result.stdout.length === 0; +} + +export async function publish() { + if (!(await hasCleanRepo())) { + process.stderr.write(`You have uncommitted changes. +To publish a release you should start from a clean repo. Run "embroider-release prepare", then commit the changes, then come back and run "embroider-release publish. +`); + process.exit(-1); + } +} From 1f9717f2d2b8626d988300ecdd58676ad0c22a4d Mon Sep 17 00:00:00 2001 From: Edward Faulkner Date: Wed, 17 May 2023 16:27:12 -0400 Subject: [PATCH 12/16] more progress on publish --- pnpm-lock.yaml | 132 ++++++++++++++++++++++++++- test-packages/release/package.json | 1 + test-packages/release/src/cli.ts | 12 ++- test-packages/release/src/plan.ts | 33 ++++++- test-packages/release/src/prepare.ts | 24 ++--- test-packages/release/src/publish.ts | 74 ++++++++++++++- 6 files changed, 248 insertions(+), 28 deletions(-) diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 364dfa98d..c2543b260 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -993,6 +993,9 @@ importers: '@ef4/lerna-changelog': specifier: ^1.0.4 version: 1.0.4 + '@octokit/rest': + specifier: ^19.0.8 + version: 19.0.8 '@types/fs-extra': specifier: ^9.0.12 version: 9.0.12 @@ -4993,6 +4996,122 @@ packages: '@nodelib/fs.scandir': 2.1.5 fastq: 1.15.0 + /@octokit/auth-token@3.0.3: + resolution: {integrity: sha512-/aFM2M4HVDBT/jjDBa84sJniv1t9Gm/rLkalaz9htOm+L+8JMj1k9w0CkUdcxNyNxZPlTxKPVko+m1VlM58ZVA==} + engines: {node: '>= 14'} + dependencies: + '@octokit/types': 9.2.2 + dev: false + + /@octokit/core@4.2.0: + resolution: {integrity: sha512-AgvDRUg3COpR82P7PBdGZF/NNqGmtMq2NiPqeSsDIeCfYFOZ9gddqWNQHnFdEUf+YwOj4aZYmJnlPp7OXmDIDg==} + engines: {node: '>= 14'} + dependencies: + '@octokit/auth-token': 3.0.3 + '@octokit/graphql': 5.0.5 + '@octokit/request': 6.2.4 + '@octokit/request-error': 3.0.3 + '@octokit/types': 9.2.2 + before-after-hook: 2.2.3 + universal-user-agent: 6.0.0 + transitivePeerDependencies: + - encoding + dev: false + + /@octokit/endpoint@7.0.5: + resolution: {integrity: sha512-LG4o4HMY1Xoaec87IqQ41TQ+glvIeTKqfjkCEmt5AIwDZJwQeVZFIEYXrYY6yLwK+pAScb9Gj4q+Nz2qSw1roA==} + engines: {node: '>= 14'} + dependencies: + '@octokit/types': 9.2.2 + is-plain-object: 5.0.0 + universal-user-agent: 6.0.0 + dev: false + + /@octokit/graphql@5.0.5: + resolution: {integrity: sha512-Qwfvh3xdqKtIznjX9lz2D458r7dJPP8l6r4GQkIdWQouZwHQK0mVT88uwiU2bdTU2OtT1uOlKpRciUWldpG0yQ==} + engines: {node: '>= 14'} + dependencies: + '@octokit/request': 6.2.4 + '@octokit/types': 9.2.2 + universal-user-agent: 6.0.0 + transitivePeerDependencies: + - encoding + dev: false + + /@octokit/openapi-types@17.2.0: + resolution: {integrity: sha512-MazrFNx4plbLsGl+LFesMo96eIXkFgEtaKbnNpdh4aQ0VM10aoylFsTYP1AEjkeoRNZiiPe3T6Gl2Hr8dJWdlQ==} + dev: false + + /@octokit/plugin-paginate-rest@6.1.0(@octokit/core@4.2.0): + resolution: {integrity: sha512-5T4iXjJdYCVA1rdWS1C+uZV9AvtZY9QgTG74kFiSFVj94dZXowyi/YK8f4SGjZaL69jZthGlBaDKRdCMCF9log==} + engines: {node: '>= 14'} + peerDependencies: + '@octokit/core': '>=4' + dependencies: + '@octokit/core': 4.2.0 + '@octokit/types': 9.2.2 + dev: false + + /@octokit/plugin-request-log@1.0.4(@octokit/core@4.2.0): + resolution: {integrity: sha512-mLUsMkgP7K/cnFEw07kWqXGF5LKrOkD+lhCrKvPHXWDywAwuDUeDwWBpc69XK3pNX0uKiVt8g5z96PJ6z9xCFA==} + peerDependencies: + '@octokit/core': '>=3' + dependencies: + '@octokit/core': 4.2.0 + dev: false + + /@octokit/plugin-rest-endpoint-methods@7.1.0(@octokit/core@4.2.0): + resolution: {integrity: sha512-SWwz/hc47GaKJR6BlJI4WIVRodbAFRvrR0QRPSoPMs7krb7anYPML3psg+ThEz/kcwOdSNh/oA8qThi/Wvs4Fw==} + engines: {node: '>= 14'} + peerDependencies: + '@octokit/core': '>=3' + dependencies: + '@octokit/core': 4.2.0 + '@octokit/types': 9.2.2 + deprecation: 2.3.1 + dev: false + + /@octokit/request-error@3.0.3: + resolution: {integrity: sha512-crqw3V5Iy2uOU5Np+8M/YexTlT8zxCfI+qu+LxUB7SZpje4Qmx3mub5DfEKSO8Ylyk0aogi6TYdf6kxzh2BguQ==} + engines: {node: '>= 14'} + dependencies: + '@octokit/types': 9.2.2 + deprecation: 2.3.1 + once: 1.4.0 + dev: false + + /@octokit/request@6.2.4: + resolution: {integrity: sha512-at92SYQstwh7HH6+Kf3bFMnHrle7aIrC0r5rTP+Bb30118B6j1vI2/M4walh6qcQgfuLIKs8NUO5CytHTnUI3A==} + engines: {node: '>= 14'} + dependencies: + '@octokit/endpoint': 7.0.5 + '@octokit/request-error': 3.0.3 + '@octokit/types': 9.2.2 + is-plain-object: 5.0.0 + node-fetch: 2.6.11 + universal-user-agent: 6.0.0 + transitivePeerDependencies: + - encoding + dev: false + + /@octokit/rest@19.0.8: + resolution: {integrity: sha512-/PKrzqn+zDzXKwBMwLI2IKrvk8yv8cedJOdcmxrjR3gmu6UIzURhP5oQj+4qkn7+uQi1gg7QqV4SqlaQ1HYW1Q==} + engines: {node: '>= 14'} + dependencies: + '@octokit/core': 4.2.0 + '@octokit/plugin-paginate-rest': 6.1.0(@octokit/core@4.2.0) + '@octokit/plugin-request-log': 1.0.4(@octokit/core@4.2.0) + '@octokit/plugin-rest-endpoint-methods': 7.1.0(@octokit/core@4.2.0) + transitivePeerDependencies: + - encoding + dev: false + + /@octokit/types@9.2.2: + resolution: {integrity: sha512-9BjDxjgQIvCjNWZsbqyH5QC2Yni16oaE6xL+8SUBMzcYPF4TGQBXGA97Cl3KceK9mwiNMb1mOYCz6FbCCLEL+g==} + dependencies: + '@octokit/openapi-types': 17.2.0 + dev: false + /@popperjs/core@2.11.7: resolution: {integrity: sha512-Cr4OjIkipTtcXKjAsm8agyleBuDHvxzeBoa1v543lbv1YaIwQjESsVcmjiWiPEbC1FIeHOG/Op9kdCmAmiS3Kw==} dev: true @@ -7102,6 +7221,10 @@ packages: dependencies: safe-buffer: 5.1.2 + /before-after-hook@2.2.3: + resolution: {integrity: sha512-NzUnlZexiaH/46WDhANlyR2bXRopNg4F/zuSA3OpZnllCUgRaOF2znDioDWrmbNVsuZk6l9pMquQB38cfBZwkQ==} + dev: false + /big.js@5.2.2: resolution: {integrity: sha512-vyL2OymJxmarO8gxMr0mhChsO9QGwhynfuu4+MHTAW6czfq9humCB7rKpUjDd9YUiDPU4mzpyupFSvOClAwbmQ==} @@ -9252,6 +9375,10 @@ packages: resolution: {integrity: sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==} engines: {node: '>= 0.8'} + /deprecation@2.3.1: + resolution: {integrity: sha512-xmHIy4F3scKVwMsQ4WnVaS8bHOx0DmVwRywosKhaILI0ywMDWPtBSku2HNxRvF7jtwDRsoEwYQSfbxj8b7RlJQ==} + dev: false + /destroy@1.2.0: resolution: {integrity: sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==} engines: {node: '>= 0.8', npm: 1.2.8000 || >= 1.4.16} @@ -14669,7 +14796,6 @@ packages: /is-plain-object@5.0.0: resolution: {integrity: sha512-VRSzKkbMm5jMDoKLbltAkFQ5Qr7VDiTFGXxYFXXowVj387GeGNOCsOH6Msy00SGZ3Fp84b1Naa1psqgcCIEP5Q==} engines: {node: '>=0.10.0'} - dev: true /is-potential-custom-element-name@1.0.1: resolution: {integrity: sha512-bCYeRA2rVibKZd+s2625gGnGF/t7DSqDs4dP7CrLA1m7jKWz6pps0LpYLJN8Q64HtmPKJ1hrN3nzPNKFEKOUiQ==} @@ -19794,6 +19920,10 @@ packages: dependencies: crypto-random-string: 2.0.0 + /universal-user-agent@6.0.0: + resolution: {integrity: sha512-isyNax3wXoKaulPDZWHQqbmIx1k2tb9fb3GGDBRxCscfYV2Ch7WxPArBsFEG8s/safwXTT7H4QGhaIkTp9447w==} + dev: false + /universalify@0.1.2: resolution: {integrity: sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==} engines: {node: '>= 4.0.0'} diff --git a/test-packages/release/package.json b/test-packages/release/package.json index 8e1a16326..de36c8805 100644 --- a/test-packages/release/package.json +++ b/test-packages/release/package.json @@ -7,6 +7,7 @@ }, "dependencies": { "@ef4/lerna-changelog": "^1.0.4", + "@octokit/rest": "^19.0.8", "@types/fs-extra": "^9.0.12", "@types/js-yaml": "^4.0.5", "@types/semver": "^7.3.6", diff --git a/test-packages/release/src/cli.ts b/test-packages/release/src/cli.ts index c0c959d45..433dd35bd 100644 --- a/test-packages/release/src/cli.ts +++ b/test-packages/release/src/cli.ts @@ -25,10 +25,14 @@ yargs(process.argv.slice(2)) .command( 'publish', `Publishes an already-prepared released by tagging, pushing tags, creating GitHub release, and publishing to NPM.`, - yargs => yargs, - async function () { - await publish(); - process.stdout.write(`\nSuccessfully published released\n`); + yargs => + yargs.option('skipRepoSafetyCheck', { + type: 'boolean', + description: + 'Allows you to run "publish" even if there are uncommited changes in your repo. Useful only for developing "publish" itself.', + }), + async function (opts) { + await publish(opts); } ) .command( diff --git a/test-packages/release/src/plan.ts b/test-packages/release/src/plan.ts index af745ff90..7d10ee9db 100644 --- a/test-packages/release/src/plan.ts +++ b/test-packages/release/src/plan.ts @@ -4,6 +4,8 @@ import assertNever from 'assert-never'; import { inc, satisfies } from 'semver'; import { highlightMarkdown } from './highlight'; import chalk from 'chalk'; +import { resolve } from 'path'; +import { existsSync, readJSONSync, writeJSONSync } from 'fs-extra'; export type Solution = Map< string, @@ -207,10 +209,33 @@ export function planVersionBumps(changed: ParsedChangelog): Solution { return plan.solve(); } -export function serializeSolution(solution: Solution): string { - return JSON.stringify(Object.fromEntries(solution), null, 2); +function solutionFile(): string { + return resolve(__dirname, '..', '..', '..', '.release-plan.json'); } -export function loadSolution(serialized: string): Solution { - return new Map(Object.entries(JSON.parse(serialized))); +export function saveSolution(solution: Solution, description: string): void { + writeJSONSync(solutionFile(), { solution: Object.fromEntries(solution), description }, { spaces: 2 }); +} + +export function loadSolution(): { solution: Solution; description: string } { + try { + if (!existsSync(solutionFile())) { + let err = new Error(`No such file ${solutionFile()}`); + (err as any).code = 'ENOENT'; + throw err; + } + let json = readJSONSync(solutionFile()); + return { + solution: new Map(Object.entries(json.solution)), + description: json.description, + }; + } catch (err) { + process.stderr.write( + `Unable to load release plan file. You must run "embroider-release prepare" first to create the file.\n` + ); + if (err.code !== 'ENOENT') { + console.error(err); + } + process.exit(-1); + } } diff --git a/test-packages/release/src/prepare.ts b/test-packages/release/src/prepare.ts index f96e6ffa9..3b883132d 100644 --- a/test-packages/release/src/prepare.ts +++ b/test-packages/release/src/prepare.ts @@ -1,13 +1,13 @@ import { parseChangeLogOrExit } from './change-parser'; import { readFileSync, writeFileSync } from 'fs'; import { resolve } from 'path'; -import { planVersionBumps, serializeSolution, Solution } from './plan'; +import { planVersionBumps, saveSolution, Solution } from './plan'; import { readJSONSync, writeJSONSync } from 'fs-extra'; const changelogPreamble = `# Embroider Changelog `; -function updateChangelog(newChangelogContent: string, solution: Solution) { +function updateChangelog(newChangelogContent: string, solution: Solution): string { let targetChangelogFile = resolve(__dirname, '..', '..', '..', 'CHANGELOG.md'); let oldChangelogContent = readFileSync(targetChangelogFile, 'utf8'); if (!oldChangelogContent.startsWith(changelogPreamble)) { @@ -18,17 +18,9 @@ function updateChangelog(newChangelogContent: string, solution: Solution) { let [firstNewLine, ...restNewLines] = newChangelogContent.trim().split('\n'); - writeFileSync( - targetChangelogFile, - changelogPreamble + - firstNewLine + - '\n\n' + - versionSummary(solution) + - '\n' + - restNewLines.join('\n') + - '\n' + - oldChangelogContent - ); + let newOutput = firstNewLine + '\n\n' + versionSummary(solution) + '\n' + restNewLines.join('\n') + '\n'; + writeFileSync(targetChangelogFile, changelogPreamble + newOutput + oldChangelogContent); + return newOutput; } function versionSummary(solution: Solution): string { @@ -53,9 +45,9 @@ function updateVersions(solution: Solution) { export async function prepare(newChangelogContent: string) { let changes = parseChangeLogOrExit(newChangelogContent); - let solution = planVersionBumps(changes); + let solution = planVersionBumps(changes, newChangelogContent); updateVersions(solution); - updateChangelog(newChangelogContent, solution); - writeFileSync(resolve(__dirname, '..', '..', '..', '.release-plan.json'), serializeSolution(solution)); + let description = updateChangelog(newChangelogContent, solution); + saveSolution(solution, description); return solution; } diff --git a/test-packages/release/src/publish.ts b/test-packages/release/src/publish.ts index ae0adcf9e..0901f9d9b 100644 --- a/test-packages/release/src/publish.ts +++ b/test-packages/release/src/publish.ts @@ -1,15 +1,83 @@ import execa from 'execa'; +import { loadSolution, Solution } from './plan'; +import { dirname } from 'path'; +import { Octokit } from '@octokit/rest'; async function hasCleanRepo(): Promise { let result = await execa('git', ['status', '--porcelain=v1'], { cwd: __dirname }); return result.stdout.length === 0; } -export async function publish() { - if (!(await hasCleanRepo())) { - process.stderr.write(`You have uncommitted changes. +function tagFor(pkgName: string, entry: { newVersion: string }): string { + return `v${entry.newVersion}-${pkgName.replace(/^@embroider\//, '')}`; +} + +class IssueReporter { + hadIssues = false; + reportFailure(message: string): void { + this.hadIssues = true; + process.stderr.write(message); + } +} + +async function makeTags(solution: Solution, reporter: IssueReporter): Promise { + for (let [pkgName, entry] of solution) { + if (!entry.impact) { + continue; + } + try { + await execa('git', ['tag', tagFor(pkgName, entry)], { + cwd: dirname(entry.pkgJSONPath), + stderr: 'inherit', + stdout: 'inherit', + }); + } catch (err) { + reporter.reportFailure(`Failed to create tag for ${pkgName}`); + } + } +} + +async function push(reporter: IssueReporter) { + try { + await execa('git', ['push', '--tags'], { cwd: __dirname }); + } catch (err) { + reporter.reportFailure(`Failed to git push`); + } +} + +async function createGithubRelease(octokit: Octokit, description: string): Promise {} + +export async function publish(opts: { skipRepoSafetyCheck?: boolean }) { + if (!opts.skipRepoSafetyCheck) { + if (!(await hasCleanRepo())) { + process.stderr.write(`You have uncommitted changes. To publish a release you should start from a clean repo. Run "embroider-release prepare", then commit the changes, then come back and run "embroider-release publish. `); + process.exit(-1); + } + } + + let { solution, description } = loadSolution(); + + if (!process.env.GITHUB_AUTH) { + process.stderr.write(`You need to set GITHUB_AUTH.`); + process.exit(-1); + } + let octokit = new Octokit({ auth: process.env.GITHUB_AUTH }); + + // from this point forward we don't stop if something goes wrong, we just keep + // track of whether anything went wrong so we can use the right exit code at + // the end. + let reporter = new IssueReporter(); + + //await makeTags(solution, reporter); + //await push(reporter); + await createGithubRelease(octokit, description); + + if (reporter.hadIssues) { + process.stderr.write(`\nSome parts of the release were unsuccessful.\n`); process.exit(-1); + } else { + process.stdout.write(`\nSuccessfully published release\n`); } } From 8a1bf5a71f00066e97b0f6b4416501e9b4c6521d Mon Sep 17 00:00:00 2001 From: Edward Faulkner Date: Wed, 17 May 2023 16:40:43 -0400 Subject: [PATCH 13/16] ready to publish --- test-packages/release/src/prepare.ts | 4 +- test-packages/release/src/publish.ts | 55 ++++++++++++++++++++++++++-- 2 files changed, 53 insertions(+), 6 deletions(-) diff --git a/test-packages/release/src/prepare.ts b/test-packages/release/src/prepare.ts index 3b883132d..6b4659054 100644 --- a/test-packages/release/src/prepare.ts +++ b/test-packages/release/src/prepare.ts @@ -19,7 +19,7 @@ function updateChangelog(newChangelogContent: string, solution: Solution): strin let [firstNewLine, ...restNewLines] = newChangelogContent.trim().split('\n'); let newOutput = firstNewLine + '\n\n' + versionSummary(solution) + '\n' + restNewLines.join('\n') + '\n'; - writeFileSync(targetChangelogFile, changelogPreamble + newOutput + oldChangelogContent); + writeFileSync(targetChangelogFile, changelogPreamble + '\n' + newOutput + oldChangelogContent); return newOutput; } @@ -45,7 +45,7 @@ function updateVersions(solution: Solution) { export async function prepare(newChangelogContent: string) { let changes = parseChangeLogOrExit(newChangelogContent); - let solution = planVersionBumps(changes, newChangelogContent); + let solution = planVersionBumps(changes); updateVersions(solution); let description = updateChangelog(newChangelogContent, solution); saveSolution(solution, description); diff --git a/test-packages/release/src/publish.ts b/test-packages/release/src/publish.ts index 0901f9d9b..14d7a2f8d 100644 --- a/test-packages/release/src/publish.ts +++ b/test-packages/release/src/publish.ts @@ -45,7 +45,51 @@ async function push(reporter: IssueReporter) { } } -async function createGithubRelease(octokit: Octokit, description: string): Promise {} +function chooseRepresentativeTag(solution: Solution): string { + for (let [pkgName, entry] of solution) { + if (entry.impact) { + return tagFor(pkgName, entry); + } + } + process.stderr.write('Found no releaseable packages in the plan'); + process.exit(-1); +} + +async function createGithubRelease( + octokit: Octokit, + description: string, + tagName: string, + reporter: IssueReporter +): Promise { + try { + await octokit.repos.createRelease({ + owner: 'embroider-build', + repo: 'embroider', + tag_name: tagName, + body: description, + }); + } catch (err) { + console.error(err); + reporter.reportFailure(`Problem while creating GitHub release`); + } +} + +async function pnpmPublish(solution: Solution, reporter: IssueReporter): Promise { + for (let [pkgName, entry] of solution) { + if (!entry.impact) { + continue; + } + try { + await execa('pnpm', ['publish', '--access=public'], { + cwd: dirname(entry.pkgJSONPath), + stderr: 'inherit', + stdout: 'inherit', + }); + } catch (err) { + reporter.reportFailure(`Failed to pnpm publish ${pkgName}`); + } + } +} export async function publish(opts: { skipRepoSafetyCheck?: boolean }) { if (!opts.skipRepoSafetyCheck) { @@ -65,14 +109,17 @@ To publish a release you should start from a clean repo. Run "embroider-release } let octokit = new Octokit({ auth: process.env.GITHUB_AUTH }); + let representativeTag = chooseRepresentativeTag(solution); + // from this point forward we don't stop if something goes wrong, we just keep // track of whether anything went wrong so we can use the right exit code at // the end. let reporter = new IssueReporter(); - //await makeTags(solution, reporter); - //await push(reporter); - await createGithubRelease(octokit, description); + await makeTags(solution, reporter); + await push(reporter); + await createGithubRelease(octokit, description, representativeTag, reporter); + await pnpmPublish(solution, reporter); if (reporter.hadIssues) { process.stderr.write(`\nSome parts of the release were unsuccessful.\n`); From df19648b1c08576e1c386d29dc9f093b9f7d7511 Mon Sep 17 00:00:00 2001 From: Edward Faulkner Date: Wed, 17 May 2023 16:46:50 -0400 Subject: [PATCH 14/16] Updating release docs --- RELEASE.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/RELEASE.md b/RELEASE.md index 4287d5c88..8ad446b24 100644 --- a/RELEASE.md +++ b/RELEASE.md @@ -19,4 +19,8 @@ For example, this can be necessary if a PR that's labeled `breaking` touches multiple packages and only one of those packages is actually a breaking change. In that case you can take the other package names out of the description of the PR. +5. Once you're happy with the plan, run `pnpm embroider-release prepare`. This will edit CHANGELOG.md, bump the version numbers in package.json files, and create a file named `.release-plan.json`. Make a PR with these changes. + +6. Once the PR is merged, in a clean local repo at the merge commit, run `pnpm embroider-release publish`. + \ No newline at end of file From ffcfbd1ac4ec33725e4f252f5ec91f1abd2848ce Mon Sep 17 00:00:00 2001 From: Edward Faulkner Date: Wed, 17 May 2023 16:54:26 -0400 Subject: [PATCH 15/16] prettierignore for the new package --- .prettierignore | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.prettierignore b/.prettierignore index 66b4f8041..3d79d5604 100644 --- a/.prettierignore +++ b/.prettierignore @@ -23,6 +23,8 @@ /packages/hbs-loader/**/*.d.ts /test-packages/support/**/*.js /test-packages/**/*.d.ts +/test-packages/release/src/*.js +/test-packages/release/src/*.d.ts /tests/scenarios/**/*.js /tests/scenarios/**/*.d.ts /packages/test-setup/**/*.js From 9ba62bad3f4256352cd9dad9465f7f9a0877e499 Mon Sep 17 00:00:00 2001 From: Edward Faulkner Date: Wed, 17 May 2023 16:58:52 -0400 Subject: [PATCH 16/16] and eslintignore the new package --- .eslintignore | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.eslintignore b/.eslintignore index 618e92150..e0f1fdcdb 100644 --- a/.eslintignore +++ b/.eslintignore @@ -14,6 +14,8 @@ /packages/hbs-loader/**/*.d.ts /test-packages/support/**/*.js /test-packages/**/*.d.ts +/test-packages/release/src/*.js +/test-packages/release/src/*.d.ts /tests/scenarios/**/*.js /tests/scenarios/**/*.d.ts /packages/test-setup/**/*.js