From 372a0a1ca82a0938e2bed7f0254eeb35b0c5231e Mon Sep 17 00:00:00 2001 From: Matt Carroll Date: Fri, 17 Jan 2025 14:29:51 +1100 Subject: [PATCH 1/8] ON-46204 # Added changelog automation from a changelog-entries directory --- README.md | 83 ++ changelog-entries/.keep | 0 changelog-entries/changelog-automation.md | 3 + package-lock.json | 789 +++++++++++++++++- package.json | 2 + src/bin.ts | 19 +- src/changelog/addNextReleaseToChangelog.ts | 102 +++ src/changelog/generateCodeChangelogEntries.ts | 80 ++ .../generateDependenciesChangelogEntry.ts | 83 ++ .../parseChangelogWithLoading.ts | 2 +- src/commands/startChangelogPreview.ts | 46 + src/{ => commands}/startProductRelease.ts | 10 +- src/commands/startRepositoryRelease.ts | 70 ++ src/{ => commands}/startUpdateDependents.ts | 6 +- src/repositories-plugins/NpmPlugin.ts | 2 +- src/repositories-plugins/NugetPlugin.ts | 2 +- .../enumerateProductRepositories.ts | 2 +- .../prepareCloneRepository.ts | 4 +- src/startRepositoryRelease.ts | 214 ----- src/{ => terminal}/executeCommand.ts | 0 src/{ => terminal}/promptForNextVersion.ts | 4 +- src/{ => terminal}/promptForReleaseName.ts | 0 src/{ => terminal}/wrapWithLoading.ts | 0 src/{ => utils}/getPreRelease.ts | 0 24 files changed, 1261 insertions(+), 262 deletions(-) create mode 100644 changelog-entries/.keep create mode 100644 changelog-entries/changelog-automation.md create mode 100644 src/changelog/addNextReleaseToChangelog.ts create mode 100644 src/changelog/generateCodeChangelogEntries.ts create mode 100644 src/changelog/generateDependenciesChangelogEntry.ts rename src/{ => changelog}/parseChangelogWithLoading.ts (90%) create mode 100644 src/commands/startChangelogPreview.ts rename src/{ => commands}/startProductRelease.ts (90%) create mode 100644 src/commands/startRepositoryRelease.ts rename src/{ => commands}/startUpdateDependents.ts (95%) rename src/{ => repositories}/enumerateProductRepositories.ts (97%) rename src/{ => repositories}/prepareCloneRepository.ts (92%) delete mode 100644 src/startRepositoryRelease.ts rename src/{ => terminal}/executeCommand.ts (100%) rename src/{ => terminal}/promptForNextVersion.ts (91%) rename src/{ => terminal}/promptForReleaseName.ts (100%) rename src/{ => terminal}/wrapWithLoading.ts (100%) rename src/{ => utils}/getPreRelease.ts (100%) diff --git a/README.md b/README.md index f434ee1..657787e 100644 --- a/README.md +++ b/README.md @@ -29,3 +29,86 @@ Run the following command for usage information ```sh oneblink-release --help ``` + +## Changelog Automation + +To avoid constant merge conflicts with the `CHANGELOG.md` file. The Release CLI can automate changelog entries by allow developers to create a single file for each change entry (or a as many entries as the developer would like to add in that single file). Start by creating a directory called: `changelog-entries` in the root of the repository and add a `.keep` file to the directory, like so: + +``` +|- changelog-entries/ + |- .keep +|- src/ + |- index.js +|- .gitignore +|- package.json +|- README.md +``` + +The `.keep` file will simply prevent the directory from being removed from source control after each release. + +Each time a developer wants to add an entry to a the changelog as part of the current release, create a file in the `changelog-entries` directory. The file must adhere to the [keepachangelog](https://keepachangelog.com/) format. + +Files can have as many entries as desired, however it is recommend to keep entries small to avoid merge conflicts with other developers. + +**All of the entry files will be removed as part of the release.** + +### Example Changelog Entry Files + +The following two files: + +- `kitchen-sink.md` + + ````md + ### Changed + + - the supported NodeJS version + - the name of a function. See the change below to migrate to the new function: + ```diff + -thisIsTheOldFunction() + +thisIsTheNewFunction() + ``` + + ### Removed + + - something that was not being used anymore + + ### Added + + - a new feature + + ### Fixed + + - a bug + ```` + +- `my-additions.md` + + ```md + ### Added + + - a really simple feature + ``` + +Would result in the following change entry: + +### Changed + +- the supported NodeJS version +- the name of a function. See the change below to migrate to the new function: + ```diff + -thisIsTheOldFunction() + +thisIsTheNewFunction() + ``` + +### Removed + +- something that was not being used anymore + +### Added + +- a new feature +- a really simple feature + +### Fixed + +- a bug diff --git a/changelog-entries/.keep b/changelog-entries/.keep new file mode 100644 index 0000000..e69de29 diff --git a/changelog-entries/changelog-automation.md b/changelog-entries/changelog-automation.md new file mode 100644 index 0000000..6f7fdf5 --- /dev/null +++ b/changelog-entries/changelog-automation.md @@ -0,0 +1,3 @@ +### Added + +- changelog automation from a `changelog-entries` directory diff --git a/package-lock.json b/package-lock.json index e3128d5..12630f1 100644 --- a/package-lock.json +++ b/package-lock.json @@ -21,6 +21,8 @@ "enquirer": "^2.4.1", "execa": "^8.0.1", "github-url-from-git": "^1.5.0", + "glob": "^11.0.1", + "keep-a-changelog": "^2.5.3", "meow": "^12.1.1", "ora": "^7.0.1", "patch-package": "^8.0.0", @@ -645,6 +647,22 @@ "integrity": "sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw==", "dev": true }, + "node_modules/@deno/shim-deno": { + "version": "0.16.1", + "resolved": "https://registry.npmjs.org/@deno/shim-deno/-/shim-deno-0.16.1.tgz", + "integrity": "sha512-s9v0kzF5bm/o9TgdwvsraHx6QNllYrXXmKzgOG2lh4LFXnVMr2gpjK/c/ve6EflQn1MqImcWmVD8HAv5ahuuZQ==", + "license": "MIT", + "dependencies": { + "@deno/shim-deno-test": "^0.4.0", + "which": "^2.0.2" + } + }, + "node_modules/@deno/shim-deno-test": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/@deno/shim-deno-test/-/shim-deno-test-0.4.0.tgz", + "integrity": "sha512-oYWcD7CpERZy/TXMTM9Tgh1HD/POHlbY9WpzmAk+5H8DohcxG415Qws8yLGlim3EaKBT2v3lJv01x4G0BosnaQ==", + "license": "MIT" + }, "node_modules/@eslint-community/eslint-utils": { "version": "4.4.0", "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.4.0.tgz", @@ -734,6 +752,102 @@ "integrity": "sha512-dvuCeX5fC9dXgJn9t+X5atfmgQAzUOWqS1254Gh0m6i8wKd10ebXkfNKiRK+1GWi/yTvvLDHpoxLr0xxxeslWw==", "dev": true }, + "node_modules/@isaacs/cliui": { + "version": "8.0.2", + "resolved": "https://registry.npmjs.org/@isaacs/cliui/-/cliui-8.0.2.tgz", + "integrity": "sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==", + "license": "ISC", + "dependencies": { + "string-width": "^5.1.2", + "string-width-cjs": "npm:string-width@^4.2.0", + "strip-ansi": "^7.0.1", + "strip-ansi-cjs": "npm:strip-ansi@^6.0.1", + "wrap-ansi": "^8.1.0", + "wrap-ansi-cjs": "npm:wrap-ansi@^7.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/@isaacs/cliui/node_modules/ansi-regex": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.1.0.tgz", + "integrity": "sha512-7HSX4QQb4CspciLpVFwyRe79O3xsIZDDLER21kERQ71oaPodF8jL725AgJMFAYbooIqolJoRLuM81SpeUkpkvA==", + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-regex?sponsor=1" + } + }, + "node_modules/@isaacs/cliui/node_modules/ansi-styles": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz", + "integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==", + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/@isaacs/cliui/node_modules/emoji-regex": { + "version": "9.2.2", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz", + "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==", + "license": "MIT" + }, + "node_modules/@isaacs/cliui/node_modules/string-width": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz", + "integrity": "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==", + "license": "MIT", + "dependencies": { + "eastasianwidth": "^0.2.0", + "emoji-regex": "^9.2.2", + "strip-ansi": "^7.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@isaacs/cliui/node_modules/strip-ansi": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", + "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", + "license": "MIT", + "dependencies": { + "ansi-regex": "^6.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/strip-ansi?sponsor=1" + } + }, + "node_modules/@isaacs/cliui/node_modules/wrap-ansi": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-8.1.0.tgz", + "integrity": "sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==", + "license": "MIT", + "dependencies": { + "ansi-styles": "^6.1.0", + "string-width": "^5.0.1", + "strip-ansi": "^7.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, "node_modules/@istanbuljs/load-nyc-config": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/@istanbuljs/load-nyc-config/-/load-nyc-config-1.1.0.tgz", @@ -1158,6 +1272,28 @@ "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", "dev": true }, + "node_modules/@jest/reporters/node_modules/glob": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "deprecated": "Glob versions prior to v9 are no longer supported", + "dev": true, + "license": "ISC", + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.1.1", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, + "engines": { + "node": "*" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, "node_modules/@jest/reporters/node_modules/has-flag": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", @@ -4076,6 +4212,34 @@ "integrity": "sha512-zAoAQiudy+r5SvnSw3KJy5os/oRJYHzrzja/tBDqrZtNhUw8bt6y8OBzMWcjWr+8liV8Eb6yOhw8WZ7VFZ5ZzA==", "dev": true }, + "node_modules/foreground-child": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.3.0.tgz", + "integrity": "sha512-Ld2g8rrAyMYFXBhEqMz8ZAHBi4J4uS1i/CxGMDnjyFWddMXLVcDp051DZfu+t7+ab7Wv6SMqpWmyFIj5UbfFvg==", + "license": "ISC", + "dependencies": { + "cross-spawn": "^7.0.0", + "signal-exit": "^4.0.1" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/foreground-child/node_modules/signal-exit": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", + "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", + "license": "ISC", + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, "node_modules/form-data-encoder": { "version": "2.1.4", "resolved": "https://registry.npmjs.org/form-data-encoder/-/form-data-encoder-2.1.4.tgz", @@ -4101,7 +4265,8 @@ "node_modules/fs.realpath": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", - "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=" + "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==", + "license": "ISC" }, "node_modules/fsevents": { "version": "2.3.3", @@ -4166,19 +4331,23 @@ "integrity": "sha512-WWOec4aRI7YAykQ9+BHmzjyNlkfJFG8QLXnDTsLz/kZefq7qkzdfo4p6fkYYMIq1aj+gZcQs/1HQhQh3DPPxlQ==" }, "node_modules/glob": { - "version": "7.1.6", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz", - "integrity": "sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==", - "dependencies": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.0.4", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" + "version": "11.0.1", + "resolved": "https://registry.npmjs.org/glob/-/glob-11.0.1.tgz", + "integrity": "sha512-zrQDm8XPnYEKawJScsnM0QzobJxlT/kHOOlRTio8IH/GrmxRE5fjllkzdaHclIuNjUQTJYH2xHNIGfdpJkDJUw==", + "license": "ISC", + "dependencies": { + "foreground-child": "^3.1.0", + "jackspeak": "^4.0.1", + "minimatch": "^10.0.0", + "minipass": "^7.1.2", + "package-json-from-dist": "^1.0.0", + "path-scurry": "^2.0.0" + }, + "bin": { + "glob": "dist/esm/bin.mjs" }, "engines": { - "node": "*" + "node": "20 || >=22" }, "funding": { "url": "https://github.com/sponsors/isaacs" @@ -4196,6 +4365,30 @@ "node": ">=10.13.0" } }, + "node_modules/glob/node_modules/brace-expansion": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0" + } + }, + "node_modules/glob/node_modules/minimatch": { + "version": "10.0.1", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-10.0.1.tgz", + "integrity": "sha512-ethXTt3SGGR+95gudmqJ1eNhRO7eGEGIgYA9vnPatK4/etz2MEVDno5GMCibdMTuBMyElzIlgxMna3K94XDIDQ==", + "license": "ISC", + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": "20 || >=22" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, "node_modules/global-dirs": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/global-dirs/-/global-dirs-3.0.0.tgz", @@ -4406,7 +4599,9 @@ "node_modules/inflight": { "version": "1.0.6", "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", - "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", + "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", + "deprecated": "This module is not supported, and leaks memory. Do not use it. Check out lru-cache if you want a good and tested way to coalesce async requests by a key value, which is much more comprehensive and powerful.", + "license": "ISC", "dependencies": { "once": "^1.3.0", "wrappy": "1" @@ -4746,6 +4941,21 @@ "node": ">=8" } }, + "node_modules/jackspeak": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-4.0.2.tgz", + "integrity": "sha512-bZsjR/iRjl1Nk1UkjGpAzLNfQtzuijhn2g+pbZb98HQ1Gk8vM9hfbxeMBP+M2/UUdwj0RqGG3mlvk2MsAqwvEw==", + "license": "BlueOak-1.0.0", + "dependencies": { + "@isaacs/cliui": "^8.0.2" + }, + "engines": { + "node": "20 || >=22" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, "node_modules/jest": { "version": "29.7.0", "resolved": "https://registry.npmjs.org/jest/-/jest-29.7.0.tgz", @@ -5203,6 +5413,28 @@ "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", "dev": true }, + "node_modules/jest-config/node_modules/glob": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "deprecated": "Glob versions prior to v9 are no longer supported", + "dev": true, + "license": "ISC", + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.1.1", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, + "engines": { + "node": "*" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, "node_modules/jest-config/node_modules/has-flag": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", @@ -5988,6 +6220,28 @@ "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", "dev": true }, + "node_modules/jest-runtime/node_modules/glob": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "deprecated": "Glob versions prior to v9 are no longer supported", + "dev": true, + "license": "ISC", + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.1.1", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, + "engines": { + "node": "*" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, "node_modules/jest-runtime/node_modules/has-flag": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", @@ -6518,6 +6772,18 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/keep-a-changelog": { + "version": "2.5.3", + "resolved": "https://registry.npmjs.org/keep-a-changelog/-/keep-a-changelog-2.5.3.tgz", + "integrity": "sha512-ChMOZLbqdvxhdUIlKkA/UqU1PclcyR57bifjwkV/9/diYFUeHQeTaFkF3GWbXL1WYG/aZ5bJWg5pDLmC2NTycw==", + "license": "MIT", + "dependencies": { + "@deno/shim-deno": "~0.16.1" + }, + "bin": { + "changelog": "esm/bin.js" + } + }, "node_modules/keyv": { "version": "4.5.2", "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.2.tgz", @@ -7203,6 +7469,15 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/minipass": { + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.2.tgz", + "integrity": "sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==", + "license": "ISC", + "engines": { + "node": ">=16 || 14 >=14.17" + } + }, "node_modules/ms": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", @@ -7458,6 +7733,12 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/package-json-from-dist": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/package-json-from-dist/-/package-json-from-dist-1.0.1.tgz", + "integrity": "sha512-UEZIS3/by4OC8vL3P2dTXRETpebLI2NiI5vIrjaD/5UtrkFX/tNbwjTSRAGC/+7CAo2pIcBaRgWmcBBHcsaCIw==", + "license": "BlueOak-1.0.0" + }, "node_modules/package-json/node_modules/@sindresorhus/is": { "version": "5.3.0", "resolved": "https://registry.npmjs.org/@sindresorhus/is/-/is-5.3.0.tgz", @@ -7711,6 +7992,27 @@ "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" }, + "node_modules/patch-package/node_modules/glob": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "deprecated": "Glob versions prior to v9 are no longer supported", + "license": "ISC", + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.1.1", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, + "engines": { + "node": "*" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, "node_modules/patch-package/node_modules/has-flag": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", @@ -7761,7 +8063,8 @@ "node_modules/path-is-absolute": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", - "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=", + "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==", + "license": "MIT", "engines": { "node": ">=0.10.0" } @@ -7780,6 +8083,31 @@ "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", "dev": true }, + "node_modules/path-scurry": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-2.0.0.tgz", + "integrity": "sha512-ypGJsmGtdXUOeM5u93TyeIEfEhM6s+ljAhrk5vAvSx8uyY/02OvrZnA0YNGUrPXfpJMgI1ODd3nwz8Npx4O4cg==", + "license": "BlueOak-1.0.0", + "dependencies": { + "lru-cache": "^11.0.0", + "minipass": "^7.1.2" + }, + "engines": { + "node": "20 || >=22" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/path-scurry/node_modules/lru-cache": { + "version": "11.0.2", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-11.0.2.tgz", + "integrity": "sha512-123qHRfJBmo2jXDbo/a5YOQrJoHF/GNQTLzQ5+IdK5pWpceK17yRc6ozlWd25FxvGKQbIUs91fDFkXmDHTKcyA==", + "license": "ISC", + "engines": { + "node": "20 || >=22" + } + }, "node_modules/path-type": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", @@ -8257,6 +8585,28 @@ "url": "https://github.com/sponsors/isaacs" } }, + "node_modules/rimraf/node_modules/glob": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "deprecated": "Glob versions prior to v9 are no longer supported", + "dev": true, + "license": "ISC", + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.1.1", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, + "engines": { + "node": "*" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, "node_modules/run-applescript": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/run-applescript/-/run-applescript-5.0.0.tgz", @@ -8592,6 +8942,21 @@ "node": ">=8" } }, + "node_modules/string-width-cjs": { + "name": "string-width", + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "license": "MIT", + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/strip-ansi": { "version": "6.0.1", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", @@ -8603,6 +8968,19 @@ "node": ">=8" } }, + "node_modules/strip-ansi-cjs": { + "name": "strip-ansi", + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "license": "MIT", + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/strip-bom": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-4.0.0.tgz", @@ -8682,6 +9060,28 @@ "node": ">=8" } }, + "node_modules/test-exclude/node_modules/glob": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "deprecated": "Glob versions prior to v9 are no longer supported", + "dev": true, + "license": "ISC", + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.1.1", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, + "engines": { + "node": "*" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, "node_modules/text-table": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", @@ -9101,6 +9501,57 @@ "url": "https://github.com/chalk/wrap-ansi?sponsor=1" } }, + "node_modules/wrap-ansi-cjs": { + "name": "wrap-ansi", + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, + "node_modules/wrap-ansi-cjs/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "license": "MIT", + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/wrap-ansi-cjs/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "license": "MIT", + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/wrap-ansi-cjs/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "license": "MIT" + }, "node_modules/wrap-ansi/node_modules/ansi-styles": { "version": "4.3.0", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", @@ -9677,6 +10128,20 @@ "integrity": "sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw==", "dev": true }, + "@deno/shim-deno": { + "version": "0.16.1", + "resolved": "https://registry.npmjs.org/@deno/shim-deno/-/shim-deno-0.16.1.tgz", + "integrity": "sha512-s9v0kzF5bm/o9TgdwvsraHx6QNllYrXXmKzgOG2lh4LFXnVMr2gpjK/c/ve6EflQn1MqImcWmVD8HAv5ahuuZQ==", + "requires": { + "@deno/shim-deno-test": "^0.4.0", + "which": "^2.0.2" + } + }, + "@deno/shim-deno-test": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/@deno/shim-deno-test/-/shim-deno-test-0.4.0.tgz", + "integrity": "sha512-oYWcD7CpERZy/TXMTM9Tgh1HD/POHlbY9WpzmAk+5H8DohcxG415Qws8yLGlim3EaKBT2v3lJv01x4G0BosnaQ==" + }, "@eslint-community/eslint-utils": { "version": "4.4.0", "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.4.0.tgz", @@ -9738,6 +10203,64 @@ "integrity": "sha512-dvuCeX5fC9dXgJn9t+X5atfmgQAzUOWqS1254Gh0m6i8wKd10ebXkfNKiRK+1GWi/yTvvLDHpoxLr0xxxeslWw==", "dev": true }, + "@isaacs/cliui": { + "version": "8.0.2", + "resolved": "https://registry.npmjs.org/@isaacs/cliui/-/cliui-8.0.2.tgz", + "integrity": "sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==", + "requires": { + "string-width": "^5.1.2", + "string-width-cjs": "npm:string-width@^4.2.0", + "strip-ansi": "^7.0.1", + "strip-ansi-cjs": "npm:strip-ansi@^6.0.1", + "wrap-ansi": "^8.1.0", + "wrap-ansi-cjs": "npm:wrap-ansi@^7.0.0" + }, + "dependencies": { + "ansi-regex": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.1.0.tgz", + "integrity": "sha512-7HSX4QQb4CspciLpVFwyRe79O3xsIZDDLER21kERQ71oaPodF8jL725AgJMFAYbooIqolJoRLuM81SpeUkpkvA==" + }, + "ansi-styles": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz", + "integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==" + }, + "emoji-regex": { + "version": "9.2.2", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz", + "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==" + }, + "string-width": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz", + "integrity": "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==", + "requires": { + "eastasianwidth": "^0.2.0", + "emoji-regex": "^9.2.2", + "strip-ansi": "^7.0.1" + } + }, + "strip-ansi": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", + "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", + "requires": { + "ansi-regex": "^6.0.1" + } + }, + "wrap-ansi": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-8.1.0.tgz", + "integrity": "sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==", + "requires": { + "ansi-styles": "^6.1.0", + "string-width": "^5.0.1", + "strip-ansi": "^7.0.1" + } + } + } + }, "@istanbuljs/load-nyc-config": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/@istanbuljs/load-nyc-config/-/load-nyc-config-1.1.0.tgz", @@ -10059,6 +10582,20 @@ "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", "dev": true }, + "glob": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "dev": true, + "requires": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.1.1", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + } + }, "has-flag": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", @@ -12158,6 +12695,22 @@ "integrity": "sha512-zAoAQiudy+r5SvnSw3KJy5os/oRJYHzrzja/tBDqrZtNhUw8bt6y8OBzMWcjWr+8liV8Eb6yOhw8WZ7VFZ5ZzA==", "dev": true }, + "foreground-child": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.3.0.tgz", + "integrity": "sha512-Ld2g8rrAyMYFXBhEqMz8ZAHBi4J4uS1i/CxGMDnjyFWddMXLVcDp051DZfu+t7+ab7Wv6SMqpWmyFIj5UbfFvg==", + "requires": { + "cross-spawn": "^7.0.0", + "signal-exit": "^4.0.1" + }, + "dependencies": { + "signal-exit": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", + "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==" + } + } + }, "form-data-encoder": { "version": "2.1.4", "resolved": "https://registry.npmjs.org/form-data-encoder/-/form-data-encoder-2.1.4.tgz", @@ -12177,7 +12730,7 @@ "fs.realpath": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", - "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=" + "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==" }, "fsevents": { "version": "2.3.3", @@ -12220,16 +12773,34 @@ "integrity": "sha512-WWOec4aRI7YAykQ9+BHmzjyNlkfJFG8QLXnDTsLz/kZefq7qkzdfo4p6fkYYMIq1aj+gZcQs/1HQhQh3DPPxlQ==" }, "glob": { - "version": "7.1.6", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz", - "integrity": "sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==", + "version": "11.0.1", + "resolved": "https://registry.npmjs.org/glob/-/glob-11.0.1.tgz", + "integrity": "sha512-zrQDm8XPnYEKawJScsnM0QzobJxlT/kHOOlRTio8IH/GrmxRE5fjllkzdaHclIuNjUQTJYH2xHNIGfdpJkDJUw==", "requires": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.0.4", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" + "foreground-child": "^3.1.0", + "jackspeak": "^4.0.1", + "minimatch": "^10.0.0", + "minipass": "^7.1.2", + "package-json-from-dist": "^1.0.0", + "path-scurry": "^2.0.0" + }, + "dependencies": { + "brace-expansion": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "requires": { + "balanced-match": "^1.0.0" + } + }, + "minimatch": { + "version": "10.0.1", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-10.0.1.tgz", + "integrity": "sha512-ethXTt3SGGR+95gudmqJ1eNhRO7eGEGIgYA9vnPatK4/etz2MEVDno5GMCibdMTuBMyElzIlgxMna3K94XDIDQ==", + "requires": { + "brace-expansion": "^2.0.1" + } + } } }, "glob-parent": { @@ -12376,7 +12947,7 @@ "inflight": { "version": "1.0.6", "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", - "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", + "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", "requires": { "once": "^1.3.0", "wrappy": "1" @@ -12601,6 +13172,14 @@ "istanbul-lib-report": "^3.0.0" } }, + "jackspeak": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-4.0.2.tgz", + "integrity": "sha512-bZsjR/iRjl1Nk1UkjGpAzLNfQtzuijhn2g+pbZb98HQ1Gk8vM9hfbxeMBP+M2/UUdwj0RqGG3mlvk2MsAqwvEw==", + "requires": { + "@isaacs/cliui": "^8.0.2" + } + }, "jest": { "version": "29.7.0", "resolved": "https://registry.npmjs.org/jest/-/jest-29.7.0.tgz", @@ -12916,6 +13495,20 @@ "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", "dev": true }, + "glob": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "dev": true, + "requires": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.1.1", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + } + }, "has-flag": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", @@ -13505,6 +14098,20 @@ "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", "dev": true }, + "glob": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "dev": true, + "requires": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.1.1", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + } + }, "has-flag": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", @@ -13904,6 +14511,14 @@ "resolved": "https://registry.npmjs.org/jsonify/-/jsonify-0.0.1.tgz", "integrity": "sha512-2/Ki0GcmuqSrgFyelQq9M05y7PS0mEwuIzrf3f1fPqkVDVRvZrPZtVSMHxdgo8Aq0sxAOb/cr2aqqA3LeWHVPg==" }, + "keep-a-changelog": { + "version": "2.5.3", + "resolved": "https://registry.npmjs.org/keep-a-changelog/-/keep-a-changelog-2.5.3.tgz", + "integrity": "sha512-ChMOZLbqdvxhdUIlKkA/UqU1PclcyR57bifjwkV/9/diYFUeHQeTaFkF3GWbXL1WYG/aZ5bJWg5pDLmC2NTycw==", + "requires": { + "@deno/shim-deno": "~0.16.1" + } + }, "keyv": { "version": "4.5.2", "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.2.tgz", @@ -14318,6 +14933,11 @@ "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz", "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==" }, + "minipass": { + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.2.tgz", + "integrity": "sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==" + }, "ms": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", @@ -14593,6 +15213,11 @@ } } }, + "package-json-from-dist": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/package-json-from-dist/-/package-json-from-dist-1.0.1.tgz", + "integrity": "sha512-UEZIS3/by4OC8vL3P2dTXRETpebLI2NiI5vIrjaD/5UtrkFX/tNbwjTSRAGC/+7CAo2pIcBaRgWmcBBHcsaCIw==" + }, "parent-module": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", @@ -14666,6 +15291,19 @@ "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" }, + "glob": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "requires": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.1.1", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + } + }, "has-flag": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", @@ -14703,7 +15341,7 @@ "path-is-absolute": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", - "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=" + "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==" }, "path-key": { "version": "3.1.1", @@ -14716,6 +15354,22 @@ "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", "dev": true }, + "path-scurry": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-2.0.0.tgz", + "integrity": "sha512-ypGJsmGtdXUOeM5u93TyeIEfEhM6s+ljAhrk5vAvSx8uyY/02OvrZnA0YNGUrPXfpJMgI1ODd3nwz8Npx4O4cg==", + "requires": { + "lru-cache": "^11.0.0", + "minipass": "^7.1.2" + }, + "dependencies": { + "lru-cache": { + "version": "11.0.2", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-11.0.2.tgz", + "integrity": "sha512-123qHRfJBmo2jXDbo/a5YOQrJoHF/GNQTLzQ5+IdK5pWpceK17yRc6ozlWd25FxvGKQbIUs91fDFkXmDHTKcyA==" + } + } + }, "path-type": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", @@ -15030,6 +15684,22 @@ "dev": true, "requires": { "glob": "^7.1.3" + }, + "dependencies": { + "glob": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "dev": true, + "requires": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.1.1", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + } + } } }, "run-applescript": { @@ -15265,6 +15935,16 @@ "strip-ansi": "^6.0.1" } }, + "string-width-cjs": { + "version": "npm:string-width@4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "requires": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + } + }, "strip-ansi": { "version": "6.0.1", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", @@ -15273,6 +15953,14 @@ "ansi-regex": "^5.0.1" } }, + "strip-ansi-cjs": { + "version": "npm:strip-ansi@6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "requires": { + "ansi-regex": "^5.0.1" + } + }, "strip-bom": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-4.0.0.tgz", @@ -15325,6 +16013,22 @@ "@istanbuljs/schema": "^0.1.2", "glob": "^7.1.4", "minimatch": "^3.0.4" + }, + "dependencies": { + "glob": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "dev": true, + "requires": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.1.1", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + } + } } }, "text-table": { @@ -15626,6 +16330,39 @@ } } }, + "wrap-ansi-cjs": { + "version": "npm:wrap-ansi@7.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "requires": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "dependencies": { + "ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "requires": { + "color-convert": "^2.0.1" + } + }, + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "requires": { + "color-name": "~1.1.4" + } + }, + "color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" + } + } + }, "wrappy": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", diff --git a/package.json b/package.json index 4795f1f..ebcc4fb 100644 --- a/package.json +++ b/package.json @@ -21,6 +21,8 @@ "enquirer": "^2.4.1", "execa": "^8.0.1", "github-url-from-git": "^1.5.0", + "glob": "^11.0.1", + "keep-a-changelog": "^2.5.3", "meow": "^12.1.1", "ora": "^7.0.1", "patch-package": "^8.0.0", diff --git a/src/bin.ts b/src/bin.ts index 0b4c2bc..affd615 100644 --- a/src/bin.ts +++ b/src/bin.ts @@ -6,14 +6,15 @@ import updateNotifier from 'update-notifier' import meow from 'meow' import chalk from 'chalk' -import startRepositoryRelease from './startRepositoryRelease.js' +import startRepositoryRelease from './commands/startRepositoryRelease.js' import semver from 'semver' -import promptForNextVersion from './promptForNextVersion.js' -import getPreRelease from './getPreRelease.js' -import startProductRelease from './startProductRelease.js' -import promptForReleaseName from './promptForReleaseName.js' +import promptForNextVersion from './terminal/promptForNextVersion.js' +import getPreRelease from './utils/getPreRelease.js' +import startProductRelease from './commands/startProductRelease.js' +import promptForReleaseName from './terminal/promptForReleaseName.js' import getRepositoryPlugin from './repositories-plugins/plugins-factory.js' -import startUpdateDependents from './startUpdateDependents.js' +import startUpdateDependents from './commands/startUpdateDependents.js' +import startChangelogPreview from './commands/startChangelogPreview.js' const cli = meow( ` @@ -145,6 +146,12 @@ async function run(): Promise { const cwd = path.resolve(process.cwd(), cli.flags.cwd) switch (command) { + case 'changelog-preview': { + await startChangelogPreview({ + cwd, + }) + break + } case 'update-dependents': { await startUpdateDependents({ cwd, diff --git a/src/changelog/addNextReleaseToChangelog.ts b/src/changelog/addNextReleaseToChangelog.ts new file mode 100644 index 0000000..2216a23 --- /dev/null +++ b/src/changelog/addNextReleaseToChangelog.ts @@ -0,0 +1,102 @@ +import fs from 'fs/promises' +import prettier from 'prettier' +import { SemVer } from 'semver' +import wrapWithLoading from '../terminal/wrapWithLoading.js' +import { RepositoryPlugin } from '../repositories-plugins/RepositoryPlugin.js' +import generateCodeChangelogEntries from './generateCodeChangelogEntries.js' +import generateDependenciesChangelogEntry from './generateDependenciesChangelogEntry.js' +import parseChangelogWithLoading from './parseChangelogWithLoading.js' + +const UNRELEASED_VERSION_INDEX = 0 + +export default async function addNextReleaseToChangelog({ + nextSemverVersion, + releaseName, + repositoryPlugin, +}: { + nextSemverVersion: SemVer + releaseName: string | undefined + repositoryPlugin: RepositoryPlugin +}) { + const { parsedChangelog, changelogPath } = await parseChangelogWithLoading( + repositoryPlugin.cwd, + ) + + const dependenciesChangelogEntry = await generateDependenciesChangelogEntry({ + parsedChangelog, + repositoryPlugin, + }) + + const { formatted: codeChangelogEntries, entryFiles } = + await generateCodeChangelogEntries({ + cwd: repositoryPlugin.cwd, + }) + + const nextReleaseTitle = `[${nextSemverVersion.version}] - ${new Date() + .toISOString() + .substring(0, 10)}` + const releaseNameSubtitle = releaseName + ? ` + +##### Release Name: ${releaseName}` + : '' + + await wrapWithLoading( + { + startText: `Updating CHANGELOG.md with next release (${nextReleaseTitle})`, + failText: `Failed to update CHANGELOG.md with next release (${nextReleaseTitle})`, + }, + async (spinner) => { + const changelog = await prettier.format( + ` +# ${parsedChangelog.title} + +${parsedChangelog.description || ''} + +${parsedChangelog.versions + .map(({ title, body }, index) => { + if (index === UNRELEASED_VERSION_INDEX) { + return ` +## ${title} + +## ${nextReleaseTitle}${releaseNameSubtitle} + +${body} + +${codeChangelogEntries} + +${dependenciesChangelogEntry} +` + } + + return ` +## ${title} + +${body} +` + }) + .join('')}`, + { + parser: 'markdown', + }, + ) + await fs.writeFile(changelogPath, changelog, 'utf-8') + spinner.succeed( + `Updated CHANGELOG.md with next release (${nextReleaseTitle})`, + ) + }, + ) + + for (const { filePath } of entryFiles) { + wrapWithLoading( + { + startText: `Deleting file: "${filePath}"`, + failText: `Failed to delete file: "${filePath}"`, + }, + async (spinner) => { + await fs.unlink(filePath) + spinner.succeed(`Deleted file: "${filePath}"`) + }, + ) + } +} diff --git a/src/changelog/generateCodeChangelogEntries.ts b/src/changelog/generateCodeChangelogEntries.ts new file mode 100644 index 0000000..ca106dd --- /dev/null +++ b/src/changelog/generateCodeChangelogEntries.ts @@ -0,0 +1,80 @@ +import { readFile } from 'fs/promises' +import { glob } from 'glob' +import { parser, Release } from 'keep-a-changelog' +import prettier from 'prettier' +import wrapWithLoading from '../terminal/wrapWithLoading.js' + +export const CHANGELOG_ENTRIES_DIRECTORY_NAME = 'changelog-entries' + +export default async function generateCodeChangelogEntries({ + cwd, +}: { + cwd: string +}) { + return await wrapWithLoading( + { + startText: `Generating changelog entries from the "${CHANGELOG_ENTRIES_DIRECTORY_NAME}" directory`, + failText: `Failed to generate changelog entries from the "${CHANGELOG_ENTRIES_DIRECTORY_NAME}" directory`, + }, + async (spinner) => { + const entryFilePaths = await glob( + `${CHANGELOG_ENTRIES_DIRECTORY_NAME}/**`, + { + cwd, + nodir: true, + }, + ) + + const finalRelease = new Release() + const entryFiles: Array<{ + filePath: string + markdown: string + }> = [] + for (const entryFilePath of entryFilePaths) { + const entry = await readFile(entryFilePath, 'utf-8') + entryFiles.push({ + filePath: entryFilePath, + markdown: entry, + }) + const parsed = parser(`# Changelog + +## Unreleased + +${entry}`) + for (const release of parsed.releases) { + for (const [type, changes] of release.changes) { + for (const change of changes) { + finalRelease.addChange(type, change) + } + } + } + } + + const releaseChangelogEntries = finalRelease + .toString() + .replace('## Unreleased', '') + const formatted = await prettier.format(releaseChangelogEntries, { + parser: 'markdown', + }) + + if (!entryFiles.length) { + spinner.info( + `Skipping inserting changelog entries from the "${CHANGELOG_ENTRIES_DIRECTORY_NAME}" directory to the CHANGELOG.md as there were no markdown files in the directory`, + ) + return { + formatted, + entryFiles, + } + } + + spinner.succeed( + `Changelog entries from the "${CHANGELOG_ENTRIES_DIRECTORY_NAME}" directory will be added to CHANGELOG.md`, + ) + + return { + formatted, + entryFiles, + } + }, + ) +} diff --git a/src/changelog/generateDependenciesChangelogEntry.ts b/src/changelog/generateDependenciesChangelogEntry.ts new file mode 100644 index 0000000..fbeb302 --- /dev/null +++ b/src/changelog/generateDependenciesChangelogEntry.ts @@ -0,0 +1,83 @@ +import parseChangelog from 'changelog-parser' +import wrapWithLoading from '../terminal/wrapWithLoading.js' +import { RepositoryPlugin } from '../repositories-plugins/RepositoryPlugin.js' + +const UNRELEASED_VERSION_INDEX = 0 +const GIT_TAG_PREFIX = 'v' + +export default async function generateDependenciesChangelogEntry({ + parsedChangelog, + repositoryPlugin, +}: { + parsedChangelog: parseChangelog.Changelog + repositoryPlugin: RepositoryPlugin +}): Promise { + return await wrapWithLoading( + { + startText: + 'Checking if the "Dependencies" heading should be added to CHANGELOG.md', + failText: + 'Failed to check if the "Dependencies" heading should be added to CHANGELOG.md', + }, + async (spinner) => { + if (!repositoryPlugin.generateDependenciesChangelog) { + spinner.info( + `Evaluating "Dependencies" is not supported for ${repositoryPlugin.displayType} repositories.`, + ) + return '' + } + + const unreleasedVersion = + parsedChangelog.versions[UNRELEASED_VERSION_INDEX] + if ( + !unreleasedVersion || + !unreleasedVersion.title.toLowerCase().includes('unreleased') + ) { + throw new Error('"Unreleased" heading in CHANGELOG.md does not exist') + } + + const dependenciesChangelogHeading = '### Dependencies' + + if (unreleasedVersion.body.includes(dependenciesChangelogHeading)) { + spinner.warn( + 'Skipping inserting the "Dependencies" heading in CHANGELOG.md as it already exists under the "Unreleased" heading. It is recommended to allow this release process to insert instead of adding them as dependencies change.', + ) + return '' + } + + const lastVersion = parsedChangelog.versions[1] + if (!lastVersion) { + spinner.info( + 'Skipping inserting the "Dependencies" heading in CHANGELOG.md as this is the first release according to the CHANGELOG.md.', + ) + return '' + } + + const lastGitTag = `${GIT_TAG_PREFIX}${lastVersion.version}` + const dependenciesChangelog = + await repositoryPlugin.generateDependenciesChangelog({ + previousVersion: lastGitTag, + }) + + if (dependenciesChangelog.result === 'WARNING') { + spinner.warn(dependenciesChangelog.message) + return '' + } + + if (!dependenciesChangelog.entries?.trim()) { + spinner.info( + `Skipping inserting the "Dependencies" heading in CHANGELOG.md as there were no dependency changes since the last release (${lastVersion.version})`, + ) + return '' + } + + spinner.succeed('"Dependencies" heading will be added to CHANGELOG.md') + + return ` +${dependenciesChangelogHeading} + +${dependenciesChangelog.entries} +` + }, + ) +} diff --git a/src/parseChangelogWithLoading.ts b/src/changelog/parseChangelogWithLoading.ts similarity index 90% rename from src/parseChangelogWithLoading.ts rename to src/changelog/parseChangelogWithLoading.ts index a9edc78..3aacedd 100644 --- a/src/parseChangelogWithLoading.ts +++ b/src/changelog/parseChangelogWithLoading.ts @@ -1,6 +1,6 @@ import path from 'path' import parseChangelog from 'changelog-parser' -import wrapWithLoading from './wrapWithLoading.js' +import wrapWithLoading from '../terminal/wrapWithLoading.js' export default async function parseChangelogWithLoading(cwd: string) { const changelogPath = path.join(cwd, 'CHANGELOG.md') diff --git a/src/commands/startChangelogPreview.ts b/src/commands/startChangelogPreview.ts new file mode 100644 index 0000000..b472ac4 --- /dev/null +++ b/src/commands/startChangelogPreview.ts @@ -0,0 +1,46 @@ +import boxen from 'boxen' +import chalk from 'chalk' +import generateChangelogEntries, { + CHANGELOG_ENTRIES_DIRECTORY_NAME, +} from '../changelog/generateCodeChangelogEntries.js' + +export default async function startChangelogPreview({ cwd }: { cwd: string }) { + const { formatted: unreleasedChangelogEntries, entryFiles } = + await generateChangelogEntries({ + cwd, + }) + if (!entryFiles.length) { + console.log( + chalk.yellow( + `There are no changelog entry files in the "${CHANGELOG_ENTRIES_DIRECTORY_NAME}" directory`, + ), + ) + process.exitCode = 1 + return + } + + console.log( + boxen( + entryFiles.map(({ filePath }) => filePath).join(` +`), + { + title: 'Unreleased Entry Files', + padding: 1, + margin: { + top: 1, + bottom: 1, + }, + }, + ), + ) + console.log( + boxen(chalk.blue(unreleasedChangelogEntries), { + title: 'Unreleased Entries', + padding: 1, + margin: { + top: 1, + bottom: 1, + }, + }), + ) +} diff --git a/src/startProductRelease.ts b/src/commands/startProductRelease.ts similarity index 90% rename from src/startProductRelease.ts rename to src/commands/startProductRelease.ts index 640c719..946af47 100644 --- a/src/startProductRelease.ts +++ b/src/commands/startProductRelease.ts @@ -1,12 +1,12 @@ import enquirer from 'enquirer' -import executeCommand from './executeCommand.js' -import parseChangelogWithLoading from './parseChangelogWithLoading.js' -import promptForNextVersion from './promptForNextVersion.js' +import executeCommand from '../terminal/executeCommand.js' +import parseChangelogWithLoading from '../changelog/parseChangelogWithLoading.js' +import promptForNextVersion from '../terminal/promptForNextVersion.js' import boxen from 'boxen' import chalk from 'chalk' import startRepositoryRelease from './startRepositoryRelease.js' -import getRepositoryPlugin from './repositories-plugins/plugins-factory.js' -import enumerateProductRepositories from './enumerateProductRepositories.js' +import getRepositoryPlugin from '../repositories-plugins/plugins-factory.js' +import enumerateProductRepositories from '../repositories/enumerateProductRepositories.js' export default async function startProductRelease({ releaseName, diff --git a/src/commands/startRepositoryRelease.ts b/src/commands/startRepositoryRelease.ts new file mode 100644 index 0000000..f4bc513 --- /dev/null +++ b/src/commands/startRepositoryRelease.ts @@ -0,0 +1,70 @@ +import semver from 'semver' +import ora from 'ora' +import executeCommand from '../terminal/executeCommand.js' +import getPreRelease from '../utils/getPreRelease.js' +import { RepositoryPlugin } from '../repositories-plugins/RepositoryPlugin.js' +import addNextReleaseToChangelog from '../changelog/addNextReleaseToChangelog.js' + +const GIT_TAG_PREFIX = 'v' + +export default async function startRepositoryRelease({ + nextVersion, + git, + releaseName, + repositoryPlugin, +}: { + nextVersion: string + git: boolean + releaseName: string | undefined + repositoryPlugin: RepositoryPlugin +}): Promise { + const nextSemverVersion = semver.parse(nextVersion) + if (!nextSemverVersion) { + throw new Error('Next version is not valid semver') + } + + const preRelease = getPreRelease(nextVersion) + + if (preRelease) { + const text = `Skipping changelog updates for "${preRelease.tag}" release` + ora(text).start().info(text) + } else { + await addNextReleaseToChangelog({ + nextSemverVersion, + releaseName, + repositoryPlugin, + }) + } + + await repositoryPlugin.incrementVersion(nextSemverVersion) + + if (!git) { + const text = `Skipping committing release changes using git` + ora(text).start().info(text) + return + } + + const message = `[RELEASE] ${nextSemverVersion.version}${ + releaseName ? ` - ${releaseName}` : '' + }` + + await executeCommand('git', ['add', '-A'], repositoryPlugin.cwd) + await executeCommand( + 'git', + ['commit', '--message', message], + repositoryPlugin.cwd, + ) + await executeCommand('git', ['push'], repositoryPlugin.cwd) + await executeCommand( + 'git', + [ + 'tag', + '-a', + `${GIT_TAG_PREFIX}${nextSemverVersion.version}`, + '-m', + message, + ], + repositoryPlugin.cwd, + ) + await executeCommand('git', ['push', '--tags'], repositoryPlugin.cwd) +} diff --git a/src/startUpdateDependents.ts b/src/commands/startUpdateDependents.ts similarity index 95% rename from src/startUpdateDependents.ts rename to src/commands/startUpdateDependents.ts index 0618308..c25bba2 100644 --- a/src/startUpdateDependents.ts +++ b/src/commands/startUpdateDependents.ts @@ -1,8 +1,8 @@ import { readPackageUp } from 'read-package-up' -import enumerateProductRepositories from './enumerateProductRepositories.js' -import getRepositoryPlugin from './repositories-plugins/plugins-factory.js' +import enumerateProductRepositories from '../repositories/enumerateProductRepositories.js' +import getRepositoryPlugin from '../repositories-plugins/plugins-factory.js' import enquirer from 'enquirer' -import executeCommand from './executeCommand.js' +import executeCommand from '../terminal/executeCommand.js' import boxen from 'boxen' export default async function startUpdateDependents({ cwd }: { cwd: string }) { diff --git a/src/repositories-plugins/NpmPlugin.ts b/src/repositories-plugins/NpmPlugin.ts index bb54289..a0ebb8c 100644 --- a/src/repositories-plugins/NpmPlugin.ts +++ b/src/repositories-plugins/NpmPlugin.ts @@ -1,7 +1,7 @@ import { readPackageUp } from 'read-package-up' import { main as packageDiffSummary } from '../package-diff-summary/index.js' import { SemVer } from 'semver' -import executeCommand from '../executeCommand.js' +import executeCommand from '../terminal/executeCommand.js' import { RepositoryPlugin } from './RepositoryPlugin.js' export default class NpmPlugin implements RepositoryPlugin { diff --git a/src/repositories-plugins/NugetPlugin.ts b/src/repositories-plugins/NugetPlugin.ts index 0fd9777..5194c70 100644 --- a/src/repositories-plugins/NugetPlugin.ts +++ b/src/repositories-plugins/NugetPlugin.ts @@ -1,7 +1,7 @@ import { readFile, writeFile } from 'fs/promises' import path from 'path' import { SemVer } from 'semver' -import getPreRelease from '../getPreRelease.js' +import getPreRelease from '../utils/getPreRelease.js' import { RepositoryPlugin } from './RepositoryPlugin.js' export default class NugetPlugin implements RepositoryPlugin { diff --git a/src/enumerateProductRepositories.ts b/src/repositories/enumerateProductRepositories.ts similarity index 97% rename from src/enumerateProductRepositories.ts rename to src/repositories/enumerateProductRepositories.ts index 0523c2e..c18425b 100644 --- a/src/enumerateProductRepositories.ts +++ b/src/repositories/enumerateProductRepositories.ts @@ -1,6 +1,6 @@ import path from 'path' import prepareCloneRepository from './prepareCloneRepository.js' -import { RepositoryType } from './repositories-plugins/plugins-factory.js' +import { RepositoryType } from '../repositories-plugins/plugins-factory.js' type Repository = { label: string diff --git a/src/prepareCloneRepository.ts b/src/repositories/prepareCloneRepository.ts similarity index 92% rename from src/prepareCloneRepository.ts rename to src/repositories/prepareCloneRepository.ts index c42b9f9..ae61379 100644 --- a/src/prepareCloneRepository.ts +++ b/src/repositories/prepareCloneRepository.ts @@ -1,8 +1,8 @@ import { mkdtemp, rm } from 'fs/promises' import { join } from 'node:path' import { tmpdir } from 'node:os' -import executeCommand from './executeCommand.js' -import wrapWithLoading from './wrapWithLoading.js' +import executeCommand from '../terminal/executeCommand.js' +import wrapWithLoading from '../terminal/wrapWithLoading.js' export default async function prepareCloneRepository({ repositoryName, diff --git a/src/startRepositoryRelease.ts b/src/startRepositoryRelease.ts deleted file mode 100644 index 2723d18..0000000 --- a/src/startRepositoryRelease.ts +++ /dev/null @@ -1,214 +0,0 @@ -import fs from 'fs' -import util from 'util' - -import prettier from 'prettier' -import semver, { SemVer } from 'semver' -import ora from 'ora' -import wrapWithLoading from './wrapWithLoading.js' -import executeCommand from './executeCommand.js' -import parseChangelogWithLoading from './parseChangelogWithLoading.js' -import getPreRelease from './getPreRelease.js' -import { RepositoryPlugin } from './repositories-plugins/RepositoryPlugin.js' - -const writeFileAsync = util.promisify(fs.writeFile) - -const UNRELEASED_VERSION_INDEX = 0 -const GIT_TAG_PREFIX = 'v' - -async function updateChangelog({ - nextSemverVersion, - releaseName, - repositoryPlugin, -}: { - nextSemverVersion: SemVer - releaseName: string | undefined - repositoryPlugin: RepositoryPlugin -}) { - const { parsedChangelog, changelogPath } = await parseChangelogWithLoading( - repositoryPlugin.cwd, - ) - - const dependenciesChangelogEntry = await wrapWithLoading( - { - startText: - 'Checking if the "Dependencies" heading should be added to CHANGELOG.md', - failText: - 'Failed to check if the "Dependencies" heading should be added to CHANGELOG.md', - }, - async (spinner) => { - if (!repositoryPlugin.generateDependenciesChangelog) { - spinner.info( - `Evaluating "Dependencies" is not supported for ${repositoryPlugin.displayType} repositories.`, - ) - return '' - } - - const unreleasedVersion = - parsedChangelog.versions[UNRELEASED_VERSION_INDEX] - if ( - !unreleasedVersion || - !unreleasedVersion.title.toLowerCase().includes('unreleased') - ) { - throw new Error('"Unreleased" heading in CHANGELOG.md does not exist') - } - - const dependenciesChangelogHeading = '### Dependencies' - - if (unreleasedVersion.body.includes(dependenciesChangelogHeading)) { - spinner.warn( - 'Skipping inserting the "Dependencies" heading in CHANGELOG.md as it already exists under the "Unreleased" heading. It is recommended to allow this release process to insert instead of adding them as dependencies change.', - ) - return '' - } - - const lastVersion = parsedChangelog.versions[1] - if (!lastVersion) { - spinner.info( - 'Skipping inserting the "Dependencies" heading in CHANGELOG.md as this is the first release according to the CHANGELOG.md.', - ) - return '' - } - - const lastGitTag = `${GIT_TAG_PREFIX}${lastVersion.version}` - const dependenciesChangelog = - await repositoryPlugin.generateDependenciesChangelog({ - previousVersion: lastGitTag, - }) - - if (dependenciesChangelog.result === 'WARNING') { - spinner.warn(dependenciesChangelog.message) - return '' - } - - if (!dependenciesChangelog.entries?.trim()) { - spinner.info( - `Skipping inserting the "Dependencies" heading in CHANGELOG.md as there were no dependency changes since the last release (${lastVersion.version})`, - ) - return '' - } - - spinner.succeed('"Dependencies" heading will be added to CHANGELOG.md') - - return ` -${dependenciesChangelogHeading} - -${dependenciesChangelog.entries} -` - }, - ) - - const nextReleaseTitle = `[${nextSemverVersion.version}] - ${new Date() - .toISOString() - .substring(0, 10)}` - const releaseNameSubtitle = releaseName - ? ` - -##### Release Name: ${releaseName}` - : '' - - await wrapWithLoading( - { - startText: `Updating CHANGELOG.md with next release (${nextReleaseTitle})`, - failText: `Failed to update CHANGELOG.md with next release (${nextReleaseTitle})`, - }, - async (spinner) => { - const changelog = await prettier.format( - ` -# ${parsedChangelog.title} - -${parsedChangelog.description || ''} - -${parsedChangelog.versions - .map(({ title, body }, index) => { - if (index === UNRELEASED_VERSION_INDEX) { - return ` -## ${title} - -## ${nextReleaseTitle}${releaseNameSubtitle} - -${body} - -${dependenciesChangelogEntry} -` - } - - return ` -## ${title} - -${body} -` - }) - .join('')}`, - { - parser: 'markdown', - }, - ) - await writeFileAsync(changelogPath, changelog, 'utf-8') - spinner.succeed( - `Updated CHANGELOG.md with next release (${nextReleaseTitle})`, - ) - }, - ) -} - -export default async function startRepositoryRelease({ - nextVersion, - git, - releaseName, - repositoryPlugin, -}: { - nextVersion: string - git: boolean - releaseName: string | undefined - repositoryPlugin: RepositoryPlugin -}): Promise { - const nextSemverVersion = semver.parse(nextVersion) - if (!nextSemverVersion) { - throw new Error('Next version is not valid semver') - } - - const preRelease = getPreRelease(nextVersion) - - if (preRelease) { - const text = `Skipping changelog updates for "${preRelease.tag}" release` - ora(text).start().info(text) - } else { - await updateChangelog({ - nextSemverVersion, - releaseName, - repositoryPlugin, - }) - } - - await repositoryPlugin.incrementVersion(nextSemverVersion) - - if (!git) { - const text = `Skipping committing release changes using git` - ora(text).start().info(text) - return - } - - const message = `[RELEASE] ${nextSemverVersion.version}${ - releaseName ? ` - ${releaseName}` : '' - }` - - await executeCommand('git', ['add', '-A'], repositoryPlugin.cwd) - await executeCommand( - 'git', - ['commit', '--message', message], - repositoryPlugin.cwd, - ) - await executeCommand('git', ['push'], repositoryPlugin.cwd) - await executeCommand( - 'git', - [ - 'tag', - '-a', - `${GIT_TAG_PREFIX}${nextSemverVersion.version}`, - '-m', - message, - ], - repositoryPlugin.cwd, - ) - await executeCommand('git', ['push', '--tags'], repositoryPlugin.cwd) -} diff --git a/src/executeCommand.ts b/src/terminal/executeCommand.ts similarity index 100% rename from src/executeCommand.ts rename to src/terminal/executeCommand.ts diff --git a/src/promptForNextVersion.ts b/src/terminal/promptForNextVersion.ts similarity index 91% rename from src/promptForNextVersion.ts rename to src/terminal/promptForNextVersion.ts index c2155b9..eaf46c3 100644 --- a/src/promptForNextVersion.ts +++ b/src/terminal/promptForNextVersion.ts @@ -1,7 +1,7 @@ import enquirer from 'enquirer' import semver from 'semver' -import getPreRelease from './getPreRelease.js' -import { RepositoryPlugin } from './repositories-plugins/RepositoryPlugin.js' +import getPreRelease from '../utils/getPreRelease.js' +import { RepositoryPlugin } from '../repositories-plugins/RepositoryPlugin.js' export default async function promptForNextVersion({ repositoryPlugin, diff --git a/src/promptForReleaseName.ts b/src/terminal/promptForReleaseName.ts similarity index 100% rename from src/promptForReleaseName.ts rename to src/terminal/promptForReleaseName.ts diff --git a/src/wrapWithLoading.ts b/src/terminal/wrapWithLoading.ts similarity index 100% rename from src/wrapWithLoading.ts rename to src/terminal/wrapWithLoading.ts diff --git a/src/getPreRelease.ts b/src/utils/getPreRelease.ts similarity index 100% rename from src/getPreRelease.ts rename to src/utils/getPreRelease.ts From 3d115e445a8f55999a7e03487b50c524561e4928 Mon Sep 17 00:00:00 2001 From: Matt Carroll Date: Fri, 17 Jan 2025 14:34:37 +1100 Subject: [PATCH 2/8] Fixed typos in docs --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 657787e..8246855 100644 --- a/README.md +++ b/README.md @@ -46,9 +46,9 @@ To avoid constant merge conflicts with the `CHANGELOG.md` file. The Release CLI The `.keep` file will simply prevent the directory from being removed from source control after each release. -Each time a developer wants to add an entry to a the changelog as part of the current release, create a file in the `changelog-entries` directory. The file must adhere to the [keepachangelog](https://keepachangelog.com/) format. +Each time a developer wants to add an entry to the changelog as part of the current release, create a file in the `changelog-entries` directory. The file must adhere to the [keepachangelog](https://keepachangelog.com/) format. -Files can have as many entries as desired, however it is recommend to keep entries small to avoid merge conflicts with other developers. +Files can have as many entries as desired, however it is recommended to keep entries small to avoid merge conflicts with other developers. **All of the entry files will be removed as part of the release.** From 9272abdd2072827d105a892cd2f21522998a1408 Mon Sep 17 00:00:00 2001 From: Matt Carroll Date: Fri, 17 Jan 2025 16:04:35 +1100 Subject: [PATCH 3/8] ON-46204 # Fixed empty change being displayed during product release --- src/changelog/addNextReleaseToChangelog.ts | 39 +++++---------- .../generateNextReleaseChangelogEntries.ts | 47 +++++++++++++++++ src/commands/startProductRelease.ts | 50 ++++++------------- 3 files changed, 74 insertions(+), 62 deletions(-) create mode 100644 src/changelog/generateNextReleaseChangelogEntries.ts diff --git a/src/changelog/addNextReleaseToChangelog.ts b/src/changelog/addNextReleaseToChangelog.ts index 2216a23..614150a 100644 --- a/src/changelog/addNextReleaseToChangelog.ts +++ b/src/changelog/addNextReleaseToChangelog.ts @@ -3,11 +3,9 @@ import prettier from 'prettier' import { SemVer } from 'semver' import wrapWithLoading from '../terminal/wrapWithLoading.js' import { RepositoryPlugin } from '../repositories-plugins/RepositoryPlugin.js' -import generateCodeChangelogEntries from './generateCodeChangelogEntries.js' -import generateDependenciesChangelogEntry from './generateDependenciesChangelogEntry.js' -import parseChangelogWithLoading from './parseChangelogWithLoading.js' - -const UNRELEASED_VERSION_INDEX = 0 +import generateNextReleaseChangelogEntries, { + UNRELEASED_VERSION_INDEX, +} from './generateNextReleaseChangelogEntries.js' export default async function addNextReleaseToChangelog({ nextSemverVersion, @@ -18,27 +16,18 @@ export default async function addNextReleaseToChangelog({ releaseName: string | undefined repositoryPlugin: RepositoryPlugin }) { - const { parsedChangelog, changelogPath } = await parseChangelogWithLoading( - repositoryPlugin.cwd, - ) - - const dependenciesChangelogEntry = await generateDependenciesChangelogEntry({ + const { parsedChangelog, - repositoryPlugin, - }) - - const { formatted: codeChangelogEntries, entryFiles } = - await generateCodeChangelogEntries({ - cwd: repositoryPlugin.cwd, - }) + changelogPath, + nextReleaseChangelogEntries, + changelogEntryFiles, + } = await generateNextReleaseChangelogEntries({ repositoryPlugin }) const nextReleaseTitle = `[${nextSemverVersion.version}] - ${new Date() .toISOString() .substring(0, 10)}` const releaseNameSubtitle = releaseName - ? ` - -##### Release Name: ${releaseName}` + ? `##### Release Name: ${releaseName}` : '' await wrapWithLoading( @@ -59,13 +48,11 @@ ${parsedChangelog.versions return ` ## ${title} -## ${nextReleaseTitle}${releaseNameSubtitle} +## ${nextReleaseTitle} -${body} +${releaseNameSubtitle} -${codeChangelogEntries} - -${dependenciesChangelogEntry} +${nextReleaseChangelogEntries} ` } @@ -87,7 +74,7 @@ ${body} }, ) - for (const { filePath } of entryFiles) { + for (const { filePath } of changelogEntryFiles) { wrapWithLoading( { startText: `Deleting file: "${filePath}"`, diff --git a/src/changelog/generateNextReleaseChangelogEntries.ts b/src/changelog/generateNextReleaseChangelogEntries.ts new file mode 100644 index 0000000..787f9ee --- /dev/null +++ b/src/changelog/generateNextReleaseChangelogEntries.ts @@ -0,0 +1,47 @@ +import prettier from 'prettier' +import { RepositoryPlugin } from '../repositories-plugins/RepositoryPlugin.js' +import generateCodeChangelogEntries from './generateCodeChangelogEntries.js' +import generateDependenciesChangelogEntry from './generateDependenciesChangelogEntry.js' +import parseChangelogWithLoading from './parseChangelogWithLoading.js' + +export const UNRELEASED_VERSION_INDEX = 0 + +export default async function generateNextReleaseChangelogEntries({ + repositoryPlugin, +}: { + repositoryPlugin: RepositoryPlugin +}) { + const { parsedChangelog, changelogPath } = await parseChangelogWithLoading( + repositoryPlugin.cwd, + ) + + const { formatted: codeChangelogEntries, entryFiles: changelogEntryFiles } = + await generateCodeChangelogEntries({ + cwd: repositoryPlugin.cwd, + }) + + const dependenciesChangelogEntry = await generateDependenciesChangelogEntry({ + parsedChangelog, + repositoryPlugin, + }) + + const nextReleaseChangelogEntries = await prettier.format( + ` +${parsedChangelog.versions[UNRELEASED_VERSION_INDEX]?.body || ''} + +${codeChangelogEntries} + +${dependenciesChangelogEntry} +`, + { + parser: 'markdown', + }, + ) + + return { + changelogEntryFiles, + parsedChangelog, + changelogPath, + nextReleaseChangelogEntries, + } +} diff --git a/src/commands/startProductRelease.ts b/src/commands/startProductRelease.ts index 946af47..87b9153 100644 --- a/src/commands/startProductRelease.ts +++ b/src/commands/startProductRelease.ts @@ -1,12 +1,12 @@ import enquirer from 'enquirer' import executeCommand from '../terminal/executeCommand.js' -import parseChangelogWithLoading from '../changelog/parseChangelogWithLoading.js' import promptForNextVersion from '../terminal/promptForNextVersion.js' import boxen from 'boxen' import chalk from 'chalk' import startRepositoryRelease from './startRepositoryRelease.js' import getRepositoryPlugin from '../repositories-plugins/plugins-factory.js' import enumerateProductRepositories from '../repositories/enumerateProductRepositories.js' +import generateNextReleaseChangelogEntries from '../changelog/generateNextReleaseChangelogEntries.js' export default async function startProductRelease({ releaseName, @@ -17,31 +17,27 @@ export default async function startProductRelease({ const deploymentRequiredUrls: string[] = [] await enumerateProductRepositories( - async ({ productRepository, cloneUrl, repositoryWorkingDirectory }) => { + async ({ productRepository, repositoryWorkingDirectory }) => { const { repositoryName } = productRepository - // Check if repository needs releasing - const { parsedChangelog } = await parseChangelogWithLoading( - repositoryWorkingDirectory, - ) - const unreleasedVersion = parsedChangelog.versions.find((version) => - version.title.toLowerCase().includes('unreleased'), - ) - if (!unreleasedVersion) { - await continuePromptWithWarning(`"${repositoryName}" CHANGELOG.md does not contain an "Unreleased" section - -You need to checkout "${cloneUrl}" to fix this before trying again.`) - return - } - const { stdout: lastCommitMessage } = await executeCommand( 'git', ['log', '-1', '--pretty=oneline'], repositoryWorkingDirectory, ) + + const repositoryPlugin = await getRepositoryPlugin({ + cwd: repositoryWorkingDirectory, + repositoryType: productRepository, + }) + + const { nextReleaseChangelogEntries } = + await generateNextReleaseChangelogEntries({ + repositoryPlugin, + }) const unreleasedChangelogEntries = - unreleasedVersion.body.trim() || - chalk.italic('There are no entries under the "Unreleased" heading.') + nextReleaseChangelogEntries.trim() || + chalk.italic('There will be no entries under the "Unreleased" heading.') console.log( boxen( chalk.blue(`${unreleasedChangelogEntries} @@ -79,11 +75,6 @@ Last Commit: ${lastCommitMessage}`), return } - const repositoryPlugin = await getRepositoryPlugin({ - cwd: repositoryWorkingDirectory, - repositoryType: productRepository, - }) - const { nextVersion } = await promptForNextVersion({ repositoryPlugin, noPreRelease: true, @@ -124,16 +115,3 @@ Last Commit: ${lastCommitMessage}`), ) } } - -async function continuePromptWithWarning(warning: string) { - console.log( - boxen(chalk.yellow(warning), { - padding: 1, - }), - ) - await enquirer.prompt({ - type: 'invisible', - name: 'continue', - message: 'Press ENTER to continue.', - }) -} From 559f7b74486a5bf46fe5ef0d381262b244beca77 Mon Sep 17 00:00:00 2001 From: Matt Carroll Date: Tue, 21 Jan 2025 12:31:22 +1100 Subject: [PATCH 4/8] ON-46204 # Added unit tests for generating changelog from files --- .eslintrc.json | 2 +- README.md | 1 - jest.config.js | 6 +- package-lock.json | 353 +++++++++++++++--- package.json | 6 +- src/changelog/generateCodeChangelogEntries.ts | 1 + test/.eslintrc.json | 4 + .../empty-changelog/changelog-entries/.keep | 0 .../valid-changelog/changelog-entries/.keep | 0 .../changelog-entries/entry1.md | 3 + .../changelog-entries/entry2.md | 3 + .../generateCodeChangelogEntries.test.ts.snap | 37 ++ .../generateCodeChangelogEntries.test.ts | 24 ++ test/src/commands/startReleaseProcess.test.ts | 5 + test/startReleaseProcess.test.ts | 10 - test/tsconfig.json | 7 + tsconfig.json | 2 +- types/package-diff-summary.d.ts | 6 - 18 files changed, 384 insertions(+), 86 deletions(-) create mode 100644 test/fixtures/empty-changelog/changelog-entries/.keep create mode 100644 test/fixtures/valid-changelog/changelog-entries/.keep create mode 100644 test/fixtures/valid-changelog/changelog-entries/entry1.md create mode 100644 test/fixtures/valid-changelog/changelog-entries/entry2.md create mode 100644 test/src/changelog/__snapshots__/generateCodeChangelogEntries.test.ts.snap create mode 100644 test/src/changelog/generateCodeChangelogEntries.test.ts create mode 100644 test/src/commands/startReleaseProcess.test.ts delete mode 100644 test/startReleaseProcess.test.ts create mode 100644 test/tsconfig.json delete mode 100644 types/package-diff-summary.d.ts diff --git a/.eslintrc.json b/.eslintrc.json index 619ab8f..ae2d5d0 100644 --- a/.eslintrc.json +++ b/.eslintrc.json @@ -15,7 +15,7 @@ "SharedArrayBuffer": "readonly" }, "parserOptions": { - "ecmaVersion": 2020 + "ecmaVersion": 2022 }, "rules": { "no-console": "off" diff --git a/README.md b/README.md index 8246855..cb39bd3 100644 --- a/README.md +++ b/README.md @@ -6,7 +6,6 @@ Used internally by OneBlink to release repositories quickly and consistently - [Node.js](https://nodejs.org/) 20.0 or newer - NPM 10.0 or newer -- See recommendation from [package-diff-summary](https://github.com/jokeyrhyme/package-diff-summary.js#github_oauth_token) regarding [GitHub API Rate Limiting](https://docs.github.com/en/rest/overview/resources-in-the-rest-api#rate-limiting) ## Installation diff --git a/jest.config.js b/jest.config.js index 04d14af..f5d1552 100644 --- a/jest.config.js +++ b/jest.config.js @@ -1,6 +1,4 @@ -/** - * @type {import('jest').Config} - */ +/** @type {import('jest').Config} */ const config = { preset: 'ts-jest', testEnvironment: 'node', @@ -11,6 +9,8 @@ const config = { 'ts-jest', { useESM: true, + isolatedModules: true, + tsconfig: './test/tsconfig.json', }, ], }, diff --git a/package-lock.json b/package-lock.json index 12630f1..5af997a 100644 --- a/package-lock.json +++ b/package-lock.json @@ -49,7 +49,7 @@ "eslint-plugin-prettier": "^5.0.1", "jest": "^29.7.0", "prettier-plugin-jsdoc": "^1.1.1", - "ts-jest": "^29.1.1", + "ts-jest": "^29.2.5", "typescript": "^5.2.2" }, "engines": { @@ -2423,6 +2423,13 @@ "node": ">=8" } }, + "node_modules/async": { + "version": "3.2.6", + "resolved": "https://registry.npmjs.org/async/-/async-3.2.6.tgz", + "integrity": "sha512-htCUDlxyyCLMgaM3xXg0C0LW2xqfuQ6p05pCEIsXuyQ+a1koYKTuBMzRNwmybfLgvJDMd0r1LTn4+E0Ti6C2AA==", + "dev": true, + "license": "MIT" + }, "node_modules/at-least-node": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/at-least-node/-/at-least-node-1.0.0.tgz", @@ -3569,6 +3576,22 @@ "resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz", "integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==" }, + "node_modules/ejs": { + "version": "3.1.10", + "resolved": "https://registry.npmjs.org/ejs/-/ejs-3.1.10.tgz", + "integrity": "sha512-UeJmFfOrAQS8OJWPZ4qtgHyWExa088/MtK5UEyoJGFH67cDEXkZSviOiKRCZ4Xij0zxI3JECgYs3oKx+AizQBA==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "jake": "^10.8.5" + }, + "bin": { + "ejs": "bin/cli.js" + }, + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/electron-to-chromium": { "version": "1.4.348", "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.348.tgz", @@ -4149,6 +4172,39 @@ "node": "^10.12.0 || >=12.0.0" } }, + "node_modules/filelist": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/filelist/-/filelist-1.0.4.tgz", + "integrity": "sha512-w1cEuf3S+DrLCQL7ET6kz+gmlJdbq9J7yXCSjK/OZCPA+qEN1WyF4ZAf0YYJa4/shHJra2t/d/r8SV4Ji+x+8Q==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "minimatch": "^5.0.1" + } + }, + "node_modules/filelist/node_modules/brace-expansion": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "dev": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0" + } + }, + "node_modules/filelist/node_modules/minimatch": { + "version": "5.1.6", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.6.tgz", + "integrity": "sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==", + "dev": true, + "license": "ISC", + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=10" + } + }, "node_modules/fill-range": { "version": "7.1.1", "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz", @@ -4956,6 +5012,101 @@ "url": "https://github.com/sponsors/isaacs" } }, + "node_modules/jake": { + "version": "10.9.2", + "resolved": "https://registry.npmjs.org/jake/-/jake-10.9.2.tgz", + "integrity": "sha512-2P4SQ0HrLQ+fw6llpLnOaGAvN2Zu6778SJMrCUwns4fOoG9ayrTiZk3VV8sCPkVZF8ab0zksVpS8FDY5pRCNBA==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "async": "^3.2.3", + "chalk": "^4.0.2", + "filelist": "^1.0.4", + "minimatch": "^3.1.2" + }, + "bin": { + "jake": "bin/cli.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/jake/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "license": "MIT", + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/jake/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/jake/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/jake/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true, + "license": "MIT" + }, + "node_modules/jake/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/jake/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "license": "MIT", + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/jest": { "version": "29.7.0", "resolved": "https://registry.npmjs.org/jest/-/jest-29.7.0.tgz", @@ -6896,17 +7047,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/lru-cache": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", - "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", - "dependencies": { - "yallist": "^4.0.0" - }, - "engines": { - "node": ">=10" - } - }, "node_modules/make-error": { "version": "1.3.6", "resolved": "https://registry.npmjs.org/make-error/-/make-error-1.3.6.tgz", @@ -8754,12 +8894,10 @@ ] }, "node_modules/semver": { - "version": "7.5.4", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", - "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", - "dependencies": { - "lru-cache": "^6.0.0" - }, + "version": "7.6.3", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", + "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==", + "license": "ISC", "bin": { "semver": "bin/semver.js" }, @@ -9151,28 +9289,31 @@ } }, "node_modules/ts-jest": { - "version": "29.1.1", - "resolved": "https://registry.npmjs.org/ts-jest/-/ts-jest-29.1.1.tgz", - "integrity": "sha512-D6xjnnbP17cC85nliwGiL+tpoKN0StpgE0TeOjXQTU6MVCfsB4v7aW05CgQ/1OywGb0x/oy9hHFnN+sczTiRaA==", + "version": "29.2.5", + "resolved": "https://registry.npmjs.org/ts-jest/-/ts-jest-29.2.5.tgz", + "integrity": "sha512-KD8zB2aAZrcKIdGk4OwpJggeLcH1FgrICqDSROWqlnJXGCXK4Mn6FcdK2B6670Xr73lHMG1kHw8R87A0ecZ+vA==", "dev": true, + "license": "MIT", "dependencies": { - "bs-logger": "0.x", - "fast-json-stable-stringify": "2.x", + "bs-logger": "^0.2.6", + "ejs": "^3.1.10", + "fast-json-stable-stringify": "^2.1.0", "jest-util": "^29.0.0", "json5": "^2.2.3", - "lodash.memoize": "4.x", - "make-error": "1.x", - "semver": "^7.5.3", - "yargs-parser": "^21.0.1" + "lodash.memoize": "^4.1.2", + "make-error": "^1.3.6", + "semver": "^7.6.3", + "yargs-parser": "^21.1.1" }, "bin": { "ts-jest": "cli.js" }, "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "node": "^14.15.0 || ^16.10.0 || ^18.0.0 || >=20.0.0" }, "peerDependencies": { "@babel/core": ">=7.0.0-beta.0 <8", + "@jest/transform": "^29.0.0", "@jest/types": "^29.0.0", "babel-jest": "^29.0.0", "jest": "^29.0.0", @@ -9182,6 +9323,9 @@ "@babel/core": { "optional": true }, + "@jest/transform": { + "optional": true + }, "@jest/types": { "optional": true }, @@ -9623,11 +9767,6 @@ "node": ">=10" } }, - "node_modules/yallist": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" - }, "node_modules/yaml": { "version": "2.3.4", "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.3.4.tgz", @@ -11463,6 +11602,12 @@ "integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==", "dev": true }, + "async": { + "version": "3.2.6", + "resolved": "https://registry.npmjs.org/async/-/async-3.2.6.tgz", + "integrity": "sha512-htCUDlxyyCLMgaM3xXg0C0LW2xqfuQ6p05pCEIsXuyQ+a1koYKTuBMzRNwmybfLgvJDMd0r1LTn4+E0Ti6C2AA==", + "dev": true + }, "at-least-node": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/at-least-node/-/at-least-node-1.0.0.tgz", @@ -12239,6 +12384,15 @@ "resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz", "integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==" }, + "ejs": { + "version": "3.1.10", + "resolved": "https://registry.npmjs.org/ejs/-/ejs-3.1.10.tgz", + "integrity": "sha512-UeJmFfOrAQS8OJWPZ4qtgHyWExa088/MtK5UEyoJGFH67cDEXkZSviOiKRCZ4Xij0zxI3JECgYs3oKx+AizQBA==", + "dev": true, + "requires": { + "jake": "^10.8.5" + } + }, "electron-to-chromium": { "version": "1.4.348", "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.348.tgz", @@ -12648,6 +12802,35 @@ "flat-cache": "^3.0.4" } }, + "filelist": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/filelist/-/filelist-1.0.4.tgz", + "integrity": "sha512-w1cEuf3S+DrLCQL7ET6kz+gmlJdbq9J7yXCSjK/OZCPA+qEN1WyF4ZAf0YYJa4/shHJra2t/d/r8SV4Ji+x+8Q==", + "dev": true, + "requires": { + "minimatch": "^5.0.1" + }, + "dependencies": { + "brace-expansion": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "dev": true, + "requires": { + "balanced-match": "^1.0.0" + } + }, + "minimatch": { + "version": "5.1.6", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.6.tgz", + "integrity": "sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==", + "dev": true, + "requires": { + "brace-expansion": "^2.0.1" + } + } + } + }, "fill-range": { "version": "7.1.1", "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz", @@ -13180,6 +13363,69 @@ "@isaacs/cliui": "^8.0.2" } }, + "jake": { + "version": "10.9.2", + "resolved": "https://registry.npmjs.org/jake/-/jake-10.9.2.tgz", + "integrity": "sha512-2P4SQ0HrLQ+fw6llpLnOaGAvN2Zu6778SJMrCUwns4fOoG9ayrTiZk3VV8sCPkVZF8ab0zksVpS8FDY5pRCNBA==", + "dev": true, + "requires": { + "async": "^3.2.3", + "chalk": "^4.0.2", + "filelist": "^1.0.4", + "minimatch": "^3.1.2" + }, + "dependencies": { + "ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "requires": { + "color-convert": "^2.0.1" + } + }, + "chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "requires": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + } + }, + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "requires": { + "color-name": "~1.1.4" + } + }, + "color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true + }, + "supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "requires": { + "has-flag": "^4.0.0" + } + } + } + }, "jest": { "version": "29.7.0", "resolved": "https://registry.npmjs.org/jest/-/jest-29.7.0.tgz", @@ -14606,14 +14852,6 @@ "is-unicode-supported": "^1.1.0" } }, - "lru-cache": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", - "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", - "requires": { - "yallist": "^4.0.0" - } - }, "make-error": { "version": "1.3.6", "resolved": "https://registry.npmjs.org/make-error/-/make-error-1.3.6.tgz", @@ -15787,12 +16025,9 @@ "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==" }, "semver": { - "version": "7.5.4", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", - "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", - "requires": { - "lru-cache": "^6.0.0" - } + "version": "7.6.3", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", + "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==" }, "semver-diff": { "version": "4.0.0", @@ -16079,19 +16314,20 @@ "requires": {} }, "ts-jest": { - "version": "29.1.1", - "resolved": "https://registry.npmjs.org/ts-jest/-/ts-jest-29.1.1.tgz", - "integrity": "sha512-D6xjnnbP17cC85nliwGiL+tpoKN0StpgE0TeOjXQTU6MVCfsB4v7aW05CgQ/1OywGb0x/oy9hHFnN+sczTiRaA==", + "version": "29.2.5", + "resolved": "https://registry.npmjs.org/ts-jest/-/ts-jest-29.2.5.tgz", + "integrity": "sha512-KD8zB2aAZrcKIdGk4OwpJggeLcH1FgrICqDSROWqlnJXGCXK4Mn6FcdK2B6670Xr73lHMG1kHw8R87A0ecZ+vA==", "dev": true, "requires": { - "bs-logger": "0.x", - "fast-json-stable-stringify": "2.x", + "bs-logger": "^0.2.6", + "ejs": "^3.1.10", + "fast-json-stable-stringify": "^2.1.0", "jest-util": "^29.0.0", "json5": "^2.2.3", - "lodash.memoize": "4.x", - "make-error": "1.x", - "semver": "^7.5.3", - "yargs-parser": "^21.0.1" + "lodash.memoize": "^4.1.2", + "make-error": "^1.3.6", + "semver": "^7.6.3", + "yargs-parser": "^21.1.1" } }, "type-check": { @@ -16389,11 +16625,6 @@ "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", "dev": true }, - "yallist": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" - }, "yaml": { "version": "2.3.4", "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.3.4.tgz", diff --git a/package.json b/package.json index ebcc4fb..8133146 100644 --- a/package.json +++ b/package.json @@ -46,7 +46,7 @@ "eslint-plugin-prettier": "^5.0.1", "jest": "^29.7.0", "prettier-plugin-jsdoc": "^1.1.1", - "ts-jest": "^29.1.1", + "ts-jest": "^29.2.5", "typescript": "^5.2.2" }, "directories": { @@ -76,7 +76,7 @@ "scripts": { "build": "tsc --build", "eslint": "eslint --fix --cache --quiet ./src", - "jest": "cross-env NODE_OPTIONS=--experimental-vm-modules jest --silent", + "jest": "cross-env NODE_OPTIONS=--experimental-vm-modules jest ", "postinstall": "patch-package", "prepare": "npm run build", "prerelease": "npm run build", @@ -86,4 +86,4 @@ "typescript": "tsc --noEmit" }, "type": "module" -} +} \ No newline at end of file diff --git a/src/changelog/generateCodeChangelogEntries.ts b/src/changelog/generateCodeChangelogEntries.ts index ca106dd..97e2506 100644 --- a/src/changelog/generateCodeChangelogEntries.ts +++ b/src/changelog/generateCodeChangelogEntries.ts @@ -20,6 +20,7 @@ export default async function generateCodeChangelogEntries({ const entryFilePaths = await glob( `${CHANGELOG_ENTRIES_DIRECTORY_NAME}/**`, { + absolute: true, cwd, nodir: true, }, diff --git a/test/.eslintrc.json b/test/.eslintrc.json index a80a425..56a92f6 100644 --- a/test/.eslintrc.json +++ b/test/.eslintrc.json @@ -5,5 +5,9 @@ }, "rules": { "@typescript-eslint/no-explicit-any": "off" + }, + "parserOptions": { + "ecmaVersion": 2022, + "project": "./test/tsconfig.json" } } diff --git a/test/fixtures/empty-changelog/changelog-entries/.keep b/test/fixtures/empty-changelog/changelog-entries/.keep new file mode 100644 index 0000000..e69de29 diff --git a/test/fixtures/valid-changelog/changelog-entries/.keep b/test/fixtures/valid-changelog/changelog-entries/.keep new file mode 100644 index 0000000..e69de29 diff --git a/test/fixtures/valid-changelog/changelog-entries/entry1.md b/test/fixtures/valid-changelog/changelog-entries/entry1.md new file mode 100644 index 0000000..b47c9bc --- /dev/null +++ b/test/fixtures/valid-changelog/changelog-entries/entry1.md @@ -0,0 +1,3 @@ +### Added + +- Feature 1 diff --git a/test/fixtures/valid-changelog/changelog-entries/entry2.md b/test/fixtures/valid-changelog/changelog-entries/entry2.md new file mode 100644 index 0000000..75e5dba --- /dev/null +++ b/test/fixtures/valid-changelog/changelog-entries/entry2.md @@ -0,0 +1,3 @@ +### Fixed + +- Bug 1 diff --git a/test/src/changelog/__snapshots__/generateCodeChangelogEntries.test.ts.snap b/test/src/changelog/__snapshots__/generateCodeChangelogEntries.test.ts.snap new file mode 100644 index 0000000..94b958f --- /dev/null +++ b/test/src/changelog/__snapshots__/generateCodeChangelogEntries.test.ts.snap @@ -0,0 +1,37 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`generateCodeChangelogEntries should handle empty changelog directory 1`] = ` +{ + "entryFiles": [], + "formatted": "", +} +`; + +exports[`generateCodeChangelogEntries should process changelog entries and format them 1`] = ` +{ + "entryFiles": [ + { + "filePath": "/Users/mattcarroll/Documents/sources/github/oneblink/release-cli/test/fixtures/valid-changelog/changelog-entries/entry2.md", + "markdown": "### Fixed + +- Bug 1 +", + }, + { + "filePath": "/Users/mattcarroll/Documents/sources/github/oneblink/release-cli/test/fixtures/valid-changelog/changelog-entries/entry1.md", + "markdown": "### Added + +- Feature 1 +", + }, + ], + "formatted": "### Added + +- Feature 1 + +### Fixed + +- Bug 1 +", +} +`; diff --git a/test/src/changelog/generateCodeChangelogEntries.test.ts b/test/src/changelog/generateCodeChangelogEntries.test.ts new file mode 100644 index 0000000..43ab928 --- /dev/null +++ b/test/src/changelog/generateCodeChangelogEntries.test.ts @@ -0,0 +1,24 @@ +import path from 'path' +import generateCodeChangelogEntries from '../../../src/changelog/generateCodeChangelogEntries.js' + +describe('generateCodeChangelogEntries', () => { + const fixturesPath = path.resolve(process.cwd(), 'test', 'fixtures') + + it('should process changelog entries and format them', async () => { + const cwd = path.join(fixturesPath, 'valid-changelog') + console.log('cwd', cwd) + + const result = await generateCodeChangelogEntries({ cwd }) + + expect(result).toMatchSnapshot() + }) + + it('should handle empty changelog directory', async () => { + const cwd = path.join(fixturesPath, 'empty-changelog') + console.log('cwd', cwd) + + const result = await generateCodeChangelogEntries({ cwd }) + + expect(result).toMatchSnapshot() + }) +}) diff --git a/test/src/commands/startReleaseProcess.test.ts b/test/src/commands/startReleaseProcess.test.ts new file mode 100644 index 0000000..6584386 --- /dev/null +++ b/test/src/commands/startReleaseProcess.test.ts @@ -0,0 +1,5 @@ +import startRepositoryRelease from '../../../src/commands/startRepositoryRelease.js' + +test('startReleaseProcess should be a function', () => { + expect(typeof startRepositoryRelease).toBe('function') +}) diff --git a/test/startReleaseProcess.test.ts b/test/startReleaseProcess.test.ts deleted file mode 100644 index d40e7a6..0000000 --- a/test/startReleaseProcess.test.ts +++ /dev/null @@ -1,10 +0,0 @@ -// import startReleaseProcess from '../src/startReleaseProcess.js' - -console.log('before test') -test('startReleaseProcess should be a function', () => { - console.log('test start') - // expect(typeof startReleaseProcess).toBe('function') - expect(1).toBe(1) - console.log('test end') -}) -console.log('after test') diff --git a/test/tsconfig.json b/test/tsconfig.json new file mode 100644 index 0000000..247515b --- /dev/null +++ b/test/tsconfig.json @@ -0,0 +1,7 @@ +{ + "extends": "../tsconfig.json", + "compilerOptions": { + "rootDir": ".." + }, + "include": ["."] +} diff --git a/tsconfig.json b/tsconfig.json index 8674f6b..1e22ef3 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -70,5 +70,5 @@ "skipLibCheck": true /* Skip type checking of declaration files. */, "forceConsistentCasingInFileNames": true /* Disallow inconsistently-cased references to the same file. */ }, - "include": ["src", "types"] + "include": ["src"] } diff --git a/types/package-diff-summary.d.ts b/types/package-diff-summary.d.ts deleted file mode 100644 index aeb451e..0000000 --- a/types/package-diff-summary.d.ts +++ /dev/null @@ -1,6 +0,0 @@ -declare module 'package-diff-summary' { - export function main(options: { - previousVersion: string - cwd: string - }): string -} From 68b033124fa72fc36a3afc1e1190426ce4f9ba31 Mon Sep 17 00:00:00 2001 From: Matt Carroll Date: Tue, 21 Jan 2025 12:40:14 +1100 Subject: [PATCH 5/8] ON-46204 # Fixed snapshots including developer file paths --- .../generateCodeChangelogEntries.test.ts.snap | 29 ++----------------- .../generateCodeChangelogEntries.test.ts | 6 ++-- 2 files changed, 7 insertions(+), 28 deletions(-) diff --git a/test/src/changelog/__snapshots__/generateCodeChangelogEntries.test.ts.snap b/test/src/changelog/__snapshots__/generateCodeChangelogEntries.test.ts.snap index 94b958f..8a521c4 100644 --- a/test/src/changelog/__snapshots__/generateCodeChangelogEntries.test.ts.snap +++ b/test/src/changelog/__snapshots__/generateCodeChangelogEntries.test.ts.snap @@ -1,37 +1,14 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP -exports[`generateCodeChangelogEntries should handle empty changelog directory 1`] = ` -{ - "entryFiles": [], - "formatted": "", -} -`; +exports[`generateCodeChangelogEntries should handle empty changelog directory 1`] = `""`; exports[`generateCodeChangelogEntries should process changelog entries and format them 1`] = ` -{ - "entryFiles": [ - { - "filePath": "/Users/mattcarroll/Documents/sources/github/oneblink/release-cli/test/fixtures/valid-changelog/changelog-entries/entry2.md", - "markdown": "### Fixed - -- Bug 1 -", - }, - { - "filePath": "/Users/mattcarroll/Documents/sources/github/oneblink/release-cli/test/fixtures/valid-changelog/changelog-entries/entry1.md", - "markdown": "### Added - -- Feature 1 -", - }, - ], - "formatted": "### Added +"### Added - Feature 1 ### Fixed - Bug 1 -", -} +" `; diff --git a/test/src/changelog/generateCodeChangelogEntries.test.ts b/test/src/changelog/generateCodeChangelogEntries.test.ts index 43ab928..48d13f2 100644 --- a/test/src/changelog/generateCodeChangelogEntries.test.ts +++ b/test/src/changelog/generateCodeChangelogEntries.test.ts @@ -10,7 +10,8 @@ describe('generateCodeChangelogEntries', () => { const result = await generateCodeChangelogEntries({ cwd }) - expect(result).toMatchSnapshot() + expect(result.entryFiles).toHaveLength(2) + expect(result.formatted).toMatchSnapshot() }) it('should handle empty changelog directory', async () => { @@ -19,6 +20,7 @@ describe('generateCodeChangelogEntries', () => { const result = await generateCodeChangelogEntries({ cwd }) - expect(result).toMatchSnapshot() + expect(result.entryFiles).toHaveLength(0) + expect(result.formatted).toMatchSnapshot() }) }) From 923a8973b50427820ff560c5618218727abeb320 Mon Sep 17 00:00:00 2001 From: Matt Carroll Date: Tue, 21 Jan 2025 12:44:29 +1100 Subject: [PATCH 6/8] ON-46204 # Added --silent back into tests --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 8133146..68bf1fc 100644 --- a/package.json +++ b/package.json @@ -76,7 +76,7 @@ "scripts": { "build": "tsc --build", "eslint": "eslint --fix --cache --quiet ./src", - "jest": "cross-env NODE_OPTIONS=--experimental-vm-modules jest ", + "jest": "cross-env NODE_OPTIONS=--experimental-vm-modules jest --silent", "postinstall": "patch-package", "prepare": "npm run build", "prerelease": "npm run build", From 4bfe927c4cddb202a2bc4043e201f4797db24e52 Mon Sep 17 00:00:00 2001 From: Matt Carroll Date: Tue, 21 Jan 2025 12:59:50 +1100 Subject: [PATCH 7/8] ON-46204 # Added help for changelog-preview command --- changelog-entries/changelog-automation.md | 1 + src/bin.ts | 27 ++++++++++++++++++----- src/commands/startChangelogPreview.ts | 23 ++++++++++--------- 3 files changed, 36 insertions(+), 15 deletions(-) diff --git a/changelog-entries/changelog-automation.md b/changelog-entries/changelog-automation.md index 6f7fdf5..d89229d 100644 --- a/changelog-entries/changelog-automation.md +++ b/changelog-entries/changelog-automation.md @@ -1,3 +1,4 @@ ### Added - changelog automation from a `changelog-entries` directory +- `oneblink-release changelog-preview` command diff --git a/src/bin.ts b/src/bin.ts index affd615..448bdc5 100644 --- a/src/bin.ts +++ b/src/bin.ts @@ -25,8 +25,8 @@ ${chalk.grey( the information required to perform the release.`, )} - --name ......... Skip the question to enter a name for the release by passing - a release name as a flag. + --name ........... Skip the question to enter a name for the release by + passing a release name as a flag. ${chalk.bold('Examples')} @@ -68,16 +68,33 @@ ${chalk.bold('Examples')} oneblink-release repository 1.1.1 --cwd ../path/to/code oneblink-release repository 1.1.1-uat.1 --no-git +${chalk.bold.blue('oneblink-release update-dependents [--cwd path]')} + ${chalk.grey('Update all product code bases that depend on an NPM package.')} - --cwd .......... Directory of the repository that is the dependency relative - to the current working directory, defaults to the current - working directory. + --cwd ............ Directory of the repository that is the dependency relative + to the current working directory, defaults to the current + working directory. ${chalk.bold('Examples')} oneblink-release update-dependents oneblink-release update-dependents --cwd ../path/to/code + +${chalk.bold.blue('oneblink-release changelog-preview [--cwd path]')} + +${chalk.grey( + `Display the changelog entries for the current "Unreleased" version based on +dependency changes and files in the "changelog-entries" directory.`, +)} + + --cwd ............ Directory of the repository to preview, defaults to the + current working directory. + +${chalk.bold('Examples')} + + oneblink-release changelog-preview + oneblink-release changelog-preview --cwd ../path/to/code `, { importMeta: import.meta, diff --git a/src/commands/startChangelogPreview.ts b/src/commands/startChangelogPreview.ts index b472ac4..7c1b298 100644 --- a/src/commands/startChangelogPreview.ts +++ b/src/commands/startChangelogPreview.ts @@ -1,18 +1,21 @@ import boxen from 'boxen' import chalk from 'chalk' -import generateChangelogEntries, { - CHANGELOG_ENTRIES_DIRECTORY_NAME, -} from '../changelog/generateCodeChangelogEntries.js' +import { CHANGELOG_ENTRIES_DIRECTORY_NAME } from '../changelog/generateCodeChangelogEntries.js' +import generateNextReleaseChangelogEntries from '../changelog/generateNextReleaseChangelogEntries.js' +import getRepositoryPlugin from '../repositories-plugins/plugins-factory.js' export default async function startChangelogPreview({ cwd }: { cwd: string }) { - const { formatted: unreleasedChangelogEntries, entryFiles } = - await generateChangelogEntries({ - cwd, + const repositoryPlugin = await getRepositoryPlugin({ + cwd, + }) + const { nextReleaseChangelogEntries, changelogEntryFiles } = + await generateNextReleaseChangelogEntries({ + repositoryPlugin, }) - if (!entryFiles.length) { + if (!nextReleaseChangelogEntries) { console.log( chalk.yellow( - `There are no changelog entry files in the "${CHANGELOG_ENTRIES_DIRECTORY_NAME}" directory`, + `There are no changelog entry files in the "${CHANGELOG_ENTRIES_DIRECTORY_NAME}" directory and there were no dependency changes`, ), ) process.exitCode = 1 @@ -21,7 +24,7 @@ export default async function startChangelogPreview({ cwd }: { cwd: string }) { console.log( boxen( - entryFiles.map(({ filePath }) => filePath).join(` + changelogEntryFiles.map(({ filePath }) => filePath).join(` `), { title: 'Unreleased Entry Files', @@ -34,7 +37,7 @@ export default async function startChangelogPreview({ cwd }: { cwd: string }) { ), ) console.log( - boxen(chalk.blue(unreleasedChangelogEntries), { + boxen(chalk.blue(nextReleaseChangelogEntries), { title: 'Unreleased Entries', padding: 1, margin: { From 5acee574a178b2cdc4b798b05793f84a15986e89 Mon Sep 17 00:00:00 2001 From: Matt Carroll Date: Tue, 21 Jan 2025 15:52:23 +1100 Subject: [PATCH 8/8] ON-46204 # Fixed duplicate changelog headings --- src/changelog/generateCodeChangelogEntries.ts | 35 ++++++++++++------- .../generateNextReleaseChangelogEntries.ts | 4 +-- .../generateCodeChangelogEntries.test.ts.snap | 17 +++++++++ .../generateCodeChangelogEntries.test.ts | 32 +++++++++++++++-- 4 files changed, 71 insertions(+), 17 deletions(-) diff --git a/src/changelog/generateCodeChangelogEntries.ts b/src/changelog/generateCodeChangelogEntries.ts index 97e2506..bab6519 100644 --- a/src/changelog/generateCodeChangelogEntries.ts +++ b/src/changelog/generateCodeChangelogEntries.ts @@ -3,13 +3,14 @@ import { glob } from 'glob' import { parser, Release } from 'keep-a-changelog' import prettier from 'prettier' import wrapWithLoading from '../terminal/wrapWithLoading.js' - export const CHANGELOG_ENTRIES_DIRECTORY_NAME = 'changelog-entries' export default async function generateCodeChangelogEntries({ cwd, + entriesInChangelog, }: { cwd: string + entriesInChangelog: string | undefined }) { return await wrapWithLoading( { @@ -27,6 +28,11 @@ export default async function generateCodeChangelogEntries({ ) const finalRelease = new Release() + + if (entriesInChangelog) { + appendEntryToRelease(entriesInChangelog, finalRelease) + } + const entryFiles: Array<{ filePath: string markdown: string @@ -37,18 +43,7 @@ export default async function generateCodeChangelogEntries({ filePath: entryFilePath, markdown: entry, }) - const parsed = parser(`# Changelog - -## Unreleased - -${entry}`) - for (const release of parsed.releases) { - for (const [type, changes] of release.changes) { - for (const change of changes) { - finalRelease.addChange(type, change) - } - } - } + appendEntryToRelease(entry, finalRelease) } const releaseChangelogEntries = finalRelease @@ -79,3 +74,17 @@ ${entry}`) }, ) } +function appendEntryToRelease(entry: string, finalRelease: Release) { + const parsed = parser(`# Changelog + +## Unreleased + +${entry}`) + for (const release of parsed.releases) { + for (const [type, changes] of release.changes) { + for (const change of changes) { + finalRelease.addChange(type, change) + } + } + } +} diff --git a/src/changelog/generateNextReleaseChangelogEntries.ts b/src/changelog/generateNextReleaseChangelogEntries.ts index 787f9ee..6d4e942 100644 --- a/src/changelog/generateNextReleaseChangelogEntries.ts +++ b/src/changelog/generateNextReleaseChangelogEntries.ts @@ -18,6 +18,8 @@ export default async function generateNextReleaseChangelogEntries({ const { formatted: codeChangelogEntries, entryFiles: changelogEntryFiles } = await generateCodeChangelogEntries({ cwd: repositoryPlugin.cwd, + entriesInChangelog: + parsedChangelog.versions[UNRELEASED_VERSION_INDEX]?.body, }) const dependenciesChangelogEntry = await generateDependenciesChangelogEntry({ @@ -27,8 +29,6 @@ export default async function generateNextReleaseChangelogEntries({ const nextReleaseChangelogEntries = await prettier.format( ` -${parsedChangelog.versions[UNRELEASED_VERSION_INDEX]?.body || ''} - ${codeChangelogEntries} ${dependenciesChangelogEntry} diff --git a/test/src/changelog/__snapshots__/generateCodeChangelogEntries.test.ts.snap b/test/src/changelog/__snapshots__/generateCodeChangelogEntries.test.ts.snap index 8a521c4..88cf5fb 100644 --- a/test/src/changelog/__snapshots__/generateCodeChangelogEntries.test.ts.snap +++ b/test/src/changelog/__snapshots__/generateCodeChangelogEntries.test.ts.snap @@ -12,3 +12,20 @@ exports[`generateCodeChangelogEntries should process changelog entries and forma - Bug 1 " `; + +exports[`generateCodeChangelogEntries should process changelog entries with existing changelog and format them 1`] = ` +"### Added + +- some stuff +- Feature 1 + +### Removed + +- almost everything + +### Fixed + +- some other stuff +- Bug 1 +" +`; diff --git a/test/src/changelog/generateCodeChangelogEntries.test.ts b/test/src/changelog/generateCodeChangelogEntries.test.ts index 48d13f2..02233c5 100644 --- a/test/src/changelog/generateCodeChangelogEntries.test.ts +++ b/test/src/changelog/generateCodeChangelogEntries.test.ts @@ -8,7 +8,32 @@ describe('generateCodeChangelogEntries', () => { const cwd = path.join(fixturesPath, 'valid-changelog') console.log('cwd', cwd) - const result = await generateCodeChangelogEntries({ cwd }) + const result = await generateCodeChangelogEntries({ + cwd, + entriesInChangelog: undefined, + }) + + expect(result.entryFiles).toHaveLength(2) + expect(result.formatted).toMatchSnapshot() + }) + + it('should process changelog entries with existing changelog and format them', async () => { + const cwd = path.join(fixturesPath, 'valid-changelog') + console.log('cwd', cwd) + + const result = await generateCodeChangelogEntries({ + cwd, + entriesInChangelog: `### Added +- some stuff + +### Fixed + +- some other stuff + +### Removed + +- almost everything`, + }) expect(result.entryFiles).toHaveLength(2) expect(result.formatted).toMatchSnapshot() @@ -18,7 +43,10 @@ describe('generateCodeChangelogEntries', () => { const cwd = path.join(fixturesPath, 'empty-changelog') console.log('cwd', cwd) - const result = await generateCodeChangelogEntries({ cwd }) + const result = await generateCodeChangelogEntries({ + cwd, + entriesInChangelog: undefined, + }) expect(result.entryFiles).toHaveLength(0) expect(result.formatted).toMatchSnapshot()