Compare commits

..
68 Commits
Author SHA1 Message Date
Rui Chen 8a0cd651e5 release 3.0.4 (#865)
main / build (push) Canceled after 0s
Signed-off-by: Rui Chen <rui@chenrui.dev>
2026-11-05 09:25:01 -05:00
dependabot[bot] ac01154694 chore(deps): bump the npm group across 1 directory with 4 updates (#864)
Bumps the npm group with 4 updates in the / directory: [@types/node](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/node), [@vitest/coverage-v8](https://github.com/vitest-dev/vitest/tree/HEAD/packages/coverage-v8), [prettier](https://github.com/prettier/prettier) and [vitest](https://github.com/vitest-dev/vitest/tree/HEAD/packages/vitest).


Updates `@types/node` from 24.19.1 to 24.19.2
- [Release notes](https://github.com/DefinitelyTyped/DefinitelyTyped/releases)
- [Commits](https://github.com/DefinitelyTyped/DefinitelyTyped/commits/HEAD/types/node)

Updates `@vitest/coverage-v8` from 5.0.3 to 5.0.5
- [Release notes](https://github.com/vitest-dev/vitest/releases)
- [Changelog](https://github.com/vitest-dev/vitest/blob/main/docs/releases.md)
- [Commits](https://github.com/vitest-dev/vitest/commits/v5.0.5/packages/coverage-v8)

Updates `prettier` from 3.9.9 to 3.9.10
- [Release notes](https://github.com/prettier/prettier/releases)
- [Changelog](https://github.com/prettier/prettier/blob/main/CHANGELOG.md)
- [Commits](https://github.com/prettier/prettier/compare/3.9.9...3.9.10)

Updates `vitest` from 5.0.3 to 5.0.5
- [Release notes](https://github.com/vitest-dev/vitest/releases)
- [Changelog](https://github.com/vitest-dev/vitest/blob/main/docs/releases.md)
- [Commits](https://github.com/vitest-dev/vitest/commits/v5.0.5/packages/vitest)

---
updated-dependencies:
- dependency-name: "@types/node"
  dependency-version: 24.19.2
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: npm
- dependency-name: "@vitest/coverage-v8"
  dependency-version: 5.0.5
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: npm
- dependency-name: prettier
  dependency-version: 3.9.10
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: npm
- dependency-name: vitest
  dependency-version: 5.0.5
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: npm
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-11-05 08:58:51 -05:00
dependabot[bot]andRui Chen ca4c9d538c chore(deps): bump minimatch and glob (#862)
* chore(deps): bump minimatch and glob

Bumps [minimatch](https://github.com/isaacs/minimatch) to 11.0.4 and updates ancestor dependency [glob](https://github.com/isaacs/node-glob). These dependencies need to be updated together.


Updates `minimatch` from 10.2.4 to 11.0.4
- [Changelog](https://github.com/isaacs/minimatch/blob/main/changelog.md)
- [Commits](https://github.com/isaacs/minimatch/compare/v10.2.4...v11.0.4)

Updates `glob` from 13.0.6 to 14.0.3
- [Changelog](https://github.com/isaacs/node-glob/blob/main/changelog.md)
- [Commits](https://github.com/isaacs/node-glob/compare/v13.0.6...v14.0.3)

---
updated-dependencies:
- dependency-name: glob
  dependency-version: 14.0.3
  dependency-type: direct:production
- dependency-name: minimatch
  dependency-version: 11.0.4
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>

* chore: rebuild dist for glob 14.0.3

Signed-off-by: Rui Chen <rui@chenrui.dev>

---------

Signed-off-by: dependabot[bot] <support@github.com>
Signed-off-by: Rui Chen <rui@chenrui.dev>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Rui Chen <rui@chenrui.dev>
2026-11-05 08:54:07 -05:00
dependabot[bot]andRui Chen e4a57aec13 chore(deps): bump undici from 6.29.0 to 6.29.1 (#859)
main / build (push) Canceled after 0s
* chore(deps): bump undici from 6.29.0 to 6.29.1

Bumps [undici](https://github.com/nodejs/undici) from 6.29.0 to 6.29.1.
- [Release notes](https://github.com/nodejs/undici/releases)
- [Commits](https://github.com/nodejs/undici/compare/v6.29.0...v6.29.1)

---
updated-dependencies:
- dependency-name: undici
  dependency-version: 6.29.1
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>

* chore: rebuild dist for undici 6.29.1

Signed-off-by: Rui Chen <rui@chenrui.dev>

---------

Signed-off-by: dependabot[bot] <support@github.com>
Signed-off-by: Rui Chen <rui@chenrui.dev>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Rui Chen <rui@chenrui.dev>
2026-11-04 23:12:09 -05:00
dependabot[bot] ee55a0ef7d chore(deps): bump vite from 8.3.2 to 8.3.5 (#855)
Bumps [vite](https://github.com/vitejs/vite/tree/HEAD/packages/vite) from 8.3.2 to 8.3.5.
- [Release notes](https://github.com/vitejs/vite/releases)
- [Changelog](https://github.com/vitejs/vite/blob/main/packages/vite/CHANGELOG.md)
- [Commits](https://github.com/vitejs/vite/commits/v8.3.5/packages/vite)

---
updated-dependencies:
- dependency-name: vite
  dependency-version: 8.3.5
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-11-04 23:03:26 -05:00
dependabot[bot] 8d42b221d5 chore(deps): bump actions/setup-node (#853)
Bumps the github-actions group with 1 update: [actions/setup-node](https://github.com/actions/setup-node).


Updates `actions/setup-node` from 7.0.0 to 7.1.0
- [Release notes](https://github.com/actions/setup-node/releases)
- [Commits](https://github.com/actions/setup-node/compare/820762786026740c76f36085b0efc47a31fe5020...949feb2413d6458794dcd2491c4babbbce0c15c1)

---
updated-dependencies:
- dependency-name: actions/setup-node
  dependency-version: 7.1.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: github-actions
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-11-04 23:03:17 -05:00
dependabot[bot] 6680cc089e chore(deps): bump the npm group with 3 updates (#851)
main / build (push) Has been cancelled
Bumps the npm group with 3 updates: [@types/node](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/node), [@vitest/coverage-v8](https://github.com/vitest-dev/vitest/tree/HEAD/packages/coverage-v8) and [vitest](https://github.com/vitest-dev/vitest/tree/HEAD/packages/vitest).


Updates `@types/node` from 24.19.0 to 24.19.1
- [Release notes](https://github.com/DefinitelyTyped/DefinitelyTyped/releases)
- [Commits](https://github.com/DefinitelyTyped/DefinitelyTyped/commits/HEAD/types/node)

Updates `@vitest/coverage-v8` from 5.0.2 to 5.0.3
- [Release notes](https://github.com/vitest-dev/vitest/releases)
- [Changelog](https://github.com/vitest-dev/vitest/blob/main/docs/releases.md)
- [Commits](https://github.com/vitest-dev/vitest/commits/v5.0.3/packages/coverage-v8)

Updates `vitest` from 5.0.2 to 5.0.3
- [Release notes](https://github.com/vitest-dev/vitest/releases)
- [Changelog](https://github.com/vitest-dev/vitest/blob/main/docs/releases.md)
- [Commits](https://github.com/vitest-dev/vitest/commits/v5.0.3/packages/vitest)

---
updated-dependencies:
- dependency-name: "@types/node"
  dependency-version: 24.19.1
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: npm
- dependency-name: "@vitest/coverage-v8"
  dependency-version: 5.0.3
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: npm
- dependency-name: vitest
  dependency-version: 5.0.3
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: npm
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-10-17 00:15:27 -04:00
dependabot[bot] 4a050bafc0 chore(deps): bump source-map-js from 1.2.1 to 1.2.2 (#850)
Bumps [source-map-js](https://github.com/7rulnik/source-map-js) from 1.2.1 to 1.2.2.
- [Release notes](https://github.com/7rulnik/source-map-js/releases)
- [Changelog](https://github.com/7rulnik/source-map-js/blob/main/CHANGELOG.md)
- [Commits](https://github.com/7rulnik/source-map-js/compare/v1.2.1...v1.2.2)

---
updated-dependencies:
- dependency-name: source-map-js
  dependency-version: 1.2.2
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-10-17 00:15:20 -04:00
dependabot[bot] b5a645e6d7 chore(deps): bump the npm group with 4 updates (#848)
main / build (push) Has been cancelled
Bumps the npm group with 4 updates: [@types/node](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/node), [@vitest/coverage-v8](https://github.com/vitest-dev/vitest/tree/HEAD/packages/coverage-v8), [prettier](https://github.com/prettier/prettier) and [vitest](https://github.com/vitest-dev/vitest/tree/HEAD/packages/vitest).


Updates `@types/node` from 24.13.6 to 24.19.0
- [Release notes](https://github.com/DefinitelyTyped/DefinitelyTyped/releases)
- [Commits](https://github.com/DefinitelyTyped/DefinitelyTyped/commits/HEAD/types/node)

Updates `@vitest/coverage-v8` from 5.0.1 to 5.0.2
- [Release notes](https://github.com/vitest-dev/vitest/releases)
- [Changelog](https://github.com/vitest-dev/vitest/blob/main/docs/releases.md)
- [Commits](https://github.com/vitest-dev/vitest/commits/v5.0.2/packages/coverage-v8)

Updates `prettier` from 3.9.8 to 3.9.9
- [Release notes](https://github.com/prettier/prettier/releases)
- [Changelog](https://github.com/prettier/prettier/blob/main/CHANGELOG.md)
- [Commits](https://github.com/prettier/prettier/compare/3.9.8...3.9.9)

Updates `vitest` from 5.0.1 to 5.0.2
- [Release notes](https://github.com/vitest-dev/vitest/releases)
- [Changelog](https://github.com/vitest-dev/vitest/blob/main/docs/releases.md)
- [Commits](https://github.com/vitest-dev/vitest/commits/v5.0.2/packages/vitest)

---
updated-dependencies:
- dependency-name: "@types/node"
  dependency-version: 24.19.0
  dependency-type: direct:development
  update-type: version-update:semver-minor
  dependency-group: npm
- dependency-name: "@vitest/coverage-v8"
  dependency-version: 5.0.2
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: npm
- dependency-name: prettier
  dependency-version: 3.9.9
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: npm
- dependency-name: vitest
  dependency-version: 5.0.2
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: npm
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-10-06 18:08:37 -04:00
dependabot[bot] d99a5de306 chore(deps): bump brace-expansion from 5.0.9 to 5.0.12 (#846)
Bumps [brace-expansion](https://github.com/juliangruber/brace-expansion) from 5.0.9 to 5.0.12.
- [Release notes](https://github.com/juliangruber/brace-expansion/releases)
- [Commits](https://github.com/juliangruber/brace-expansion/compare/v5.0.9...v5.0.12)

---
updated-dependencies:
- dependency-name: brace-expansion
  dependency-version: 5.0.12
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-10-06 18:08:27 -04:00
dependabot[bot]andRui Chen 4d8ab33c14 chore(deps): bump undici from 6.28.0 to 6.29.0 (#845)
main / build (push) Has been cancelled
* chore(deps): bump undici from 6.28.0 to 6.29.0

Bumps [undici](https://github.com/nodejs/undici) from 6.28.0 to 6.29.0.
- [Release notes](https://github.com/nodejs/undici/releases)
- [Commits](https://github.com/nodejs/undici/compare/v6.28.0...v6.29.0)

---
updated-dependencies:
- dependency-name: undici
  dependency-version: 6.29.0
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>

* update dist/index.js

Signed-off-by: Rui Chen <rui@chenrui.dev>

---------

Signed-off-by: dependabot[bot] <support@github.com>
Signed-off-by: Rui Chen <rui@chenrui.dev>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Rui Chen <rui@chenrui.dev>
2026-09-30 08:14:45 -04:00
dependabot[bot] 5969a5da4c chore(deps): bump the npm group with 4 updates (#843)
Bumps the npm group with 4 updates: [@types/node](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/node), [@vitest/coverage-v8](https://github.com/vitest-dev/vitest/tree/HEAD/packages/coverage-v8), [prettier](https://github.com/prettier/prettier) and [vitest](https://github.com/vitest-dev/vitest/tree/HEAD/packages/vitest).


Updates `@types/node` from 24.13.4 to 24.13.6
- [Release notes](https://github.com/DefinitelyTyped/DefinitelyTyped/releases)
- [Commits](https://github.com/DefinitelyTyped/DefinitelyTyped/commits/HEAD/types/node)

Updates `@vitest/coverage-v8` from 5.0.0 to 5.0.1
- [Release notes](https://github.com/vitest-dev/vitest/releases)
- [Changelog](https://github.com/vitest-dev/vitest/blob/main/docs/releases.md)
- [Commits](https://github.com/vitest-dev/vitest/commits/v5.0.1/packages/coverage-v8)

Updates `prettier` from 3.9.6 to 3.9.8
- [Release notes](https://github.com/prettier/prettier/releases)
- [Changelog](https://github.com/prettier/prettier/blob/main/CHANGELOG.md)
- [Commits](https://github.com/prettier/prettier/compare/3.9.6...3.9.8)

Updates `vitest` from 5.0.0 to 5.0.1
- [Release notes](https://github.com/vitest-dev/vitest/releases)
- [Changelog](https://github.com/vitest-dev/vitest/blob/main/docs/releases.md)
- [Commits](https://github.com/vitest-dev/vitest/commits/v5.0.1/packages/vitest)

---
updated-dependencies:
- dependency-name: "@types/node"
  dependency-version: 24.13.6
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: npm
- dependency-name: "@vitest/coverage-v8"
  dependency-version: 5.0.1
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: npm
- dependency-name: prettier
  dependency-version: 3.9.8
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: npm
- dependency-name: vitest
  dependency-version: 5.0.1
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: npm
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-09-30 08:13:08 -04:00
dependabot[bot] a4f117a9dd chore(deps): bump the npm group across 1 directory with 3 updates (#842)
main / build (push) Has been cancelled
Bumps the npm group with 3 updates in the / directory: [@types/node](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/node), [@vitest/coverage-v8](https://github.com/vitest-dev/vitest/tree/HEAD/packages/coverage-v8) and [vitest](https://github.com/vitest-dev/vitest/tree/HEAD/packages/vitest).


Updates `@types/node` from 24.13.3 to 24.13.4
- [Release notes](https://github.com/DefinitelyTyped/DefinitelyTyped/releases)
- [Commits](https://github.com/DefinitelyTyped/DefinitelyTyped/commits/HEAD/types/node)

Updates `@vitest/coverage-v8` from 4.1.11 to 5.0.0
- [Release notes](https://github.com/vitest-dev/vitest/releases)
- [Changelog](https://github.com/vitest-dev/vitest/blob/main/docs/releases.md)
- [Commits](https://github.com/vitest-dev/vitest/commits/v5.0.0/packages/coverage-v8)

Updates `vitest` from 4.1.11 to 5.0.0
- [Release notes](https://github.com/vitest-dev/vitest/releases)
- [Changelog](https://github.com/vitest-dev/vitest/blob/main/docs/releases.md)
- [Commits](https://github.com/vitest-dev/vitest/commits/v5.0.0/packages/vitest)

---
updated-dependencies:
- dependency-name: "@types/node"
  dependency-version: 24.13.4
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: npm
- dependency-name: "@vitest/coverage-v8"
  dependency-version: 5.0.0
  dependency-type: direct:development
  update-type: version-update:semver-major
  dependency-group: npm
- dependency-name: vitest
  dependency-version: 5.0.0
  dependency-type: direct:development
  update-type: version-update:semver-major
  dependency-group: npm
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-09-21 09:36:09 -04:00
Rui Chen efb35369e0 release 3.0.3 (#840)
main / build (push) Has been cancelled
Signed-off-by: Rui Chen <rui@chenrui.dev>
2026-08-29 20:27:42 -04:00
dependabot[bot] 6441963a75 chore(deps): bump the npm group with 2 updates (#839)
Bumps the npm group with 2 updates: [@vitest/coverage-v8](https://github.com/vitest-dev/vitest/tree/HEAD/packages/coverage-v8) and [vitest](https://github.com/vitest-dev/vitest/tree/HEAD/packages/vitest).


Updates `@vitest/coverage-v8` from 4.1.10 to 4.1.11
- [Release notes](https://github.com/vitest-dev/vitest/releases)
- [Changelog](https://github.com/vitest-dev/vitest/blob/main/docs/releases.md)
- [Commits](https://github.com/vitest-dev/vitest/commits/v4.1.11/packages/coverage-v8)

Updates `vitest` from 4.1.10 to 4.1.11
- [Release notes](https://github.com/vitest-dev/vitest/releases)
- [Changelog](https://github.com/vitest-dev/vitest/blob/main/docs/releases.md)
- [Commits](https://github.com/vitest-dev/vitest/commits/v4.1.11/packages/vitest)

---
updated-dependencies:
- dependency-name: "@vitest/coverage-v8"
  dependency-version: 4.1.11
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: npm
- dependency-name: vitest
  dependency-version: 4.1.11
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: npm
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-08-29 20:15:24 -04:00
dependabot[bot] e5ee6bc58a chore(deps): bump esbuild from 0.28.1 to 0.28.2 in the npm group (#837)
main / build (push) Has been cancelled
Bumps the npm group with 1 update: [esbuild](https://github.com/evanw/esbuild).


Updates `esbuild` from 0.28.1 to 0.28.2
- [Release notes](https://github.com/evanw/esbuild/releases)
- [Changelog](https://github.com/evanw/esbuild/blob/main/CHANGELOG.md)
- [Commits](https://github.com/evanw/esbuild/compare/v0.28.1...v0.28.2)

---
updated-dependencies:
- dependency-name: esbuild
  dependency-version: 0.28.2
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: npm
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-08-16 16:38:50 -04:00
dependabot[bot]andRui Chen d1e66170d3 chore(deps): bump undici from 6.27.0 to 6.28.0 (#831)
main / build (push) Has been cancelled
* chore(deps): bump undici from 6.27.0 to 6.28.0

Bumps [undici](https://github.com/nodejs/undici) from 6.27.0 to 6.28.0.
- [Release notes](https://github.com/nodejs/undici/releases)
- [Commits](https://github.com/nodejs/undici/compare/v6.27.0...v6.28.0)

---
updated-dependencies:
- dependency-name: undici
  dependency-version: 6.28.0
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>

* chore: rebuild dist bundle for undici 6.28.0

Signed-off-by: Rui Chen <rui@chenrui.dev>

---------

Signed-off-by: dependabot[bot] <support@github.com>
Signed-off-by: Rui Chen <rui@chenrui.dev>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Rui Chen <rui@chenrui.dev>
2026-08-09 17:55:53 -04:00
dependabot[bot] 64037519ba chore(deps): bump the npm group with 2 updates (#835)
Bumps the npm group with 2 updates: [@octokit/plugin-retry](https://github.com/octokit/plugin-retry.js) and [@octokit/plugin-throttling](https://github.com/octokit/plugin-throttling.js).


Updates `@octokit/plugin-retry` from 8.1.0 to 8.1.1
- [Release notes](https://github.com/octokit/plugin-retry.js/releases)
- [Commits](https://github.com/octokit/plugin-retry.js/compare/v8.1.0...v8.1.1)

Updates `@octokit/plugin-throttling` from 11.0.3 to 11.0.5
- [Release notes](https://github.com/octokit/plugin-throttling.js/releases)
- [Commits](https://github.com/octokit/plugin-throttling.js/compare/v11.0.3...v11.0.5)

---
updated-dependencies:
- dependency-name: "@octokit/plugin-retry"
  dependency-version: 8.1.1
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: npm
- dependency-name: "@octokit/plugin-throttling"
  dependency-version: 11.0.5
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: npm
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-08-09 17:52:26 -04:00
dependabot[bot] 7c7184b687 chore(deps): bump postcss from 8.5.19 to 8.5.25 (#833)
Bumps [postcss](https://github.com/postcss/postcss) from 8.5.19 to 8.5.25.
- [Release notes](https://github.com/postcss/postcss/releases)
- [Changelog](https://github.com/postcss/postcss/blob/main/CHANGELOG.md)
- [Commits](https://github.com/postcss/postcss/compare/8.5.19...8.5.25)

---
updated-dependencies:
- dependency-name: postcss
  dependency-version: 8.5.25
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-08-09 17:52:17 -04:00
dependabot[bot] 0f3f0d2943 chore(deps): bump brace-expansion from 5.0.8 to 5.0.9 (#832)
Bumps [brace-expansion](https://github.com/juliangruber/brace-expansion) from 5.0.8 to 5.0.9.
- [Release notes](https://github.com/juliangruber/brace-expansion/releases)
- [Commits](https://github.com/juliangruber/brace-expansion/compare/v5.0.8...v5.0.9)

---
updated-dependencies:
- dependency-name: brace-expansion
  dependency-version: 5.0.9
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-08-09 17:52:08 -04:00
dependabot[bot] 77fb938f2f chore(deps): bump prettier from 3.9.5 to 3.9.6 in the npm group (#830)
main / build (push) Has been cancelled
Bumps the npm group with 1 update: [prettier](https://github.com/prettier/prettier).


Updates `prettier` from 3.9.5 to 3.9.6
- [Release notes](https://github.com/prettier/prettier/releases)
- [Changelog](https://github.com/prettier/prettier/blob/main/CHANGELOG.md)
- [Commits](https://github.com/prettier/prettier/compare/3.9.5...3.9.6)

---
updated-dependencies:
- dependency-name: prettier
  dependency-version: 3.9.6
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: npm
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-08-03 20:10:11 -04:00
dependabot[bot] 5a6f51711c chore(deps): bump brace-expansion from 5.0.7 to 5.0.8 (#828)
main / build (push) Has been cancelled
Bumps [brace-expansion](https://github.com/juliangruber/brace-expansion) from 5.0.7 to 5.0.8.
- [Release notes](https://github.com/juliangruber/brace-expansion/releases)
- [Commits](https://github.com/juliangruber/brace-expansion/compare/v5.0.7...v5.0.8)

---
updated-dependencies:
- dependency-name: brace-expansion
  dependency-version: 5.0.8
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-07-29 08:57:07 -04:00
dependabot[bot] a3c91c98f8 chore(deps): bump the github-actions group with 2 updates (#825)
Bumps the github-actions group with 2 updates: [actions/checkout](https://github.com/actions/checkout) and [actions/setup-node](https://github.com/actions/setup-node).


Updates `actions/checkout` from 7.0.0 to 7.0.1
- [Release notes](https://github.com/actions/checkout/releases)
- [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md)
- [Commits](https://github.com/actions/checkout/compare/9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0...3d3c42e5aac5ba805825da76410c181273ba90b1)

Updates `actions/setup-node` from 6.4.0 to 7.0.0
- [Release notes](https://github.com/actions/setup-node/releases)
- [Commits](https://github.com/actions/setup-node/compare/48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e...820762786026740c76f36085b0efc47a31fe5020)

---
updated-dependencies:
- dependency-name: actions/checkout
  dependency-version: 7.0.1
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: github-actions
- dependency-name: actions/setup-node
  dependency-version: 7.0.0
  dependency-type: direct:production
  update-type: version-update:semver-major
  dependency-group: github-actions
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-07-29 08:53:24 -04:00
dependabot[bot] 5018f9ec04 chore(deps): bump brace-expansion from 5.0.6 to 5.0.7 (#824)
main / build (push) Has been cancelled
Bumps [brace-expansion](https://github.com/juliangruber/brace-expansion) from 5.0.6 to 5.0.7.
- [Release notes](https://github.com/juliangruber/brace-expansion/releases)
- [Commits](https://github.com/juliangruber/brace-expansion/compare/v5.0.6...v5.0.7)

---
updated-dependencies:
- dependency-name: brace-expansion
  dependency-version: 5.0.7
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-07-22 21:57:13 -04:00
dependabot[bot] c1e290273a chore(deps): bump the npm group with 4 updates (#823)
Bumps the npm group with 4 updates: [@types/node](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/node), [@vitest/coverage-v8](https://github.com/vitest-dev/vitest/tree/HEAD/packages/coverage-v8), [prettier](https://github.com/prettier/prettier) and [vitest](https://github.com/vitest-dev/vitest/tree/HEAD/packages/vitest).


Updates `@types/node` from 24.13.2 to 24.13.3
- [Release notes](https://github.com/DefinitelyTyped/DefinitelyTyped/releases)
- [Commits](https://github.com/DefinitelyTyped/DefinitelyTyped/commits/HEAD/types/node)

Updates `@vitest/coverage-v8` from 4.1.9 to 4.1.10
- [Release notes](https://github.com/vitest-dev/vitest/releases)
- [Changelog](https://github.com/vitest-dev/vitest/blob/main/docs/releases.md)
- [Commits](https://github.com/vitest-dev/vitest/commits/v4.1.10/packages/coverage-v8)

Updates `prettier` from 3.9.0 to 3.9.5
- [Release notes](https://github.com/prettier/prettier/releases)
- [Changelog](https://github.com/prettier/prettier/blob/main/CHANGELOG.md)
- [Commits](https://github.com/prettier/prettier/compare/3.9.0...3.9.5)

Updates `vitest` from 4.1.9 to 4.1.10
- [Release notes](https://github.com/vitest-dev/vitest/releases)
- [Changelog](https://github.com/vitest-dev/vitest/blob/main/docs/releases.md)
- [Commits](https://github.com/vitest-dev/vitest/commits/v4.1.10/packages/vitest)

---
updated-dependencies:
- dependency-name: "@types/node"
  dependency-version: 24.13.3
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: npm
- dependency-name: "@vitest/coverage-v8"
  dependency-version: 4.1.10
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: npm
- dependency-name: prettier
  dependency-version: 3.9.5
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: npm
- dependency-name: vitest
  dependency-version: 4.1.10
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: npm
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-07-22 21:57:04 -04:00
Rui Chen 1c214ab373 fix: safely classify GitHub API errors (#822)
main / build (push) Has been cancelled
* refactor: harden GitHub error classification

Signed-off-by: Rui Chen <rui@chenrui.dev>

* test: define nested GitHub status handling

Signed-off-by: Rui Chen <rui@chenrui.dev>

---------

Signed-off-by: Rui Chen <rui@chenrui.dev>
2026-07-15 11:06:56 -04:00
Rui Chen d100e75a45 docs: mark v2 as unsupported (#821)
main / build (push) Has been cancelled
Signed-off-by: Rui Chen <rui@chenrui.dev>
2026-07-13 13:15:35 -04:00
Rui Chen 81bcd9dd59 test: cover release lookup after tag replacement (#820)
Signed-off-by: Rui Chen <rui@chenrui.dev>
2026-07-13 12:39:38 -04:00
Rui Chen b05950fac2 docs: update the release verification workflow (#819)
Signed-off-by: Rui Chen <rui@chenrui.dev>
2026-07-13 10:53:12 -04:00
Rui Chen 3d0d9888cb release 3.0.2 (#818)
main / build (push) Has been cancelled
Signed-off-by: Rui Chen <rui@chenrui.dev>
2026-07-13 10:24:38 -04:00
Rui Chen 7e13ed4ac5 fix: clarify release creation 404 errors (#817)
* fix: clarify release creation 404 errors

Signed-off-by: Rui Chen <rui@chenrui.dev>

* fix: clarify inaccessible release targets

Signed-off-by: Rui Chen <rui@chenrui.dev>

---------

Signed-off-by: Rui Chen <rui@chenrui.dev>
2026-07-13 10:02:44 -04:00
Rui Chen e6c70a53cf fix: replace existing release assets on Gitea (#816)
main / build (push) Has been cancelled
Signed-off-by: Rui Chen <rui@chenrui.dev>
2026-07-13 08:44:02 -04:00
fenleyandRui Chen f345337888 fix: publish existing draft releases as prereleases (#801)
* fix: respect input_draft when updating existing release

* fix: reuse draft releases before publishing

Signed-off-by: Rui Chen <rui@chenrui.dev>

* fix: bound and canonicalize draft discovery

Signed-off-by: Rui Chen <rui@chenrui.dev>

* fix: preserve unowned draft releases

Signed-off-by: Rui Chen <rui@chenrui.dev>

* fix: recheck duplicate drafts before cleanup

Signed-off-by: Rui Chen <rui@chenrui.dev>

---------

Signed-off-by: Rui Chen <rui@chenrui.dev>
Co-authored-by: Rui Chen <rui@chenrui.dev>
2026-07-13 01:59:29 -04:00
Rui Chen d8a89a2066 fix: upload small checksum assets reliably (#815)
main / build (push) Has been cancelled
Signed-off-by: Rui Chen <rui@chenrui.dev>
2026-07-12 23:26:33 -04:00
Rui Chen 45ece40c31 chore(deps): remove unused TypeScript tooling (#814)
Signed-off-by: Rui Chen <rui@chenrui.dev>
2026-07-12 22:07:52 -04:00
Rui Chen f6b913c3f9 feat: improve release error reporting and test coverage (#813)
Signed-off-by: Rui Chen <rui@chenrui.dev>
2026-07-12 21:52:34 -04:00
Rui Chen 15f193d7d8 chore(deps): upgrade TypeScript to 7 (#812)
Signed-off-by: Rui Chen <rui@chenrui.dev>
2026-07-12 21:26:48 -04:00
dependabot[bot] cc8268d46a chore(deps): bump actions/checkout in the github-actions group (#810)
Bumps the github-actions group with 1 update: [actions/checkout](https://github.com/actions/checkout).


Updates `actions/checkout` from 6.0.3 to 7.0.0
- [Release notes](https://github.com/actions/checkout/releases)
- [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md)
- [Commits](https://github.com/actions/checkout/compare/df4cb1c069e1874edd31b4311f1884172cec0e10...9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0)

---
updated-dependencies:
- dependency-name: actions/checkout
  dependency-version: 7.0.0
  dependency-type: direct:production
  update-type: version-update:semver-major
  dependency-group: github-actions
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-07-12 20:22:42 -04:00
dependabot[bot] fd0ed1e85b chore(deps): bump the npm group with 3 updates (#811)
Bumps the npm group with 3 updates: [@vitest/coverage-v8](https://github.com/vitest-dev/vitest/tree/HEAD/packages/coverage-v8), [prettier](https://github.com/prettier/prettier) and [vitest](https://github.com/vitest-dev/vitest/tree/HEAD/packages/vitest).


Updates `@vitest/coverage-v8` from 4.1.8 to 4.1.9
- [Release notes](https://github.com/vitest-dev/vitest/releases)
- [Changelog](https://github.com/vitest-dev/vitest/blob/main/docs/releases.md)
- [Commits](https://github.com/vitest-dev/vitest/commits/v4.1.9/packages/coverage-v8)

Updates `prettier` from 3.8.4 to 3.9.0
- [Release notes](https://github.com/prettier/prettier/releases)
- [Changelog](https://github.com/prettier/prettier/blob/main/CHANGELOG.md)
- [Commits](https://github.com/prettier/prettier/compare/3.8.4...3.9.0)

Updates `vitest` from 4.1.8 to 4.1.9
- [Release notes](https://github.com/vitest-dev/vitest/releases)
- [Changelog](https://github.com/vitest-dev/vitest/blob/main/docs/releases.md)
- [Commits](https://github.com/vitest-dev/vitest/commits/v4.1.9/packages/vitest)

---
updated-dependencies:
- dependency-name: "@vitest/coverage-v8"
  dependency-version: 4.1.9
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: npm
- dependency-name: prettier
  dependency-version: 3.9.0
  dependency-type: direct:development
  update-type: version-update:semver-minor
  dependency-group: npm
- dependency-name: vitest
  dependency-version: 4.1.9
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: npm
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-07-12 20:22:35 -04:00
Rui Chen 132dbbba49 chore: bump node 24 pin to 24.18.0
main / build (push) Has been cancelled
Signed-off-by: Rui Chen <rui@chenrui.dev>
2026-06-25 12:27:27 -04:00
dependabot[bot]andRui Chen 3743f4e7d1 chore(deps): bump undici from 6.24.1 to 6.27.0 (#807)
* chore(deps): bump undici from 6.24.1 to 6.27.0

Bumps [undici](https://github.com/nodejs/undici) from 6.24.1 to 6.27.0.
- [Release notes](https://github.com/nodejs/undici/releases)
- [Commits](https://github.com/nodejs/undici/compare/v6.24.1...v6.27.0)

---
updated-dependencies:
- dependency-name: undici
  dependency-version: 6.27.0
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>

* chore(deps): rebuild dist for undici 6.27.0

Signed-off-by: Rui Chen <rui@chenrui.dev>

---------

Signed-off-by: dependabot[bot] <support@github.com>
Signed-off-by: Rui Chen <rui@chenrui.dev>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Rui Chen <rui@chenrui.dev>
2026-06-25 12:25:02 -04:00
dependabot[bot] 566ec910ab chore(deps): bump the npm group with 2 updates (#808)
Bumps the npm group with 2 updates: [@types/node](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/node) and [prettier](https://github.com/prettier/prettier).


Updates `@types/node` from 24.13.1 to 24.13.2
- [Release notes](https://github.com/DefinitelyTyped/DefinitelyTyped/releases)
- [Commits](https://github.com/DefinitelyTyped/DefinitelyTyped/commits/HEAD/types/node)

Updates `prettier` from 3.8.3 to 3.8.4
- [Release notes](https://github.com/prettier/prettier/releases)
- [Changelog](https://github.com/prettier/prettier/blob/main/CHANGELOG.md)
- [Commits](https://github.com/prettier/prettier/compare/3.8.3...3.8.4)

---
updated-dependencies:
- dependency-name: "@types/node"
  dependency-version: 24.13.2
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: npm
- dependency-name: prettier
  dependency-version: 3.8.4
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: npm
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-06-25 12:13:00 -04:00
Rui Chen 718ea10b13 release 3.0.1
main / build (push) Has been cancelled
Signed-off-by: Rui Chen <rui@chenrui.dev>
2026-06-19 10:41:38 -04:00
dependabot[bot]andRui Chen f1a938b9d8 chore(deps): bump esbuild from 0.28.0 to 0.28.1 (#802)
* chore(deps): bump esbuild from 0.28.0 to 0.28.1

Bumps [esbuild](https://github.com/evanw/esbuild) from 0.28.0 to 0.28.1.
- [Release notes](https://github.com/evanw/esbuild/releases)
- [Changelog](https://github.com/evanw/esbuild/blob/main/CHANGELOG.md)
- [Commits](https://github.com/evanw/esbuild/compare/v0.28.0...v0.28.1)

---
updated-dependencies:
- dependency-name: esbuild
  dependency-version: 0.28.1
  dependency-type: direct:development
...

Signed-off-by: dependabot[bot] <support@github.com>

* chore(deps): rebuild dist for esbuild 0.28.1

Signed-off-by: Rui Chen <rui@chenrui.dev>

---------

Signed-off-by: dependabot[bot] <support@github.com>
Signed-off-by: Rui Chen <rui@chenrui.dev>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Rui Chen <rui@chenrui.dev>
2026-06-19 10:37:08 -04:00
dependabot[bot] 0066ead0de chore(deps): bump vite from 8.0.14 to 8.0.16 (#806)
Bumps [vite](https://github.com/vitejs/vite/tree/HEAD/packages/vite) from 8.0.14 to 8.0.16.
- [Release notes](https://github.com/vitejs/vite/releases)
- [Changelog](https://github.com/vitejs/vite/blob/main/packages/vite/CHANGELOG.md)
- [Commits](https://github.com/vitejs/vite/commits/v8.0.16/packages/vite)

---
updated-dependencies:
- dependency-name: vite
  dependency-version: 8.0.16
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-06-19 10:19:47 -04:00
dependabot[bot] dc643cac62 chore(deps): bump the npm group with 3 updates (#805)
Bumps the npm group with 3 updates: [@types/node](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/node), [@vitest/coverage-v8](https://github.com/vitest-dev/vitest/tree/HEAD/packages/coverage-v8) and [vitest](https://github.com/vitest-dev/vitest/tree/HEAD/packages/vitest).


Updates `@types/node` from 24.12.4 to 24.13.1
- [Release notes](https://github.com/DefinitelyTyped/DefinitelyTyped/releases)
- [Commits](https://github.com/DefinitelyTyped/DefinitelyTyped/commits/HEAD/types/node)

Updates `@vitest/coverage-v8` from 4.1.7 to 4.1.8
- [Release notes](https://github.com/vitest-dev/vitest/releases)
- [Changelog](https://github.com/vitest-dev/vitest/blob/main/docs/releases.md)
- [Commits](https://github.com/vitest-dev/vitest/commits/v4.1.8/packages/coverage-v8)

Updates `vitest` from 4.1.7 to 4.1.8
- [Release notes](https://github.com/vitest-dev/vitest/releases)
- [Changelog](https://github.com/vitest-dev/vitest/blob/main/docs/releases.md)
- [Commits](https://github.com/vitest-dev/vitest/commits/v4.1.8/packages/vitest)

---
updated-dependencies:
- dependency-name: "@types/node"
  dependency-version: 24.13.1
  dependency-type: direct:development
  update-type: version-update:semver-minor
  dependency-group: npm
- dependency-name: "@vitest/coverage-v8"
  dependency-version: 4.1.8
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: npm
- dependency-name: vitest
  dependency-version: 4.1.8
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: npm
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-06-19 10:19:40 -04:00
dependabot[bot] 85ee99b6b2 chore(deps): bump actions/checkout in the github-actions group (#804)
Bumps the github-actions group with 1 update: [actions/checkout](https://github.com/actions/checkout).


Updates `actions/checkout` from 6.0.2 to 6.0.3
- [Release notes](https://github.com/actions/checkout/releases)
- [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md)
- [Commits](https://github.com/actions/checkout/compare/de0fac2e4500dabe0009e67214ff5f5447ce83dd...df4cb1c069e1874edd31b4311f1884172cec0e10)

---
updated-dependencies:
- dependency-name: actions/checkout
  dependency-version: 6.0.3
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: github-actions
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-06-19 10:19:30 -04:00
dependabot[bot] 9ed3cf9a68 chore(deps): bump the npm group with 2 updates (#800)
main / build (push) Has been cancelled
Bumps the npm group with 2 updates: [@vitest/coverage-v8](https://github.com/vitest-dev/vitest/tree/HEAD/packages/coverage-v8) and [vitest](https://github.com/vitest-dev/vitest/tree/HEAD/packages/vitest).


Updates `@vitest/coverage-v8` from 4.1.6 to 4.1.7
- [Release notes](https://github.com/vitest-dev/vitest/releases)
- [Changelog](https://github.com/vitest-dev/vitest/blob/main/docs/releases.md)
- [Commits](https://github.com/vitest-dev/vitest/commits/v4.1.7/packages/coverage-v8)

Updates `vitest` from 4.1.6 to 4.1.7
- [Release notes](https://github.com/vitest-dev/vitest/releases)
- [Changelog](https://github.com/vitest-dev/vitest/blob/main/docs/releases.md)
- [Commits](https://github.com/vitest-dev/vitest/commits/v4.1.7/packages/vitest)

---
updated-dependencies:
- dependency-name: "@vitest/coverage-v8"
  dependency-version: 4.1.7
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: npm
- dependency-name: vitest
  dependency-version: 4.1.7
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: npm
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-06-07 16:28:00 -04:00
dependabot[bot] 3efcac8951 chore(deps): bump the npm group with 3 updates (#798)
main / build (push) Has been cancelled
Bumps the npm group with 3 updates: [@types/node](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/node), [@vitest/coverage-v8](https://github.com/vitest-dev/vitest/tree/HEAD/packages/coverage-v8) and [vitest](https://github.com/vitest-dev/vitest/tree/HEAD/packages/vitest).


Updates `@types/node` from 24.12.3 to 24.12.4
- [Release notes](https://github.com/DefinitelyTyped/DefinitelyTyped/releases)
- [Commits](https://github.com/DefinitelyTyped/DefinitelyTyped/commits/HEAD/types/node)

Updates `@vitest/coverage-v8` from 4.1.5 to 4.1.6
- [Release notes](https://github.com/vitest-dev/vitest/releases)
- [Changelog](https://github.com/vitest-dev/vitest/blob/main/docs/releases.md)
- [Commits](https://github.com/vitest-dev/vitest/commits/v4.1.6/packages/coverage-v8)

Updates `vitest` from 4.1.5 to 4.1.6
- [Release notes](https://github.com/vitest-dev/vitest/releases)
- [Changelog](https://github.com/vitest-dev/vitest/blob/main/docs/releases.md)
- [Commits](https://github.com/vitest-dev/vitest/commits/v4.1.6/packages/vitest)

---
updated-dependencies:
- dependency-name: "@types/node"
  dependency-version: 24.12.4
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: npm
- dependency-name: "@vitest/coverage-v8"
  dependency-version: 4.1.6
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: npm
- dependency-name: vitest
  dependency-version: 4.1.6
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: npm
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-05-29 09:38:53 -04:00
dependabot[bot] 05d6b9164a chore(deps): bump brace-expansion from 5.0.5 to 5.0.6 (#797)
Bumps [brace-expansion](https://github.com/juliangruber/brace-expansion) from 5.0.5 to 5.0.6.
- [Release notes](https://github.com/juliangruber/brace-expansion/releases)
- [Commits](https://github.com/juliangruber/brace-expansion/compare/v5.0.5...v5.0.6)

---
updated-dependencies:
- dependency-name: brace-expansion
  dependency-version: 5.0.6
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-05-29 09:38:47 -04:00
dependabot[bot] 403a5240f3 chore(deps): bump @types/node from 24.12.2 to 24.12.3 in the npm group (#796)
main / build (push) Has been cancelled
Bumps the npm group with 1 update: [@types/node](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/node).


Updates `@types/node` from 24.12.2 to 24.12.3
- [Release notes](https://github.com/DefinitelyTyped/DefinitelyTyped/releases)
- [Commits](https://github.com/DefinitelyTyped/DefinitelyTyped/commits/HEAD/types/node)

---
updated-dependencies:
- dependency-name: "@types/node"
  dependency-version: 24.12.3
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: npm
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-05-17 16:56:11 -04:00
dependabot[bot] 437e073e78 chore(deps): bump the npm group with 4 updates (#792)
main / build (push) Has been cancelled
Bumps the npm group with 4 updates: [@actions/core](https://github.com/actions/toolkit/tree/HEAD/packages/core), [@actions/github](https://github.com/actions/toolkit/tree/HEAD/packages/github), [@vitest/coverage-v8](https://github.com/vitest-dev/vitest/tree/HEAD/packages/coverage-v8) and [vitest](https://github.com/vitest-dev/vitest/tree/HEAD/packages/vitest).


Updates `@actions/core` from 3.0.0 to 3.0.1
- [Changelog](https://github.com/actions/toolkit/blob/main/packages/core/RELEASES.md)
- [Commits](https://github.com/actions/toolkit/commits/HEAD/packages/core)

Updates `@actions/github` from 9.1.0 to 9.1.1
- [Changelog](https://github.com/actions/toolkit/blob/main/packages/github/RELEASES.md)
- [Commits](https://github.com/actions/toolkit/commits/HEAD/packages/github)

Updates `@vitest/coverage-v8` from 4.1.4 to 4.1.5
- [Release notes](https://github.com/vitest-dev/vitest/releases)
- [Commits](https://github.com/vitest-dev/vitest/commits/v4.1.5/packages/coverage-v8)

Updates `vitest` from 4.1.4 to 4.1.5
- [Release notes](https://github.com/vitest-dev/vitest/releases)
- [Commits](https://github.com/vitest-dev/vitest/commits/v4.1.5/packages/vitest)

---
updated-dependencies:
- dependency-name: "@actions/core"
  dependency-version: 3.0.1
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: npm
- dependency-name: "@actions/github"
  dependency-version: 9.1.1
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: npm
- dependency-name: "@vitest/coverage-v8"
  dependency-version: 4.1.5
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: npm
- dependency-name: vitest
  dependency-version: 4.1.5
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: npm
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-05-05 22:09:35 -04:00
dependabot[bot] 5a1e17dcea chore(deps): bump actions/setup-node in the github-actions group (#791)
Bumps the github-actions group with 1 update: [actions/setup-node](https://github.com/actions/setup-node).


Updates `actions/setup-node` from 6.3.0 to 6.4.0
- [Release notes](https://github.com/actions/setup-node/releases)
- [Commits](https://github.com/actions/setup-node/compare/53b83947a5a98c8d113130e565377fae1a50d02f...48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e)

---
updated-dependencies:
- dependency-name: actions/setup-node
  dependency-version: 6.4.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: github-actions
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-05-05 22:09:28 -04:00
dependabot[bot] 2bc819c87a chore(deps): bump postcss from 8.5.9 to 8.5.10 (#789)
main / build (push) Has been cancelled
Bumps [postcss](https://github.com/postcss/postcss) from 8.5.9 to 8.5.10.
- [Release notes](https://github.com/postcss/postcss/releases)
- [Changelog](https://github.com/postcss/postcss/blob/main/CHANGELOG.md)
- [Commits](https://github.com/postcss/postcss/compare/8.5.9...8.5.10)

---
updated-dependencies:
- dependency-name: postcss
  dependency-version: 8.5.10
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-04-26 01:22:12 -04:00
dependabot[bot] c90b8762f6 chore(deps): bump the npm group with 2 updates (#788)
Bumps the npm group with 2 updates: [prettier](https://github.com/prettier/prettier) and [typescript](https://github.com/microsoft/TypeScript).


Updates `prettier` from 3.8.2 to 3.8.3
- [Release notes](https://github.com/prettier/prettier/releases)
- [Changelog](https://github.com/prettier/prettier/blob/main/CHANGELOG.md)
- [Commits](https://github.com/prettier/prettier/compare/3.8.2...3.8.3)

Updates `typescript` from 6.0.2 to 6.0.3
- [Release notes](https://github.com/microsoft/TypeScript/releases)
- [Commits](https://github.com/microsoft/TypeScript/compare/v6.0.2...v6.0.3)

---
updated-dependencies:
- dependency-name: prettier
  dependency-version: 3.8.3
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: npm
- dependency-name: typescript
  dependency-version: 6.0.3
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: npm
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-04-25 22:38:20 -04:00
Rui Chen 4dd30955cc chore: remove .github/FUNDING.yml
main / build (push) Has been cancelled
Signed-off-by: Rui Chen <rui@chenrui.dev>
2026-04-12 11:52:07 -04:00
Rui Chen be9cff7d8e feat: add dependabot cooldown, update pinact annotations (#785)
Signed-off-by: Rui Chen <rui@chenrui.dev>
2026-04-12 11:31:15 -04:00
Rui Chen 07399f3317 docs: clarify issue links in release summaries
main / build (push) Has been cancelled
closes #778

Signed-off-by: Rui Chen <rui@chenrui.dev>
2026-04-12 08:16:23 -04:00
dependabot[bot]andRui Chen 93e4a0038b chore(deps): keep @types/node on the Node 24 line (#784)
main / build (push) Has been cancelled
* chore(deps): bump @types/node from 24.12.2 to 25.6.0 in the npm group

Bumps the npm group with 1 update: [@types/node](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/node).


Updates `@types/node` from 24.12.2 to 25.6.0
- [Release notes](https://github.com/DefinitelyTyped/DefinitelyTyped/releases)
- [Commits](https://github.com/DefinitelyTyped/DefinitelyTyped/commits/HEAD/types/node)

---
updated-dependencies:
- dependency-name: "@types/node"
  dependency-version: 25.6.0
  dependency-type: direct:development
  update-type: version-update:semver-major
  dependency-group: npm
...

Signed-off-by: dependabot[bot] <support@github.com>

* chore(deps): keep @types/node on the node24 line

Signed-off-by: Rui Chen <rui@chenrui.dev>

---------

Signed-off-by: dependabot[bot] <support@github.com>
Signed-off-by: Rui Chen <rui@chenrui.dev>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Rui Chen <rui@chenrui.dev>
2026-04-12 00:57:20 -04:00
Copilot b430933298 release: cut v3.0.0 for Node 24 upgrade (#670)
- feat: move action runtime to node24 and require Node >=24
- chore: bump @types/node, enable Dependabot updates, rebuild dist
- cut 3.0.0 release

Signed-off-by: Rui Chen <rui@chenrui.dev>
2026-04-12 00:45:48 -04:00
dependabot[bot]andRui Chen c2e35e05a7 chore(deps): bump the npm group across 1 directory with 7 updates (#783)
* chore(deps): bump the npm group across 1 directory with 7 updates

Bumps the npm group with 6 updates in the / directory:

| Package | From | To |
| --- | --- | --- |
| [@actions/github](https://github.com/actions/toolkit/tree/HEAD/packages/github) | `9.0.0` | `9.1.0` |
| [@types/node](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/node) | `20.19.37` | `20.19.39` |
| [@vitest/coverage-v8](https://github.com/vitest-dev/vitest/tree/HEAD/packages/coverage-v8) | `4.1.0` | `4.1.4` |
| [esbuild](https://github.com/evanw/esbuild) | `0.27.4` | `0.28.0` |
| [prettier](https://github.com/prettier/prettier) | `3.8.1` | `3.8.2` |
| [typescript](https://github.com/microsoft/TypeScript) | `5.9.3` | `6.0.2` |



Updates `@actions/github` from 9.0.0 to 9.1.0
- [Changelog](https://github.com/actions/toolkit/blob/main/packages/github/RELEASES.md)
- [Commits](https://github.com/actions/toolkit/commits/HEAD/packages/github)

Updates `@types/node` from 20.19.37 to 20.19.39
- [Release notes](https://github.com/DefinitelyTyped/DefinitelyTyped/releases)
- [Commits](https://github.com/DefinitelyTyped/DefinitelyTyped/commits/HEAD/types/node)

Updates `@vitest/coverage-v8` from 4.1.0 to 4.1.4
- [Release notes](https://github.com/vitest-dev/vitest/releases)
- [Commits](https://github.com/vitest-dev/vitest/commits/v4.1.4/packages/coverage-v8)

Updates `esbuild` from 0.27.4 to 0.28.0
- [Release notes](https://github.com/evanw/esbuild/releases)
- [Changelog](https://github.com/evanw/esbuild/blob/main/CHANGELOG.md)
- [Commits](https://github.com/evanw/esbuild/compare/v0.27.4...v0.28.0)

Updates `prettier` from 3.8.1 to 3.8.2
- [Release notes](https://github.com/prettier/prettier/releases)
- [Changelog](https://github.com/prettier/prettier/blob/main/CHANGELOG.md)
- [Commits](https://github.com/prettier/prettier/compare/3.8.1...3.8.2)

Updates `typescript` from 5.9.3 to 6.0.2
- [Release notes](https://github.com/microsoft/TypeScript/releases)
- [Commits](https://github.com/microsoft/TypeScript/compare/v5.9.3...v6.0.2)

Updates `vitest` from 4.1.0 to 4.1.4
- [Release notes](https://github.com/vitest-dev/vitest/releases)
- [Commits](https://github.com/vitest-dev/vitest/commits/v4.1.4/packages/vitest)

---
updated-dependencies:
- dependency-name: "@actions/github"
  dependency-version: 9.1.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: npm
- dependency-name: "@types/node"
  dependency-version: 20.19.39
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: npm
- dependency-name: "@vitest/coverage-v8"
  dependency-version: 4.1.4
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: npm
- dependency-name: esbuild
  dependency-version: 0.28.0
  dependency-type: direct:development
  update-type: version-update:semver-minor
  dependency-group: npm
- dependency-name: prettier
  dependency-version: 3.8.2
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: npm
- dependency-name: typescript
  dependency-version: 6.0.2
  dependency-type: direct:development
  update-type: version-update:semver-major
  dependency-group: npm
- dependency-name: vitest
  dependency-version: 4.1.4
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: npm
...

Signed-off-by: dependabot[bot] <support@github.com>

* ci: comment on stale dist bundles

Signed-off-by: Rui Chen <rui@chenrui.dev>

* update dist/index.js

Signed-off-by: Rui Chen <rui@chenrui.dev>

---------

Signed-off-by: dependabot[bot] <support@github.com>
Signed-off-by: Rui Chen <rui@chenrui.dev>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Rui Chen <rui@chenrui.dev>
2026-04-11 23:55:00 -04:00
Rui Chen 3bb12739c2 release 2.6.2
Signed-off-by: Rui Chen <rui@chenrui.dev>
2026-04-11 23:31:51 -04:00
Rui Chen c34030fec9 chore: bump node to 24.14.1
Signed-off-by: Rui Chen <rui@chenrui.dev>
2026-04-11 23:27:31 -04:00
dependabot[bot] 8975bd05c0 chore(deps): bump vite from 8.0.0 to 8.0.5 (#781)
Bumps [vite](https://github.com/vitejs/vite/tree/HEAD/packages/vite) from 8.0.0 to 8.0.5.
- [Release notes](https://github.com/vitejs/vite/releases)
- [Changelog](https://github.com/vitejs/vite/blob/main/packages/vite/CHANGELOG.md)
- [Commits](https://github.com/vitejs/vite/commits/v8.0.5/packages/vite)

---
updated-dependencies:
- dependency-name: vite
  dependency-version: 8.0.5
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-04-11 23:22:58 -04:00
dependabot[bot] f71937f44d chore(deps): bump brace-expansion from 5.0.4 to 5.0.5 (#777)
Bumps [brace-expansion](https://github.com/juliangruber/brace-expansion) from 5.0.4 to 5.0.5.
- [Release notes](https://github.com/juliangruber/brace-expansion/releases)
- [Commits](https://github.com/juliangruber/brace-expansion/compare/v5.0.4...v5.0.5)

---
updated-dependencies:
- dependency-name: brace-expansion
  dependency-version: 5.0.5
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-04-11 23:22:21 -04:00
dependabot[bot] 3f0d239d58 chore(deps): bump picomatch from 4.0.3 to 4.0.4 (#775)
Bumps [picomatch](https://github.com/micromatch/picomatch) from 4.0.3 to 4.0.4.
- [Release notes](https://github.com/micromatch/picomatch/releases)
- [Changelog](https://github.com/micromatch/picomatch/blob/master/CHANGELOG.md)
- [Commits](https://github.com/micromatch/picomatch/compare/4.0.3...4.0.4)

---
updated-dependencies:
- dependency-name: picomatch
  dependency-version: 4.0.4
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-04-11 23:22:10 -04:00
Rui Chen 153bb8e044 release 2.6.1
main / build (push) Has been cancelled
Signed-off-by: Rui Chen <rui@chenrui.dev>
2026-03-15 20:57:00 -04:00
Rui Chen 569deb874d fix: preserve discussion category when publishing releases (#765)
Signed-off-by: Rui Chen <rui@chenrui.dev>
2026-03-15 20:54:29 -04:00
24 changed files with 3891 additions and 1338 deletions

No files matched your search

-1
View File
@@ -1 +0,0 @@
ko_fi: softprops
+5 -1
View File
@@ -14,7 +14,9 @@ updates:
- ">=3.0.0"
- dependency-name: "@types/node"
versions:
- ">=22.0.0"
- ">=25.0.0"
cooldown:
default-days: 7
commit-message:
prefix: "chore(deps)"
- package-ecosystem: github-actions
@@ -25,5 +27,7 @@ updates:
github-actions:
patterns:
- "*"
cooldown:
default-days: 7
commit-message:
prefix: "chore(deps)"
+48 -2
View File
@@ -4,26 +4,72 @@ on:
push:
pull_request:
permissions:
contents: read
issues: write
pull-requests: write
jobs:
build:
runs-on: ubuntu-24.04
steps:
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v5
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
- uses: actions/setup-node@53b83947a5a98c8d113130e565377fae1a50d02f # v6
- uses: actions/setup-node@949feb2413d6458794dcd2491c4babbbce0c15c1 # v7.1.0
with:
node-version-file: ".tool-versions"
cache: "npm"
- name: Install
run: npm ci
- name: Typecheck
run: npm run typecheck
- name: Build
run: npm run build
- name: Check dist freshness
id: dist_freshness
continue-on-error: true
run: |
git diff --exit-code --stat -- dist/index.js \
|| (echo "##[error] found changed dist/index.js after build. please run 'npm run build' and commit the updated bundle" \
&& exit 1)
- name: Comment on stale dist bundle
if: github.event_name == 'pull_request' && steps.dist_freshness.outcome == 'failure'
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
GH_REPO: ${{ github.repository }}
PR_NUMBER: ${{ github.event.pull_request.number }}
run: |
marker='<!-- dist-freshness-check -->'
diff_stat="$(git diff --stat -- dist/index.js)"
body=$(cat <<EOF
$marker
\`dist/index.js\` changed after \`npm run build\`.
Please run \`npm run build\` and commit the regenerated bundle.
\`\`\`text
$diff_stat
\`\`\`
EOF
)
existing_id="$(
gh api "repos/$GH_REPO/issues/$PR_NUMBER/comments" \
--jq '.[] | select(.user.login == "github-actions[bot]" and (.body | contains("<!-- dist-freshness-check -->"))) | .id' \
| tail -n 1
)"
if [ -n "$existing_id" ]; then
gh api --method PATCH "repos/$GH_REPO/issues/comments/$existing_id" -f body="$body" >/dev/null
else
gh api --method POST "repos/$GH_REPO/issues/$PR_NUMBER/comments" -f body="$body" >/dev/null
fi
- name: Fail on stale dist bundle
if: steps.dist_freshness.outcome == 'failure'
run: |
echo "##[error] found changed dist/index.js after build. please run 'npm run build' and commit the updated bundle"
exit 1
- name: Test
run: npm run test
- name: Format
+1 -1
View File
@@ -1 +1 @@
nodejs 24.11.0
nodejs 24.18.0
+1 -1
View File
@@ -15,7 +15,7 @@ Optimize for stability, reproducibility, and clear user value over broad rewrite
## Current Architecture
- `src/main.ts` is the orchestration layer: parse config, validate inputs, create/update release, upload assets, finalize, set outputs.
- `src/main.ts` is the action bootstrap; `src/run.ts` orchestrates config parsing, validation, release creation/update, asset uploads, finalization, and outputs.
- `src/github.ts` owns release semantics: lookup, create/update/finalize, asset upload, race handling, and GitHub API interaction.
- `src/util.ts` owns parsing and path normalization.
- Keep behavior-specific logic in `src/github.ts` or `src/util.ts`; avoid growing `src/main.ts` with ad-hoc feature branches.
+97
View File
@@ -1,3 +1,100 @@
## 3.0.4
- maintenance release with updated dependencies
## 3.0.3
`3.0.3` is a maintenance release with updated dependencies. It also safely
classifies malformed GitHub API errors to avoid secondary failures (#822).
## What's Changed
### Bug fixes 🐛
* fix: safely classify GitHub API errors by @chenrui333 in https://github.com/softprops/action-gh-release/pull/822
### Other Changes 🔄
* dependency updates
## 3.0.2
`3.0.2` is a patch release focused on release reliability and compatibility. It
reuses existing draft releases when publishing prereleases, supports replacing
release assets on Gitea, hardens streamed asset uploads, and provides clearer
release-creation diagnostics. It also includes TypeScript, coverage, and tooling
maintenance merged since `3.0.1`.
This release fixes #795, #438, and #803. The upload transport hardening covers the
historical failure reported in #790, although current hosted Node 24 runners did
not reproduce it naturally. The diagnostics work is related to #786 and does not
claim a reproducible release-creation fix.
## What's Changed
### Exciting New Features 🎉
* feat: improve release error reporting and test coverage by @chenrui333 in https://github.com/softprops/action-gh-release/pull/813
### Bug fixes 🐛
* fix: publish existing draft releases as prereleases by @godfengliang in https://github.com/softprops/action-gh-release/pull/801
* fix: upload small checksum assets reliably by @chenrui333 in https://github.com/softprops/action-gh-release/pull/815
* fix: replace existing release assets on Gitea by @chenrui333 in https://github.com/softprops/action-gh-release/pull/816
* fix: clarify release creation 404 errors by @chenrui333 in https://github.com/softprops/action-gh-release/pull/817
### Other Changes 🔄
* chore(deps): upgrade TypeScript to 7 by @chenrui333 in https://github.com/softprops/action-gh-release/pull/812
* chore(deps): remove unused TypeScript tooling by @chenrui333 in https://github.com/softprops/action-gh-release/pull/814
* dependency, Node 24 pin, and CI maintenance merged since `3.0.1`
## 3.0.1
- maintenance release with updated dependencies
## 3.0.0
`3.0.0` is a major release that moves the action runtime from Node 20 to Node 24.
Use `v3` on GitHub-hosted runners and self-hosted fleets that already support the
Node 24 Actions runtime. `v2.6.2` was the final Node 20-compatible release and is
no longer maintained or supported.
## What's Changed
### Other Changes 🔄
* Move the action runtime and bundle target to Node 24
* Update `@types/node` to the Node 24 line and allow future Dependabot updates
* Keep the floating major tag on `v3`; freeze `v2` at the final `v2.6.2` release
## 2.6.2
`2.6.2` is the final `v2` release and is no longer maintained or supported. Upgrade
to `v3` for the supported Node 24 runtime and current fixes.
## What's Changed
### Other Changes 🔄
* chore(deps): bump picomatch from 4.0.3 to 4.0.4 by @dependabot[bot] in https://github.com/softprops/action-gh-release/pull/775
* chore(deps): bump brace-expansion from 5.0.4 to 5.0.5 by @dependabot[bot] in https://github.com/softprops/action-gh-release/pull/777
* chore(deps): bump vite from 8.0.0 to 8.0.5 by @dependabot[bot] in https://github.com/softprops/action-gh-release/pull/781
## 2.6.1
`2.6.1` is a patch release focused on restoring linked discussion thread creation when
`discussion_category_name` is set. It fixes `#764`, where the draft-first publish flow
stopped carrying the discussion category through the final publish step.
If you still hit an issue after upgrading, please open a report with the bug template and include a minimal repro or sanitized workflow snippet where possible.
## What's Changed
### Bug fixes 🐛
* fix: preserve discussion category on publish by @chenrui333 in https://github.com/softprops/action-gh-release/pull/765
## 2.6.0
`2.6.0` is a minor release centered on `previous_tag` support for `generate_release_notes`,
+13 -7
View File
@@ -39,6 +39,12 @@ Typically usage of this action involves adding a step to a build that
is gated pushes to git tags. You may find `step.if` field helpful in accomplishing this
as it maximizes the reuse value of your workflow for non-tag pushes.
`v2.6.2` is the final `v2` release and is no longer maintained or supported. It
uses the [Node 20 runtime deprecated by GitHub Actions](https://github.blog/changelog/2025-09-19-deprecation-of-node-20-on-github-actions-runners/).
Upgrade to `v3`, which runs on Node 24. If a problem still reproduces on the
latest `v3`, open a new issue with the exact action ref, workflow run URL,
runner, and relevant logs.
Below is a simple example of `step.if` tag gating
```yaml
@@ -53,7 +59,7 @@ jobs:
- name: Checkout
uses: actions/checkout@v6
- name: Release
uses: softprops/action-gh-release@v2
uses: softprops/action-gh-release@v3
if: github.ref_type == 'tag'
```
@@ -74,7 +80,7 @@ jobs:
- name: Checkout
uses: actions/checkout@v6
- name: Release
uses: softprops/action-gh-release@v2
uses: softprops/action-gh-release@v3
```
### ⬆️ Uploading release assets
@@ -105,7 +111,7 @@ jobs:
- name: Test
run: cat Release.txt
- name: Release
uses: softprops/action-gh-release@v2
uses: softprops/action-gh-release@v3
if: github.ref_type == 'tag'
with:
files: Release.txt
@@ -129,7 +135,7 @@ jobs:
- name: Test
run: cat Release.txt
- name: Release
uses: softprops/action-gh-release@v2
uses: softprops/action-gh-release@v3
if: github.ref_type == 'tag'
with:
files: |
@@ -146,7 +152,7 @@ and keep the `files` patterns relative to that directory.
```yaml
- name: Release
uses: softprops/action-gh-release@v2
uses: softprops/action-gh-release@v3
if: github.ref_type == 'tag'
with:
working_directory: dist
@@ -175,7 +181,7 @@ jobs:
- name: Generate Changelog
run: echo "# Good things have arrived" > ${{ github.workspace }}-CHANGELOG.txt
- name: Release
uses: softprops/action-gh-release@v2
uses: softprops/action-gh-release@v3
if: github.ref_type == 'tag'
with:
body_path: ${{ github.workspace }}-CHANGELOG.txt
@@ -193,7 +199,7 @@ comparison range does not match the release series you want to publish.
```yaml
- name: Release
uses: softprops/action-gh-release@v2
uses: softprops/action-gh-release@v3
with:
tag_name: stage-2026-03-15
target_commitish: ${{ github.sha }}
+25 -10
View File
@@ -13,6 +13,7 @@ Use this checklist when cutting a new `action-gh-release` release.
1. Update [package.json](package.json) to the new version.
2. Add the new entry at the top of [CHANGELOG.md](CHANGELOG.md).
- Summarize the release in 1 short paragraph.
- If the summary mentions issues, use plain `#123` references or full issue links; do not wrap issue numbers like `#123` in backticks.
- Prefer user-facing fixes and features over internal churn.
- Keep the merged PR list aligned with `.github/release.yml` categories.
3. Run `npm i` to refresh [package-lock.json](package-lock.json).
@@ -22,20 +23,34 @@ Use this checklist when cutting a new `action-gh-release` release.
- `npm run build`
- `npm test`
5. Commit the release prep.
- Use a plain release commit message like `release 2.5.4`.
6. Create the annotated tag for the release commit.
- Example: `git tag -a v2.5.4 -m "v2.5.4"`
7. Push the commit and tag.
- Example: `git push origin master && git push origin v2.5.4`
8. Move the floating major tag to the new release tag.
- For the current major line, either run `npm run updatetag` or update the script first if the major ever changes.
- Verify the floating tag points at the same commit as the new full tag.
9. Create the GitHub release from the new tag.
- Use `git commit -s` so the release commit carries a DCO sign-off.
- Use a plain release commit message like `release X.Y.Z`.
6. Push a release branch and open a pull request against `master`.
- Wait for required checks and reviews.
- Do not bypass branch protection or tag an unmerged release branch.
7. After merge, fetch `origin/master` and resolve the exact merged release commit.
- Confirm that commit contains the expected package version and top changelog entry.
- When the PR is squash-merged, do not assume the release branch commit is the release commit.
8. Create and push the full annotated version tag on the merged release commit.
- Example: `git tag -a vX.Y.Z -m "vX.Y.Z" <release-commit>`
- Push only the full version tag first, then wait for its tag-triggered CI to pass.
9. Move the floating major tag to the same merged release commit.
- For the current major line, run `npm run updatetag` to move `v3`.
- Do not move `v2`; it is frozen at the final, unsupported `v2.6.2` release.
- Verify `v3` and the full version tag are annotated and peel to the same commit.
- Verify `v2` did not move, then wait for the separate `v3` tag-triggered CI run to pass.
10. Create the GitHub release from the full version tag.
- Prefer the release body from [CHANGELOG.md](CHANGELOG.md), then let GitHub append generated notes only if they add value.
- Verify the release shows the expected tag, title, notes, and attached artifacts.
- Verify the release shows the expected tag, title, notes, draft/prerelease state, and attached artifacts.
11. Run post-release consumer verification in `ruitest2/action-gh-release-test`.
- Run the generic smoke against both the full version tag and `v3`.
- Run regression workflows relevant to the fixes in the release.
- Confirm that every disposable release, tag, discussion, container, volume, and temporary credential was cleaned up.
## Notes
- Behavior changes should already have matching updates in [README.md](README.md), [action.yml](action.yml), tests, and `dist/index.js` before release prep begins.
- Docs-only releases still need an intentional changelog entry and version bump decision.
- If a release is mainly bug fixes, keep the title and summary patch-oriented; do not bury the actual fixes under dependency noise.
- Do not move the floating major tag or publish the GitHub release until the full
version tag's CI passes.
+1251 -57
View File
File diff suppressed because it is too large. Load diff
+11
View File
@@ -0,0 +1,11 @@
import { expect, it, vi } from 'vitest';
const run = vi.hoisted(() => vi.fn().mockResolvedValue(undefined));
vi.mock('../src/run', () => ({ run }));
it('starts the action orchestration', async () => {
await import('../src/main');
expect(run).toHaveBeenCalledOnce();
});
+182
View File
@@ -0,0 +1,182 @@
import { getOctokit } from '@actions/github';
import { createServer, type Server } from 'http';
import { type AddressInfo } from 'net';
import { afterAll, beforeAll, describe, expect, it } from 'vitest';
import { GitHubReleaser, release, type Release } from '../src/github';
import { parseConfig, type Config } from '../src/util';
type CapturedRequest = {
path: string;
authorization: string | undefined;
contentType: string | undefined;
body: Record<string, unknown>;
};
const closeServer = async (server: Server): Promise<void> => {
server.closeIdleConnections();
server.closeAllConnections();
await new Promise<void>((resolve, reject) => {
server.close((error) => (error ? reject(error) : resolve()));
});
};
describe('release creation transport', () => {
let server: Server;
let baseUrl: string;
const requests: CapturedRequest[] = [];
const releases = new Map<string, Release>();
beforeAll(async () => {
server = createServer(async (request, response) => {
const url = new URL(request.url || '/', 'http://127.0.0.1');
const tagMatch = url.pathname.match(/^\/repos\/owner\/remote\/releases\/tags\/(.+)$/);
if (request.method === 'GET' && tagMatch) {
const release = releases.get(decodeURIComponent(tagMatch[1]));
response.writeHead(release ? 200 : 404, { 'content-type': 'application/json' });
response.end(JSON.stringify(release ?? { message: 'Not Found' }));
return;
}
if (request.method === 'GET' && url.pathname === '/repos/owner/remote/releases') {
response.writeHead(200, { 'content-type': 'application/json' });
response.end(JSON.stringify([...releases.values()]));
return;
}
if (request.method === 'POST' && url.pathname === '/repos/owner/remote/releases') {
const chunks: Buffer[] = [];
for await (const chunk of request) {
chunks.push(Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk));
}
const body = JSON.parse(Buffer.concat(chunks).toString('utf8')) as Record<string, unknown>;
requests.push({
path: url.pathname,
authorization: request.headers.authorization,
contentType: request.headers['content-type'],
body,
});
const tag = String(body.tag_name);
const createdRelease: Release = {
id: requests.length,
upload_url: `http://127.0.0.1/uploads/${requests.length}`,
html_url: `http://127.0.0.1/releases/${requests.length}`,
tag_name: tag,
name: String(body.name),
body: typeof body.body === 'string' ? body.body : null,
target_commitish: 'main',
draft: Boolean(body.draft),
prerelease: Boolean(body.prerelease),
assets: [],
};
releases.set(tag, createdRelease);
response.writeHead(201, { 'content-type': 'application/json' });
response.end(JSON.stringify(createdRelease));
return;
}
response.writeHead(500, { 'content-type': 'application/json' });
response.end(
JSON.stringify({ message: `Unexpected route ${request.method} ${url.pathname}` }),
);
});
await new Promise<void>((resolve, reject) => {
server.once('error', reject);
server.listen(0, '127.0.0.1', resolve);
});
const address = server.address() as AddressInfo;
baseUrl = `http://127.0.0.1:${address.port}`;
});
afterAll(async () => {
await closeServer(server);
});
it('serializes user-facing category inputs through the real Octokit request path', async () => {
const parsedEmptyCategory = parseConfig({
INPUT_DISCUSSION_CATEGORY_NAME: '',
}).input_discussion_category_name;
expect(parsedEmptyCategory).toBeUndefined();
const cases: Array<{
name: string;
categoryProperty: 'absent' | 'present';
category: string | undefined;
expectedCategory: string | undefined;
}> = [
{
name: 'absent-category',
categoryProperty: 'absent',
category: undefined,
expectedCategory: undefined,
},
{
name: 'undefined-category',
categoryProperty: 'present',
category: undefined,
expectedCategory: undefined,
},
{
name: 'empty-input-category',
categoryProperty: 'present',
category: parsedEmptyCategory,
expectedCategory: undefined,
},
{
name: 'valid-category',
categoryProperty: 'present',
category: 'Announcements',
expectedCategory: 'Announcements',
},
];
for (const testCase of cases) {
const config: Config = {
github_token: 'not-a-real-token',
github_ref: 'refs/heads/main',
github_repository: 'owner/remote',
input_tag_name: testCase.name,
input_name: `Release ${testCase.name}`,
input_files: [],
input_draft: false,
input_prerelease: true,
input_fail_on_unmatched_files: false,
input_generate_release_notes: false,
input_append_body: false,
input_make_latest: undefined,
};
if (testCase.categoryProperty === 'present') {
config.input_discussion_category_name = testCase.category;
}
const releaser = new GitHubReleaser(
getOctokit(config.github_token, {
baseUrl,
}),
);
await expect(release(config, releaser, 1)).resolves.toMatchObject({
release: { tag_name: testCase.name },
created: true,
});
const request = requests.at(-1);
expect(request).toMatchObject({
path: '/repos/owner/remote/releases',
authorization: 'token not-a-real-token',
contentType: 'application/json; charset=utf-8',
body: {
tag_name: testCase.name,
name: `Release ${testCase.name}`,
draft: false,
prerelease: true,
generate_release_notes: false,
},
});
if (testCase.expectedCategory) {
expect(request?.body.discussion_category_name).toBe(testCase.expectedCategory);
} else {
expect(request?.body).not.toHaveProperty('discussion_category_name');
}
}
});
});
+433
View File
@@ -0,0 +1,433 @@
import type { Config } from '../src/util';
import type { Release } from '../src/github';
import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest';
const mocks = vi.hoisted(() => ({
setFailed: vi.fn(),
setOutput: vi.fn(),
getOctokit: vi.fn(),
GitHubReleaser: vi.fn(function () {
return mocks.releaser;
}),
releaser: { name: 'releaser' },
release: vi.fn(),
finalizeRelease: vi.fn(),
upload: vi.fn(),
listReleaseAssets: vi.fn(),
parseConfig: vi.fn(),
isTag: vi.fn(),
paths: vi.fn(),
unmatchedPatterns: vi.fn(),
uploadUrl: vi.fn(),
}));
vi.mock('@actions/core', () => ({
setFailed: mocks.setFailed,
setOutput: mocks.setOutput,
}));
vi.mock('@actions/github', () => ({ getOctokit: mocks.getOctokit }));
vi.mock('../src/github', () => ({
GitHubReleaser: mocks.GitHubReleaser,
release: mocks.release,
finalizeRelease: mocks.finalizeRelease,
upload: mocks.upload,
listReleaseAssets: mocks.listReleaseAssets,
}));
vi.mock('../src/util', async (importOriginal) => {
const actual = await importOriginal<typeof import('../src/util')>();
return {
...actual,
parseConfig: mocks.parseConfig,
isTag: mocks.isTag,
paths: mocks.paths,
unmatchedPatterns: mocks.unmatchedPatterns,
uploadUrl: mocks.uploadUrl,
};
});
import { run } from '../src/run';
const baseConfig: Config = {
github_token: 'token',
github_ref: 'refs/tags/v1.0.0',
github_repository: 'owner/repo',
input_files: [],
input_draft: false,
input_prerelease: false,
input_preserve_order: false,
input_overwrite_files: true,
input_fail_on_unmatched_files: false,
input_generate_release_notes: false,
input_append_body: false,
input_make_latest: undefined,
};
const initialRelease: Release = {
id: 41,
upload_url: 'https://uploads.example.test/releases/41/assets{?name,label}',
html_url: 'https://example.test/releases/41',
tag_name: 'v1.0.0',
name: 'v1.0.0',
target_commitish: 'main',
draft: true,
prerelease: false,
assets: [{ id: 1, name: 'existing.zip' }],
};
const finalizedRelease: Release = {
...initialRelease,
id: 42,
upload_url: 'https://uploads.example.test/releases/42/assets{?name,label}',
html_url: 'https://example.test/releases/42',
draft: false,
};
const deferred = <T>() => {
let resolve!: (value: T) => void;
const promise = new Promise<T>((resolvePromise) => {
resolve = resolvePromise;
});
return { promise, resolve };
};
describe('run', () => {
let config: Config;
beforeEach(() => {
vi.clearAllMocks();
config = { ...baseConfig };
mocks.parseConfig.mockImplementation(() => config);
mocks.isTag.mockImplementation((ref: string) => ref.startsWith('refs/tags/'));
mocks.unmatchedPatterns.mockReturnValue([]);
mocks.paths.mockReturnValue([]);
mocks.uploadUrl.mockImplementation((url: string) => url.split('{')[0]);
mocks.getOctokit.mockReturnValue({ name: 'octokit' });
mocks.release.mockResolvedValue({ release: initialRelease, created: true });
mocks.finalizeRelease.mockResolvedValue(finalizedRelease);
mocks.upload.mockResolvedValue(undefined);
mocks.listReleaseAssets.mockResolvedValue([]);
vi.spyOn(console, 'log').mockImplementation(() => undefined);
vi.spyOn(console, 'warn').mockImplementation(() => undefined);
});
afterEach(() => {
vi.restoreAllMocks();
});
it.each([
['an explicit tag', { github_ref: 'refs/heads/main', input_tag_name: 'v1.0.0' }],
['a tag ref', { github_ref: 'refs/tags/v1.0.0', input_tag_name: undefined }],
[
'a draft without a tag',
{ github_ref: 'refs/heads/main', input_tag_name: undefined, input_draft: true },
],
])('accepts %s', async (_name, patch) => {
config = { ...config, ...patch };
await run();
expect(mocks.release).toHaveBeenCalledOnce();
expect(mocks.setFailed).not.toHaveBeenCalled();
});
it('reports the documented tag requirement for a non-tag ref', async () => {
config = { ...config, github_ref: 'refs/heads/main', input_tag_name: undefined };
await run();
expect(mocks.setFailed).toHaveBeenCalledWith('⚠️ GitHub Releases requires a tag');
expect(mocks.release).not.toHaveBeenCalled();
});
it('warns with each unmatched input pattern when strict matching is disabled', async () => {
config = { ...config, input_files: ['dist/*.zip'] };
mocks.unmatchedPatterns.mockReturnValue(['dist/*.zip']);
await run();
expect(console.warn).toHaveBeenCalledWith("🤔 Pattern 'dist/*.zip' does not match any files.");
expect(mocks.setFailed).not.toHaveBeenCalled();
});
it('fails with the unmatched input pattern when strict matching is enabled', async () => {
config = {
...config,
input_files: ['dist/*.zip'],
input_fail_on_unmatched_files: true,
};
mocks.unmatchedPatterns.mockReturnValue(['dist/*.zip']);
await run();
expect(mocks.setFailed).toHaveBeenCalledWith(
"⚠️ Pattern 'dist/*.zip' does not match any files.",
);
expect(mocks.release).not.toHaveBeenCalled();
});
it.each([
[false, 'warns', '🤔 dist/*.zip does not include a valid file.'],
[true, 'fails', '⚠️ dist/*.zip does not include a valid file.'],
])(
'%s strict matching %s when resolved patterns contain no files',
async (strict, _verb, message) => {
config = {
...config,
input_files: ['dist/*.zip'],
input_fail_on_unmatched_files: strict,
};
await run();
if (strict) {
expect(mocks.setFailed).toHaveBeenCalledWith(message);
expect(mocks.finalizeRelease).not.toHaveBeenCalled();
} else {
expect(console.warn).toHaveBeenCalledWith(message);
expect(mocks.finalizeRelease).toHaveBeenCalledOnce();
}
},
);
it('forwards valid files and the working directory through upload boundaries', async () => {
config = {
...config,
input_files: ['dist/*.zip'],
input_working_directory: 'fixture',
};
mocks.paths.mockReturnValue(['fixture/dist/action.zip']);
mocks.upload.mockResolvedValue({ id: 7 });
mocks.listReleaseAssets.mockResolvedValue([{ id: 7, name: 'action.zip' }]);
await run();
expect(mocks.paths).toHaveBeenCalledWith(['dist/*.zip'], 'fixture');
expect(mocks.upload).toHaveBeenCalledWith(
config,
mocks.releaser,
'https://uploads.example.test/releases/41/assets',
'fixture/dist/action.zip',
initialRelease.assets,
initialRelease.id,
);
});
it('starts uploads concurrently by default', async () => {
config = { ...config, input_files: ['one.zip', 'two.zip'] };
mocks.paths.mockReturnValue(['one.zip', 'two.zip']);
const first = deferred<{ id: number }>();
const second = deferred<{ id: number }>();
mocks.upload.mockImplementation((_config, _releaser, _url, path) =>
path === 'one.zip' ? first.promise : second.promise,
);
const result = run();
await Promise.resolve();
expect(mocks.upload).toHaveBeenCalledTimes(2);
first.resolve({ id: 1 });
second.resolve({ id: 2 });
await result;
});
it('waits for each upload when preserve_order is enabled', async () => {
config = {
...config,
input_files: ['one.zip', 'two.zip'],
input_preserve_order: true,
};
mocks.paths.mockReturnValue(['one.zip', 'two.zip']);
const first = deferred<{ id: number }>();
const second = deferred<{ id: number }>();
mocks.upload.mockImplementation((_config, _releaser, _url, path) =>
path === 'one.zip' ? first.promise : second.promise,
);
const result = run();
await Promise.resolve();
expect(mocks.upload).toHaveBeenCalledTimes(1);
first.resolve({ id: 1 });
await vi.waitFor(() => expect(mocks.upload).toHaveBeenCalledTimes(2));
second.resolve({ id: 2 });
await result;
});
it('keeps an existing draft unpublished until its upload completes', async () => {
config = {
...config,
input_draft: false,
input_prerelease: true,
input_files: ['asset.zip'],
};
mocks.release.mockResolvedValue({ release: initialRelease, created: false });
mocks.paths.mockReturnValue(['asset.zip']);
const pendingUpload = deferred<{ id: number }>();
mocks.upload.mockReturnValue(pendingUpload.promise);
const result = run();
await Promise.resolve();
expect(mocks.upload).toHaveBeenCalledOnce();
expect(mocks.finalizeRelease).not.toHaveBeenCalled();
pendingUpload.resolve({ id: 7 });
await result;
expect(mocks.finalizeRelease).toHaveBeenCalledWith(
config,
mocks.releaser,
initialRelease,
false,
);
});
it('uses the selected moving-tag release ID for upload, finalization, and outputs', async () => {
config = {
...config,
input_tag_name: 'nightly',
input_draft: false,
input_prerelease: true,
input_files: ['nightly.zip'],
};
const selectedRelease: Release = {
...initialRelease,
id: 77,
upload_url: 'https://uploads.example.test/releases/77/assets{?name,label}',
html_url: 'https://example.test/releases/77',
tag_name: 'nightly',
name: 'nightly',
prerelease: true,
};
const publishedRelease: Release = {
...selectedRelease,
draft: false,
};
mocks.release.mockResolvedValue({ release: selectedRelease, created: false });
mocks.paths.mockReturnValue(['nightly.zip']);
mocks.upload.mockResolvedValue({ id: 9 });
mocks.finalizeRelease.mockResolvedValue(publishedRelease);
mocks.listReleaseAssets.mockResolvedValue([{ id: 9, name: 'nightly.zip' }]);
await run();
expect(mocks.upload).toHaveBeenCalledWith(
config,
mocks.releaser,
'https://uploads.example.test/releases/77/assets',
'nightly.zip',
selectedRelease.assets,
77,
);
expect(mocks.finalizeRelease).toHaveBeenCalledWith(
config,
mocks.releaser,
selectedRelease,
false,
);
expect(mocks.listReleaseAssets).toHaveBeenCalledWith(config, mocks.releaser, publishedRelease);
expect(mocks.setOutput).toHaveBeenCalledWith('id', '77');
expect(mocks.setOutput).toHaveBeenCalledWith('url', publishedRelease.html_url);
});
it('leaves an existing draft recoverable when an upload fails', async () => {
config = {
...config,
input_draft: false,
input_prerelease: true,
input_files: ['asset.zip'],
};
mocks.release.mockResolvedValue({ release: initialRelease, created: false });
mocks.paths.mockReturnValue(['asset.zip']);
mocks.upload.mockRejectedValue(new Error('upload failed'));
await run();
expect(mocks.finalizeRelease).not.toHaveBeenCalled();
expect(mocks.setFailed).toHaveBeenCalledWith('upload failed');
});
it('finalizes after uploads and outputs only newly uploaded assets without uploader data', async () => {
config = { ...config, input_files: ['one.zip', 'skipped.zip', 'two.zip'] };
mocks.paths.mockReturnValue(['one.zip', 'skipped.zip', 'two.zip']);
mocks.upload
.mockResolvedValueOnce({ id: 7 })
.mockResolvedValueOnce(null)
.mockResolvedValueOnce({ id: 9 });
mocks.listReleaseAssets.mockResolvedValue([
{ id: 1, name: 'existing.zip', uploader: { login: 'someone' } },
{ id: 7, name: 'one.zip', size: 10, uploader: { login: 'bot' } },
{ id: 9, name: 'two.zip', label: 'Two', uploader: null },
]);
await run();
expect(mocks.release.mock.invocationCallOrder[0]).toBeLessThan(
mocks.upload.mock.invocationCallOrder[0],
);
expect(mocks.upload.mock.invocationCallOrder[2]).toBeLessThan(
mocks.finalizeRelease.mock.invocationCallOrder[0],
);
expect(mocks.finalizeRelease).toHaveBeenCalledWith(
config,
mocks.releaser,
initialRelease,
true,
);
expect(mocks.listReleaseAssets).toHaveBeenCalledWith(config, mocks.releaser, finalizedRelease);
expect(mocks.setOutput).toHaveBeenCalledWith('assets', [
{ id: 7, name: 'one.zip', size: 10 },
{ id: 9, name: 'two.zip', label: 'Two' },
]);
expect(mocks.setOutput).toHaveBeenCalledWith('url', finalizedRelease.html_url);
expect(mocks.setOutput).toHaveBeenCalledWith('id', '42');
expect(mocks.setOutput).toHaveBeenCalledWith('upload_url', finalizedRelease.upload_url);
});
it('outputs an empty asset list and skips refresh when no upload returns an ID', async () => {
config = { ...config, input_files: ['skipped.zip'] };
mocks.paths.mockReturnValue(['skipped.zip']);
mocks.upload.mockResolvedValue(undefined);
await run();
expect(mocks.listReleaseAssets).not.toHaveBeenCalled();
expect(mocks.setOutput).toHaveBeenCalledWith('assets', []);
});
it('configures rate-limit and abuse callbacks without making live requests', async () => {
await run();
const options = mocks.getOctokit.mock.calls[0][1];
const request = { method: 'GET', url: '/repos/owner/repo', request: { retryCount: 0 } };
expect(options.throttle.onRateLimit(5, request)).toBe(true);
expect(
options.throttle.onRateLimit(5, { ...request, request: { retryCount: 1 } }),
).toBeUndefined();
expect(options.throttle.onAbuseLimit(10, request)).toBeUndefined();
expect(console.warn).toHaveBeenCalledWith(
'Request quota exhausted for request GET /repos/owner/repo',
);
expect(console.warn).toHaveBeenCalledWith('Abuse detected for request GET /repos/owner/repo');
});
it.each([
[new Error('release failed'), 'release failed'],
['release failed', 'release failed'],
[{ message: 'release failed' }, 'release failed'],
[null, 'Unknown error'],
[undefined, 'Unknown error'],
])('normalizes a thrown value before reporting failure', async (thrown, expected) => {
mocks.parseConfig.mockImplementation(() => {
throw thrown;
});
await run();
expect(mocks.setFailed).toHaveBeenCalledWith(expected);
});
});
+394
View File
@@ -0,0 +1,394 @@
import { getOctokit } from '@actions/github';
import { createHash } from 'crypto';
import { createServer, type Server } from 'http';
import { type AddressInfo } from 'net';
import { mkdtemp, open, rm, writeFile } from 'fs/promises';
import { tmpdir } from 'os';
import { join } from 'path';
import { afterAll, beforeAll, describe, expect, it, vi } from 'vitest';
import { GitHubReleaser, upload } from '../src/github';
import type { Config } from '../src/util';
const openFile = vi.hoisted(() => vi.fn());
vi.mock('fs/promises', async (importOriginal) => {
const actual = await importOriginal<typeof import('fs/promises')>();
openFile.mockImplementation(actual.open);
return { ...actual, open: openFile };
});
type Fixture = {
name: string;
path: string;
size: number;
digest: string;
contentType: string;
bytes?: Buffer;
};
type Receipt = {
method: string | undefined;
pathname: string;
filename: string | null;
contentLength: string | undefined;
contentType: string | undefined;
size: number;
digest: string;
chunks: number;
chunkTypes: string[];
bytes?: Buffer;
};
const config: Config = {
github_token: 'not-a-real-token',
github_ref: 'refs/tags/v1.0.0',
github_repository: 'owner/repo',
input_files: [],
input_fail_on_unmatched_files: false,
input_generate_release_notes: false,
input_append_body: false,
input_make_latest: undefined,
};
const sha256 = (data: Buffer): string => createHash('sha256').update(data).digest('hex');
const expectLastFileHandleClosed = async (): Promise<void> => {
const result = openFile.mock.results.at(-1);
expect(result?.type).toBe('return');
const fileHandle = await result?.value;
await expect(fileHandle.stat()).rejects.toMatchObject({ code: 'EBADF' });
};
const closeServer = async (server: Server): Promise<void> => {
server.closeIdleConnections();
server.closeAllConnections();
await new Promise<void>((resolve, reject) => {
server.close((error) => (error ? reject(error) : resolve()));
});
};
const startUploadServer = async (
responseStatus: (requestIndex: number) => number = () => 201,
): Promise<{ server: Server; uploadUrl: string; receipts: Receipt[] }> => {
const receipts: Receipt[] = [];
const server = createServer(async (request, response) => {
const url = new URL(request.url || '/', 'http://127.0.0.1');
const hash = createHash('sha256');
const bufferedChunks: Buffer[] = [];
const chunkTypes: string[] = [];
let size = 0;
let chunks = 0;
for await (const chunk of request) {
chunkTypes.push(chunk?.constructor?.name || typeof chunk);
const bytes = Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk);
chunks += 1;
size += bytes.length;
hash.update(bytes);
if (size <= 1024 * 1024) {
bufferedChunks.push(Buffer.from(bytes));
}
}
receipts.push({
method: request.method,
pathname: url.pathname,
filename: url.searchParams.get('name'),
contentLength: request.headers['content-length'],
contentType: request.headers['content-type'],
size,
digest: hash.digest('hex'),
chunks,
chunkTypes,
bytes: size <= 1024 * 1024 ? Buffer.concat(bufferedChunks) : undefined,
});
const status = responseStatus(receipts.length - 1);
response.writeHead(status, { 'content-type': 'application/json' });
response.end(
JSON.stringify(
status === 201
? { id: 123, name: url.searchParams.get('name') }
: {
message: 'Validation Failed',
errors: [{ code: 'already_exists' }],
},
),
);
});
await new Promise<void>((resolve, reject) => {
server.once('error', reject);
server.listen(0, '127.0.0.1', resolve);
});
const address = server.address() as AddressInfo;
return {
server,
uploadUrl: `http://127.0.0.1:${address.port}/repos/owner/repo/releases/1/assets`,
receipts,
};
};
describe('release asset upload transport', () => {
let tempDirectory: string;
let fixtures: Fixture[];
beforeAll(async () => {
tempDirectory = await mkdtemp(join(tmpdir(), 'action-gh-release-upload-'));
const smallFixtures = [
{
name: 'artifact.zip.sha512',
bytes: Buffer.from(`${'a'.repeat(128)}\n`),
contentType: 'application/octet-stream',
},
{
name: 'artifact.md5',
bytes: Buffer.from(`${'b'.repeat(32)}\n`),
contentType: 'application/octet-stream',
},
{ name: 'one-byte.txt', bytes: Buffer.from([0x7f]), contentType: 'text/plain' },
{ name: 'empty.bin', bytes: Buffer.alloc(0), contentType: 'application/octet-stream' },
{
name: 'binary.bin',
bytes: Buffer.from([0x00, 0x01, 0x7f, 0x80, 0xfe, 0xff]),
contentType: 'application/octet-stream',
},
];
fixtures = [];
for (const fixture of smallFixtures) {
const path = join(tempDirectory, fixture.name);
await writeFile(path, fixture.bytes);
fixtures.push({
...fixture,
path,
size: fixture.bytes.length,
digest: sha256(fixture.bytes),
});
}
const largePath = join(tempDirectory, 'large.bin');
const largeHandle = await open(largePath, 'w');
const largeHash = createHash('sha256');
const block = Buffer.alloc(64 * 1024);
for (let index = 0; index < block.length; index += 1) {
block[index] = index % 251;
}
try {
for (let index = 0; index < 128; index += 1) {
await largeHandle.write(block);
largeHash.update(block);
}
} finally {
await largeHandle.close();
}
fixtures.push({
name: 'large.bin',
path: largePath,
size: 8 * 1024 * 1024,
digest: largeHash.digest('hex'),
contentType: 'application/octet-stream',
});
});
afterAll(async () => {
await rm(tempDirectory, { recursive: true, force: true });
});
it.each([0, 1, 2, 3, 4, 5])(
'uploads fixture %i through the real Octokit request path',
async (fixtureIndex) => {
const fixture = fixtures[fixtureIndex];
const { server, uploadUrl, receipts } = await startUploadServer();
const releaser = new GitHubReleaser(getOctokit(config.github_token));
openFile.mockClear();
try {
await expect(upload(config, releaser, uploadUrl, fixture.path, [], 1)).resolves.toEqual({
id: 123,
name: fixture.name,
});
expect(receipts).toHaveLength(1);
expect(receipts[0]).toMatchObject({
method: 'POST',
pathname: '/repos/owner/repo/releases/1/assets',
filename: fixture.name,
contentLength: String(fixture.size),
contentType: fixture.contentType,
size: fixture.size,
digest: fixture.digest,
});
if (fixture.bytes) {
expect(receipts[0].bytes).toEqual(fixture.bytes);
}
expect(new Set(receipts[0].chunkTypes)).toEqual(
fixture.size === 0 ? new Set() : new Set(['Buffer']),
);
if (fixture.size > 1024 * 1024) {
expect(receipts[0].chunks).toBeGreaterThan(1);
}
await expectLastFileHandleClosed();
} finally {
await closeServer(server);
}
},
);
it('closes the file handle when the request fails', async () => {
const fixture = fixtures[0];
const { server, uploadUrl } = await startUploadServer(() => 500);
const releaser = new GitHubReleaser(getOctokit(config.github_token));
openFile.mockClear();
try {
await expect(upload(config, releaser, uploadUrl, fixture.path, [], 1)).rejects.toThrow(
'Validation Failed',
);
await expectLastFileHandleClosed();
} finally {
await closeServer(server);
}
});
it('normalizes ArrayBuffer chunks before they reach the Octokit transport', async () => {
const fixture = fixtures[0];
const { server, uploadUrl, receipts } = await startUploadServer();
const releaser = new GitHubReleaser(getOctokit(config.github_token));
const actual = await vi.importActual<typeof import('fs/promises')>('fs/promises');
openFile.mockImplementationOnce(async (...args: Parameters<typeof actual.open>) => {
const fileHandle = await actual.open(...args);
const readableWebStream = fileHandle.readableWebStream.bind(fileHandle);
Object.defineProperty(fileHandle, 'readableWebStream', {
configurable: true,
value: () =>
readableWebStream().pipeThrough(
new TransformStream<Uint8Array, ArrayBuffer>({
transform(chunk, controller) {
controller.enqueue(chunk.slice().buffer);
},
}),
),
});
return fileHandle;
});
try {
await expect(upload(config, releaser, uploadUrl, fixture.path, [], 1)).resolves.toEqual({
id: 123,
name: fixture.name,
});
expect(receipts).toHaveLength(1);
expect(receipts[0]).toMatchObject({
size: fixture.size,
digest: fixture.digest,
});
await expectLastFileHandleClosed();
} finally {
await closeServer(server);
}
});
it('opens a fresh upload body after an already-exists response', async () => {
const fixture = fixtures[0];
const { server, uploadUrl, receipts } = await startUploadServer((index) =>
index === 0 ? 422 : 201,
);
const releaser = new GitHubReleaser(getOctokit(config.github_token));
vi.spyOn(releaser, 'listReleaseAssets').mockResolvedValue([{ id: 9, name: fixture.name }]);
const deleteReleaseAsset = vi
.spyOn(releaser, 'deleteReleaseAsset')
.mockResolvedValue(undefined);
openFile.mockClear();
try {
await expect(upload(config, releaser, uploadUrl, fixture.path, [], 1)).resolves.toEqual({
id: 123,
name: fixture.name,
});
expect(receipts).toHaveLength(2);
expect(receipts.map(({ size }) => size)).toEqual([fixture.size, fixture.size]);
expect(receipts.map(({ digest }) => digest)).toEqual([fixture.digest, fixture.digest]);
expect(openFile).toHaveBeenCalledTimes(2);
expect(deleteReleaseAsset).toHaveBeenCalledWith({
owner: 'owner',
repo: 'repo',
release_id: 1,
asset_id: 9,
});
for (const result of openFile.mock.results) {
const fileHandle = await result.value;
await expect(fileHandle.stat()).rejects.toMatchObject({ code: 'EBADF' });
}
} finally {
await closeServer(server);
}
});
it('falls back to the release-scoped delete route through the real Octokit request path', async () => {
const requests: Array<{
method: string | undefined;
pathname: string;
authorization: string | undefined;
}> = [];
const server = createServer((request, response) => {
const url = new URL(request.url || '/', 'http://127.0.0.1');
requests.push({
method: request.method,
pathname: url.pathname,
authorization: request.headers.authorization,
});
if (url.pathname === '/repos/owner/repo/releases/assets/9') {
response.writeHead(404, { 'content-type': 'application/json' });
response.end(JSON.stringify({ message: 'page not found' }));
return;
}
if (url.pathname === '/repos/owner/repo/releases/1/assets/9') {
response.writeHead(204);
response.end();
return;
}
response.writeHead(500, { 'content-type': 'application/json' });
response.end(JSON.stringify({ message: 'unexpected route' }));
});
await new Promise<void>((resolve, reject) => {
server.once('error', reject);
server.listen(0, '127.0.0.1', resolve);
});
const address = server.address() as AddressInfo;
const releaser = new GitHubReleaser(
getOctokit(config.github_token, {
baseUrl: `http://127.0.0.1:${address.port}`,
}),
);
try {
await expect(
releaser.deleteReleaseAsset({
owner: 'owner',
repo: 'repo',
release_id: 1,
asset_id: 9,
}),
).resolves.toBeUndefined();
expect(requests).toEqual([
{
method: 'DELETE',
pathname: '/repos/owner/repo/releases/assets/9',
authorization: 'token not-a-real-token',
},
{
method: 'DELETE',
pathname: '/repos/owner/repo/releases/1/assets/9',
authorization: 'token not-a-real-token',
},
]);
} finally {
await closeServer(server);
}
});
});
+25
View File
@@ -1,5 +1,6 @@
import {
alignAssetName,
errorMessage,
expandHomePattern,
isTag,
normalizeFilePattern,
@@ -25,6 +26,26 @@ describe('util', () => {
'https://uploads.github.com/repos/octocat/Hello-World/releases/1/assets',
);
});
it('leaves a URL without a template unchanged', () => {
assert.equal(
uploadUrl('https://uploads.github.com/repos/octocat/Hello-World/releases/1/assets'),
'https://uploads.github.com/repos/octocat/Hello-World/releases/1/assets',
);
});
});
describe('errorMessage', () => {
it.each([
[new Error('failed'), 'failed'],
[{ message: 'failed' }, 'failed'],
['failed', 'failed'],
[42, '42'],
[null, 'Unknown error'],
[undefined, 'Unknown error'],
])('normalizes unknown thrown values', (error, expected) => {
expect(errorMessage(error)).toBe(expected);
});
});
describe('parseInputFiles', () => {
it('parses empty strings', () => {
@@ -213,6 +234,10 @@ describe('util', () => {
);
});
it('treats an empty draft input as omitted', () => {
assert.strictEqual(parseConfig({ INPUT_DRAFT: '' }).input_draft, undefined);
});
it('parses basic config with commitish', () => {
assert.deepStrictEqual(
parseConfig({
+1 -1
View File
@@ -75,7 +75,7 @@ outputs:
assets:
description: "JSON array containing information about each uploaded asset, in the format given [here](https://docs.github.com/en/rest/reference/repos#upload-a-release-asset--code-samples) (minus the `uploader` field)"
runs:
using: "node20"
using: "node24"
main: "dist/index.js"
branding:
color: "green"
+38 -39
View File
@@ -1,58 +1,57 @@
"use strict";var Uw=Object.create;var hp=Object.defineProperty;var Nw=Object.getOwnPropertyDescriptor;var Gw=Object.getOwnPropertyNames;var Mw=Object.getPrototypeOf,Lw=Object.prototype.hasOwnProperty;var Q=(e,t)=>()=>(t||e((t={exports:{}}).exports,t),t.exports);var _w=(e,t,s,r)=>{if(t&&typeof t=="object"||typeof t=="function")for(let i of Gw(t))!Lw.call(e,i)&&i!==s&&hp(e,i,{get:()=>t[i],enumerable:!(r=Nw(t,i))||r.enumerable});return e};var de=(e,t,s)=>(s=e!=null?Uw(Mw(e)):{},_w(t||!e||!e.__esModule?hp(s,"default",{value:e,enumerable:!0}):s,e));var bp=Q(Ks=>{"use strict";var t2=require("net"),Pw=require("tls"),eA=require("http"),Cp=require("https"),Hw=require("events"),s2=require("assert"),Vw=require("util");Ks.httpOverHttp=qw;Ks.httpsOverHttp=Ww;Ks.httpOverHttps=jw;Ks.httpsOverHttps=zw;function qw(e){var t=new Rt(e);return t.request=eA.request,t}function Ww(e){var t=new Rt(e);return t.request=eA.request,t.createSocket=Ip,t.defaultPort=443,t}function jw(e){var t=new Rt(e);return t.request=Cp.request,t}function zw(e){var t=new Rt(e);return t.request=Cp.request,t.createSocket=Ip,t.defaultPort=443,t}function Rt(e){var t=this;t.options=e||{},t.proxyOptions=t.options.proxy||{},t.maxSockets=t.options.maxSockets||eA.Agent.defaultMaxSockets,t.requests=[],t.sockets=[],t.on("free",function(r,i,o,n){for(var a=wp(i,o,n),A=0,c=t.requests.length;A<c;++A){var u=t.requests[A];if(u.host===a.host&&u.port===a.port){t.requests.splice(A,1),u.request.onSocket(r);return}}r.destroy(),t.removeSocket(r)})}Vw.inherits(Rt,Hw.EventEmitter);Rt.prototype.addRequest=function(t,s,r,i){var o=this,n=tA({request:t},o.options,wp(s,r,i));if(o.sockets.length>=this.maxSockets){o.requests.push(n);return}o.createSocket(n,function(a){a.on("free",A),a.on("close",c),a.on("agentRemove",c),t.onSocket(a);function A(){o.emit("free",a,n)}function c(u){o.removeSocket(a),a.removeListener("free",A),a.removeListener("close",c),a.removeListener("agentRemove",c)}})};Rt.prototype.createSocket=function(t,s){var r=this,i={};r.sockets.push(i);var o=tA({},r.proxyOptions,{method:"CONNECT",path:t.host+":"+t.port,agent:!1,headers:{host:t.host+":"+t.port}});t.localAddress&&(o.localAddress=t.localAddress),o.proxyAuth&&(o.headers=o.headers||{},o.headers["Proxy-Authorization"]="Basic "+new Buffer(o.proxyAuth).toString("base64")),Zt("making CONNECT request");var n=r.request(o);n.useChunkedEncodingByDefault=!1,n.once("response",a),n.once("upgrade",A),n.once("connect",c),n.once("error",u),n.end();function a(l){l.upgrade=!0}function A(l,p,g){process.nextTick(function(){c(l,p,g)})}function c(l,p,g){if(n.removeAllListeners(),p.removeAllListeners(),l.statusCode!==200){Zt("tunneling socket could not be established, statusCode=%d",l.statusCode),p.destroy();var h=new Error("tunneling socket could not be established, statusCode="+l.statusCode);h.code="ECONNRESET",t.request.emit("error",h),r.removeSocket(i);return}if(g.length>0){Zt("got illegal response body from proxy"),p.destroy();var h=new Error("got illegal response body from proxy");h.code="ECONNRESET",t.request.emit("error",h),r.removeSocket(i);return}return Zt("tunneling connection has established"),r.sockets[r.sockets.indexOf(i)]=p,s(p)}function u(l){n.removeAllListeners(),Zt(`tunneling socket could not be established, cause=%s
`,l.message,l.stack);var p=new Error("tunneling socket could not be established, cause="+l.message);p.code="ECONNRESET",t.request.emit("error",p),r.removeSocket(i)}};Rt.prototype.removeSocket=function(t){var s=this.sockets.indexOf(t);if(s!==-1){this.sockets.splice(s,1);var r=this.requests.shift();r&&this.createSocket(r,function(i){r.request.onSocket(i)})}};function Ip(e,t){var s=this;Rt.prototype.createSocket.call(s,e,function(r){var i=e.request.getHeader("host"),o=tA({},s.options,{socket:r,servername:i?i.replace(/:.*$/,""):e.host}),n=Pw.connect(0,o);s.sockets[s.sockets.indexOf(r)]=n,t(n)})}function wp(e,t,s){return typeof e=="string"?{host:e,port:t,localAddress:s}:e}function tA(e){for(var t=1,s=arguments.length;t<s;++t){var r=arguments[t];if(typeof r=="object")for(var i=Object.keys(r),o=0,n=i.length;o<n;++o){var a=i[o];r[a]!==void 0&&(e[a]=r[a])}}return e}var Zt;process.env.NODE_DEBUG&&/\btunnel\b/.test(process.env.NODE_DEBUG)?Zt=function(){var e=Array.prototype.slice.call(arguments);typeof e[0]=="string"?e[0]="TUNNEL: "+e[0]:e.unshift("TUNNEL:"),console.error.apply(console,e)}:Zt=function(){};Ks.debug=Zt});var sA=Q((i2,yp)=>{yp.exports=bp()});var j=Q((o2,xp)=>{xp.exports={kClose:Symbol("close"),kDestroy:Symbol("destroy"),kDispatch:Symbol("dispatch"),kUrl:Symbol("url"),kWriting:Symbol("writing"),kResuming:Symbol("resuming"),kQueue:Symbol("queue"),kConnect:Symbol("connect"),kConnecting:Symbol("connecting"),kKeepAliveDefaultTimeout:Symbol("default keep alive timeout"),kKeepAliveMaxTimeout:Symbol("max keep alive timeout"),kKeepAliveTimeoutThreshold:Symbol("keep alive timeout threshold"),kKeepAliveTimeoutValue:Symbol("keep alive timeout"),kKeepAlive:Symbol("keep alive"),kHeadersTimeout:Symbol("headers timeout"),kBodyTimeout:Symbol("body timeout"),kServerName:Symbol("server name"),kLocalAddress:Symbol("local address"),kHost:Symbol("host"),kNoRef:Symbol("no ref"),kBodyUsed:Symbol("used"),kBody:Symbol("abstracted request body"),kRunning:Symbol("running"),kBlocking:Symbol("blocking"),kPending:Symbol("pending"),kSize:Symbol("size"),kBusy:Symbol("busy"),kQueued:Symbol("queued"),kFree:Symbol("free"),kConnected:Symbol("connected"),kClosed:Symbol("closed"),kNeedDrain:Symbol("need drain"),kReset:Symbol("reset"),kDestroyed:Symbol.for("nodejs.stream.destroyed"),kResume:Symbol("resume"),kOnError:Symbol("on error"),kMaxHeadersSize:Symbol("max headers size"),kRunningIdx:Symbol("running index"),kPendingIdx:Symbol("pending index"),kError:Symbol("error"),kClients:Symbol("clients"),kClient:Symbol("client"),kParser:Symbol("parser"),kOnDestroyed:Symbol("destroy callbacks"),kPipelining:Symbol("pipelining"),kSocket:Symbol("socket"),kHostHeader:Symbol("host header"),kConnector:Symbol("connector"),kStrictContentLength:Symbol("strict content length"),kMaxRedirections:Symbol("maxRedirections"),kMaxRequests:Symbol("maxRequestsPerClient"),kProxy:Symbol("proxy agent options"),kCounter:Symbol("socket request counter"),kInterceptors:Symbol("dispatch interceptors"),kMaxResponseSize:Symbol("max response size"),kHTTP2Session:Symbol("http2Session"),kHTTP2SessionState:Symbol("http2Session state"),kRetryHandlerDefaultRetry:Symbol("retry agent default retry"),kConstruct:Symbol("constructable"),kListeners:Symbol("listeners"),kHTTPContext:Symbol("http context"),kMaxConcurrentStreams:Symbol("max concurrent streams"),kNoProxyAgent:Symbol("no proxy agent"),kHttpProxyAgent:Symbol("http proxy agent"),kHttpsProxyAgent:Symbol("https proxy agent")}});var Y=Q((n2,Kp)=>{"use strict";var vp=Symbol.for("undici.error.UND_ERR"),z=class extends Error{constructor(t){super(t),this.name="UndiciError",this.code="UND_ERR"}static[Symbol.hasInstance](t){return t&&t[vp]===!0}[vp]=!0},kp=Symbol.for("undici.error.UND_ERR_CONNECT_TIMEOUT"),rA=class extends z{constructor(t){super(t),this.name="ConnectTimeoutError",this.message=t||"Connect Timeout Error",this.code="UND_ERR_CONNECT_TIMEOUT"}static[Symbol.hasInstance](t){return t&&t[kp]===!0}[kp]=!0},Dp=Symbol.for("undici.error.UND_ERR_HEADERS_TIMEOUT"),iA=class extends z{constructor(t){super(t),this.name="HeadersTimeoutError",this.message=t||"Headers Timeout Error",this.code="UND_ERR_HEADERS_TIMEOUT"}static[Symbol.hasInstance](t){return t&&t[Dp]===!0}[Dp]=!0},Rp=Symbol.for("undici.error.UND_ERR_HEADERS_OVERFLOW"),oA=class extends z{constructor(t){super(t),this.name="HeadersOverflowError",this.message=t||"Headers Overflow Error",this.code="UND_ERR_HEADERS_OVERFLOW"}static[Symbol.hasInstance](t){return t&&t[Rp]===!0}[Rp]=!0},Tp=Symbol.for("undici.error.UND_ERR_BODY_TIMEOUT"),nA=class extends z{constructor(t){super(t),this.name="BodyTimeoutError",this.message=t||"Body Timeout Error",this.code="UND_ERR_BODY_TIMEOUT"}static[Symbol.hasInstance](t){return t&&t[Tp]===!0}[Tp]=!0},Fp=Symbol.for("undici.error.UND_ERR_RESPONSE_STATUS_CODE"),aA=class extends z{constructor(t,s,r,i){super(t),this.name="ResponseStatusCodeError",this.message=t||"Response Status Code Error",this.code="UND_ERR_RESPONSE_STATUS_CODE",this.body=i,this.status=s,this. Line truncated
`)||e.includes("\r")||e.includes("\0"))===!1}function ux(e,t){let{headersList:s}=t,r=(s.get("referrer-policy",!0)??"").split(","),i="";if(r.length>0)for(let o=r.length;o!==0;o--){let n=r[o-1].trim();if(zy.has(n)){i=n;break}}i!==""&&(e.referrerPolicy=i)}function px(){return"allowed"}function gx(){return"success"}function hx(){return"success"}function dx(e){let t=null;t=e.mode,e.headersList.set("sec-fetch-mode",t,!0)}function Ex(e){let t=e.origin;if(!(t==="client"||t===void 0)){if(e.responseTainting==="cors"||e.mode==="websocket")e.headersList.append("origin",t,!0);else if(e.method!=="GET"&&e.method!=="HEAD"){switch(e.referrerPolicy){case"no-referrer":t=null;break;case"no-referrer-when-downgrade":case"strict-origin":case"strict-origin-when-cross-origin":e.origin&&XA(e.origin)&&!XA(Ai(e))&&(t=null);break;case"same-origin":Jo(e,Ai(e))||(t=null);break;default:}e.headersList.append("origin",t,!0)}}}function ar(e,t){return e}function mx(e,t,s){return!e?.startTime||e.startTime<t?{domainLookupStartTime:t,domainLookupEndTime:t,connectionStartTime:t,connectionEndTime:t,secureConnectionStartTime:t,ALPNNegotiatedProtocol:e?.ALPNNegotiatedProtocol}:{domainLookupStartTime:ar(e.domainLookupStartTime,s),domainLookupEndTime:ar(e.domainLookupEndTime,s),connectionStartTime:ar(e.connectionStartTime,s),connectionEndTime:ar(e.connectionEndTime,s),secureConnectionStartTime:ar(e.secureConnectionStartTime,s),ALPNNegotiatedProtocol:e.ALPNNegotiatedProtocol}}function fx(e){return ar(ex.now(),e)}function Qx(e){return{startTime:e.startTime??0,redirectStartTime:0,redirectEndTime:0,postRedirectStartTime:e.startTime??0,finalServiceWorkerStartTime:0,finalNetworkResponseStartTime:0,finalNetworkRequestStartTime:0,endTime:0,encodedBodySize:0,decodedBodySize:0,finalConnectionTimingInfo:null}}function uh(){return{referrerPolicy:"strict-origin-when-cross-origin"}}function Bx(e){return{referrerPolicy:e.referrerPolicy}}function Cx(e){let t=e.referrerPolicy;ws(t);let s=null;if(e.referrer==="client"){let a=oh();if(!a||a.origin==="null")return"no-referrer";s=new URL(a)}else e.referrer instanceof URL&&(s=e.referrer);let r=KA(s),i=KA(s,!0);r.toString().length>4096&&(r=i);let o=Jo(e,r),n=ai(r)&&!ai(e.url);switch(t){case"origin":return i??KA(s,!0);case"unsafe-url":return r;case"same-origin":return o?i:"no-referrer";case"origin-when-cross-origin":return o?r:i;case"strict-origin-when-cross-origin":{let a=Ai(e);return Jo(r,a)?r:ai(r)&&!ai(a)?"no-referrer":i}default:return n?"no-referrer":i}}function KA(e,t){return ws(e instanceof URL),e=new URL(e),e.protocol==="file:"||e.protocol==="about:"||e.protocol==="blank:"?"no-referrer":(e.username="",e.password="",e.hash="",t&&(e.pathname="",e.search=""),e)}function ai(e){if(!(e instanceof URL))return!1;if(e.href==="about:blank"||e.href==="about:srcdoc"||e.protocol==="data:"||e.protocol==="file:")return!0;return t(e.origin);function t(s){if(s==null||s==="null")return!1;let r=new URL(s);return!!(r.protocol==="https:"||r.protocol==="wss:"||/^127(?:\.[0-9]+){0,2}\.[0-9]+$|^\[(?:0*:)*?:?0*1\]$/.test(r.hostname)||r.hostname==="localhost"||r.hostname.includes("localhost.")||r.hostname.endsWith(".localhost"))}}function Ix(e,t){if(Oo===void 0)return!0;let s=ph(t);if(s==="no metadata"||s.length===0)return!0;let r=bx(s),i=yx(s,r);for(let o of i){let n=o.algo,a=o.hash,A=Oo.createHash(n).update(e).digest("base64");if(A[A.length-1]==="="&&(A[A.length-2]==="="?A=A.slice(0,-2):A=A.slice(0,-1)),xx(A,a))return!0}return!1}var wx=/(?<algo>sha256|sha384|sha512)-((?<hash>[A-Za-z0-9+/]+|[A-Za-z0-9_-]+)={0,2}(?:\s|$)( +[!-~]*)?)?/i;function ph(e){let t=[],s=!0;for(let r of e.split(" ")){s=!1;let i=wx.exec(r);if(i===null||i.groups===void 0||i.groups.algo===void 0)continue;let o=i.groups.algo.toLowerCase();ah.includes(o)&&t.push(i.groups)}return s===!0?"no metadata":t}function bx(e){let t=e[0].algo;if(t[3]==="5")return t;for(let s=1;s<e.length;++s){let r=e[s];if(r.algo[3]==="5"){t="sha512";break}else{if(t[3]==="3")continue;r.algo[3]==="3"&&(t="sha384")}}return t}function yx(e,t){if(e.length===1)return e;let s=0;for(let r=0;r<e.length;++r)e[r].algo===t&&(e[s++]=e[r]);return e.length=s,e}function xx(e,t){if(e.length!==t.length)return!1;for(let s=0;s<e.length;++s)if(e[s]!==t[s]){if(e[s]==="+"&&t[s]==="-"||e[s]==="/"&&t[s]==="_")continue;return!1}return!0}function vx(e){}function Jo(e,t){return e.origin===t.origin&&e.origin==="null"||e.protocol===t.protocol&&e.hostname===t.hostname&&e.port===t.port}function kx(){let e,t;return{promise:new Promise((r,i)=>{e=r,t=i}),resolve:e,reject:t}}function Dx(e){return e.controller.state==="aborted"}function Rx(e){return e.controller.state==="aborted"||e.controller.state==="terminated"}function Tx(e){return rx[e.toLowerCase()]??e}function Fx(e){let t=JSON.stringify(e);if(t===void 0)throw new TypeError("Value is not JSON serializable");return ws(typeof t=="string"),t}var Sx=Object.getPrototypeOf(Object.getPrototypeOf([][Symbol.iterator]()));function gh(e,t,s=0,r=1){class i{#e;#t;#i;constructor(n,a){this.#e=n, Line truncated
`);function cv(e){for(let t=0;t<e.length;++t)if((e.charCodeAt(t)&-128)!==0)return!1;return!0}function lv(e){let t=e.length;if(t<27||t>70)return!1;for(let s=0;s<t;++s){let r=e.charCodeAt(s);if(!(r>=48&&r<=57||r>=65&&r<=90||r>=97&&r<=122||r===39||r===45||r===95))return!1}return!0}function uv(e,t){Ho(t!=="failure"&&t.essence==="multipart/form-data");let s=t.parameters.get("boundary");if(s===void 0)return"failure";let r=Buffer.from(`--${s}`,"utf8"),i=[],o={position:0};for(;e[o.position]===13&&e[o.position+1]===10;)o.position+=2;let n=e.length;for(;e[n-1]===10&&e[n-2]===13;)n-=2;for(n!==e.length&&(e=e.subarray(0,n));;){if(e.subarray(o.position,o.position+r.length).equals(r))o.position+=r.length;else return"failure";if(o.position===e.length-2&&Vo(e,av,o)||o.position===e.length-4&&Vo(e,Av,o))return i;if(e[o.position]!==13||e[o.position+1]!==10)return"failure";o.position+=2;let a=pv(e,o);if(a==="failure")return"failure";let{name:A,filename:c,contentType:u,encoding:l}=a;o.position+=2;let p;{let h=e.indexOf(r.subarray(2),o.position);if(h===-1)return"failure";p=e.subarray(o.position,h-4),o.position+=p.length,l==="base64"&&(p=Buffer.from(p.toString(),"base64"))}if(e[o.position]!==13||e[o.position+1]!==10)return"failure";o.position+=2;let g;c!==null?(u??="text/plain",cv(u)||(u=""),g=new ov([p],c,{type:u})):g=ev(Buffer.from(p)),Ho(yh(A)),Ho(typeof g=="string"&&yh(g)||sv(g)),i.push(rv(A,g,c))}}function pv(e,t){let s=null,r=null,i=null,o=null;for(;;){if(e[t.position]===13&&e[t.position+1]===10)return s===null?"failure":{name:s,filename:r,contentType:i,encoding:o};let n=cr(a=>a!==10&&a!==13&&a!==58,e,t);if(n=oc(n,!0,!0,a=>a===9||a===32),!tv.test(n.toString())||e[t.position]!==58)return"failure";switch(t.position++,cr(a=>a===32||a===9,e,t),$x(n)){case"content-disposition":{if(s=r=null,!Vo(e,nv,t)||(t.position+=17,s=kh(e,t),s===null))return"failure";if(Vo(e,vh,t)){let a=t.position+vh.length;if(e[a]===42&&(t.position+=1,a+=1),e[a]!==61||e[a+1]!==34||(t.position+=12,r=kh(e,t),r===null))return"failure"}break}case"content-type":{let a=cr(A=>A!==10&&A!==13,e,t);a=oc(a,!1,!0,A=>A===9||A===32),i=xh(a);break}case"content-transfer-encoding":{let a=cr(A=>A!==10&&A!==13,e,t);a=oc(a,!1,!0,A=>A===9||A===32),o=xh(a);break}default:cr(a=>a!==10&&a!==13,e,t)}if(e[t.position]!==13&&e[t.position+1]!==10)return"failure";t.position+=2}}function kh(e,t){Ho(e[t.position-1]===34);let s=cr(r=>r!==10&&r!==13&&r!==34,e,t);return e[t.position]!==34?null:(t.position++,s=new TextDecoder().decode(s).replace(/%0A/ig,`
`).replace(/%0D/ig,"\r").replace(/%22/g,'"'),s)}function cr(e,t,s){let r=s.position;for(;r<t.length&&e(t[r]);)++r;return t.subarray(s.position,s.position=r)}function oc(e,t,s,r){let i=0,o=e.length-1;if(t)for(;i<e.length&&r(e[i]);)i++;if(s)for(;o>0&&r(e[o]);)o--;return i===0&&o===e.length-1?e:e.subarray(i,o+1)}function Vo(e,t,s){if(e.length<t.length)return!1;for(let r=0;r<t.length;r++)if(t[r]!==e[s.position+r])return!1;return!0}Dh.exports={multipartFormDataParser:uv,validateBoundary:lv}});var pr=Q((T2,Yh)=>{"use strict";var ui=N(),{ReadableStreamFrom:gv,isBlobLike:Th,isReadableStreamLike:hv,readableStreamClose:dv,createDeferredPromise:Ev,fullyReadBody:mv,extractMimeType:fv,utf8DecodeBytes:Uh}=Ue(),{FormData:Fh}=li(),{kState:ur}=Kt(),{webidl:Qv}=ge(),{Blob:Bv}=require("node:buffer"),nc=require("node:assert"),{isErrored:Nh,isDisturbed:Cv}=require("node:stream"),{isArrayBuffer:Iv}=require("node:util/types"),{serializeAMimeType:wv}=ve(),{multipartFormDataParser:bv}=Rh(),ac;try{let e=require("node:crypto");ac=t=>e.randomInt(0,t)}catch{ac=e=>Math.floor(Math.random(e))}var qo=new TextEncoder;function yv(){}var Gh=globalThis.FinalizationRegistry&&process.version.indexOf("v18")!==0,Mh;Gh&&(Mh=new FinalizationRegistry(e=>{let t=e.deref();t&&!t.locked&&!Cv(t)&&!Nh(t)&&t.cancel("Response object has been garbage collected").catch(yv)}));function Lh(e,t=!1){let s=null;e instanceof ReadableStream?s=e:Th(e)?s=e.stream():s=new ReadableStream({async pull(A){let c=typeof i=="string"?qo.encode(i):i;c.byteLength&&A.enqueue(c),queueMicrotask(()=>dv(A))},start(){},type:"bytes"}),nc(hv(s));let r=null,i=null,o=null,n=null;if(typeof e=="string")i=e,n="text/plain;charset=UTF-8";else if(e instanceof URLSearchParams)i=e.toString(),n="application/x-www-form-urlencoded;charset=UTF-8";else if(Iv(e))i=new Uint8Array(e.slice());else if(ArrayBuffer.isView(e))i=new Uint8Array(e.buffer.slice(e.byteOffset,e.byteOffset+e.byteLength));else if(ui.isFormDataLike(e)){let A=`----formdata-undici-0${`${ac(1e11)}`.padStart(11,"0")}`,c=`--${A}\r
Content-Disposition: form-data`;let u=f=>f.replace(/\n/g,"%0A").replace(/\r/g,"%0D").replace(/"/g,"%22"),l=f=>f.replace(/\r?\n|\r/g,`\r
`),p=[],g=new Uint8Array([13,10]);o=0;let h=!1;for(let[f,d]of e)if(typeof d=="string"){let m=qo.encode(c+`; name="${u(l(f))}"\r
"use strict";var Yb=Object.create;var sg=Object.defineProperty;var Ob=Object.getOwnPropertyDescriptor;var Pb=Object.getOwnPropertyNames;var Jb=Object.getPrototypeOf,Hb=Object.prototype.hasOwnProperty;var Q=(e,t)=>()=>{try{return t||e((t={exports:{}}).exports,t),t.exports}catch(s){throw t=0,s}};var Vb=(e,t,s,i)=>{if(t&&typeof t=="object"||typeof t=="function")for(let r of Pb(t))!Hb.call(e,r)&&r!==s&&sg(e,r,{get:()=>t[r],enumerable:!(i=Ob(t,r))||i.enumerable});return e};var Qe=(e,t,s)=>(s=e!=null?Yb(Jb(e)):{},Vb(t||!e||!e.__esModule?sg(s,"default",{value:e,enumerable:!0}):s,e));var pg=Q(oi=>{"use strict";var uY=require("net"),zb=require("tls"),IA=require("http"),cg=require("https"),Zb=require("events"),pY=require("assert"),Kb=require("util");oi.httpOverHttp=Xb;oi.httpsOverHttp=$b;oi.httpOverHttps=ey;oi.httpsOverHttps=ty;function Xb(e){var t=new Ft(e);return t.request=IA.request,t}function $b(e){var t=new Ft(e);return t.request=IA.request,t.createSocket=lg,t.defaultPort=443,t}function ey(e){var t=new Ft(e);return t.request=cg.request,t}function ty(e){var t=new Ft(e);return t.request=cg.request,t.createSocket=lg,t.defaultPort=443,t}function Ft(e){var t=this;t.options=e||{},t.proxyOptions=t.options.proxy||{},t.maxSockets=t.options.maxSockets||IA.Agent.defaultMaxSockets,t.requests=[],t.sockets=[],t.on("free",function(i,r,n,o){for(var a=ug(r,n,o),A=0,c=t.requests.length;A<c;++A){var l=t.requests[A];if(l.host===a.host&&l.port===a.port){t.requests.splice(A,1),l.request.onSocket(i);return}}i.destroy(),t.removeSocket(i)})}Kb.inherits(Ft,Zb.EventEmitter);Ft.prototype.addRequest=function(t,s,i,r){var n=this,o=wA({request:t},n.options,ug(s,i,r));if(n.sockets.length>=this.maxSockets){n.requests.push(o);return}n.createSocket(o,function(a){a.on("free",A),a.on("close",c),a.on("agentRemove",c),t.onSocket(a);function A(){n.emit("free",a,o)}function c(l){n.removeSocket(a),a.removeListener("free",A),a.removeListener("close",c),a.removeListener("agentRemove",c)}})};Ft.prototype.createSocket=function(t,s){var i=this,r={};i.sockets.push(r);var n=wA({},i.proxyOptions,{method:"CONNECT",path:t.host+":"+t.port,agent:!1,headers:{host:t.host+":"+t.port}});t.localAddress&&(n.localAddress=t.localAddress),n.proxyAuth&&(n.headers=n.headers||{},n.headers["Proxy-Authorization"]="Basic "+new Buffer(n.proxyAuth).toString("base64")),Zt("making CONNECT request");var o=i.request(n);o.useChunkedEncodingByDefault=!1,o.once("response",a),o.once("upgrade",A),o.once("connect",c),o.once("error",l),o.end();function a(u){u.upgrade=!0}function A(u,p,h){process.nextTick(function(){c(u,p,h)})}function c(u,p,h){if(o.removeAllListeners(),p.removeAllListeners(),u.statusCode!==200){Zt("tunneling socket could not be established, statusCode=%d",u.statusCode),p.destroy();var d=new Error("tunneling socket could not be established, statusCode="+u.statusCode);d.code="ECONNRESET",t.request.emit("error",d),i.removeSocket(r);return}if(h.length>0){Zt("got illegal response body from proxy"),p.destroy();var d=new Error("got illegal response body from proxy");d.code="ECONNRESET",t.request.emit("error",d),i.removeSocket(r);return}return Zt("tunneling connection has established"),i.sockets[i.sockets.indexOf(r)]=p,s(p)}function l(u){o.removeAllListeners(),Zt(`tunneling socket could not be established, cause=%s
`,u.message,u.stack);var p=new Error("tunneling socket could not be established, cause="+u.message);p.code="ECONNRESET",t.request.emit("error",p),i.removeSocket(r)}};Ft.prototype.removeSocket=function(t){var s=this.sockets.indexOf(t);if(s!==-1){this.sockets.splice(s,1);var i=this.requests.shift();i&&this.createSocket(i,function(r){i.request.onSocket(r)})}};function lg(e,t){var s=this;Ft.prototype.createSocket.call(s,e,function(i){var r=e.request.getHeader("host"),n=wA({},s.options,{socket:i,servername:r?r.replace(/:.*$/,""):e.host}),o=zb.connect(0,n);s.sockets[s.sockets.indexOf(i)]=o,t(o)})}function ug(e,t,s){return typeof e=="string"?{host:e,port:t,localAddress:s}:e}function wA(e){for(var t=1,s=arguments.length;t<s;++t){var i=arguments[t];if(typeof i=="object")for(var r=Object.keys(i),n=0,o=r.length;n<o;++n){var a=r[n];i[a]!==void 0&&(e[a]=i[a])}}return e}var Zt;process.env.NODE_DEBUG&&/\btunnel\b/.test(process.env.NODE_DEBUG)?Zt=function(){var e=Array.prototype.slice.call(arguments);typeof e[0]=="string"?e[0]="TUNNEL: "+e[0]:e.unshift("TUNNEL:"),console.error.apply(console,e)}:Zt=function(){};oi.debug=Zt});var bA=Q((hY,gg)=>{gg.exports=pg()});var Z=Q((dY,hg)=>{hg.exports={kClose:Symbol("close"),kDestroy:Symbol("destroy"),kDispatch:Symbol("dispatch"),kUrl:Symbol("url"),kWriting:Symbol("writing"),kResuming:Symbol("resuming"),kQueue:Symbol("queue"),kConnect:Symbol("connect"),kConnecting:Symbol("connecting"),kKeepAliveDefaultTimeout:Symbol("default keep alive timeout"),kKeepAliveMaxTimeout:Symbol("max keep alive timeout"),kKeepAliveTimeoutThreshold:Symbol("keep alive timeout threshold"),kKeepAliveTimeoutValue:Symbol("keep alive timeout"),kKeepAlive:Symbol("keep alive"),kHeadersTimeout:Symbol("headers timeout"),kBodyTimeout:Symbol("body timeout"),kServerName:Symbol("server name"),kLocalAddress:Symbol("local address"),kHost:Symbol("host"),kNoRef:Symbol("no ref"),kBodyUsed:Symbol("used"),kBody:Symbol("abstracted request body"),kRunning:Symbol("running"),kBlocking:Symbol("blocking"),kPending:Symbol("pending"),kSize:Symbol("size"),kBusy:Symbol("busy"),kQueued:Symbol("queued"),kFree:Symbol("free"),kConnected:Symbol("connected"),kClosed:Symbol("closed"),kNeedDrain:Symbol("need drain"),kReset:Symbol("reset"),kDestroyed:Symbol.for("nodejs.stream.destroyed"),kResume:Symbol("resume"),kOnError:Symbol("on error"),kMaxHeadersSize:Symbol("max headers size"),kRunningIdx:Symbol("running index"),kPendingIdx:Symbol("pending index"),kError:Symbol("error"),kClients:Symbol("clients"),kClient:Symbol("client"),kParser:Symbol("parser"),kOnDestroyed:Symbol("destroy callbacks"),kPipelining:Symbol("pipelining"),kSocket:Symbol("socket"),kHostHeader:Symbol("host header"),kConnector:Symbol("connector"),kStrictContentLength:Symbol("strict content length"),kMaxRedirections:Symbol("maxRedirections"),kMaxRequests:Symbol("maxRequestsPerClient"),kProxy:Symbol("proxy agent options"),kCounter:Symbol("socket request counter"),kInterceptors:Symbol("dispatch interceptors"),kMaxResponseSize:Symbol("max response size"),kHTTP2Session:Symbol("http2Session"),kHTTP2SessionState:Symbol("http2Session state"),kRetryHandlerDefaultRetry:Symbol("retry agent default retry"),kConstruct:Symbol("constructable"),kListeners:Symbol("listeners"),kHTTPContext:Symbol("http context"),kMaxConcurrentStreams:Symbol("max concurrent streams"),kNoProxyAgent:Symbol("no proxy agent"),kHttpProxyAgent:Symbol("http proxy agent"),kHttpsProxyAgent:Symbol("https proxy agent")}});var Y=Q((EY,_g)=>{"use strict";var dg=Symbol.for("undici.error.UND_ERR"),K=class extends Error{constructor(t){super(t),this.name="UndiciError",this.code="UND_ERR"}static[Symbol.hasInstance](t){return t&&t[dg]===!0}[dg]=!0},Eg=Symbol.for("undici.error.UND_ERR_CONNECT_TIMEOUT"),yA=class extends K{constructor(t){super(t),this.name="ConnectTimeoutError",this.message=t||"Connect Timeout Error",this.code="UND_ERR_CONNECT_TIMEOUT"}static[Symbol.hasInstance](t){return t&&t[Eg]===!0}[Eg]=!0},mg=Symbol.for("undici.error.UND_ERR_HEADERS_TIMEOUT"),xA=class extends K{constructor(t){super(t),this.name="HeadersTimeoutError",this.message=t||"Headers Timeout Error",this.code="UND_ERR_HEADERS_TIMEOUT"}static[Symbol.hasInstance](t){return t&&t[mg]===!0}[mg]=!0},fg=Symbol.for("undici.error.UND_ERR_HEADERS_OVERFLOW"),vA=class extends K{constructor(t){super(t),this.name="HeadersOverflowError",this.message=t||"Headers Overflow Error",this.code="UND_ERR_HEADERS_OVERFLOW"}static[Symbol.hasInstance](t){return t&&t[fg]===!0}[fg]=!0},Qg=Symbol.for("undici.error.UND_ERR_BODY_TIMEOUT"),kA=class extends K{constructor(t){super(t),this.name="BodyTimeoutError",this.message=t||"Body Timeout Error",this.code="UND_ERR_BODY_TIMEOUT"}static[Symbol.hasInstance](t){return t&&t[Qg]===!0}[Qg]=!0},Bg=Symbol.for("undici.error.UND_ERR_RESPONSE_STATUS_CODE"),DA=class extends K{constructor(t,s,i,r){super(t),this.name="ResponseStatusCodeError",this.message=t||"Response Status Code Error",this.code="UND_ERR_RESPONSE_STATUS_CODE",this.body=r,this.status=s,this. Line truncated
`)||e.includes("\r")||e.includes("\0"))===!1}function fv(e,t){let{headersList:s}=t,i=(s.get("referrer-policy",!0)??"").split(","),r="";if(i.length>0)for(let n=i.length;n!==0;n--){let o=i[n-1].trim();if(sv.has(o)){r=o;break}}r!==""&&(e.referrerPolicy=r)}function Qv(){return"allowed"}function Bv(){return"success"}function Cv(){return"success"}function Iv(e){let t=null;t=e.mode,e.headersList.set("sec-fetch-mode",t,!0)}function wv(e){let t=e.origin;if(!(t==="client"||t===void 0)){if(e.responseTainting==="cors"||e.mode==="websocket")e.headersList.append("origin",t,!0);else if(e.method!=="GET"&&e.method!=="HEAD"){switch(e.referrerPolicy){case"no-referrer":t=null;break;case"no-referrer-when-downgrade":case"strict-origin":case"strict-origin-when-cross-origin":e.origin&&Bc(e.origin)&&!Bc(mr(e))&&(t=null);break;case"same-origin":io(e,mr(e))||(t=null);break;default:}e.headersList.append("origin",t,!0)}}}function Ei(e,t){return e}function bv(e,t,s){return!e?.startTime||e.startTime<t?{domainLookupStartTime:t,domainLookupEndTime:t,connectionStartTime:t,connectionEndTime:t,secureConnectionStartTime:t,ALPNNegotiatedProtocol:e?.ALPNNegotiatedProtocol}:{domainLookupStartTime:Ei(e.domainLookupStartTime,s),domainLookupEndTime:Ei(e.domainLookupEndTime,s),connectionStartTime:Ei(e.connectionStartTime,s),connectionEndTime:Ei(e.connectionEndTime,s),secureConnectionStartTime:Ei(e.secureConnectionStartTime,s),ALPNNegotiatedProtocol:e.ALPNNegotiatedProtocol}}function yv(e){return Ei(av.now(),e)}function xv(e){return{startTime:e.startTime??0,redirectStartTime:0,redirectEndTime:0,postRedirectStartTime:e.startTime??0,finalServiceWorkerStartTime:0,finalNetworkResponseStartTime:0,finalNetworkRequestStartTime:0,endTime:0,encodedBodySize:0,decodedBodySize:0,finalConnectionTimingInfo:null}}function ed(){return{referrerPolicy:"strict-origin-when-cross-origin"}}function vv(e){return{referrerPolicy:e.referrerPolicy}}function kv(e){let t=e.referrerPolicy;bs(t);let s=null;if(e.referrer==="client"){let a=jh();if(!a||a.origin==="null")return"no-referrer";s=new URL(a)}else e.referrer instanceof URL&&(s=e.referrer);let i=Qc(s),r=Qc(s,!0);i.toString().length>4096&&(i=r);let n=io(e,i),o=Er(i)&&!Er(e.url);switch(t){case"origin":return r??Qc(s,!0);case"unsafe-url":return i;case"same-origin":return n?r:"no-referrer";case"origin-when-cross-origin":return n?i:r;case"strict-origin-when-cross-origin":{let a=mr(e);return io(i,a)?i:Er(i)&&!Er(a)?"no-referrer":r}default:return o?"no-referrer":r}}function Qc(e,t){return bs(e instanceof URL),e=new URL(e),e.protocol==="file:"||e.protocol==="about:"||e.protocol==="blank:"?"no-referrer":(e.username="",e.password="",e.hash="",t&&(e.pathname="",e.search=""),e)}function Er(e){if(!(e instanceof URL))return!1;if(e.href==="about:blank"||e.href==="about:srcdoc"||e.protocol==="data:"||e.protocol==="file:")return!0;return t(e.origin);function t(s){if(s==null||s==="null")return!1;let i=new URL(s);return!!(i.protocol==="https:"||i.protocol==="wss:"||/^127(?:\.[0-9]+){0,2}\.[0-9]+$|^\[(?:0*:)*?:?0*1\]$/.test(i.hostname)||i.hostname==="localhost"||i.hostname.includes("localhost.")||i.hostname.endsWith(".localhost"))}}function Dv(e,t){if(so===void 0)return!0;let s=td(t);if(s==="no metadata"||s.length===0)return!0;let i=Tv(s),r=Sv(s,i);for(let n of r){let o=n.algo,a=n.hash,A=so.createHash(o).update(e).digest("base64");if(A[A.length-1]==="="&&(A[A.length-2]==="="?A=A.slice(0,-2):A=A.slice(0,-1)),Fv(A,a))return!0}return!1}var Rv=/(?<algo>sha256|sha384|sha512)-((?<hash>[A-Za-z0-9+/]+|[A-Za-z0-9_-]+)={0,2}(?:\s|$)( +[!-~]*)?)?/i;function td(e){let t=[],s=!0;for(let i of e.split(" ")){s=!1;let r=Rv.exec(i);if(r===null||r.groups===void 0||r.groups.algo===void 0)continue;let n=r.groups.algo.toLowerCase();Zh.includes(n)&&t.push(r.groups)}return s===!0?"no metadata":t}function Tv(e){let t=e[0].algo;if(t[3]==="5")return t;for(let s=1;s<e.length;++s){let i=e[s];if(i.algo[3]==="5"){t="sha512";break}else{if(t[3]==="3")continue;i.algo[3]==="3"&&(t="sha384")}}return t}function Sv(e,t){if(e.length===1)return e;let s=0;for(let i=0;i<e.length;++i)e[i].algo===t&&(e[s++]=e[i]);return e.length=s,e}function Fv(e,t){if(e.length!==t.length)return!1;for(let s=0;s<e.length;++s)if(e[s]!==t[s]){if(e[s]==="+"&&t[s]==="-"||e[s]==="/"&&t[s]==="_")continue;return!1}return!0}function Uv(e){}function io(e,t){return e.origin===t.origin&&e.origin==="null"||e.protocol===t.protocol&&e.hostname===t.hostname&&e.port===t.port}function Nv(){let e,t;return{promise:new Promise((i,r)=>{e=i,t=r}),resolve:e,reject:t}}function Mv(e){return e.controller.state==="aborted"}function Gv(e){return e.controller.state==="aborted"||e.controller.state==="terminated"}function Lv(e){return lv[e.toLowerCase()]??e}function _v(e){let t=JSON.stringify(e);if(t===void 0)throw new TypeError("Value is not JSON serializable");return bs(typeof t=="string"),t}var Yv=Object.getPrototypeOf(Object.getPrototypeOf([][Symbol.iterator]()));function sd(e,t,s=0,i=1){class r{#e;#t;#s;constructor(o,a){this.#e=o, Line truncated
`);function Ek(e){for(let t=0;t<e.length;++t)if((e.charCodeAt(t)&-128)!==0)return!1;return!0}function mk(e){let t=e.length;if(t<27||t>70)return!1;for(let s=0;s<t;++s){let i=e.charCodeAt(s);if(!(i>=48&&i<=57||i>=65&&i<=90||i>=97&&i<=122||i===39||i===45||i===95))return!1}return!0}function fk(e,t){no(t!=="failure"&&t.essence==="multipart/form-data");let s=t.parameters.get("boundary");if(s===void 0)return"failure";let i=Buffer.from(`--${s}`,"utf8"),r=[],n={position:0};for(;e[n.position]===13&&e[n.position+1]===10;)n.position+=2;let o=e.length;for(;e[o-1]===10&&e[o-2]===13;)o-=2;for(o!==e.length&&(e=e.subarray(0,o));;){if(e.subarray(n.position,n.position+i.length).equals(i))n.position+=i.length;else return"failure";if(n.position===e.length-2&&oo(e,hk,n)||n.position===e.length-4&&oo(e,dk,n))return r;if(e[n.position]!==13||e[n.position+1]!==10)return"failure";n.position+=2;let a=Qk(e,n);if(a==="failure")return"failure";let{name:A,filename:c,contentType:l,encoding:u}=a;n.position+=2;let p;{let d=e.indexOf(i.subarray(2),n.position);if(d===-1)return"failure";p=e.subarray(n.position,d-4),n.position+=p.length,u==="base64"&&(p=Buffer.from(p.toString(),"base64"))}if(e[n.position]!==13||e[n.position+1]!==10)return"failure";n.position+=2;let h;c!==null?(l??="text/plain",Ek(l)||(l=""),h=new pk([p],c,{type:l})):h=ak(Buffer.from(p)),no(hd(A)),no(typeof h=="string"&&hd(h)||ck(h)),r.push(lk(A,h,c))}}function Qk(e,t){let s=null,i=null,r=null,n=null;for(;;){if(e[t.position]===13&&e[t.position+1]===10)return s===null?"failure":{name:s,filename:i,contentType:r,encoding:n};let o=fi(a=>a!==10&&a!==13&&a!==58,e,t);if(o=vc(o,!0,!0,a=>a===9||a===32),!Ak.test(o.toString())||e[t.position]!==58)return"failure";switch(t.position++,fi(a=>a===32||a===9,e,t),ok(o)){case"content-disposition":{if(s=i=null,!oo(e,gk,t)||(t.position+=17,s=md(e,t),s===null))return"failure";if(oo(e,Ed,t)){let a=t.position+Ed.length;if(e[a]===42&&(t.position+=1,a+=1),e[a]!==61||e[a+1]!==34||(t.position+=12,i=md(e,t),i===null))return"failure"}break}case"content-type":{let a=fi(A=>A!==10&&A!==13,e,t);a=vc(a,!1,!0,A=>A===9||A===32),r=dd(a);break}case"content-transfer-encoding":{let a=fi(A=>A!==10&&A!==13,e,t);a=vc(a,!1,!0,A=>A===9||A===32),n=dd(a);break}default:fi(a=>a!==10&&a!==13,e,t)}if(e[t.position]!==13&&e[t.position+1]!==10)return"failure";t.position+=2}}function md(e,t){no(e[t.position-1]===34);let s=fi(i=>i!==10&&i!==13&&i!==34,e,t);return e[t.position]!==34?null:(t.position++,s=new TextDecoder().decode(s).replace(/%0A/ig,`
`).replace(/%0D/ig,"\r").replace(/%22/g,'"'),s)}function fi(e,t,s){let i=s.position;for(;i<t.length&&e(t[i]);)++i;return t.subarray(s.position,s.position=i)}function vc(e,t,s,i){let r=0,n=e.length-1;if(t)for(;r<e.length&&i(e[r]);)r++;if(s)for(;n>0&&i(e[n]);)n--;return r===0&&n===e.length-1?e:e.subarray(r,n+1)}function oo(e,t,s){if(e.length<t.length)return!1;for(let i=0;i<t.length;i++)if(t[i]!==e[s.position+i])return!1;return!0}fd.exports={multipartFormDataParser:fk,validateBoundary:mk}});var Ci=Q((OY,Dd)=>{"use strict";var Br=N(),{ReadableStreamFrom:Bk,isBlobLike:Bd,isReadableStreamLike:Ck,readableStreamClose:Ik,createDeferredPromise:wk,fullyReadBody:bk,extractMimeType:yk,utf8DecodeBytes:wd}=Ge(),{FormData:Cd}=Qr(),{kState:Bi}=Kt(),{webidl:xk}=Ee(),{Blob:vk}=require("node:buffer"),kc=require("node:assert"),{isErrored:bd,isDisturbed:kk}=require("node:stream"),{isArrayBuffer:Dk}=require("node:util/types"),{serializeAMimeType:Rk}=De(),{multipartFormDataParser:Tk}=Qd(),Dc;try{let e=require("node:crypto");Dc=t=>e.randomInt(0,t)}catch{Dc=e=>Math.floor(Math.random(e))}var ao=new TextEncoder;function Sk(){}var yd=globalThis.FinalizationRegistry&&process.version.indexOf("v18")!==0,xd;yd&&(xd=new FinalizationRegistry(e=>{let t=e.deref();t&&!t.locked&&!kk(t)&&!bd(t)&&t.cancel("Response object has been garbage collected").catch(Sk)}));function vd(e,t=!1){let s=null;e instanceof ReadableStream?s=e:Bd(e)?s=e.stream():s=new ReadableStream({async pull(A){let c=typeof r=="string"?ao.encode(r):r;c.byteLength&&A.enqueue(c),queueMicrotask(()=>Ik(A))},start(){},type:"bytes"}),kc(Ck(s));let i=null,r=null,n=null,o=null;if(typeof e=="string")r=e,o="text/plain;charset=UTF-8";else if(e instanceof URLSearchParams)r=e.toString(),o="application/x-www-form-urlencoded;charset=UTF-8";else if(Dk(e))r=new Uint8Array(e.slice());else if(ArrayBuffer.isView(e))r=new Uint8Array(e.buffer.slice(e.byteOffset,e.byteOffset+e.byteLength));else if(Br.isFormDataLike(e)){let A=`----formdata-undici-0${`${Dc(1e11)}`.padStart(11,"0")}`,c=`--${A}\r
Content-Disposition: form-data`;let l=f=>f.replace(/\n/g,"%0A").replace(/\r/g,"%0D").replace(/"/g,"%22"),u=f=>f.replace(/\r?\n|\r/g,`\r
`),p=[],h=new Uint8Array([13,10]);n=0;let d=!1;for(let[f,g]of e)if(typeof g=="string"){let m=ao.encode(c+`; name="${l(u(f))}"\r
\r
${l(d)}\r
`);p.push(m),o+=m.byteLength}else{let m=qo.encode(`${c}; name="${u(l(f))}"`+(d.name?`; filename="${u(d.name)}"`:"")+`\r
Content-Type: ${d.type||"application/octet-stream"}\r
${u(g)}\r
`);p.push(m),n+=m.byteLength}else{let m=ao.encode(`${c}; name="${l(u(f))}"`+(g.name?`; filename="${l(g.name)}"`:"")+`\r
Content-Type: ${g.type||"application/octet-stream"}\r
\r
`);p.push(m,d,g),typeof d.size=="number"?o+=m.byteLength+d.size+g.byteLength:h=!0}let E=qo.encode(`--${A}--\r
`);p.push(E),o+=E.byteLength,h&&(o=null),i=e,r=async function*(){for(let f of p)f.stream?yield*f.stream():yield f},n=`multipart/form-data; boundary=${A}`}else if(Th(e))i=e,o=e.size,e.type&&(n=e.type);else if(typeof e[Symbol.asyncIterator]=="function"){if(t)throw new TypeError("keepalive");if(ui.isDisturbed(e)||e.locked)throw new TypeError("Response body object should not be disturbed or locked");s=e instanceof ReadableStream?e:gv(e)}if((typeof i=="string"||ui.isBuffer(i))&&(o=Buffer.byteLength(i)),r!=null){let A;s=new ReadableStream({async start(){A=r(e)[Symbol.asyncIterator]()},async pull(c){let{value:u,done:l}=await A.next();if(l)queueMicrotask(()=>{c.close(),c.byobRequest?.respond(0)});else if(!Nh(s)){let p=new Uint8Array(u);p.byteLength&&c.enqueue(p)}return c.desiredSize>0},async cancel(c){await A.return()},type:"bytes"})}return[{stream:s,source:i,length:o},n]}function xv(e,t=!1){return e instanceof ReadableStream&&(nc(!ui.isDisturbed(e),"The body has already been consumed."),nc(!e.locked,"The stream is locked.")),Lh(e,t)}function vv(e,t){let[s,r]=t.stream.tee();return t.stream=s,{stream:r,length:t.length,source:t.source}}function kv(e){if(e.aborted)throw new DOMException("The operation was aborted.","AbortError")}function Dv(e){return{blob(){return lr(this,s=>{let r=Sh(this);return r===null?r="":r&&(r=wv(r)),new Bv([s],{type:r})},e)},arrayBuffer(){return lr(this,s=>new Uint8Array(s).buffer,e)},text(){return lr(this,Uh,e)},json(){return lr(this,Tv,e)},formData(){return lr(this,s=>{let r=Sh(this);if(r!==null)switch(r.essence){case"multipart/form-data":{let i=bv(s,r);if(i==="failure")throw new TypeError("Failed to parse body as FormData.");let o=new Fh;return o[ur]=i,o}case"application/x-www-form-urlencoded":{let i=new URLSearchParams(s.toString()),o=new Fh;for(let[n,a]of i)o.append(n,a);return o}}throw new TypeError('Content-Type was not one of "multipart/form-data" or "application/x-www-form-urlencoded".')},e)},bytes(){return lr(this,s=>new Uint8Array(s),e)}}}function Rv(e){Object.assign(e.prototype,Dv(e))}async function lr(e,t,s){if(Qv.brandCheck(e,s),_h(e))throw new TypeError("Body is unusable: Body has already been read");kv(e[ur]);let r=Ev(),i=n=>r.reject(n),o=n=>{try{r.resolve(t(n))}catch(a){i(a)}};return e[ur].body==null?(o(Buffer.allocUnsafe(0)),r.promise):(await mv(e[ur].body,o,i),r.promise)}function _h(e){let t=e[ur].body;return t!=null&&(t.stream.locked||ui.isDisturbed(t.stream))}function Tv(e){return JSON.parse(Uh(e))}function Sh(e){let t=e[ur].headersList,s=fv(t);return s==="failure"?null:s}Yh.exports={extractBody:Lh,safelyExtractBody:xv,cloneBody:vv,mixinBody:Rv,streamRegistry:Mh,hasFinalizationRegistry:Gh,bodyUnusable:_h}});var Kh=Q((F2,Zh)=>{"use strict";var k=require("node:assert"),F=N(),{channels:Oh}=$s(),Ac=PA(),{RequestContentLengthMismatchError:bs,ResponseContentLengthMismatchError:Fv,RequestAbortedError:Wh,HeadersTimeoutError:Sv,HeadersOverflowError:Uv,SocketError:Xo,InformationalError:gr,BodyTimeoutError:Nv,HTTPParserError:Gv,ResponseExceededMaxSizeError:Mv}=Y(),{kUrl:jh,kReset:ke,kClient:pc,kParser:X,kBlocking:hi,kRunning:Ee,kPending:Lv,kSize:Jh,kWriting:$t,kQueue:st,kNoRef:pi,kKeepAliveDefaultTimeout:_v,kHostHeader:Yv,kPendingIdx:Ov,kRunningIdx:qe,kError:We,kPipelining:Zo,kSocket:hr,kKeepAliveTimeoutValue:$o,kMaxHeadersSize:cc,kKeepAliveMaxTimeout:Jv,kKeepAliveTimeoutThreshold:Pv,kHeadersTimeout:Hv,kBodyTimeout:Vv,kStrictContentLength:gc,kMaxRequests:Ph,kCounter:qv,kMaxResponseSize:Wv,kOnError:jv,kResume:Xt,kHTTPContext:zh}=j(),ft=Mg(),zv=Buffer.alloc(0),Wo=Buffer[Symbol.species],jo=F.addListener,Zv=F.removeAllListeners,lc;async function Kv(){let e=process.env.JEST_WORKER_ID?qA():void 0,t;try{t=await WebAssembly.compile(Yg())}catch{t=await WebAssembly.compile(e||qA())}return await WebAssembly.instantiate(t,{env:{wasm_on_url:(s,r,i)=>0,wasm_on_status:(s,r,i)=>{k(oe.ptr===s);let o=r-Bt+Qt.byteOffset;return oe.onStatus(new Wo(Qt.buffer,o,i))||0},wasm_on_message_begin:s=>(k(oe.ptr===s),oe.onMessageBegin()||0),wasm_on_header_field:(s,r,i)=>{k(oe.ptr===s);let o=r-Bt+Qt.byteOffset;return oe.onHeaderField(new Wo(Qt.buffer,o,i))||0},wasm_on_header_value:(s,r,i)=>{k(oe.ptr===s);let o=r-Bt+Qt.byteOffset;return oe.onHeaderValue(new Wo(Qt.buffer,o,i))||0},wasm_on_headers_complete:(s,r,i,o)=>(k(oe.ptr===s),oe.onHeadersComplete(r,!!i,!!o)||0),wasm_on_body:(s,r,i)=>{k(oe.ptr===s);let o=r-Bt+Qt.byteOffset;return oe.onBody(new Wo(Qt.buffer,o,i))||0},wasm_on_message_complete:s=>(k(oe.ptr===s),oe.onMessageComplete()||0)}})}var uc=null,hc=Kv();hc.catch();var oe=null,Qt=null,zo=0,Bt=null,Xv=0,gi=1,dr=2|gi,Ko=4|gi,dc=8|Xv,Ec=class{constructor(t,s,{exports:r}){k(Number.isFinite(t[cc])&&t[cc]>0),this.llhttp=r,this.ptr=this.llhttp.llhttp_alloc(ft.TYPE.RESPONSE),this.client=t,this.socket=s,this.timeout=null,this.timeoutValue=null,this.timeoutType=null,this.statusCode=null,this.statusText="",this.upgrade=!1,this.headers=[],this.headersSize=0,this.headersMaxSize=t[cc],this.shouldKeepAlive=!1,this.paused=!1, Line truncated
`;if(typeof i=="string"?E+=`host: ${i}\r
`:E+=e[Yv],o?E+=`connection: upgrade\r
upgrade: ${o}\r
`:e[Zo]&&!g[ke]?E+=`connection: keep-alive\r
`);p.push(m,g,h),typeof g.size=="number"?n+=m.byteLength+g.size+h.byteLength:d=!0}let E=ao.encode(`--${A}--\r
`);p.push(E),n+=E.byteLength,d&&(n=null),r=e,i=async function*(){for(let f of p)f.stream?yield*f.stream():yield f},o=`multipart/form-data; boundary=${A}`}else if(Bd(e))r=e,n=e.size,e.type&&(o=e.type);else if(typeof e[Symbol.asyncIterator]=="function"){if(t)throw new TypeError("keepalive");if(Br.isDisturbed(e)||e.locked)throw new TypeError("Response body object should not be disturbed or locked");s=e instanceof ReadableStream?e:Bk(e)}if((typeof r=="string"||Br.isBuffer(r))&&(n=Buffer.byteLength(r)),i!=null){let A;s=new ReadableStream({async start(){A=i(e)[Symbol.asyncIterator]()},async pull(c){let{value:l,done:u}=await A.next();if(u)queueMicrotask(()=>{c.close(),c.byobRequest?.respond(0)});else if(!bd(s)){let p=new Uint8Array(l);p.byteLength&&c.enqueue(p)}return c.desiredSize>0},async cancel(c){await A.return()},type:"bytes"})}return[{stream:s,source:r,length:n},o]}function Fk(e,t=!1){return e instanceof ReadableStream&&(kc(!Br.isDisturbed(e),"The body has already been consumed."),kc(!e.locked,"The stream is locked.")),vd(e,t)}function Uk(e,t){let[s,i]=t.stream.tee();return t.stream=s,{stream:i,length:t.length,source:t.source}}function Nk(e){if(e.aborted)throw new DOMException("The operation was aborted.","AbortError")}function Mk(e){return{blob(){return Qi(this,s=>{let i=Id(this);return i===null?i="":i&&(i=Rk(i)),new vk([s],{type:i})},e)},arrayBuffer(){return Qi(this,s=>new Uint8Array(s).buffer,e)},text(){return Qi(this,wd,e)},json(){return Qi(this,Lk,e)},formData(){return Qi(this,s=>{let i=Id(this);if(i!==null)switch(i.essence){case"multipart/form-data":{let r=Tk(s,i);if(r==="failure")throw new TypeError("Failed to parse body as FormData.");let n=new Cd;return n[Bi]=r,n}case"application/x-www-form-urlencoded":{let r=new URLSearchParams(s.toString()),n=new Cd;for(let[o,a]of r)n.append(o,a);return n}}throw new TypeError('Content-Type was not one of "multipart/form-data" or "application/x-www-form-urlencoded".')},e)},bytes(){return Qi(this,s=>new Uint8Array(s),e)}}}function Gk(e){Object.assign(e.prototype,Mk(e))}async function Qi(e,t,s){if(xk.brandCheck(e,s),kd(e))throw new TypeError("Body is unusable: Body has already been read");Nk(e[Bi]);let i=wk(),r=o=>i.reject(o),n=o=>{try{i.resolve(t(o))}catch(a){r(a)}};return e[Bi].body==null?(n(Buffer.allocUnsafe(0)),i.promise):(await bk(e[Bi].body,n,r),i.promise)}function kd(e){let t=e[Bi].body;return t!=null&&(t.stream.locked||Br.isDisturbed(t.stream))}function Lk(e){return JSON.parse(wd(e))}function Id(e){let t=e[Bi].headersList,s=yk(t);return s==="failure"?null:s}Dd.exports={extractBody:vd,safelyExtractBody:Fk,cloneBody:Uk,mixinBody:Gk,streamRegistry:xd,hasFinalizationRegistry:yd,bodyUnusable:kd}});var Vd=Q((PY,Hd)=>{"use strict";var D=require("node:assert"),x=N(),{channels:Rd}=Ai(),Rc=uc(),{RequestContentLengthMismatchError:ys,ResponseContentLengthMismatchError:Td,RequestAbortedError:_d,InvalidArgumentError:_k,HeadersTimeoutError:Yk,HeadersOverflowError:Ok,SocketError:Ii,InformationalError:xs,BodyTimeoutError:Pk,HTTPParserError:Jk,ResponseExceededMaxSizeError:Hk}=Y(),{kUrl:Yd,kReset:Re,kClient:uo,kParser:j,kBlocking:wr,kRunning:oe,kPending:Od,kSize:Sd,kWriting:Xt,kQueue:rt,kNoRef:Cr,kKeepAliveDefaultTimeout:Vk,kHostHeader:qk,kPendingIdx:Wk,kRunningIdx:Ke,kError:be,kPipelining:po,kSocket:vs,kKeepAliveTimeoutValue:ho,kMaxHeadersSize:Tc,kKeepAliveMaxTimeout:jk,kKeepAliveTimeoutThreshold:zk,kHeadersTimeout:Zk,kBodyTimeout:Kk,kStrictContentLength:Uc,kMaxRequests:Fd,kCounter:Xk,kMaxResponseSize:$k,kOnError:Ud,kResume:Lt,kHTTPContext:Pd}=Z(),Le=xh(),Nd=Buffer.alloc(0),Ao=Buffer[Symbol.species],co=x.addListener,e0=x.removeAllListeners,ks=Symbol("kIdleSocketValidation"),wi=Symbol("kIdleSocketValidationTimeout"),Lc=Symbol("kSocketUsed"),Sc;async function t0(){let e=process.env.JEST_WORKER_ID?hc():void 0,t;try{t=await WebAssembly.compile(Dh())}catch{t=await WebAssembly.compile(e||hc())}return await WebAssembly.instantiate(t,{env:{wasm_on_url:(s,i,r)=>0,wasm_on_status:(s,i,r)=>{D(ee.ptr===s);let n=i-Qt+ft.byteOffset;return ee.onStatus(new Ao(ft.buffer,n,r))||0},wasm_on_message_begin:s=>(D(ee.ptr===s),ee.onMessageBegin()||0),wasm_on_header_field:(s,i,r)=>{D(ee.ptr===s);let n=i-Qt+ft.byteOffset;return ee.onHeaderField(new Ao(ft.buffer,n,r))||0},wasm_on_header_value:(s,i,r)=>{D(ee.ptr===s);let n=i-Qt+ft.byteOffset;return ee.onHeaderValue(new Ao(ft.buffer,n,r))||0},wasm_on_headers_complete:(s,i,r,n)=>(D(ee.ptr===s),ee.onHeadersComplete(i,!!r,!!n)||0),wasm_on_body:(s,i,r)=>{D(ee.ptr===s);let n=i-Qt+ft.byteOffset;return ee.onBody(new Ao(ft.buffer,n,r))||0},wasm_on_message_complete:s=>(D(ee.ptr===s),ee.onMessageComplete()||0)}})}var Fc=null,Nc=t0();Nc.catch();var ee=null,ft=null,lo=0,Qt=null,s0=0,Ir=1,bi=2|Ir,go=4|Ir,Mc=8|s0,Gc=class{constructor(t,s,{exports:i}){D(Number.isFinite(t[Tc])&&t[Tc]>0),this.llhttp=i,this.ptr=this.llhttp.llhttp_alloc(Le.TYPE.RESPONSE),this.client=t,this.socket=s,this.timeout=null,this.timeoutValue=null,this.timeoutType=null,this.statusCode=null,this.stat Line truncated
`;if(typeof r=="string"?E+=`host: ${r}\r
`:E+=e[qk],n?E+=`connection: upgrade\r
upgrade: ${n}\r
`:e[po]&&!h[Re]?E+=`connection: keep-alive\r
`:E+=`connection: close\r
`,Array.isArray(c))for(let f=0;f<c.length;f+=2){let d=c[f+0],m=c[f+1];if(Array.isArray(m))for(let C=0;C<m.length;C++)E+=`${d}: ${m[C]}\r
`;else E+=`${d}: ${m}\r
`}return Oh.sendHeaders.hasSubscribers&&Oh.sendHeaders.publish({request:t,headers:E,socket:g}),!A||p===0?Vh(h,null,e,t,g,u,E,l):F.isBuffer(A)?Vh(h,A,e,t,g,u,E,l):F.isBlobLike(A)?typeof A.stream=="function"?qh(h,A.stream(),e,t,g,u,E,l):ik(h,A,e,t,g,u,E,l):F.isStream(A)?rk(h,A,e,t,g,u,E,l):F.isIterable(A)?qh(h,A,e,t,g,u,E,l):k(!1),!0}function rk(e,t,s,r,i,o,n,a){k(o!==0||s[Ee]===0,"stream body cannot be pipelined");let A=!1,c=new en({abort:e,socket:i,request:r,contentLength:o,client:s,expectsPayload:a,header:n}),u=function(h){if(!A)try{!c.write(h)&&this.pause&&this.pause()}catch(E){F.destroy(this,E)}},l=function(){A||t.resume&&t.resume()},p=function(){if(queueMicrotask(()=>{t.removeListener("error",g)}),!A){let h=new Wh;queueMicrotask(()=>g(h))}},g=function(h){if(!A){if(A=!0,k(i.destroyed||i[$t]&&s[Ee]<=1),i.off("drain",l).off("error",g),t.removeListener("data",u).removeListener("end",g).removeListener("close",p),!h)try{c.end()}catch(E){h=E}c.destroy(h),h&&(h.code!=="UND_ERR_INFO"||h.message!=="reset")?F.destroy(t,h):F.destroy(t)}};t.on("data",u).on("end",g).on("error",g).on("close",p),t.resume&&t.resume(),i.on("drain",l).on("error",g),t.errorEmitted??t.errored?setImmediate(()=>g(t.errored)):(t.endEmitted??t.readableEnded)&&setImmediate(()=>g(null)),(t.closeEmitted??t.closed)&&setImmediate(p)}function Vh(e,t,s,r,i,o,n,a){try{t?F.isBuffer(t)&&(k(o===t.byteLength,"buffer body must have content length"),i.cork(),i.write(`${n}content-length: ${o}\r
`,Array.isArray(c))for(let f=0;f<c.length;f+=2){let g=c[f+0],m=c[f+1];if(Array.isArray(m))for(let B=0;B<m.length;B++)E+=`${g}: ${m[B]}\r
`;else E+=`${g}: ${m}\r
`}return Rd.sendHeaders.hasSubscribers&&Rd.sendHeaders.publish({request:t,headers:E,socket:h}),!A||p===0?Gd(d,null,e,t,h,l,E,u):x.isBuffer(A)?Gd(d,A,e,t,h,l,E,u):x.isBlobLike(A)?typeof A.stream=="function"?Ld(d,A.stream(),e,t,h,l,E,u):c0(d,A,e,t,h,l,E,u):x.isStream(A)?A0(d,A,e,t,h,l,E,u):x.isIterable(A)?Ld(d,A,e,t,h,l,E,u):D(!1),!0}function A0(e,t,s,i,r,n,o,a){D(n!==0||s[oe]===0,"stream body cannot be pipelined");let A=!1,c=new Eo({abort:e,socket:r,request:i,contentLength:n,client:s,expectsPayload:a,header:o}),l=function(d){if(!A)try{!c.write(d)&&this.pause&&this.pause()}catch(E){x.destroy(this,E)}},u=function(){A||t.resume&&t.resume()},p=function(){if(queueMicrotask(()=>{t.removeListener("error",h)}),!A){let d=new _d;queueMicrotask(()=>h(d))}},h=function(d){if(!A){if(A=!0,D(r.destroyed||r[Xt]&&s[oe]<=1),r.off("drain",u).off("error",h),t.removeListener("data",l).removeListener("end",h).removeListener("close",p),!d)try{c.end()}catch(E){d=E}c.destroy(d),d&&(d.code!=="UND_ERR_INFO"||d.message!=="reset")?x.destroy(t,d):x.destroy(t)}};t.on("data",l).on("end",h).on("error",h).on("close",p),t.resume&&t.resume(),r.on("drain",u).on("error",h),t.errorEmitted??t.errored?setImmediate(()=>h(t.errored)):(t.endEmitted??t.readableEnded)&&setImmediate(()=>h(null)),(t.closeEmitted??t.closed)&&setImmediate(p)}function Gd(e,t,s,i,r,n,o,a){try{t?x.isBuffer(t)&&(D(n===t.byteLength,"buffer body must have content length"),r.cork(),r.write(`${o}content-length: ${n}\r
\r
`,"latin1"),i.write(t),i.uncork(),r.onBodySent(t),!a&&r.reset!==!1&&(i[ke]=!0)):o===0?i.write(`${n}content-length: 0\r
`,"latin1"),r.write(t),r.uncork(),i.onBodySent(t),!a&&i.reset!==!1&&(r[Re]=!0)):n===0?r.write(`${o}content-length: 0\r
\r
`,"latin1"):(k(o===null,"no body must not have content length"),i.write(`${n}\r
`,"latin1")),r.onRequestSent(),s[Xt]()}catch(A){e(A)}}async function ik(e,t,s,r,i,o,n,a){k(o===t.size,"blob body must have content length");try{if(o!=null&&o!==t.size)throw new bs;let A=Buffer.from(await t.arrayBuffer());i.cork(),i.write(`${n}content-length: ${o}\r
`,"latin1"):(D(n===null,"no body must not have content length"),r.write(`${o}\r
`,"latin1")),i.onRequestSent(),s[Lt]()}catch(A){e(A)}}async function c0(e,t,s,i,r,n,o,a){D(n===t.size,"blob body must have content length");try{if(n!=null&&n!==t.size)throw new ys;let A=Buffer.from(await t.arrayBuffer());r.cork(),r.write(`${o}content-length: ${n}\r
\r
`,"latin1"),i.write(A),i.uncork(),r.onBodySent(A),r.onRequestSent(),!a&&r.reset!==!1&&(i[ke]=!0),s[Xt]()}catch(A){e(A)}}async function qh(e,t,s,r,i,o,n,a){k(o!==0||s[Ee]===0,"iterator body cannot be pipelined");let A=null;function c(){if(A){let p=A;A=null,p()}}let u=()=>new Promise((p,g)=>{k(A===null),i[We]?g(i[We]):A=p});i.on("close",c).on("drain",c);let l=new en({abort:e,socket:i,request:r,contentLength:o,client:s,expectsPayload:a,header:n});try{for await(let p of t){if(i[We])throw i[We];l.write(p)||await u()}l.end()}catch(p){l.destroy(p)}finally{i.off("close",c).off("drain",c)}}var en=class{constructor({abort:t,socket:s,request:r,contentLength:i,client:o,expectsPayload:n,header:a}){this.socket=s,this.request=r,this.contentLength=i,this.client=o,this.bytesWritten=0,this.expectsPayload=n,this.header=a,this.abort=t,s[$t]=!0}write(t){let{socket:s,request:r,contentLength:i,client:o,bytesWritten:n,expectsPayload:a,header:A}=this;if(s[We])throw s[We];if(s.destroyed)return!1;let c=Buffer.byteLength(t);if(!c)return!0;if(i!==null&&n+c>i){if(o[gc])throw new bs;process.emitWarning(new bs)}s.cork(),n===0&&(!a&&r.reset!==!1&&(s[ke]=!0),i===null?s.write(`${A}transfer-encoding: chunked\r
`,"latin1"):s.write(`${A}content-length: ${i}\r
`,"latin1"),r.write(A),r.uncork(),i.onBodySent(A),i.onRequestSent(),!a&&i.reset!==!1&&(r[Re]=!0),s[Lt]()}catch(A){e(A)}}async function Ld(e,t,s,i,r,n,o,a){D(n!==0||s[oe]===0,"iterator body cannot be pipelined");let A=null;function c(){if(A){let p=A;A=null,p()}}let l=()=>new Promise((p,h)=>{D(A===null),r[be]?h(r[be]):A=p});r.on("close",c).on("drain",c);let u=new Eo({abort:e,socket:r,request:i,contentLength:n,client:s,expectsPayload:a,header:o});try{for await(let p of t){if(r[be])throw r[be];u.write(p)||await l()}u.end()}catch(p){u.destroy(p)}finally{r.off("close",c).off("drain",c)}}var Eo=class{constructor({abort:t,socket:s,request:i,contentLength:r,client:n,expectsPayload:o,header:a}){this.socket=s,this.request=i,this.contentLength=r,this.client=n,this.bytesWritten=0,this.expectsPayload=o,this.header=a,this.abort=t,s[Xt]=!0}write(t){let{socket:s,request:i,contentLength:r,client:n,bytesWritten:o,expectsPayload:a,header:A}=this;if(s[be])throw s[be];if(s.destroyed)return!1;let c=Buffer.byteLength(t);if(!c)return!0;if(r!==null&&o+c>r){if(n[Uc])throw new ys;process.emitWarning(new ys)}s.cork(),o===0&&(!a&&i.reset!==!1&&(s[Re]=!0),r===null?s.write(`${A}transfer-encoding: chunked\r
`,"latin1"):s.write(`${A}content-length: ${r}\r
\r
`,"latin1")),i===null&&s.write(`\r
`,"latin1")),r===null&&s.write(`\r
${c.toString(16)}\r
`,"latin1"),this.bytesWritten+=c;let u=s.write(t);return s.uncork(),r.onBodySent(t),u||s[X].timeout&&s[X].timeoutType===dr&&s[X].timeout.refresh&&s[X].timeout.refresh(),u}end(){let{socket:t,contentLength:s,client:r,bytesWritten:i,expectsPayload:o,header:n,request:a}=this;if(a.onRequestSent(),t[$t]=!1,t[We])throw t[We];if(!t.destroyed){if(i===0?o?t.write(`${n}content-length: 0\r
`,"latin1"),this.bytesWritten+=c;let l=s.write(t);return s.uncork(),i.onBodySent(t),l||s[j].timeout&&s[j].timeoutType===bi&&s[j].timeout.refresh&&s[j].timeout.refresh(),l}end(){let{socket:t,contentLength:s,client:i,bytesWritten:r,expectsPayload:n,header:o,request:a}=this;if(a.onRequestSent(),t[Xt]=!1,t[be])throw t[be];if(!t.destroyed){if(r===0?n?t.write(`${o}content-length: 0\r
\r
`,"latin1"):t.write(`${n}\r
`,"latin1"):t.write(`${o}\r
`,"latin1"):s===null&&t.write(`\r
0\r
\r
`,"latin1"),s!==null&&i!==s){if(r[gc])throw new bs;process.emitWarning(new bs)}t[X].timeout&&t[X].timeoutType===dr&&t[X].timeout.refresh&&t[X].timeout.refresh(),r[Xt]()}}destroy(t){let{socket:s,client:r,abort:i}=this;s[$t]=!1,t&&(k(r[Ee]<=1,"pipeline should only contain this request"),i(t))}};Zh.exports=$v});var od=Q((S2,id)=>{"use strict";var je=require("node:assert"),{pipeline:ok}=require("node:stream"),M=N(),{RequestContentLengthMismatchError:mc,RequestAbortedError:Xh,SocketError:di,InformationalError:fc}=Y(),{kUrl:tn,kReset:rn,kClient:Er,kRunning:on,kPending:nk,kQueue:es,kPendingIdx:Qc,kRunningIdx:rt,kError:ot,kSocket:ae,kStrictContentLength:ak,kOnError:Bc,kMaxConcurrentStreams:rd,kHTTP2Session:it,kResume:ts,kSize:Ak,kHTTPContext:ck}=j(),Gt=Symbol("open streams"),$h,ed=!1,sn;try{sn=require("node:http2")}catch{sn={constants:{}}}var{constants:{HTTP2_HEADER_AUTHORITY:lk,HTTP2_HEADER_METHOD:uk,HTTP2_HEADER_PATH:pk,HTTP2_HEADER_SCHEME:gk,HTTP2_HEADER_CONTENT_LENGTH:hk,HTTP2_HEADER_EXPECT:dk,HTTP2_HEADER_STATUS:Ek}}=sn;function mk(e){let t=[];for(let[s,r]of Object.entries(e))if(Array.isArray(r))for(let i of r)t.push(Buffer.from(s),Buffer.from(i));else t.push(Buffer.from(s),Buffer.from(r));return t}async function fk(e,t){e[ae]=t,ed||(ed=!0,process.emitWarning("H2 support is experimental, expect them to change at any time.",{code:"UNDICI-H2"}));let s=sn.connect(e[tn],{createConnection:()=>t,peerMaxConcurrentStreams:e[rd]});s[Gt]=0,s[Er]=e,s[ae]=t,M.addListener(s,"error",Bk),M.addListener(s,"frameError",Ck),M.addListener(s,"end",Ik),M.addListener(s,"goaway",wk),M.addListener(s,"close",function(){let{[Er]:i}=this,{[ae]:o}=i,n=this[ae][ot]||this[ot]||new di("closed",M.getSocketInfo(o));if(i[it]=null,i.destroyed){je(i[nk]===0);let a=i[es].splice(i[rt]);for(let A=0;A<a.length;A++){let c=a[A];M.errorRequest(i,c,n)}}}),s.unref(),e[it]=s,t[it]=s,M.addListener(t,"error",function(i){je(i.code!=="ERR_TLS_CERT_ALTNAME_INVALID"),this[ot]=i,this[Er][Bc](i)}),M.addListener(t,"end",function(){M.destroy(this,new di("other side closed",M.getSocketInfo(this)))}),M.addListener(t,"close",function(){let i=this[ot]||new di("closed",M.getSocketInfo(this));e[ae]=null,this[it]!=null&&this[it].destroy(i),e[Qc]=e[rt],je(e[on]===0),e.emit("disconnect",e[tn],[e],i),e[ts]()});let r=!1;return t.on("close",()=>{r=!0}),{version:"h2",defaultPipelining:1/0,write(...i){return yk(e,...i)},resume(){Qk(e)},destroy(i,o){r?queueMicrotask(o):t.destroy(i).on("close",o)},get destroyed(){return t.destroyed},busy(){return!1}}}function Qk(e){let t=e[ae];t?.destroyed===!1&&(e[Ak]===0&&e[rd]===0?(t.unref(),e[it].unref()):(t.ref(),e[it].ref()))}function Bk(e){je(e.code!=="ERR_TLS_CERT_ALTNAME_INVALID"),this[ae][ot]=e,this[Er][Bc](e)}function Ck(e,t,s){if(s===0){let r=new fc(`HTTP/2: "frameError" received - type ${e}, code ${t}`);this[ae][ot]=r,this[Er][Bc](r)}}function Ik(){let e=new di("other side closed",M.getSocketInfo(this[ae]));this.destroy(e),M.destroy(this[ae],e)}function wk(e){let t=this[ot]||new di(`HTTP/2: "GOAWAY" frame received with code ${e}`,M.getSocketInfo(this)),s=this[Er];if(s[ae]=null,s[ck]=null,this[it]!=null&&(this[it].destroy(t),this[it]=null),M.destroy(this[ae],t),s[rt]<s[es].length){let r=s[es][s[rt]];s[es][s[rt]++]=null,M.errorRequest(s,r,t),s[Qc]=s[rt]}je(s[on]===0),s.emit("disconnect",s[tn],[s],t),s[ts]()}function bk(e){return e!=="GET"&&e!=="HEAD"&&e!=="OPTIONS"&&e!=="TRACE"&&e!=="CONNECT"}function yk(e,t){let s=e[it],{method:r,path:i,host:o,upgrade:n,expectContinue:a,signal:A,headers:c}=t,{body:u}=t;if(n)return M.errorRequest(e,t,new Error("Upgrade not supported for H2")),!1;let l={};for(let B=0;B<c.length;B+=2){let b=c[B+0],S=c[B+1];if(Array.isArray(S))for(let G=0;G<S.length;G++)l[b]?l[b]+=`,${S[G]}`:l[b]=S[G];else l[b]=S}let p,{hostname:g,port:h}=e[tn];l[lk]=o||`${g}${h?`:${h}`:""}`,l[uk]=r;let E=B=>{t.aborted||t.completed||(B=B||new Xh,M.errorRequest(e,t,B),p!=null&&M.destroy(p,B),M.destroy(u,B),e[es][e[rt]++]=null,e[ts]())};try{t.onConnect(E)}catch(B){M.errorRequest(e,t,B)}if(t.aborted)return!1;if(r==="CONNECT")return s.ref(),p=s.request(l,{endStream:!1,signal:A}),p.id&&!p.pending?(t.onUpgrade(null,null,p),++s[Gt],e[es][e[rt]++]=null):p.once("ready",()=>{t.onUpgrade(null,null,p),++s[Gt],e[es][e[rt]++]=null}),p.once("close",()=>{s[Gt]-=1,s[Gt]===0&&s.unref()}),!0;l[pk]=i,l[gk]="https";let f=r==="PUT"||r==="POST"||r==="PATCH";u&&typeof u.read=="function"&&u.read(0);let d=M.bodyLength(u);if(M.isFormDataLike(u)){$h??=pr().extractBody;let[B,b]=$h(u);l["content-type"]=b,u=B.stream,d=B.length}if(d==null&&(d=t.contentLength),(d===0||!f)&&(d=null),bk(r)&&d>0&&t.contentLength!=null&&t.contentLength!==d){if(e[ak])return M.errorRequest(e,t,new mc),!1;process.emitWarning(new mc)}d!=null&&(je(u,"no body must not have content length"),l[hk]=`${d}`),s.ref();let m=r==="GET"||r==="HEAD"||u===null;return a?(l[dk]="100-continue",p=s.request(l,{endStream:m,signal:A}),p.once("continue",C)):(p=s.request(l,{endStream:m,signal:A}),C()),++s[Gt],p.once("r Line truncated
`,this[Kk]=A??3e5,this[Zk]=i??3e5,this[Xk]=m??!0,this[$k]=B,this[bc]=S,this[rs]=null,this[i0]=pe>-1?pe:-1,this[n0]=Wt??100,this[ee]=null,this[nt]=[],this[Lt]=0,this[at]=0,this[Qi]=jt=>xc(this,jt),this[o0]=jt=>md(this,jt)}get pipelining(){return this[cn]}set pipelining(t){this[cn]=t,this[Qi](!0)}get[Ii](){return this[nt].length-this[at]}get[Ci](){return this[at]-this[Lt]}get[Bi](){return this[nt].length-this[Lt]}get[Pk](){return!!this[ee]&&!this[fr]&&!this[ee].destroyed}get[wc](){return!!(this[ee]?.busy(null)||this[Bi]>=(Ed(this)||1)||this[Ii]>0)}[Jk](t){fd(this),this.once("connect",t)}[r0](t,s){let r=t.origin||this[It].origin,i=new Gk(r,t,s);return this[nt].push(i),this[xs]||(ys.bodyLength(i.body)==null&&ys.isIterable(i.body)?(this[xs]=1,queueMicrotask(()=>xc(this))):this[Qi](!0)),this[xs]&&this[is]!==2&&this[wc]&&(this[is]=2),this[is]<2}async[t0](){return new Promise(t=>{this[Bi]?this[rs]=t:t(null)})}async[s0](t){return new Promise(s=>{let r=this[nt].splice(this[at]);for(let o=0;o<r.length;o++){let n=r[o];ys.errorRequest(this,n,t)}let i=()=>{this[rs]&&(this[rs](),this[rs]=null),s(null)};this[ee]?(this[ee].destroy(t,i),this[ee]=null):queueMicrotask(i),this[Qi]()})}},c0=An();function md(e,t){if(e[Ci]===0&&t.code!=="UND_ERR_INFO"&&t.code!=="UND_ERR_SOCKET"){Mt(e[at]===e[Lt]);let s=e[nt].splice(e[Lt]);for(let r=0;r<s.length;r++){let i=s[r];ys.errorRequest(e,i,t)}Mt(e[Bi]===0)}}async function fd(e){Mt(!e[fr]),Mt(!e[ee]);let{host:t,hostname:s,protocol:r,port:i}=e[It];if(s[0]==="["){let o=s.indexOf("]");Mt(o!==-1);let n=s.substring(1,o);Mt(dd.isIP(n)),s=n}e[fr]=!0,mr.beforeConnect.hasSubscribers&&mr.beforeConnect.publish({connectParams:{host:t,hostname:s,protocol:r,port:i,version:e[ee]?.version,servername:e[ss],localAddress:e[fi]},connector:e[mi]});try{let o=await new Promise((n,a)=>{e[mi]({host:t,hostname:s,protocol:r,port:i,servername:e[ss],localAddress:e[fi]},(A,c)=>{A?a(A):n(c)})});if(e.destroyed){ys.destroy(o.on("error",gd),new _k);return}Mt(o);try{e[ee]=o.alpnProtocol==="h2"?await A0(e,o):await a0(e,o)}catch(n){throw o.destroy().on("error",gd),n}e[fr]=!1,o[e0]=0,o[bc]=e[bc],o[Ok]=e,o[Vk]=null,mr.connected.hasSubscribers&&mr.connected.publish({connectParams:{host:t,hostname:s,protocol:r,port:i,version:e[ee]?.version,servername:e[ss],localAddress:e[fi]},connector:e[mi],socket:o}),e.emit("connect",e[It],[e])}catch(o){if(e.destroyed)return;if(e[fr]=!1,mr.connectError.hasSubscribers&&mr.connectError.publish({connectParams:{host:t,hostname:s,protocol:r,port:i,version:e[ee]?.version,servername:e[ss],localAddress:e[fi]},connector:e[mi],error:o}),o.code==="ERR_TLS_CERT_ALTNAME_INVALID")for(Mt(e[Ci]===0);e[Ii]>0&&e[nt][e[at]].servername===e[ss];){let n=e[nt][e[at]++];ys.errorRequest(e,n,o)}else md(e,o);e.emit("connectionError",e[It],[e],o)}e[Qi]()}function hd(e){e[is]=0,e.emit("drain",e[It],[e])}function xc(e,t){e[xs]!==2&&(e[xs]=2,l0(e,t),e[xs]=0,e[Lt]>256&&(e[nt].splice(0,e[Lt]),e[at]-=e[Lt],e[Lt]=0))}function l0(e,t){for(;;){if(e.destroyed){Mt(e[Ii]===0);return}if(e[rs]&&!e[Bi]){e[rs](),e[rs]=null;return}if(e[ee]&&e[ee].resume(),e[wc])e[is]=2;else if(e[is]===2){t?(e[is]=1,queueMicrotask(()=>hd(e))):hd(e);continue}if(e[Ii]===0||e[Ci]>=(Ed(e)||1))return;let s=e[nt][e[at]];if(e[It].protocol==="https:"&&e[ss]!==s.servername){if(e[Ci]>0)return;e[ss]=s.servername,e[ee]?.destroy(new Lk("servername changed"),()=>{e[ee]=null,xc(e)})}if(e[fr])return;if(!e[ee]){fd(e);return}if(e[ee].destroyed||e[ee].busy(s))return;!s.aborted&&e[ee].write(s)?e[at]++:e[nt].splice(e[at],1)}}Qd.exports=yc});var vc=Q((L2,Bd)=>{"use strict";var ln=class{constructor(){this.bottom=0,this.top=0,this.list=new Array(2048),this.next=null}isEmpty(){return this.top===this.bottom}isFull(){return(this.top+1&2047)===this.bottom}push(t){this.list[this.top]=t,this.top=this.top+1&2047}shift(){let t=this.list[this.bottom];return t===void 0?null:(this.list[this.bottom]=void 0,this.bottom=this.bottom+1&2047,t)}};Bd.exports=class{constructor(){this.head=this.tail=new ln}isEmpty(){return this.head.isEmpty()}push(t){this.head.isFull()&&(this.head=this.head.next=new ln),this.head.push(t)}shift(){let t=this.tail,s=t.shift();return t.isEmpty()&&t.next!==null&&(this.tail=t.next),s}}});var Id=Q((_2,Cd)=>{var{kFree:u0,kConnected:p0,kPending:g0,kQueued:h0,kRunning:d0,kSize:E0}=j(),vs=Symbol("pool"),kc=class{constructor(t){this[vs]=t}get connected(){return this[vs][p0]}get free(){return this[vs][u0]}get pending(){return this[vs][g0]}get queued(){return this[vs][h0]}get running(){return this[vs][d0]}get size(){return this[vs][E0]}};Cd.exports=kc});var Uc=Q((Y2,Fd)=>{"use strict";var m0=rr(),f0=vc(),{kConnected:Dc,kSize:wd,kRunning:bd,kPending:yd,kQueued:wi,kBusy:Q0,kFree:B0,kUrl:C0,kClose:I0,kDestroy:w0,kDispatch:b0}=j(),y0=Id(),De=Symbol("clients"),Ce=Symbol("needDrain"),bi=Symbol("queue"),Rc=Symbol("closed resolve"),Tc=Symbol("onDrain"),xd=Symbol("onConnect"),vd=Symbol("onDisconnect"),kd=Symbol("onConnectionError"),Fc=Symbol("get dispatcher"),Rd=Symbol("add client"),Td=Sym Line truncated
${r.count} ${r.noun} ${r.is} pending:
`,"latin1"),s!==null&&r!==s){if(i[Uc])throw new ys;process.emitWarning(new ys)}t[j].timeout&&t[j].timeoutType===bi&&t[j].timeout.refresh&&t[j].timeout.refresh(),i[Lt]()}}destroy(t){let{socket:s,client:i,abort:r}=this;s[Xt]=!1,t&&(D(i[oe]<=1,"pipeline should only contain this request"),r(t))}};Hd.exports=i0});var $d=Q((JY,Xd)=>{"use strict";var Ct=require("node:assert"),{errorMonitor:_c}=require("node:events"),{pipeline:l0}=require("node:stream"),M=N(),{RequestContentLengthMismatchError:Oc,RequestAbortedError:Yc,SocketError:br,InformationalError:mo}=Y(),{kUrl:fo,kReset:Bo,kClient:yi,kRunning:Co,kPending:u0,kQueue:Ds,kPendingIdx:Jc,kRunningIdx:Bt,kError:ot,kSocket:le,kStrictContentLength:p0,kOnError:Hc,kMaxConcurrentStreams:Zd,kHTTP2Session:nt,kResume:es,kSize:g0,kHTTPContext:h0}=Z(),$t=Symbol("open streams"),qd,Wd=!1,Qo;try{Qo=require("node:http2")}catch{Qo={constants:{}}}var{constants:{HTTP2_HEADER_AUTHORITY:d0,HTTP2_HEADER_METHOD:E0,HTTP2_HEADER_PATH:m0,HTTP2_HEADER_SCHEME:f0,HTTP2_HEADER_CONTENT_LENGTH:Q0,HTTP2_HEADER_EXPECT:B0,HTTP2_HEADER_STATUS:Pc}}=Qo;function Kd(e){let t=[];for(let[s,i]of Object.entries(e))if(Array.isArray(i))for(let r of i)t.push(Buffer.from(s),Buffer.from(r));else t.push(Buffer.from(s),Buffer.from(i));return t}function C0(e){let{[Pc]:t,...s}=e;return Kd(s)}async function I0(e,t){e[le]=t,Wd||(Wd=!0,process.emitWarning("H2 support is experimental, expect them to change at any time.",{code:"UNDICI-H2"}));let s=Qo.connect(e[fo],{createConnection:()=>t,peerMaxConcurrentStreams:e[Zd]});s[$t]=0,s[yi]=e,s[le]=t,M.addListener(s,"error",b0),M.addListener(s,"frameError",y0),M.addListener(s,"end",x0),M.addListener(s,"goaway",v0),M.addListener(s,"close",function(){let{[yi]:r}=this,{[le]:n}=r,o=this[le][ot]||this[ot]||new br("closed",M.getSocketInfo(n));if(r[nt]=null,r.destroyed){Ct(r[u0]===0);let a=r[Ds].splice(r[Bt]);for(let A=0;A<a.length;A++){let c=a[A];M.errorRequest(r,c,o)}}}),s.unref(),e[nt]=s,t[nt]=s,M.addListener(t,"error",function(r){this[ot]=r,this[yi][Hc](r)}),M.addListener(t,"end",function(){M.destroy(this,new br("other side closed",M.getSocketInfo(this)))}),M.addListener(t,"close",function(){let r=this[ot]||new br("closed",M.getSocketInfo(this));e[le]=null,this[nt]!=null&&this[nt].destroy(r),e[Jc]=e[Bt],Ct(e[Co]===0),e.emit("disconnect",e[fo],[e],r),e[es]()});let i=!1;return t.on("close",()=>{i=!0}),{version:"h2",defaultPipelining:1/0,write(...r){return D0(e,...r)},resume(){w0(e)},destroy(r,n){i?queueMicrotask(n):t.destroy(r).on("close",n)},get destroyed(){return t.destroyed},busy(){return!1}}}function w0(e){let t=e[le];t?.destroyed===!1&&(e[g0]===0&&e[Zd]===0?(t.unref(),e[nt].unref()):(t.ref(),e[nt].ref()))}function b0(e){this[le][ot]=e,this[yi][Hc](e)}function y0(e,t,s){if(s===0){let i=new mo(`HTTP/2: "frameError" received - type ${e}, code ${t}`);this[le][ot]=i,this[yi][Hc](i)}}function x0(){let e=new br("other side closed",M.getSocketInfo(this[le]));this.destroy(e),M.destroy(this[le],e)}function v0(e){let t=this[ot]||new br(`HTTP/2: "GOAWAY" frame received with code ${e}`,M.getSocketInfo(this)),s=this[yi];if(s[le]=null,s[h0]=null,this[nt]!=null&&(this[nt].destroy(t),this[nt]=null),M.destroy(this[le],t),s[Bt]<s[Ds].length){let i=s[Ds][s[Bt]];s[Ds][s[Bt]++]=null,M.errorRequest(s,i,t),s[Jc]=s[Bt]}Ct(s[Co]===0),s.emit("disconnect",s[fo],[s],t),s[es]()}function k0(e){return e!=="GET"&&e!=="HEAD"&&e!=="OPTIONS"&&e!=="TRACE"&&e!=="CONNECT"}function D0(e,t){let s=e[nt],{method:i,path:r,host:n,upgrade:o,expectContinue:a,signal:A,headers:c}=t,{body:l}=t;if(o)return M.errorRequest(e,t,new Error("Upgrade not supported for H2")),!1;let u={};for(let C=0;C<c.length;C+=2){let b=c[C+0],U=c[C+1];if(Array.isArray(U))for(let G=0;G<U.length;G++)u[b]?u[b]+=`,${U[G]}`:u[b]=U[G];else u[b]=U}let p,{hostname:h,port:d}=e[fo];u[d0]=n||`${h}${d?`:${d}`:""}`,u[E0]=i;let E=C=>{if(!t.aborted){if(t.completed){i==="CONNECT"&&p!=null&&M.destroy(p,C||new Yc);return}C=C||new Yc,M.errorRequest(e,t,C),p!=null&&M.destroy(p,C),M.destroy(l,C),e[Ds][e[Bt]++]=null,e[es]()}};try{t.onConnect(E)}catch(C){M.errorRequest(e,t,C)}if(t.aborted)return!1;if(i==="CONNECT"){s.ref(),p=s.request(u,{endStream:!1,signal:A});let C=!1,b=q=>{C=!0,p.off(_c,U),t.onUpgradeResponse(Number(q[Pc]),q,C0)},U=q=>{C=!0,p.off("response",b),t.onUpgradeError(q)},G=()=>{try{t.onUpgrade(null,null,p)}catch(q){p.off("response",b),E(q);return}t.aborted||(p.off("error",E),p.once(_c,U),e[Ds][e[Bt]++]=null)};return p.once("response",b),p.once("error",E),++s[$t],G(),p.once("close",()=>{!C&&t.completed&&(p.off("response",b),p.off(_c,U),t.onUpgradeError(new mo(`HTTP/2: "stream error" received - code ${p.rstCode}`))),s[$t]-=1,s[$t]===0&&s.unref()}),!0}u[m0]=r,u[f0]="https";let f=i==="PUT"||i==="POST"||i==="PATCH";l&&typeof l.read=="function"&&l.read(0);let g=M.bodyLength(l);if(M.isFormDataLike(l)){qd??=Ci().extractBody;let[C,b]=qd(l);u["content-type"]=b,l=C.stream,g=C.length}if(g==null&&(g=t.contentLength),(g===0||!f)&&(g=null),k0(i)&&g>0&&t.contentLength!=null&& Line truncated
`,this[tD]=A??3e5,this[eD]=r??3e5,this[sD]=m??!0,this[iD]=C,this[jc]=U,this[ss]=null,this[AD]=q>-1?q:-1,this[lD]=ze??100,this[ie]=null,this[at]=[],this[Yt]=0,this[At]=0,this[kr]=Bs=>Zc(this,Bs),this[cD]=Bs=>uE(this,Bs)}get pipelining(){return this[yo]}set pipelining(t){this[yo]=t,this[kr](!0)}get[Tr](){return this[at].length-this[At]}get[Rr](){return this[At]-this[Yt]}get[Dr](){return this[at].length-this[Yt]}get[W0](){return!!this[ie]&&!this[vi]&&!this[ie].destroyed}get[Wc](){return!!(this[ie]?.busy(null)||this[Dr]>=(lE(this)||1)||this[Tr]>0)}[q0](t){pE(this),this.once("connect",t)}[aD](t,s){let i=t.origin||this[wt].origin,r=new Y0(i,t,s);return this[at].push(r),this[Ts]||(Rs.bodyLength(r.body)==null&&Rs.isIterable(r.body)?(this[Ts]=1,queueMicrotask(()=>Zc(this))):this[kr](!0)),this[Ts]&&this[is]!==2&&this[Wc]&&(this[is]=2),this[is]<2}async[nD](){return new Promise(t=>{this[Dr]?this[ss]=t:t(null)})}async[oD](t){return new Promise(s=>{let i=this[at].splice(this[At]);for(let n=0;n<i.length;n++){let o=i[n];Rs.errorRequest(this,o,t)}let r=()=>{this[ss]&&(this[ss](),this[ss]=null),s(null)};this[ie]?(this[ie].destroy(t,r),this[ie]=null):queueMicrotask(r),this[kr]()})}},gD=bo();function uE(e,t){if(e[Rr]===0&&t.code!=="UND_ERR_INFO"&&t.code!=="UND_ERR_SOCKET"){_t(e[At]===e[Yt]);let s=e[at].splice(e[Yt]);for(let i=0;i<s.length;i++){let r=s[i];Rs.errorRequest(e,r,t)}_t(e[Dr]===0)}}async function pE(e){_t(!e[vi]),_t(!e[ie]);let{host:t,hostname:s,protocol:i,port:r}=e[wt];if(s[0]==="["){let n=s.indexOf("]");_t(n!==-1);let o=s.substring(1,n);_t(cE.isIP(o)),s=o}e[vi]=!0,xi.beforeConnect.hasSubscribers&&xi.beforeConnect.publish({connectParams:{host:t,hostname:s,protocol:i,port:r,version:e[ie]?.version,servername:e[ts],localAddress:e[vr]},connector:e[xr]});try{let n=await new Promise((o,a)=>{e[xr]({host:t,hostname:s,protocol:i,port:r,servername:e[ts],localAddress:e[vr]},(A,c)=>{A?a(A):o(c)})});if(e.destroyed){Rs.destroy(n.on("error",aE),new J0);return}_t(n);try{e[ie]=n.alpnProtocol==="h2"?await pD(e,n):await uD(e,n)}catch(o){throw n.destroy().on("error",aE),o}e[vi]=!1,n[rD]=0,n[jc]=e[jc],n[V0]=e,n[z0]=null,xi.connected.hasSubscribers&&xi.connected.publish({connectParams:{host:t,hostname:s,protocol:i,port:r,version:e[ie]?.version,servername:e[ts],localAddress:e[vr]},connector:e[xr],socket:n}),e.emit("connect",e[wt],[e])}catch(n){if(e.destroyed)return;if(e[vi]=!1,xi.connectError.hasSubscribers&&xi.connectError.publish({connectParams:{host:t,hostname:s,protocol:i,port:r,version:e[ie]?.version,servername:e[ts],localAddress:e[vr]},connector:e[xr],error:n}),n.code==="ERR_TLS_CERT_ALTNAME_INVALID")for(_t(e[Rr]===0);e[Tr]>0&&e[at][e[At]].servername===e[ts];){let o=e[at][e[At]++];Rs.errorRequest(e,o,n)}else uE(e,n);e.emit("connectionError",e[wt],[e],n)}e[kr]()}function AE(e){e[is]=0,e.emit("drain",e[wt],[e])}function Zc(e,t){e[Ts]!==2&&(e[Ts]=2,hD(e,t),e[Ts]=0,e[Yt]>256&&(e[at].splice(0,e[Yt]),e[At]-=e[Yt],e[Yt]=0))}function hD(e,t){for(;;){if(e.destroyed){_t(e[Tr]===0);return}if(e[ss]&&!e[Dr]){e[ss](),e[ss]=null;return}if(e[ie]&&e[ie].resume(),e[Wc])e[is]=2;else if(e[is]===2){t?(e[is]=1,queueMicrotask(()=>AE(e))):AE(e);continue}if(e[Tr]===0||e[Rr]>=(lE(e)||1))return;let s=e[at][e[At]];if(e[wt].protocol==="https:"&&e[ts]!==s.servername){if(e[Rr]>0)return;e[ts]=s.servername,e[ie]?.destroy(new P0("servername changed"),()=>{e[ie]=null,Zc(e)})}if(e[vi])return;if(!e[ie]){pE(e);return}if(e[ie].destroyed||e[ie].busy(s))return;!s.aborted&&e[ie].write(s)?e[At]++:e[at].splice(e[At],1)}}gE.exports=zc});var Kc=Q((jY,hE)=>{"use strict";var xo=class{constructor(){this.bottom=0,this.top=0,this.list=new Array(2048),this.next=null}isEmpty(){return this.top===this.bottom}isFull(){return(this.top+1&2047)===this.bottom}push(t){this.list[this.top]=t,this.top=this.top+1&2047}shift(){let t=this.list[this.bottom];return t===void 0?null:(this.list[this.bottom]=void 0,this.bottom=this.bottom+1&2047,t)}};hE.exports=class{constructor(){this.head=this.tail=new xo}isEmpty(){return this.head.isEmpty()}push(t){this.head.isFull()&&(this.head=this.head.next=new xo),this.head.push(t)}shift(){let t=this.tail,s=t.shift();return t.isEmpty()&&t.next!==null&&(this.tail=t.next),s}}});var EE=Q((zY,dE)=>{var{kFree:dD,kConnected:ED,kPending:mD,kQueued:fD,kRunning:QD,kSize:BD}=Z(),Ss=Symbol("pool"),Xc=class{constructor(t){this[Ss]=t}get connected(){return this[Ss][ED]}get free(){return this[Ss][dD]}get pending(){return this[Ss][mD]}get queued(){return this[Ss][fD]}get running(){return this[Ss][QD]}get size(){return this[Ss][BD]}};dE.exports=Xc});var rl=Q((ZY,xE)=>{"use strict";var CD=pi(),ID=Kc(),{kConnected:$c,kSize:mE,kRunning:fE,kPending:QE,kQueued:Sr,kBusy:wD,kFree:bD,kUrl:yD,kClose:xD,kDestroy:vD,kDispatch:kD}=Z(),DD=EE(),Te=Symbol("clients"),ye=Symbol("needDrain"),Fr=Symbol("queue"),el=Symbol("closed resolve"),tl=Symbol("onDrain"),BE=Symbol("onConnect"),CE=Symbol("onDisconnect"),IE=Symbol("onConnectionError"),sl=Symbol("get dispatcher"),bE=Symbol("add client"),yE=Symbo Line truncated
${i.count} ${i.noun} ${i.is} pending:
${t.format(s)}
`.trim())}};Lm.exports=Ul});var kn=Q((hY,Pm)=>{"use strict";var Ym=Symbol.for("undici.globalDispatcher.1"),{InvalidArgumentError:KR}=Y(),XR=Cr();Jm()===void 0&&Om(new XR);function Om(e){if(!e||typeof e.dispatch!="function")throw new KR("Argument agent must implement Agent");Object.defineProperty(globalThis,Ym,{value:e,writable:!0,enumerable:!1,configurable:!1})}function Jm(){return globalThis[Ym]}Pm.exports={setGlobalDispatcher:Om,getGlobalDispatcher:Jm}});var Dn=Q((EY,Hm)=>{"use strict";Hm.exports=class{#e;constructor(t){if(typeof t!="object"||t===null)throw new TypeError("handler must be an object");this.#e=t}onConnect(...t){return this.#e.onConnect?.(...t)}onError(...t){return this.#e.onError?.(...t)}onUpgrade(...t){return this.#e.onUpgrade?.(...t)}onResponseStarted(...t){return this.#e.onResponseStarted?.(...t)}onHeaders(...t){return this.#e.onHeaders?.(...t)}onData(...t){return this.#e.onData?.(...t)}onComplete(...t){return this.#e.onComplete?.(...t)}onBodySent(...t){return this.#e.onBodySent?.(...t)}}});var qm=Q((mY,Vm)=>{"use strict";var $R=an();Vm.exports=e=>{let t=e?.maxRedirections;return s=>function(i,o){let{maxRedirections:n=t,...a}=i;if(!n)return s(i,o);let A=new $R(s,n,i,o);return s(a,A)}}});var jm=Q((fY,Wm)=>{"use strict";var eT=fn();Wm.exports=e=>t=>function(r,i){return t(r,new eT({...r,retryOptions:{...e,...r.retryOptions}},{handler:i,dispatch:t}))}});var Zm=Q((QY,zm)=>{"use strict";var tT=N(),{InvalidArgumentError:sT,RequestAbortedError:rT}=Y(),iT=Dn(),Nl=class extends iT{#e=1024*1024;#t=null;#i=!1;#s=!1;#r=0;#A=null;#a=null;constructor({maxSize:t},s){if(super(s),t!=null&&(!Number.isFinite(t)||t<1))throw new sT("maxSize must be a number greater than 0");this.#e=t??this.#e,this.#a=s}onConnect(t){this.#t=t,this.#a.onConnect(this.#c.bind(this))}#c(t){this.#s=!0,this.#A=t}onHeaders(t,s,r,i){let n=tT.parseHeaders(s)["content-length"];if(n!=null&&n>this.#e)throw new rT(`Response size (${n}) larger than maxSize (${this.#e})`);return this.#s?!0:this.#a.onHeaders(t,s,r,i)}onError(t){this.#i||(t=this.#A??t,this.#a.onError(t))}onData(t){return this.#r=this.#r+t.length,this.#r>=this.#e&&(this.#i=!0,this.#s?this.#a.onError(this.#A):this.#a.onComplete([])),!0}onComplete(t){if(!this.#i){if(this.#s){this.#a.onError(this.reason);return}this.#a.onComplete(t)}}};function oT({maxSize:e}={maxSize:1024*1024}){return t=>function(r,i){let{dumpMaxSize:o=e}=r,n=new Nl({maxSize:o},i);return t(r,n)}}zm.exports=oT});var $m=Q((BY,Xm)=>{"use strict";var{isIP:nT}=require("node:net"),{lookup:aT}=require("node:dns"),AT=Dn(),{InvalidArgumentError:Tr,InformationalError:cT}=Y(),Km=Math.pow(2,31)-1,Gl=class{#e=0;#t=0;#i=new Map;dualStack=!0;affinity=null;lookup=null;pick=null;constructor(t){this.#e=t.maxTTL,this.#t=t.maxItems,this.dualStack=t.dualStack,this.affinity=t.affinity,this.lookup=t.lookup??this.#s,this.pick=t.pick??this.#r}get full(){return this.#i.size===this.#t}runLookup(t,s,r){let i=this.#i.get(t.hostname);if(i==null&&this.full){r(null,t.origin);return}let o={affinity:this.affinity,dualStack:this.dualStack,lookup:this.lookup,pick:this.pick,...s.dns,maxTTL:this.#e,maxItems:this.#t};if(i==null)this.lookup(t,o,(n,a)=>{if(n||a==null||a.length===0){r(n??new cT("No DNS entries found"));return}this.setRecords(t,a);let A=this.#i.get(t.hostname),c=this.pick(t,A,o.affinity),u;typeof c.port=="number"?u=`:${c.port}`:t.port!==""?u=`:${t.port}`:u="",r(null,`${t.protocol}//${c.family===6?`[${c.address}]`:c.address}${u}`)});else{let n=this.pick(t,i,o.affinity);if(n==null){this.#i.delete(t.hostname),this.runLookup(t,s,r);return}let a;typeof n.port=="number"?a=`:${n.port}`:t.port!==""?a=`:${t.port}`:a="",r(null,`${t.protocol}//${n.family===6?`[${n.address}]`:n.address}${a}`)}}#s(t,s,r){aT(t.hostname,{all:!0,family:this.dualStack===!1?this.affinity:0,order:"ipv4first"},(i,o)=>{if(i)return r(i);let n=new Map;for(let a of o)n.set(`${a.address}:${a.family}`,a);r(null,n.values())})}#r(t,s,r){let i=null,{records:o,offset:n}=s,a;if(this.dualStack?(r==null&&(n==null||n===Km?(s.offset=0,r=4):(s.offset++,r=(s.offset&1)===1?6:4)),o[r]!=null&&o[r].ips.length>0?a=o[r]:a=o[r===4?6:4]):a=o[r],a==null||a.ips.length===0)return i;a.offset==null||a.offset===Km?a.offset=0:a.offset++;let A=a.offset%a.ips.length;return i=a.ips[A]??null,i==null?i:Date.now()-i.timestamp>i.ttl?(a.ips.splice(A,1),this.pick(t,s,r)):i}setRecords(t,s){let r=Date.now(),i={records:{4:null,6:null}};for(let o of s){o.timestamp=r,typeof o.ttl=="number"?o.ttl=Math.min(o.ttl,this.#e):o.ttl=this.#e;let n=i.records[o.family]??{ips:[]};n.ips.push(o),i.records[o.family]=n}this.#i.set(t.hostname,i)}getHandler(t,s){return new Ml(this,t,s)}},Ml=class extends AT{#e=null;#t=null;#i=null;#s=null;#r=null;constructor(t,{origin:s,handler:r,dispatch:i},o){super(r),this.#r=s,this.#s=r,this.#t={...o},this.#e=t,this.#i=i}onError(t){switch(t.code){case"ETIMEDOUT":case"ECONNREFUSED":{if(this.#e.dualStack){this.#e.runLookup(this.#r,this.#t,(s,r)=>{if(s)return this.#s.onError(s);let i={...this.#t,origin: Line truncated
${o}`;break;case"retry":SB(o)&&(s[i]=o);break;case"id":UB(o)&&(s[i]=o);break;case"event":o.length>0&&(s[i]=o);break}}processEvent(t){t.retry&&SB(t.retry)&&(this.state.reconnectionTime=parseInt(t.retry,10)),t.id&&UB(t.id)&&(this.state.lastEventId=t.id),t.data!==void 0&&this.push({type:t.event||"message",options:{data:t.data,lastEventId:this.state.lastEventId,origin:this.state.origin}})}clearEvent(){this.event={data:void 0,event:void 0,id:void 0,retry:void 0}}};NB.exports={EventSourceStream:Iu}});var HB=Q((KY,PB)=>{"use strict";var{pipeline:QN}=require("node:stream"),{fetching:BN}=Mi(),{makeRequest:CN}=Ur(),{webidl:Pt}=ge(),{EventSourceStream:IN}=GB(),{parseMIMEType:wN}=ve(),{createFastMessageEvent:bN}=Yr(),{isNetworkError:MB}=Ni(),{delay:yN}=Bu(),{kEnumerableProperty:Js}=N(),{environmentSettingsObject:LB}=Ue(),_B=!1,YB=3e3,Zi=0,OB=1,Ki=2,xN="anonymous",vN="use-credentials",Vr=class e extends EventTarget{#e={open:null,error:null,message:null};#t=null;#i=!1;#s=Zi;#r=null;#A=null;#a;#c;constructor(t,s={}){super(),Pt.util.markAsUncloneable(this);let r="EventSource constructor";Pt.argumentLengthCheck(arguments,1,r),_B||(_B=!0,process.emitWarning("EventSource is experimental, expect them to change at any time.",{code:"UNDICI-ES"})),t=Pt.converters.USVString(t,r,"url"),s=Pt.converters.EventSourceInitDict(s,r,"eventSourceInitDict"),this.#a=s.dispatcher,this.#c={lastEventId:"",reconnectionTime:YB};let i=LB,o;try{o=new URL(t,i.settingsObject.baseUrl),this.#c.origin=o.origin}catch(A){throw new DOMException(A,"SyntaxError")}this.#t=o.href;let n=xN;s.withCredentials&&(n=vN,this.#i=!0);let a={redirect:"follow",keepalive:!0,mode:"cors",credentials:n==="anonymous"?"same-origin":"omit",referrer:"no-referrer"};a.client=LB.settingsObject,a.headersList=[["accept",{name:"accept",value:"text/event-stream"}]],a.cache="no-store",a.initiator="other",a.urlList=[new URL(this.#t)],this.#r=CN(a),this.#l()}get readyState(){return this.#s}get url(){return this.#t}get withCredentials(){return this.#i}#l(){if(this.#s===Ki)return;this.#s=Zi;let t={request:this.#r,dispatcher:this.#a},s=r=>{MB(r)&&(this.dispatchEvent(new Event("error")),this.close()),this.#g()};t.processResponseEndOfBody=s,t.processResponse=r=>{if(MB(r))if(r.aborted){this.close(),this.dispatchEvent(new Event("error"));return}else{this.#g();return}let i=r.headersList.get("content-type",!0),o=i!==null?wN(i):"failure",n=o!=="failure"&&o.essence==="text/event-stream";if(r.status!==200||n===!1){this.close(),this.dispatchEvent(new Event("error"));return}this.#s=OB,this.dispatchEvent(new Event("open")),this.#c.origin=r.urlList[r.urlList.length-1].origin;let a=new IN({eventSourceSettings:this.#c,push:A=>{this.dispatchEvent(bN(A.type,A.options))}});QN(r.body.stream,a,A=>{A?.aborted===!1&&(this.close(),this.dispatchEvent(new Event("error")))})},this.#A=BN(t)}async#g(){this.#s!==Ki&&(this.#s=Zi,this.dispatchEvent(new Event("error")),await yN(this.#c.reconnectionTime),this.#s===Zi&&(this.#c.lastEventId.length&&this.#r.headersList.set("last-event-id",this.#c.lastEventId,!0),this.#l()))}close(){Pt.brandCheck(this,e),this.#s!==Ki&&(this.#s=Ki,this.#A.abort(),this.#r=null)}get onopen(){return this.#e.open}set onopen(t){this.#e.open&&this.removeEventListener("open",this.#e.open),typeof t=="function"?(this.#e.open=t,this.addEventListener("open",t)):this.#e.open=null}get onmessage(){return this.#e.message}set onmessage(t){this.#e.message&&this.removeEventListener("message",this.#e.message),typeof t=="function"?(this.#e.message=t,this.addEventListener("message",t)):this.#e.message=null}get onerror(){return this.#e.error}set onerror(t){this.#e.error&&this.removeEventListener("error",this.#e.error),typeof t=="function"?(this.#e.error=t,this.addEventListener("error",t)):this.#e.error=null}},JB={CONNECTING:{__proto__:null,configurable:!1,enumerable:!0,value:Zi,writable:!1},OPEN:{__proto__:null,configurable:!1,enumerable:!0,value:OB,writable:!1},CLOSED:{__proto__:null,configurable:!1,enumerable:!0,value:Ki,writable:!1}};Object.defineProperties(Vr,JB);Object.defineProperties(Vr.prototype,JB);Object.defineProperties(Vr.prototype,{close:Js,onerror:Js,onmessage:Js,onopen:Js,readyState:Js,url:Js,withCredentials:Js});Pt.converters.EventSourceInitDict=Pt.dictionaryConverter([{key:"withCredentials",converter:Pt.converters.boolean,defaultValue:()=>!1},{key:"dispatcher",converter:Pt.converters.any}]);PB.exports={EventSource:Vr,defaultReconnectionTime:YB}});var ma=Q((XY,R)=>{"use strict";var kN=Qr(),VB=ti(),DN=Br(),RN=Od(),TN=Cr(),FN=Wc(),SN=uE(),UN=mE(),qB=Y(),Ea=N(),{InvalidArgumentError:da}=qB,qr=rm(),NN=ri(),GN=kl(),MN=_m(),LN=Tl(),_N=dl(),YN=fn(),{getGlobalDispatcher:WB,setGlobalDispatcher:ON}=kn(),JN=Dn(),PN=an(),HN=An();Object.assign(VB.prototype,qr);R.exports.Dispatcher=VB;R.exports.Client=kN;R.exports.Pool=DN;R.exports.BalancedPool=RN;R.exports.Agent=TN;R.exports.ProxyAgent=FN;R.exports.EnvHttpProxyAgent=SN;R.exports.RetryAgent=UN;R.exports.RetryHandler=YN;R.exports.DecoratorHandler=JN;R.exports.Redire Line truncated
`.trim())}};Uf.exports=ru});var Pr=Q((bO,_f)=>{"use strict";var Mf=Symbol.for("undici.globalDispatcher.1"),{InvalidArgumentError:tS}=Y(),sS=Ri();Lf()===void 0&&Gf(new sS);function Gf(e){if(!e||typeof e.dispatch!="function")throw new tS("Argument agent must implement Agent");Object.defineProperty(globalThis,Mf,{value:e,writable:!0,enumerable:!1,configurable:!1})}function Lf(){return globalThis[Mf]}_f.exports={setGlobalDispatcher:Gf,getGlobalDispatcher:Lf}});var Ho=Q((xO,Yf)=>{"use strict";Yf.exports=class{#e;constructor(t){if(typeof t!="object"||t===null)throw new TypeError("handler must be an object");this.#e=t}onConnect(...t){return this.#e.onConnect?.(...t)}onError(...t){return this.#e.onError?.(...t)}onUpgrade(...t){return this.#e.onUpgrade?.(...t)}onResponseStarted(...t){return this.#e.onResponseStarted?.(...t)}onHeaders(...t){return this.#e.onHeaders?.(...t)}onData(...t){return this.#e.onData?.(...t)}onComplete(...t){return this.#e.onComplete?.(...t)}onBodySent(...t){return this.#e.onBodySent?.(...t)}}});var Pf=Q((vO,Of)=>{"use strict";var iS=wo();Of.exports=e=>{let t=e?.maxRedirections;return s=>function(r,n){let{maxRedirections:o=t,...a}=r;if(!o)return s(r,n);let A=new iS(s,o,r,n);return s(a,A)}}});var Hf=Q((kO,Jf)=>{"use strict";var rS=Uo();Jf.exports=e=>t=>function(i,r){return t(i,new rS({...i,retryOptions:{...e,...i.retryOptions}},{handler:r,dispatch:t}))}});var qf=Q((DO,Vf)=>{"use strict";var nS=N(),{InvalidArgumentError:oS,RequestAbortedError:aS}=Y(),AS=Ho(),nu=class extends AS{#e=1024*1024;#t=null;#s=!1;#r=!1;#i=0;#n=null;#a=null;constructor({maxSize:t},s){if(super(s),t!=null&&(!Number.isFinite(t)||t<1))throw new oS("maxSize must be a number greater than 0");this.#e=t??this.#e,this.#a=s}onConnect(t){this.#t=t,this.#a.onConnect(this.#c.bind(this))}#c(t){this.#r=!0,this.#n=t}onHeaders(t,s,i,r){let o=nS.parseHeaders(s)["content-length"];if(o!=null&&o>this.#e)throw new aS(`Response size (${o}) larger than maxSize (${this.#e})`);return this.#r?!0:this.#a.onHeaders(t,s,i,r)}onError(t){this.#s||(t=this.#n??t,this.#a.onError(t))}onData(t){return this.#i=this.#i+t.length,this.#i>=this.#e&&(this.#s=!0,this.#r?this.#a.onError(this.#n):this.#a.onComplete([])),!0}onComplete(t){if(!this.#s){if(this.#r){this.#a.onError(this.reason);return}this.#a.onComplete(t)}}};function cS({maxSize:e}={maxSize:1024*1024}){return t=>function(i,r){let{dumpMaxSize:n=e}=i,o=new nu({maxSize:n},r);return t(i,o)}}Vf.exports=cS});var zf=Q((RO,jf)=>{"use strict";var{isIP:lS}=require("node:net"),{lookup:uS}=require("node:dns"),pS=Ho(),{InvalidArgumentError:_i,InformationalError:gS}=Y(),Wf=Math.pow(2,31)-1,ou=class{#e=0;#t=0;#s=new Map;dualStack=!0;affinity=null;lookup=null;pick=null;constructor(t){this.#e=t.maxTTL,this.#t=t.maxItems,this.dualStack=t.dualStack,this.affinity=t.affinity,this.lookup=t.lookup??this.#r,this.pick=t.pick??this.#i}get full(){return this.#s.size===this.#t}runLookup(t,s,i){let r=this.#s.get(t.hostname);if(r==null&&this.full){i(null,t.origin);return}let n={affinity:this.affinity,dualStack:this.dualStack,lookup:this.lookup,pick:this.pick,...s.dns,maxTTL:this.#e,maxItems:this.#t};if(r==null)this.lookup(t,n,(o,a)=>{if(o||a==null||a.length===0){i(o??new gS("No DNS entries found"));return}this.setRecords(t,a);let A=this.#s.get(t.hostname),c=this.pick(t,A,n.affinity),l;typeof c.port=="number"?l=`:${c.port}`:t.port!==""?l=`:${t.port}`:l="",i(null,`${t.protocol}//${c.family===6?`[${c.address}]`:c.address}${l}`)});else{let o=this.pick(t,r,n.affinity);if(o==null){this.#s.delete(t.hostname),this.runLookup(t,s,i);return}let a;typeof o.port=="number"?a=`:${o.port}`:t.port!==""?a=`:${t.port}`:a="",i(null,`${t.protocol}//${o.family===6?`[${o.address}]`:o.address}${a}`)}}#r(t,s,i){uS(t.hostname,{all:!0,family:this.dualStack===!1?this.affinity:0,order:"ipv4first"},(r,n)=>{if(r)return i(r);let o=new Map;for(let a of n)o.set(`${a.address}:${a.family}`,a);i(null,o.values())})}#i(t,s,i){let r=null,{records:n,offset:o}=s,a;if(this.dualStack?(i==null&&(o==null||o===Wf?(s.offset=0,i=4):(s.offset++,i=(s.offset&1)===1?6:4)),n[i]!=null&&n[i].ips.length>0?a=n[i]:a=n[i===4?6:4]):a=n[i],a==null||a.ips.length===0)return r;a.offset==null||a.offset===Wf?a.offset=0:a.offset++;let A=a.offset%a.ips.length;return r=a.ips[A]??null,r==null?r:Date.now()-r.timestamp>r.ttl?(a.ips.splice(A,1),this.pick(t,s,i)):r}setRecords(t,s){let i=Date.now(),r={records:{4:null,6:null}};for(let n of s){n.timestamp=i,typeof n.ttl=="number"?n.ttl=Math.min(n.ttl,this.#e):n.ttl=this.#e;let o=r.records[n.family]??{ips:[]};o.ips.push(n),r.records[n.family]=o}this.#s.set(t.hostname,r)}getHandler(t,s){return new au(this,t,s)}},au=class extends pS{#e=null;#t=null;#s=null;#r=null;#i=null;constructor(t,{origin:s,handler:i,dispatch:r},n){super(i),this.#i=s,this.#r=i,this.#t={...n},this.#e=t,this.#s=r}onError(t){switch(t.code){case"ETIMEDOUT":case"ECONNREFUSED":{if(this.#e.dualStack){this.#e.runLookup(this.#i,this.#t,(s,i)=>{if(s)return this.#r.onError(s);let r={...this.#t,origin: Line truncated
${A}`,this.dataLineCount++;return}if(Ra(t,r,kM)){SM(t,n)&&(this.setEventFieldSize("retry",t.length-n),s.retry=t.toString("utf8",n));return}if(Ra(t,r,vM)){FM(t,n)&&(this.setEventFieldSize("id",t.length-n),s.id=t.toString("utf8",n));return}Ra(t,r,xM)&&n<t.length&&(this.setEventFieldSize("event",t.length-n),s.event=t.toString("utf8",n))}setEventFieldSize(t,s){let i=this.eventSize-this.eventFieldSizes[t]+s;if(this.maxEventSize>0&&i>this.maxEventSize)throw Ta();this.eventSize=i,this.eventFieldSizes[t]=s}processEvent(t){t.retry&&BM(t.retry)&&(this.state.reconnectionTime=parseInt(t.retry,10)),t.id&&CM(t.id)&&(this.state.lastEventId=t.id),t.data!==void 0&&this.push({type:t.event||"message",options:{data:t.data,lastEventId:this.state.lastEventId,origin:this.state.origin}})}clearEvent(){this.event.data=void 0,this.event.event=void 0,this.event.id=void 0,this.event.retry=void 0,this.eventSize=0,this.dataLineCount=0,this.eventFieldSizes.data=0,this.eventFieldSizes.event=0,this.eventFieldSizes.id=0,this.eventFieldSizes.retry=0}hasPendingEvent(){return this.event.data!==void 0||this.event.event!==void 0||this.event.id!==void 0||this.event.retry!==void 0}hasCurrentByte(){return this.chunkIndex<this.chunks.length&&this.pos<this.chunks[this.chunkIndex].length}currentByte(){return this.chunks[this.chunkIndex][this.pos]}consumeCurrentByte(){this.advanceCursor(),this.syncLineStartToCursor()}advanceCursor(){for(this.pos++;this.chunkIndex<this.chunks.length&&this.pos>=this.chunks[this.chunkIndex].length;)this.chunkIndex++,this.pos=0}syncLineStartToCursor(){this.lineChunkIndex=this.chunkIndex,this.linePos=this.pos,this.lineLength=0,this.dropConsumedChunks()}dropConsumedChunks(){if(this.lineChunkIndex>0){let t=this.lineChunkIndex;this.chunks.splice(0,t),this.lineChunkIndex=0,this.chunkIndex-=t}this.chunkIndex===this.chunks.length&&(this.chunks.length=0,this.chunkIndex=0,this.pos=0,this.lineChunkIndex=0,this.linePos=0)}readLine(){if(this.lineChunkIndex===this.chunkIndex)return this.chunks[this.chunkIndex].subarray(this.linePos,this.pos);let t=[],s=0;for(let i=this.lineChunkIndex;i<=this.chunkIndex;i++){let r=this.chunks[i],n=i===this.lineChunkIndex?this.linePos:0,o=i===this.chunkIndex?this.pos:r.length,a=r.subarray(n,o);s+=a.length,t.push(a)}return Buffer.concat(t,s)}peekBufferedByte(t){let s=this.lineChunkIndex,i=this.linePos;for(;s<this.chunks.length;){let r=this.chunks[s],n=r.length-i;if(t<n)return r[i+t];t-=n,s++,i=0}}discardLeadingBytes(t){for(;t>0&&this.lineChunkIndex<this.chunks.length;){let i=this.chunks[this.lineChunkIndex].length-this.linePos;t<i?(this.linePos+=t,t=0):(t-=i,this.lineChunkIndex++,this.linePos=0)}this.chunkIndex=this.lineChunkIndex,this.pos=this.linePos,this.dropConsumedChunks()}handleBOM(){let t=this.peekBufferedByte(0),s=this.peekBufferedByte(1),i=this.peekBufferedByte(2);return s===void 0?(t===$i[0]||(this.checkBOM=!1),!0):i===void 0?t===$i[0]&&s===$i[1]?!0:(this.checkBOM=!1,!1):(t===$i[0]&&s===$i[1]&&i===$i[2]&&this.discardLeadingBytes(3),this.checkBOM=!1,!this.hasCurrentByte())}};xC.exports={EventSourceStream:Zu}});var NC=Q((a1,UC)=>{"use strict";var{pipeline:UM}=require("node:stream"),{fetching:NM}=Wr(),{makeRequest:MM}=Pi(),{webidl:Ht}=Ee(),{EventSourceStream:GM}=vC(),{parseMIMEType:LM}=De(),{createFastMessageEvent:_M}=ji(),{isNetworkError:kC}=Vr(),{delay:YM}=zu(),{kEnumerableProperty:js}=N(),{environmentSettingsObject:DC}=Ge(),{getGlobalDispatcher:OM}=Pr(),RC=!1,TC=3e3,cn=0,SC=1,ln=2,PM="anonymous",JM="use-credentials",er=class e extends EventTarget{#e={open:null,error:null,message:null};#t=null;#s=!1;#r=cn;#i=null;#n=null;#a;#c;constructor(t,s={}){super(),Ht.util.markAsUncloneable(this);let i="EventSource constructor";Ht.argumentLengthCheck(arguments,1,i),RC||(RC=!0,process.emitWarning("EventSource is experimental, expect them to change at any time.",{code:"UNDICI-ES"})),t=Ht.converters.USVString(t,i,"url"),s=Ht.converters.EventSourceInitDict(s,i,"eventSourceInitDict"),this.#a=s.dispatcher,this.#c={lastEventId:"",reconnectionTime:TC};let r=DC,n;try{n=new URL(t,r.settingsObject.baseUrl),this.#c.origin=n.origin}catch(A){throw new DOMException(A,"SyntaxError")}this.#t=n.href;let o=PM;s.withCredentials&&(o=JM,this.#s=!0);let a={redirect:"follow",keepalive:!0,mode:"cors",credentials:o==="anonymous"?"same-origin":"omit",referrer:"no-referrer"};a.client=DC.settingsObject,a.headersList=[["accept",{name:"accept",value:"text/event-stream"}]],a.cache="no-store",a.initiator="other",a.urlList=[new URL(this.#t)],this.#i=MM(a),this.#l()}get readyState(){return this.#r}get url(){return this.#t}get withCredentials(){return this.#s}#l(){if(this.#r===ln)return;this.#r=cn;let t={request:this.#i,dispatcher:this.#a},s=i=>{kC(i)&&(this.dispatchEvent(new Event("error")),this.close()),this.#p()};t.processResponseEndOfBody=s,t.processResponse=i=>{if(kC(i))if(i.aborted){this.close(),this.dispatchEvent(new Event("error"));return}else{this.#p();return}let r=i.headersList.get("content-type",!0),n=r!==null?LM(r):"failure",o=n!= Line truncated
`+e.errors.map(t=>` - ${t.message}`).join(`
`)}var BM=class extends Error{constructor(e,t,s){super(QM(s)),this.request=e,this.headers=t,this.response=s,this.errors=s.errors,this.data=s.data,Error.captureStackTrace&&Error.captureStackTrace(this,this.constructor)}name="GraphqlResponseError";errors;data},CM=["method","baseUrl","url","headers","request","query","mediaType","operationName"],IM=["query","method","url"],LC=/\/api\/v3\/?$/;function wM(e,t,s){if(s){if(typeof t=="string"&&"query"in s)return Promise.reject(new Error('[@octokit/graphql] "query" cannot be used as variable name'));for(let n in s)if(IM.includes(n))return Promise.reject(new Error(`[@octokit/graphql] "${n}" cannot be used as variable name`))}let r=typeof t=="string"?Object.assign({query:t},s):t,i=Object.keys(r).reduce((n,a)=>CM.includes(a)?(n[a]=r[a],n):(n.variables||(n.variables={}),n.variables[a]=r[a],n),{}),o=r.baseUrl||e.endpoint.DEFAULTS.baseUrl;return LC.test(o)&&(i.url=o.replace(LC,"/api/graphql")),e(i).then(n=>{if(n.data.errors){let a={};for(let A of Object.keys(n.headers))a[A]=n.headers[A];throw new BM(i,a,n.data)}return n.data.data})}function Gu(e,t){let s=e.defaults(t);return Object.assign((i,o)=>wM(s,i,o),{defaults:Gu.bind(null,s),endpoint:s.endpoint})}var uJ=Gu(io,{headers:{"user-agent":`octokit-graphql.js/${fM} ${ds()}`},method:"POST",url:"/graphql"});function _C(e){return Gu(e,{method:"POST",url:"/graphql"})}var Mu="(?:[a-zA-Z0-9_-]+)",YC="\\.",OC=new RegExp(`^${Mu}${YC}${Mu}${YC}${Mu}$`),bM=OC.test.bind(OC);async function yM(e){let t=bM(e),s=e.startsWith("v1.")||e.startsWith("ghs_"),r=e.startsWith("ghu_");return{type:"token",token:e,tokenType:t?"app":s?"installation":r?"user-to-server":"oauth"}}function xM(e){return e.split(/\./).length===3?`bearer ${e}`:`token ${e}`}async function vM(e,t,s,r){let i=t.endpoint.merge(s,r);return i.headers.authorization=xM(e),t(i)}var JC=function(t){if(!t)throw new Error("[@octokit/auth-token] No token passed to createTokenAuth");if(typeof t!="string")throw new Error("[@octokit/auth-token] Token passed to createTokenAuth is not a string");return t=t.replace(/^(token|bearer) +/i,""),Object.assign(yM.bind(null,t),{hook:vM.bind(null,t)})};var Lu="7.0.6";var PC=()=>{},kM=console.warn.bind(console),DM=console.error.bind(console);function RM(e={}){return typeof e.debug!="function"&&(e.debug=PC),typeof e.info!="function"&&(e.info=PC),typeof e.warn!="function"&&(e.warn=kM),typeof e.error!="function"&&(e.error=DM),e}var HC=`octokit-core.js/${Lu} ${ds()}`,Ta=class{static VERSION=Lu;static defaults(t){return class extends this{constructor(...r){let i=r[0]||{};if(typeof t=="function"){super(t(i));return}super(Object.assign({},t,i,i.userAgent&&t.userAgent?{userAgent:`${i.userAgent} ${t.userAgent}`}:null))}}}static plugins=[];static plugin(...t){let s=this.plugins;return class extends this{static plugins=s.concat(t.filter(i=>!s.includes(i)))}}constructor(t={}){let s=new mC.Collection,r={baseUrl:io.endpoint.DEFAULTS.baseUrl,headers:{},request:Object.assign({},t.request,{hook:s.bind(null,"request")}),mediaType:{previews:[],format:""}};if(r.headers["user-agent"]=t.userAgent?`${t.userAgent} ${HC}`:HC,t.baseUrl&&(r.baseUrl=t.baseUrl),t.previews&&(r.mediaType.previews=t.previews),t.timeZone&&(r.headers["time-zone"]=t.timeZone),this.request=io.defaults(r),this.graphql=_C(this.request).defaults(r),this.log=RM(t.log),this.hook=s,t.authStrategy){let{authStrategy:o,...n}=t,a=o(Object.assign({request:this.request,log:this.log,octokit:this,octokitOptions:n},t.auth));s.wrap("request",a.hook),this.auth=a}else if(!t.auth)this.auth=async()=>({type:"unauthenticated"});else{let o=JC(t.auth);s.wrap("request",o.hook),this.auth=o}let i=this.constructor;for(let o=0;o<i.plugins.length;++o)Object.assign(this,i.plugins[o](this,t))}request;graphql;log;hook;auth};var _u="17.0.0";var TM={actions:{addCustomLabelsToSelfHostedRunnerForOrg:["POST /orgs/{org}/actions/runners/{runner_id}/labels"],addCustomLabelsToSelfHostedRunnerForRepo:["POST /repos/{owner}/{repo}/actions/runners/{runner_id}/labels"],addRepoAccessToSelfHostedRunnerGroupInOrg:["PUT /orgs/{org}/actions/runner-groups/{runner_group_id}/repositories/{repository_id}"],addSelectedRepoToOrgSecret:["PUT /orgs/{org}/actions/secrets/{secret_name}/repositories/{repository_id}"],addSelectedRepoToOrgVariable:["PUT /orgs/{org}/actions/variables/{name}/repositories/{repository_id}"],approveWorkflowRun:["POST /repos/{owner}/{repo}/actions/runs/{run_id}/approve"],cancelWorkflowRun:["POST /repos/{owner}/{repo}/actions/runs/{run_id}/cancel"],createEnvironmentVariable:["POST /repos/{owner}/{repo}/environments/{environment_name}/variables"],createHostedRunnerForOrg:["POST /orgs/{org}/actions/hosted-runners"],createOrUpdateEnvironmentSecret:["PUT /repos/{owner}/{repo}/environments/{environment_name}/secrets/{secret_name}"],createOrUpdateOrgSecret:["PUT /orgs/{org}/actions/secrets/{secret_name}"],createOrUpdateRepoSecret:["PUT /repos/{owner}/{repo}/actions/secrets/{secret_name}"],createOrgVariable:["POST /orgs/{org}/actions/variables"],cre Line truncated
globstar while`,e,l,t,p,g),this.matchOne(e.slice(l),t.slice(p),s))return this.debug("globstar found match!",l,a,g),!0;if(g==="."||g===".."||!r.dot&&g.charAt(0)==="."){this.debug("dot detected!",e,l,t,p);break}this.debug("globstar swallow a segment, and continue"),l++}return!!(s&&(this.debug(`
>>> no match, partial?`,e,l,t,p),l===a))}let h;if(typeof c=="string"?(h=u===c,this.debug("string match",c,u,h)):(h=c.test(u),this.debug("pattern match",c,u,h)),!h)return!1}if(o===a&&n===A)return!0;if(o===a)return s;if(n===A)return o===a-1&&e[o]==="";throw new Error("wtf?")}braceExpand(){return PI(this.pattern,this.options)}parse(e){Ja(e);let t=this.options;if(e==="**")return be;if(e==="")return"";let s,r=null;(s=e.match(RL))?r=t.dot?FL:TL:(s=e.match(BL))?r=(t.nocase?t.dot?bL:wL:t.dot?IL:CL)(s[1]):(s=e.match(SL))?r=(t.nocase?t.dot?NL:UL:t.dot?GL:ML)(s):(s=e.match(yL))?r=t.dot?vL:xL:(s=e.match(kL))&&(r=DL);let i=LI.fromGlob(e,this.options).toMMPattern();return r&&typeof i=="object"&&Reflect.defineProperty(i,"test",{value:r}),i}makeRe(){if(this.regexp||this.regexp===!1)return this.regexp;let e=this.set;if(!e.length)return this.regexp=!1,this.regexp;let t=this.options,s=t.noglobstar?YL:t.dot?OL:JL,r=new Set(t.nocase?["i"]:[]),i=e.map(a=>{let A=a.map(u=>{if(u instanceof RegExp)for(let l of u.flags.split(""))r.add(l);return typeof u=="string"?WL(u):u===be?be:u._src});A.forEach((u,l)=>{let p=A[l+1],g=A[l-1];u!==be||g===be||(g===void 0?p!==void 0&&p!==be?A[l+1]="(?:\\/|"+s+"\\/)?"+p:A[l]=s:p===void 0?A[l-1]=g+"(?:\\/|\\/"+s+")?":p!==be&&(A[l-1]=g+"(?:\\/|\\/"+s+"\\/)"+p,A[l+1]=be))});let c=A.filter(u=>u!==be);if(this.partial&&c.length>=1){let u=[];for(let l=1;l<=c.length;l++)u.push(c.slice(0,l).join("/"));return"(?:"+u.join("|")+")"}return c.join("/")}).join("|"),[o,n]=e.length>1?["(?:",")"]:["",""];i="^"+o+i+n+"$",this.partial&&(i="^(?:\\/|"+o+i.slice(1,-1)+n+")$"),this.negate&&(i="^(?!"+i+").+$");try{this.regexp=new RegExp(i,[...r].join(""))}catch{this.regexp=!1}return this.regexp}slashSplit(e){return this.preserveMultipleSlashes?e.split("/"):this.isWindows&&/^\/\/[^\/]+/.test(e)?["",...e.split(/\/+/)]:e.split(/\/+/)}match(e,t=this.partial){if(this.debug("match",e,this.pattern),this.comment)return!1;if(this.empty)return e==="";if(e==="/"&&t)return!0;let s=this.options;this.isWindows&&(e=e.split("\\").join("/"));let r=this.slashSplit(e);this.debug(this.pattern,"split",r);let i=this.set;this.debug(this.pattern,"set",i);let o=r[r.length-1];if(!o)for(let n=r.length-2;!o&&n>=0;n--)o=r[n];for(let n=0;n<i.length;n++){let a=i[n],A=r;if(s.matchBase&&a.length===1&&(A=[o]),this.matchOne(A,a,t))return s.flipNegate?!0:!this.negate}return s.flipNegate?!1:this.negate}static defaults(e){return ye.defaults(e).Minimatch}};ye.AST=LI;ye.Minimatch=fs;ye.escape=_I;ye.unescape=Xr;var jL=typeof performance=="object"&&performance&&typeof performance.now=="function"?performance:Date,VI=new Set,ep=typeof process=="object"&&process?process:{},qI=(e,t,s,r)=>{typeof ep.emitWarning=="function"?ep.emitWarning(e,t,s,r):console.error(`[${s}] ${t}: ${e}`)},Pa=globalThis.AbortController,EI=globalThis.AbortSignal;if(typeof Pa>"u"){EI=class{onabort;_onabort=[];reason;aborted=!1;addEventListener(s,r){this._onabort.push(r)}},Pa=class{constructor(){t()}signal=new EI;abort(s){if(!this.signal.aborted){this.signal.reason=s,this.signal.aborted=!0;for(let r of this.signal._onabort)r(s);this.signal.onabort?.(s)}}};let e=ep.env?.LRU_CACHE_IGNORE_AC_WARNING!=="1",t=()=>{e&&(e=!1,qI("AbortController is not defined. If using lru-cache in node 14, load an AbortController polyfill from the `node-abort-controller` package. A minimal polyfill is provided for use by LRUCache.fetch(), but it should not be relied upon in other contexts (eg, passing it to other APIs that use AbortController/AbortSignal might have undesirable effects). You may disable this with LRU_CACHE_IGNORE_AC_WARNING=1 in the env.","NO_ABORT_CONTROLLER","ENOTSUP",t))}}var zL=e=>!VI.has(e),ms=e=>e&&e===Math.floor(e)&&e>0&&isFinite(e),WI=e=>ms(e)?e<=Math.pow(2,8)?Uint8Array:e<=Math.pow(2,16)?Uint16Array:e<=Math.pow(2,32)?Uint32Array:e<=Number.MAX_SAFE_INTEGER?Ya:null:null,Ya=class extends Array{constructor(e){super(e),this.fill(0)}},ZL=class po{heap;length;static#e=!1;static create(t){let s=WI(t);if(!s)return[];po.#e=!0;let r=new po(t,s);return po.#e=!1,r}constructor(t,s){if(!po.#e)throw new TypeError("instantiate Stack using Stack.create(n)");this.heap=new s(t),this.length=0}push(t){this.heap[this.length++]=t}pop(){return this.heap[--this.length]}},Va=class jI{#e;#t;#i;#s;#r;#A;#a;#c;get perf(){return this.#c}ttl;ttlResolution;ttlAutopurge;updateAgeOnGet;updateAgeOnHas;allowStale;noDisposeOnSet;noUpdateTTL;maxEntrySize;sizeCalculation;noDeleteOnFetchRejection;noDeleteOnStaleGet;allowStaleOnFetchAbort;allowStaleOnFetchRejection;ignoreFetchAbort;#l;#g;#h;#u;#n;#d;#C;#B;#E;#k;#m;#b;#y;#f;#Q;#I;#x;#o;#U;static unsafeExposeInternals(t){return{starts:t.#y,ttls:t.#f,autopurgeTimers:t.#Q,sizes:t.#b,keyMap:t.#h,keyList:t.#u,valList:t.#n,next:t.#d,prev:t.#C,get head(){return t.#B},get tail(){return t.#E},free:t.#k,isBackgroundFetch:s=>t.#p(s),backgroundFetch:(s,r,i,o)=>t.#J(s,r,i,o),moveToTail:s=>t.#G(s),indexes:s=>t.#R(s),rindexes:s=>t.#T(s),isStale:s=>t.#w(s)}}get max(){return this.#e}get maxSize(){return th Line truncated
`)}var ML=class extends Error{constructor(e,t,s){super(NL(s)),this.request=e,this.headers=t,this.response=s,this.errors=s.errors,this.data=s.data,Error.captureStackTrace&&Error.captureStackTrace(this,this.constructor)}name="GraphqlResponseError";errors;data},GL=["method","baseUrl","url","headers","request","query","mediaType","operationName"],LL=["query","method","url"],DI=/\/api\/v3\/?$/;function _L(e,t,s){if(s){if(typeof t=="string"&&"query"in s)return Promise.reject(new Error('[@octokit/graphql] "query" cannot be used as variable name'));for(let o in s)if(LL.includes(o))return Promise.reject(new Error(`[@octokit/graphql] "${o}" cannot be used as variable name`))}let i=typeof t=="string"?Object.assign({query:t},s):t,r=Object.keys(i).reduce((o,a)=>GL.includes(a)?(o[a]=i[a],o):(o.variables||(o.variables={}),o.variables[a]=i[a],o),{}),n=i.baseUrl||e.endpoint.DEFAULTS.baseUrl;return DI.test(n)&&(r.url=n.replace(DI,"/api/graphql")),e(r).then(o=>{if(o.data.errors){let a={};for(let A of Object.keys(o.headers))a[A]=o.headers[A];throw new ML(r,a,o.data)}return o.data.data})}function up(e,t){let s=e.defaults(t);return Object.assign((r,n)=>_L(s,r,n),{defaults:up.bind(null,s),endpoint:s.endpoint})}var CP=up(mn,{headers:{"user-agent":`octokit-graphql.js/${UL} ${hs()}`},method:"POST",url:"/graphql"});function RI(e){return up(e,{method:"POST",url:"/graphql"})}var pp="(?:[a-zA-Z0-9_-]+)",TI="\\.",SI=new RegExp(`^${pp}${TI}${pp}${TI}${pp}$`),YL=SI.test.bind(SI);async function OL(e){let t=YL(e),s=e.startsWith("v1.")||e.startsWith("ghs_"),i=e.startsWith("ghu_");return{type:"token",token:e,tokenType:t?"app":s?"installation":i?"user-to-server":"oauth"}}function PL(e){return e.split(/\./).length===3?`bearer ${e}`:`token ${e}`}async function JL(e,t,s,i){let r=t.endpoint.merge(s,i);return r.headers.authorization=PL(e),t(r)}var FI=function(t){if(!t)throw new Error("[@octokit/auth-token] No token passed to createTokenAuth");if(typeof t!="string")throw new Error("[@octokit/auth-token] Token passed to createTokenAuth is not a string");return t=t.replace(/^(token|bearer) +/i,""),Object.assign(OL.bind(null,t),{hook:JL.bind(null,t)})};var gp="7.0.6";var UI=()=>{},HL=console.warn.bind(console),VL=console.error.bind(console);function qL(e={}){return typeof e.debug!="function"&&(e.debug=UI),typeof e.info!="function"&&(e.info=UI),typeof e.warn!="function"&&(e.warn=HL),typeof e.error!="function"&&(e.error=VL),e}var NI=`octokit-core.js/${gp} ${hs()}`,ja=class{static VERSION=gp;static defaults(t){return class extends this{constructor(...i){let r=i[0]||{};if(typeof t=="function"){super(t(r));return}super(Object.assign({},t,r,r.userAgent&&t.userAgent?{userAgent:`${r.userAgent} ${t.userAgent}`}:null))}}}static plugins=[];static plugin(...t){let s=this.plugins;return class extends this{static plugins=s.concat(t.filter(r=>!s.includes(r)))}}constructor(t={}){let s=new AI.Collection,i={baseUrl:mn.endpoint.DEFAULTS.baseUrl,headers:{},request:Object.assign({},t.request,{hook:s.bind(null,"request")}),mediaType:{previews:[],format:""}};if(i.headers["user-agent"]=t.userAgent?`${t.userAgent} ${NI}`:NI,t.baseUrl&&(i.baseUrl=t.baseUrl),t.previews&&(i.mediaType.previews=t.previews),t.timeZone&&(i.headers["time-zone"]=t.timeZone),this.request=mn.defaults(i),this.graphql=RI(this.request).defaults(i),this.log=qL(t.log),this.hook=s,t.authStrategy){let{authStrategy:n,...o}=t,a=n(Object.assign({request:this.request,log:this.log,octokit:this,octokitOptions:o},t.auth));s.wrap("request",a.hook),this.auth=a}else if(!t.auth)this.auth=async()=>({type:"unauthenticated"});else{let n=FI(t.auth);s.wrap("request",n.hook),this.auth=n}let r=this.constructor;for(let n=0;n<r.plugins.length;++n)Object.assign(this,r.plugins[n](this,t))}request;graphql;log;hook;auth};var hp="17.0.0";var WL={actions:{addCustomLabelsToSelfHostedRunnerForOrg:["POST /orgs/{org}/actions/runners/{runner_id}/labels"],addCustomLabelsToSelfHostedRunnerForRepo:["POST /repos/{owner}/{repo}/actions/runners/{runner_id}/labels"],addRepoAccessToSelfHostedRunnerGroupInOrg:["PUT /orgs/{org}/actions/runner-groups/{runner_group_id}/repositories/{repository_id}"],addSelectedRepoToOrgSecret:["PUT /orgs/{org}/actions/secrets/{secret_name}/repositories/{repository_id}"],addSelectedRepoToOrgVariable:["PUT /orgs/{org}/actions/variables/{name}/repositories/{repository_id}"],approveWorkflowRun:["POST /repos/{owner}/{repo}/actions/runs/{run_id}/approve"],cancelWorkflowRun:["POST /repos/{owner}/{repo}/actions/runs/{run_id}/cancel"],createEnvironmentVariable:["POST /repos/{owner}/{repo}/environments/{environment_name}/variables"],createHostedRunnerForOrg:["POST /orgs/{org}/actions/hosted-runners"],createOrUpdateEnvironmentSecret:["PUT /repos/{owner}/{repo}/environments/{environment_name}/secrets/{secret_name}"],createOrUpdateOrgSecret:["PUT /orgs/{org}/actions/secrets/{secret_name}"],createOrUpdateRepoSecret:["PUT /repos/{owner}/{repo}/actions/secrets/{secret_name}"],createOrgVariable:["POST /orgs/{org}/actions/variables"],cre Line truncated
`)},Y_=class{gen;threads=[];match=!1;runs=[];ids=[];constructor(e){this.gen=e}get dead(){return!this.threads.length&&!this.match&&!this.runs.length}},Uw=(e,t)=>e.ids.length!==t.ids.length||e.runs.length!==t.runs.length||e.ids.some((s,i)=>s!==t.ids[i])?!1:e.runs.every(s=>t.runs.some(i=>i.neg===s.neg&&Uw(i.state,s.state))),tw=e=>({has:new Float64Array(e),seen:new Float64Array(e),gen:0}),Lp=class{dots;dotStart;#e;constructor(e,t,s){this.dots=e,this.dotStart=t,this.#e=s}state(){return new Y_(++this.#e.gen)}done(e){return e.ids=e.threads.map(t=>t.id).sort((t,s)=>t-s),e.match&&e.ids.unshift(Mp.id),e}#t(e,t){let{seen:s}=this.#e;return s[t.id]===e.gen?!1:(s[t.id]=e.gen,!0)}#s(e,t){let{has:s}=this.#e;return s[t.id]===e.gen?!1:(s[t.id]=e.gen,e.threads.push(t),!0)}restricted(e,t){return t&&(this.dots||this.dotStart&&e===0)}add(e,t,s,i){switch(t.t){case"split":if(!this.#t(e,t))return;for(let n of t.out)this.add(e,n,s,i);return;case"neg":if(!this.#t(e,t))return;let r=this.state();return this.add(r,t.sub,s,!1),this.done(r),this.addRun(e,{t:"run",neg:t,state:r},s,i);case"star":if(this.restricted(s,i))return;this.#s(e,t)&&this.add(e,t.next,s,i);return;case"match":e.match=!0;return;default:this.#s(e,t)}}addRun(e,t,s,i){for(let r of e.runs)if(r.neg===t.neg&&Uw(r.state,t.state))return;e.runs.push(t),t.state.match||this.add(e,t.neg.next,s,i)}step(e,t,s,i){let r=this.state();for(let n of e.threads)switch(n.t){case"lit":Jp(n,t)&&this.add(r,n.next,s+1,i);break;case"any":this.restricted(s,i)||this.add(r,n.next,s+1,i);break;case"class":!this.restricted(s,i)&&n.re.test(t)&&this.add(r,n.next,s+1,i);break;case"star":this.restricted(s,i)||this.add(r,n,s+1,i)}if(!this.restricted(s,i))for(let n of e.runs){if(n.state.dead){this.addRun(r,n,s+1,i);continue}let o=this.step(n.state,t,s,!1);this.addRun(r,{t:"run",neg:n.neg,state:o},s+1,i)}return this.done(r)}},Nw=e=>{let t=e.ids.join();if(!e.runs.length)return t;let s=e.runs.map(i=>`${i.neg.id}(${Nw(i.state)})`);return`${t}|${s.sort().join("|")}`},O_=1<<18,P_=class{#e;#t=new Map;#s=0;#r;#i;#n;#a;constructor(e,t){this.#e=e,this.#n=new Lp(!1,!1,t),this.#a=new Lp(!1,!0,t)}#c(e){return{state:e,match:e.match,dead:e.dead,next:new Map}}#l(e){let t=Nw(e),s=this.#t.get(t);if(s)return s;this.#s>O_&&this.#p();let i=this.#c(e);return this.#t.set(t,i),this.#s+=t.length+1,i}#p(){this.#t.clear(),this.#s=0,this.#r=void 0,this.#i=void 0}start(e){if(e){if(this.#i)return this.#i;let s=this.#a.state();return this.#a.add(s,this.#e,0,!0),this.#i=this.#c(this.#a.done(s))}if(this.#r)return this.#r;let t=this.#n.state();return this.#n.add(t,this.#e,0,!0),this.#r=this.#l(this.#n.done(t))}next(e,t){let s=t.charCodeAt(0),i=s<128?void 0:e.next.get(t);if(i)return i;let r=e===this.#i?this.#l(this.#a.step(e.state,t,0,!0)):this.#l(this.#n.step(e.state,t,1,!0));return s<128?(e.ascii||(e.ascii=new Array(128),this.#s+=128),e.ascii[s]=r):e.next.set(t,r),this.#s++,r}},J_=e=>{let t=[];for(let s=e;s.t!=="match";s=s.next){if(s.t==="split"||s.t==="neg")return;t.push(s)}return t},H_=(e,t,s,i)=>{let r=0,n=s,o=-1,a=0;for(;n<i;){let A=e[r];if(A?.t==="star"){o=r++,a=n;continue}let c=t[n];if(A&&(A.t==="any"||A.t==="lit"&&Jp(A,c)||A.t==="class"&&A.re.test(c))){r++,n++;continue}if(o===-1)return!1;r=o+1,n=++a}for(;e[r]?.t==="star";)r++;return r===e.length},Mw=e=>{let t=0,s=0;for(let i of e){let[r,n]=V_(i);t+=r,s+=n}return[t,s]},V_=e=>{if(e.t==="star")return[0,1/0];if(e.t!=="ext")return[1,1];if(e.type==="!")return[0,1/0];let t=e.alts.map(Mw),s=Math.min(...t.map(n=>n[0])),i=Math.max(...t.map(n=>n[1])),r=i===0?0:1/0;return e.type==="@"?[s,i]:e.type==="?"?[0,i]:e.type==="*"?[0,r]:[s,r]},sw=(e,t,s)=>{for(let i=0;i<e.length;i++)if(!Jp(e[i],t[s+i]))return!1;return!0},q_=/[/\ud800-\udfff]/,W_=/[\ud800-\udfff]/,za=e=>W_.test(e)?[...e]:e,iw=e=>{if(e.includes("/"))throw new Error("can only match a single path portion, got: "+e)},rw=class{pattern;options;#e;#t;#s;#r;#i;#n;#a;#c=!1;#l=0;#p=1/0;#u=[];#g=[];#A;#m;#I=!1;#f;#h;constructor(e,t={}){if(e.includes("/"))throw new Error("can only match a single path portion, got pattern: "+e);this.pattern=e,this.options=t;let{nocase:s=!1,noext:i=!1,normalize:r}=t;this.#h=r===!0?"NFC":r||void 0;let n=/^[?*+@]\(\)$/.test(e),o=M_(e,s,i||n,this.#h),[a]=Sw(o,G_(o),0,o.length,!0);this.#h&&(a=Fw(a,this.#h));let[A,c]=L_(a,s);if(this.#e=A,this.#t=c,a.every(l=>l.t==="lit"))this.#i=a.map(l=>l.ch).join(""),s&&(this.#n=Gp(this.#i));else{let l=h=>h.t!=="lit"?void 0:s?{ch:h.ch,re:Gp(h.ch)}:{ch:h.ch};for(let h of a){let d=l(h);if(!d)break;this.#u.push(d)}for(let h=a.length-1;h>=0;h--){let d=l(a[h]);if(!d)break;this.#g.unshift(d)}this.#I=!!(this.#u.length||this.#g.length),s||(this.#A=this.#u.map(h=>h.ch).join(""),this.#m=this.#g.map(h=>h.ch).join("")),this.#a=J_(this.#e)?.slice(this.#u.length,-this.#g.length||void 0),this.#c=!!this.#a?.every(h=>h.t==="star"||h.t==="any");let[u,p]=Mw(a);this.#l=u,this.#p=p}}test(e){return this.#h?(iw(e),this.#C(e.normalize(this.#h))):q_.test(e)?(iw(e),this.#C(e,[...e])):this.#C(e,e)}testUnchecked(e) Line truncated
${i.data.body}`:r.body=i.data.body}return r.body=r.body?this.truncateReleaseNotes(r.body):void 0,r}truncateReleaseNotes(t){return t.substring(0,124999)}async createRelease(t){return this.github.rest.repos.createRelease(await this.prepareReleaseMutation(t))}async updateRelease(t){return this.github.rest.repos.updateRelease(await this.prepareReleaseMutation(t))}async finalizeRelease(t){return await this.github.rest.repos.updateRelease({owner:t.owner,repo:t.repo,release_id:t.release_id,draft:!1,make_latest:t.make_latest})}allReleases(t){let s={per_page:100,...t};return this.github.paginate.iterator(this.github.rest.repos.listReleases.endpoint.merge(s))}async listReleaseAssets(t){return this.github.paginate(this.github.rest.repos.listReleaseAssets,{...t,per_page:100})}async deleteReleaseAsset(t){await this.github.rest.repos.deleteReleaseAsset(t)}async deleteRelease(t){await this.github.rest.repos.deleteRelease(t)}async updateReleaseAsset(t){return await this.github.rest.repos.updateReleaseAsset(t)}async uploadReleaseAsset(t){return this.github.request({method:"POST",url:t.url,headers:{"content-length":`${t.size}`,"content-type":t.mime,authorization:`token ${t.token}`},data:t.data})}},N_=e=>({name:(0,Rw.basename)(e),mime:G_(e),size:(0,vw.statSync)(e).size}),G_=e=>(0,Dw.lookup)(e)||"application/octet-stream",cp=(e,t)=>t.name===e||t.name===yw(e)||t.label===e,M_=e=>{let t=e?.status??e?.response?.status,s=e?.request?.url,r=e?.message,i=typeof s=="string"&&(/\/releases\/assets\//.test(s)||/\/releases\/\d+\/assets(?:\?|$)/.test(s));return t===404&&(i||typeof r=="string"&&r.includes("update-a-release-asset"))},L_=e=>{let t=e?.status??e?.response?.status,s=e?.response?.data?.message??e?.message;return t===422&&/immutable release/i.test(String(s))},__=(e,t)=>t?`Cannot upload asset ${e} to an immutable release. GitHub only allows asset uploads before a release is published, but draft prereleases publish with the release.published event instead of release.prereleased. If you need prereleases with assets on an immutable-release repository, keep the release as a draft with draft: true, then publish it later from that draft and subscribe downstream workflows to release.published.`:`Cannot upload asset ${e} to an immutable release. GitHub only allows asset uploads before a release is published, so upload assets to a draft release before you publish it.`,Tw=async(e,t,s,r,i)=>{let[o,n]=e.github_repository.split("/"),{name:a,mime:A,size:c}=N_(r),u=s.match(/\/releases\/(\d+)\/assets/),l=u?Number(u[1]):void 0,p=i.find(m=>cp(a,m));if(p){if(e.input_overwrite_files===!1)return console.log(`Asset ${a} already exists and overwrite_files is false...`),null;console.log(`\u267B\uFE0F Deleting previously uploaded asset ${a}...`),await t.deleteReleaseAsset({asset_id:p.id||1,owner:o,repo:n})}console.log(`\u2B06\uFE0F Uploading ${a}...`);let g=new URL(s);g.searchParams.append("name",a);let h=async(m,C=3)=>{if(l!==void 0)for(let B=1;B<=C;B++){let S=(await t.listReleaseAssets({owner:o,repo:n,release_id:l})).find(m);if(S)return S;B<C&&await new Promise(G=>setTimeout(G,1e3))}},E=async()=>{let m=await(0,kw.open)(r);try{return await t.uploadReleaseAsset({url:g.toString(),size:c,mime:A,token:e.github_token,data:m.readableWebStream({type:"bytes"})})}finally{await m.close()}},f=async m=>{if(!m.name||m.name===a||!m.id)return m;console.log(`\u270F\uFE0F Restoring asset label to ${a}...`);let C=async B=>{let{data:b}=await t.updateReleaseAsset({owner:o,repo:n,asset_id:B,name:m.name,label:a});return b};try{return await C(m.id)}catch(B){if((B?.status??B?.response?.status)===404&&l!==void 0)try{let S=await h(G=>G.id===m.id||G.name===m.name);if(S)return await C(S.id)}catch(S){console.warn(`error refreshing release assets for ${a}: ${S}`)}return console.warn(`error updating release asset label for ${a}: ${B}`),m}},d=async m=>{let C=m.data;if(m.status!==201)throw new Error(`Failed to upload release asset ${a}. received status code ${m.status}
${C.message}
${JSON.stringify(C.errors)}`);let B=await f(C);return console.log(`\u2705 Uploaded ${a}`),B};try{return await d(await E())}catch(m){let C=m?.status??m?.response?.status,B=m?.response?.data;if(L_(m))throw new Error(__(a,e.input_prerelease));if(l!==void 0&&M_(m))try{let b=await h(S=>cp(a,S));if(b)return console.warn(`error updating release asset metadata for ${a}: ${m}. Matching asset is present after refresh; continuing...`),b}catch(b){console.warn(`error refreshing release assets after metadata update failure: ${b}`)}if(e.input_overwrite_files!==!1&&C===422&&B?.errors?.[0]?.code==="already_exists"&&l!==void 0){console.log(`\u26A0\uFE0F Asset ${a} already exists (race condition), refreshing assets and retrying once...`);let S=(await t.listReleaseAssets({owner:o,repo:n,release_id:l})).find(G=>cp(a,G));if(S)return await t.deleteReleaseAsset({owner:o,repo:n,asset_id:S.id}),await d(await E())}throw m}},lp=async(e,t,s=3)=>{if(s<=0)throw console.log("\u274C Too many retries. Aborting..."),new Error("Too many retries.");let[r,i]=e.github_repository.split("/"),o=Ap(e.input_tag_name)||(fo(e.github_ref)?e.github_ref.replace("refs/tags/",""):""),n=e.input_discussion_category_name,a=e.input_generate_release_notes,A=e.input_previous_tag;a&&A&&console.log(`\u{1F4DD} Generating release notes using previous tag ${A}`);try{let c=await Fw(t,r,i,o);if(c===void 0)return await xw(o,e,t,r,i,n,a,s,A);let u=c;console.log(`Found release ${u.name} (with id=${u.id})`);let l=u.id,p;e.input_target_commitish&&e.input_target_commitish!==u.target_commitish?(console.log(`Updating commit from "${u.target_commitish}" to "${e.input_target_commitish}"`),p=e.input_target_commitish):p=u.target_commitish;let g=o,h=e.input_name||u.name||o,E=ap(e)||"",f=u.body||"",d;e.input_append_body&&E&&f?d=f+`
`+E:d=E||f;let m=e.input_prerelease!==void 0?e.input_prerelease:u.prerelease,C=e.input_make_latest;return{release:(await t.updateRelease({owner:r,repo:i,release_id:l,tag_name:g,target_commitish:p,name:h,body:d,draft:u.draft,prerelease:m,discussion_category_name:n,generate_release_notes:a,make_latest:C,previous_tag_name:A})).data,created:!1}}catch(c){if(c.status!==404)throw console.log(`\u26A0\uFE0F Unexpected error fetching GitHub release for tag ${e.github_ref}: ${c}`),c;return await xw(o,e,t,r,i,n,a,s,A)}},up=async(e,t,s,r=!1,i=3)=>{if(e.input_draft===!0||s.draft===!1)return s;if(i<=0)throw console.log("\u274C Too many retries. Aborting..."),new Error("Too many retries.");let[o,n]=e.github_repository.split("/");try{let{data:a}=await t.finalizeRelease({owner:o,repo:n,release_id:s.id,make_latest:e.input_make_latest});return a}catch(a){if(console.warn(`error finalizing release: ${a}`),r&&s.draft&&W_(a)){let A=!1;try{console.log(`\u{1F9F9} Deleting draft release ${s.id} for tag ${s.tag_name} because tag creation is blocked by repository rules...`),await t.deleteRelease({owner:o,repo:n,release_id:s.id}),A=!0}catch(u){console.warn(`error deleting orphan draft release ${s.id}: ${u}`)}let c=A?`Deleted draft release ${s.id} to avoid leaving an orphaned draft release.`:`Failed to delete draft release ${s.id}; manual cleanup may still be required.`;throw new Error(`Tag creation for ${s.tag_name} is blocked by repository rules. ${c}`)}return console.log(`retrying... (${i-1} retries remaining)`),up(e,t,s,r,i-1)}},pp=async(e,t,s,r=3)=>{if(r<=0)throw console.log("\u274C Too many retries. Aborting..."),new Error("Too many retries.");let[i,o]=e.github_repository.split("/");try{return await t.listReleaseAssets({owner:i,repo:o,release_id:s.id})}catch(n){return console.warn(`error listing assets of release: ${n}`),console.log(`retrying... (${r-1} retries remaining)`),pp(e,t,s,r-1)}};async function Fw(e,t,s,r){try{let{data:i}=await e.getReleaseByTag({owner:t,repo:s,tag:r});return i}catch(i){if(i.status===404)return;throw i}}var Y_=1e3,O_=2;async function J_(e){await new Promise(t=>setTimeout(t,e))}async function P_(e,t,s,r){let i=[],o=0;for await(let n of e.allReleases({owner:t,repo:s}))if(i.push(...n.data.filter(a=>a.tag_name===r)),o+=1,o>=O_)break;return i}function H_(e,t){return t&&e.some(s=>s.id===t.id)||e.length===0?t:[...e].sort((s,r)=>s.draft!==r.draft?Number(s.draft)-Number(r.draft):s.id-r.id)[0]}async function V_(e,t,s,r,i,o){let n=Array.from(new Map(o.map(a=>[a.id,a])).values());for(let a of n)if(!(a.id===i||!a.draft||a.assets.length>0))try{console.log(`\u{1F9F9} Removing duplicate draft release ${a.id} for tag ${r}...`),await e.deleteRelease({owner:t,repo:s,release_id:a.id})}catch(A){console.warn(`error deleting duplicate release ${a.id}: ${A}`)}}async function q_(e,t,s,r,i,o){let n=Math.max(o,1);for(let a=1;a<=n;a+=1){let A;try{A=await Fw(e,t,s,r)}catch(l){console.warn(`error reloading release for tag ${r}: ${l}`)}let c=[];try{c=await P_(e,t,s,r)}catch(l){console.warn(`error listing recent releases for tag ${r}: ${l}`)}let u=H_(c,A);if(u)return u.id!==i.id&&console.log(`\u21AA\uFE0F Using release ${u.id} for tag ${r} instead of duplicate draft ${i.id}`),await V_(e,t,s,r,u.id,[i,...c]),u;a<n&&(console.log(`Release ${i.id} is not yet discoverable by tag ${r}, retrying... (${n-a} retries remaining)`),await J_(Y_))}return console.log(`\u26A0\uFE0F Continuing with newly created release ${i.id} because tag ${r} is still not discoverable`),i}async function xw(e,t,s,r,i,o,n,a,A){let c=e,u=t.input_name||e,l=ap(t),p=t.input_prerelease,g=p===!0?t.input_draft===!0:!0,h=t.input_target_commitish,E=t.input_make_latest,f="";h&&(f=` using commit "${h}"`),console.log(`\u{1F469}\u200D\u{1F3ED} Creating new GitHub release for tag ${c}${f}...`);try{let d=await s.createRelease({owner:r,repo:i,tag_name:c,name:u,body:l,draft:g,prerelease:p,target_commitish:h,discussion_category_name:o,generate_release_notes:n,make_latest:E,previous_tag_name:A}),m=await q_(s,r,i,c,d.data,a);return{release:m,created:m.id===d.data.id}}catch(d){switch(console.log(`\u26A0\uFE0F GitHub release failed with status: ${d.status}`),console.log(`${JSON.stringify(d.response.data)}`),d.status){case 403:throw console.log("Skip retry \u2014 your GitHub token/PAT does not have the required permission to create a release"),d;case 404:throw console.log("Skip retry - discussion category mismatch"),d;case 422:if(d.response?.data?.errors?.[0]?.code==="already_exists")console.log("\u26A0\uFE0F Release already exists (race condition detected), retrying to find and update existing release...");else throw console.log("Skip retry - validation failed"),d;break}return console.log(`retrying... (${a-1} retries remaining)`),lp(t,s,a-1)}}function W_(e){let t=e?.response?.data?.errors;return!Array.isArray(t)||e?.status!==422?!1:t.some(({field:s,message:r})=>s==="pre_receive"&&typeof r=="string"&&r.includes("creations being restricted"))}var Sw=require("process");async function j_(){try{ Line truncated
${r.data.body}`:i.body=r.data.body}return i.body=i.body?this.truncateReleaseNotes(i.body):void 0,i}truncateReleaseNotes(t){return t.substring(0,124999)}async createRelease(t){return this.github.rest.repos.createRelease(await this.prepareReleaseMutation(t))}async updateRelease(t){return this.github.rest.repos.updateRelease(await this.prepareReleaseMutation(t))}async finalizeRelease(t){return await this.github.rest.repos.updateRelease({owner:t.owner,repo:t.repo,release_id:t.release_id,draft:!1,make_latest:t.make_latest,discussion_category_name:t.discussion_category_name})}allReleases(t){let s={per_page:100,...t};return this.github.paginate.iterator(this.github.rest.repos.listReleases.endpoint.merge(s))}async listReleaseAssets(t){return this.github.paginate(this.github.rest.repos.listReleaseAssets,{...t,per_page:100})}async deleteReleaseAsset(t){let{release_id:s,...i}=t;try{await this.github.rest.repos.deleteReleaseAsset(i)}catch(r){if(St(r)!==404)throw r;try{await this.github.request("DELETE /repos/{owner}/{repo}/releases/{release_id}/assets/{asset_id}",t)}catch(n){throw new AggregateError([r,n],`Failed to delete release asset ${t.asset_id}. GitHub endpoint: ${Qs(r)}; release-scoped endpoint: ${Qs(n)}`)}}}async deleteRelease(t){await this.github.rest.repos.deleteRelease(t)}async updateReleaseAsset(t){return await this.github.rest.repos.updateReleaseAsset(t)}async uploadReleaseAsset(t){return this.github.request({method:"POST",url:t.url,headers:{"content-length":`${t.size}`,"content-type":t.mime,authorization:`token ${t.token}`},data:t.data})}},Z2=e=>({name:(0,xb.basename)(e),mime:K2(e),size:(0,wb.statSync)(e).size}),K2=e=>(0,yb.lookup)(e)||"application/octet-stream",Kp=(e,t)=>t.name===e||t.name===Cb(e)||t.label===e,X2=e=>{let t=St(e),s=q2(e),i=kb(e),r=typeof s=="string"&&(/\/releases\/assets\//.test(s)||/\/releases\/\d+\/assets(?:\?|$)/.test(s));return t===404&&(r||typeof i=="string"&&i.includes("update-a-release-asset"))},$2=e=>{let t=St(e),s=vb(e)?.message??kb(e);return t===422&&/immutable release/i.test(String(s))},eY=(e,t)=>t?`Cannot upload asset ${e} to an immutable release. GitHub only allows asset uploads before a release is published, but draft prereleases publish with the release.published event instead of release.prereleased. If you need prereleases with assets on an immutable-release repository, keep the release as a draft with draft: true, then publish it later from that draft and subscribe downstream workflows to release.published.`:`Cannot upload asset ${e} to an immutable release. GitHub only allows asset uploads before a release is published, so upload assets to a draft release before you publish it.`,Sb=async(e,t,s,i,r,n)=>{let[o,a]=e.github_repository.split("/"),{name:A,mime:c,size:l}=Z2(i),u=r.find(g=>Kp(A,g));if(u){if(e.input_overwrite_files===!1)return console.log(`Asset ${A} already exists and overwrite_files is false...`),null;console.log(`\u267B\uFE0F Deleting previously uploaded asset ${A}...`),await t.deleteReleaseAsset({asset_id:u.id||1,owner:o,repo:a,release_id:n})}console.log(`\u2B06\uFE0F Uploading ${A}...`);let p=new URL(s);p.searchParams.append("name",A);let h=async(g,m=3)=>{if(n!==void 0)for(let B=1;B<=m;B++){let b=(await t.listReleaseAssets({owner:o,repo:a,release_id:n})).find(g);if(b)return b;B<m&&await new Promise(U=>setTimeout(U,1e3))}},d=async()=>{let g=await(0,bb.open)(i);try{return await t.uploadReleaseAsset({url:p.toString(),size:l,mime:c,token:e.github_token,data:W2(g)})}finally{await g.close()}},E=async g=>{if(!g.name||g.name===A||!g.id)return g;console.log(`\u270F\uFE0F Restoring asset label to ${A}...`);let m=async B=>{let{data:C}=await t.updateReleaseAsset({owner:o,repo:a,asset_id:B,name:g.name,label:A});return C};try{return await m(g.id)}catch(B){if(St(B)===404&&n!==void 0)try{let b=await h(U=>U.id===g.id||U.name===g.name);if(b)return await m(b.id)}catch(b){console.warn(`error refreshing release assets for ${A}: ${b}`)}return console.warn(`error updating release asset label for ${A}: ${B}`),g}},f=async g=>{let m=g.data;if(g.status!==201)throw new Error(`Failed to upload release asset ${A}. received status code ${g.status}
${m.message}
${JSON.stringify(m.errors)}`);let B=await E(m);return console.log(`\u2705 Uploaded ${A}`),B};try{return await f(await d())}catch(g){let m=St(g);if($2(g))throw new Error(eY(A,e.input_prerelease));if(n!==void 0&&X2(g))try{let B=await h(C=>Kp(A,C));if(B)return console.warn(`error updating release asset metadata for ${A}: ${g}. Matching asset is present after refresh; continuing...`),B}catch(B){console.warn(`error refreshing release assets after metadata update failure: ${B}`)}if(e.input_overwrite_files!==!1&&m===422&&Rb(g,"already_exists")&&n!==void 0){console.log(`\u26A0\uFE0F Asset ${A} already exists (race condition), refreshing assets and retrying once...`);let C=(await t.listReleaseAssets({owner:o,repo:a,release_id:n})).find(b=>Kp(A,b));if(C)return await t.deleteReleaseAsset({owner:o,repo:a,release_id:n,asset_id:C.id}),await f(await d())}throw g}},$p=async(e,t,s=3)=>{if(s<=0)throw console.log("\u274C Too many retries. Aborting..."),new Error("Too many retries.");let[i,r]=e.github_repository.split("/"),n=Zp(e.input_tag_name)||(Sn(e.github_ref)?e.github_ref.replace("refs/tags/",""):""),o=e.input_discussion_category_name,a=e.input_generate_release_notes,A=e.input_previous_tag;a&&A&&console.log(`\u{1F4DD} Generating release notes using previous tag ${A}`);let c;try{c=await Fb(t,i,r,n,s)}catch(l){if(St(l)===404){let u=z2(i,r,l);throw console.log(`\u26A0\uFE0F ${u}`),new Xp(u,l)}throw console.log(`\u26A0\uFE0F Unexpected error fetching GitHub release for tag ${e.github_ref}: ${l}`),l}if(c===void 0)return await Ib(n,e,t,i,r,o,a,s,A);try{let l=c;console.log(`Found release ${l.name} (with id=${l.id})`);let u=l.id,p;e.input_target_commitish&&e.input_target_commitish!==l.target_commitish?(console.log(`Updating commit from "${l.target_commitish}" to "${e.input_target_commitish}"`),p=e.input_target_commitish):p=l.target_commitish;let h=n,d=e.input_name||l.name||n,E=zp(e)||"",f=l.body||"",g;e.input_append_body&&E&&f?g=f+`
`+E:g=E||f;let m=e.input_prerelease!==void 0?e.input_prerelease:l.prerelease,B=e.input_make_latest;return{release:(await t.updateRelease({owner:i,repo:r,release_id:u,tag_name:h,target_commitish:p,name:d,body:g,draft:l.draft,prerelease:m,discussion_category_name:o,generate_release_notes:a,make_latest:B,previous_tag_name:A})).data,created:!1}}catch(l){if(l instanceof fA)throw l;if(St(l)!==404)throw console.log(`\u26A0\uFE0F Unexpected error fetching GitHub release for tag ${e.github_ref}: ${l}`),l;return await Ib(n,e,t,i,r,o,a,s,A)}},eg=async(e,t,s,i=!1,r=3)=>{if(e.input_draft===!0||s.draft===!1)return s;if(r<=0)throw console.log("\u274C Too many retries. Aborting..."),new Error("Too many retries.");let[n,o]=e.github_repository.split("/");try{let{data:a}=await t.finalizeRelease({owner:n,repo:o,release_id:s.id,make_latest:e.input_make_latest,discussion_category_name:e.input_discussion_category_name});return a}catch(a){if(console.warn(`error finalizing release: ${a}`),i&&s.draft&&rY(a)){let A=!1;try{console.log(`\u{1F9F9} Deleting draft release ${s.id} for tag ${s.tag_name} because tag creation is blocked by repository rules...`),await t.deleteRelease({owner:n,repo:o,release_id:s.id}),A=!0}catch(l){console.warn(`error deleting orphan draft release ${s.id}: ${l}`)}let c=A?`Deleted draft release ${s.id} to avoid leaving an orphaned draft release.`:`Failed to delete draft release ${s.id}; manual cleanup may still be required.`;throw new Error(`Tag creation for ${s.tag_name} is blocked by repository rules. ${c}`)}return console.log(`retrying... (${r-1} retries remaining)`),eg(e,t,s,i,r-1)}},tg=async(e,t,s,i=3)=>{if(i<=0)throw console.log("\u274C Too many retries. Aborting..."),new Error("Too many retries.");let[r,n]=e.github_repository.split("/");try{return await t.listReleaseAssets({owner:r,repo:n,release_id:s.id})}catch(o){return console.warn(`error listing assets of release: ${o}`),console.log(`retrying... (${i-1} retries remaining)`),tg(e,t,s,i-1)}};async function Fb(e,t,s,i,r=1){try{let{data:o}=await e.getReleaseByTag({owner:t,repo:s,tag:i});return o}catch(o){if(St(o)!==404)throw o}if(r<=0)return;let n=Math.max(1,r);for(let o=0;o<n;o+=1){let a=await Mb(e,t,s,i),A=Gb(a,void 0);if(A)return A;o<n-1&&await Nb(Ub)}}var Ub=1e3,tY=2;async function Nb(e){await new Promise(t=>setTimeout(t,e))}async function Mb(e,t,s,i){let r=[],n=0;for await(let o of e.allReleases({owner:t,repo:s}))if(r.push(...o.data.filter(a=>a.tag_name===i)),n+=1,n>=tY)break;return r}function Gb(e,t){return t&&e.some(s=>s.id===t.id)||e.length===0?t:[...e].sort((s,i)=>s.draft!==i.draft?Number(s.draft)-Number(i.draft):s.id-i.id)[0]}async function sY(e,t,s,i,r,n){if(!(n.id===r||!n.draft||n.assets.length>0))try{console.log(`\u{1F9F9} Removing duplicate draft release ${n.id} for tag ${i}...`),await e.deleteRelease({owner:t,repo:s,release_id:n.id})}catch(o){console.warn(`error deleting duplicate release ${n.id}: ${o}`)}}async function iY(e,t,s,i,r,n){let o=Math.max(n,1);for(let a=1;a<=o;a+=1){let A;try{A=await Fb(e,t,s,i,0)}catch(u){console.warn(`error reloading release for tag ${i}: ${u}`)}let c=[];try{c=await Mb(e,t,s,i)}catch(u){console.warn(`error listing recent releases for tag ${i}: ${u}`)}let l=Gb(c,A);if(l){l.id!==r.id&&console.log(`\u21AA\uFE0F Using release ${l.id} for tag ${i} instead of duplicate draft ${r.id}`);let u=c.find(p=>p.id===r.id);return u&&await sY(e,t,s,i,l.id,u),l}a<o&&(console.log(`Release ${r.id} is not yet discoverable by tag ${i}, retrying... (${o-a} retries remaining)`),await Nb(Ub))}return console.log(`\u26A0\uFE0F Continuing with newly created release ${r.id} because tag ${i} is still not discoverable`),r}async function Ib(e,t,s,i,r,n,o,a,A){let c=e,l=t.input_name||e,u=zp(t),p=t.input_prerelease,h=p===!0?t.input_draft===!0:!0,d=t.input_target_commitish,E=t.input_make_latest,f="";d&&(f=` using commit "${d}"`),console.log(`\u{1F469}\u200D\u{1F3ED} Creating new GitHub release for tag ${c}${f}...`);try{let g=await s.createRelease({owner:i,repo:r,tag_name:c,name:l,body:u,draft:h,prerelease:p,target_commitish:d,discussion_category_name:n,generate_release_notes:o,make_latest:E,previous_tag_name:A}),m=await iY(s,i,r,c,g.data,a);return{release:m,created:m.id===g.data.id}}catch(g){let m=St(g);switch(console.log(`\u26A0\uFE0F GitHub release failed with status: ${m}`),console.log(Qs(g)),m){case 403:throw console.log("Skip retry \u2014 your GitHub token/PAT does not have the required permission to create a release"),g;case 404:let B=j2(i,r,n,g);throw console.log(`Skip retry \u2014 ${B}`),new fA(B,g);case 422:if(Rb(g,"already_exists"))console.log("\u26A0\uFE0F Release already exists (race condition detected), retrying to find and update existing release...");else throw console.log("Skip retry - validation failed"),g;break}return console.log(`retrying... (${a-1} retries remaining)`),$p(t,s,a-1)}}function rY(e){return St(e)!==422?!1:Db(e).some(t=>{let s=Tt(t);return s?.field==="pre_receive"&&typeof s.message=="string"&&s.message.includes( Line truncated
/*! Bundled license information:
undici/lib/web/fetch/body.js:
+963 -996
View File
File diff suppressed because it is too large. Load diff
+18 -18
View File
@@ -1,17 +1,17 @@
{
"name": "action-gh-release",
"version": "2.6.0",
"version": "3.0.4",
"private": true,
"description": "GitHub Action for creating GitHub Releases",
"main": "lib/main.js",
"scripts": {
"build": "esbuild src/main.ts --bundle --platform=node --format=cjs --target=node20 --outfile=dist/index.js --minify",
"build-debug": "esbuild src/main.ts --bundle --platform=node --format=cjs --target=node20 --outfile=dist/index.js --sourcemap --keep-names",
"build": "esbuild src/main.ts --bundle --platform=node --format=cjs --target=node24 --outfile=dist/index.js --minify",
"build-debug": "esbuild src/main.ts --bundle --platform=node --format=cjs --target=node24 --outfile=dist/index.js --sourcemap --keep-names",
"typecheck": "tsc --noEmit",
"test": "vitest --coverage",
"fmt": "prettier --write \"src/**/*.ts\" \"__tests__/**/*.ts\"",
"fmtcheck": "prettier --check \"src/**/*.ts\" \"__tests__/**/*.ts\"",
"updatetag": "git tag -d v2 && git push origin :v2 && git tag -a v2 -m '' && git push origin v2"
"updatetag": "git tag -d v3 >/dev/null 2>&1 || true; git push origin :v3 >/dev/null 2>&1 || true; git tag -a v3 -m '' && git push origin v3"
},
"repository": {
"type": "git",
@@ -21,24 +21,24 @@
"actions"
],
"author": "softprops",
"engines": {
"node": ">=24"
},
"dependencies": {
"@actions/core": "^3.0.0",
"@actions/github": "^9.0.0",
"@octokit/plugin-retry": "^8.1.0",
"@octokit/plugin-throttling": "^11.0.3",
"glob": "^13.0.6",
"@actions/core": "^3.0.1",
"@actions/github": "^9.1.1",
"@octokit/plugin-retry": "^8.1.1",
"@octokit/plugin-throttling": "^11.0.5",
"glob": "^14.0.3",
"mime-types": "^3.0.2"
},
"devDependencies": {
"@types/glob": "^9.0.0",
"@types/mime-types": "^3.0.1",
"@types/node": "^20.19.37",
"@vitest/coverage-v8": "^4.1.0",
"esbuild": "^0.27.3",
"prettier": "3.8.1",
"ts-node": "^10.9.2",
"typescript": "^5.9.3",
"typescript-formatter": "^7.2.2",
"vitest": "^4.0.4"
"@types/node": "^24",
"@vitest/coverage-v8": "^5.0.5",
"esbuild": "^0.28.2",
"prettier": "3.9.10",
"typescript": "^7.0.2",
"vitest": "^5.0.0"
}
}
+252 -89
View File
@@ -1,12 +1,63 @@
import { GitHub } from '@actions/github/lib/utils';
import { statSync } from 'fs';
import { open } from 'fs/promises';
import { open, type FileHandle } from 'fs/promises';
import { lookup } from 'mime-types';
import { basename } from 'path';
import { alignAssetName, Config, isTag, normalizeTagName, releaseBody } from './util';
import { alignAssetName, Config, errorMessage, isTag, normalizeTagName, releaseBody } from './util';
type GitHub = InstanceType<typeof GitHub>;
type UploadChunk = ArrayBuffer | Uint8Array<ArrayBufferLike>;
type UploadBody = ReadableStream<Uint8Array<ArrayBufferLike>>;
type UnknownRecord = Record<string, unknown>;
const asRecord = (value: unknown): UnknownRecord | undefined =>
typeof value === 'object' && value !== null ? (value as UnknownRecord) : undefined;
const getErrorStatus = (error: unknown): number | undefined => {
const errorRecord = asRecord(error);
if (typeof errorRecord?.status === 'number') {
return errorRecord.status;
}
const response = asRecord(errorRecord?.response);
return typeof response?.status === 'number' ? response.status : undefined;
};
const getResponseData = (error: unknown): UnknownRecord | undefined => {
const response = asRecord(asRecord(error)?.response);
return asRecord(response?.data);
};
const getErrorMessage = (error: unknown): string | undefined => {
const message = asRecord(error)?.message;
return typeof message === 'string' ? message : undefined;
};
const getRequestUrl = (error: unknown): string | undefined => {
const request = asRecord(asRecord(error)?.request);
return typeof request?.url === 'string' ? request.url : undefined;
};
const getValidationErrors = (error: unknown): unknown[] => {
const errors = getResponseData(error)?.errors;
return Array.isArray(errors) ? errors : [];
};
const hasValidationErrorCode = (error: unknown, code: string): boolean =>
asRecord(getValidationErrors(error)[0])?.code === code;
const fileUploadStream = (fileHandle: FileHandle): UploadBody => {
const source = fileHandle.readableWebStream() as ReadableStream<UploadChunk>;
return source.pipeThrough(
new TransformStream<UploadChunk, Uint8Array<ArrayBufferLike>>({
transform(chunk, controller) {
controller.enqueue(chunk instanceof Uint8Array ? chunk : new Uint8Array(chunk));
},
}),
);
};
export interface ReleaseAsset {
name: string;
mime: string;
@@ -54,6 +105,43 @@ type ReleaseMutationParams = {
previous_tag_name?: string;
};
class ReleaseCreationError extends Error {
readonly status = 404;
constructor(message: string, cause: unknown) {
super(message, { cause });
this.name = 'ReleaseCreationError';
}
}
class ReleaseAccessError extends Error {
readonly status = 404;
constructor(message: string, cause: unknown) {
super(message, { cause });
this.name = 'ReleaseAccessError';
}
}
const repositoryAccessGuidance = (owner: string, repo: string): string =>
`Verify that ${owner}/${repo} exists under the expected owner, the token can access it, the repository is selected when using a fine-grained PAT, and the token has Contents: write permission.`;
const releaseCreation404Message = (
owner: string,
repo: string,
discussionCategory: string | undefined,
error: unknown,
): string => {
const discussionGuidance = discussionCategory
? ` Also verify that Discussions and the requested category "${discussionCategory}" are enabled.`
: '';
return `GitHub returned 404 while creating the release. ${repositoryAccessGuidance(owner, repo)}${discussionGuidance} GitHub response: ${errorMessage(error)}`;
};
const releaseLookup404Message = (owner: string, repo: string, error: unknown): string =>
`GitHub returned 404 while checking existing releases. ${repositoryAccessGuidance(owner, repo)} GitHub response: ${errorMessage(error)}`;
export interface Releaser {
getReleaseByTag(params: { owner: string; repo: string; tag: string }): Promise<{ data: Release }>;
@@ -71,6 +159,7 @@ export interface Releaser {
repo: string;
release_id: number;
make_latest: 'true' | 'false' | 'legacy' | undefined;
discussion_category_name: string | undefined;
}): Promise<{ data: Release }>;
allReleases(params: { owner: string; repo: string }): AsyncIterable<{ data: Release[] }>;
@@ -81,7 +170,12 @@ export interface Releaser {
release_id: number;
}): Promise<Array<{ id: number; name: string; label?: string | null; [key: string]: any }>>;
deleteReleaseAsset(params: { owner: string; repo: string; asset_id: number }): Promise<void>;
deleteReleaseAsset(params: {
owner: string;
repo: string;
release_id: number;
asset_id: number;
}): Promise<void>;
deleteRelease(params: { owner: string; repo: string; release_id: number }): Promise<void>;
@@ -98,7 +192,7 @@ export interface Releaser {
size: number;
mime: string;
token: string;
data: any;
data: UploadBody;
}): Promise<{ status: number; data: any }>;
}
@@ -181,6 +275,7 @@ export class GitHubReleaser implements Releaser {
repo: string;
release_id: number;
make_latest: 'true' | 'false' | 'legacy' | undefined;
discussion_category_name: string | undefined;
}) {
return await this.github.rest.repos.updateRelease({
owner: params.owner,
@@ -188,6 +283,7 @@ export class GitHubReleaser implements Releaser {
release_id: params.release_id,
draft: false,
make_latest: params.make_latest,
discussion_category_name: params.discussion_category_name,
});
}
@@ -212,9 +308,31 @@ export class GitHubReleaser implements Releaser {
async deleteReleaseAsset(params: {
owner: string;
repo: string;
release_id: number;
asset_id: number;
}): Promise<void> {
await this.github.rest.repos.deleteReleaseAsset(params);
const { release_id, ...githubParams } = params;
try {
await this.github.rest.repos.deleteReleaseAsset(githubParams);
} catch (error: unknown) {
if (getErrorStatus(error) !== 404) {
throw error;
}
try {
await this.github.request(
'DELETE /repos/{owner}/{repo}/releases/{release_id}/assets/{asset_id}',
params,
);
} catch (fallbackError: unknown) {
throw new AggregateError(
[error, fallbackError],
`Failed to delete release asset ${params.asset_id}. GitHub endpoint: ${errorMessage(
error,
)}; release-scoped endpoint: ${errorMessage(fallbackError)}`,
);
}
}
}
async deleteRelease(params: { owner: string; repo: string; release_id: number }): Promise<void> {
@@ -236,7 +354,7 @@ export class GitHubReleaser implements Releaser {
size: number;
mime: string;
token: string;
data: any;
data: UploadBody;
}): Promise<{ status: number; data: any }> {
return this.github.request({
method: 'POST',
@@ -268,10 +386,10 @@ const releaseAssetMatchesName = (
asset: { name: string; label?: string | null },
): boolean => asset.name === name || asset.name === alignAssetName(name) || asset.label === name;
const isReleaseAssetUpdateNotFound = (error: any): boolean => {
const errorStatus = error?.status ?? error?.response?.status;
const requestUrl = error?.request?.url;
const errorMessage = error?.message;
const isReleaseAssetUpdateNotFound = (error: unknown): boolean => {
const errorStatus = getErrorStatus(error);
const requestUrl = getRequestUrl(error);
const message = getErrorMessage(error);
const isReleaseAssetRequest =
typeof requestUrl === 'string' &&
(/\/releases\/assets\//.test(requestUrl) || /\/releases\/\d+\/assets(?:\?|$)/.test(requestUrl));
@@ -279,15 +397,15 @@ const isReleaseAssetUpdateNotFound = (error: any): boolean => {
return (
errorStatus === 404 &&
(isReleaseAssetRequest ||
(typeof errorMessage === 'string' && errorMessage.includes('update-a-release-asset')))
(typeof message === 'string' && message.includes('update-a-release-asset')))
);
};
const isImmutableReleaseAssetUploadFailure = (error: any): boolean => {
const errorStatus = error?.status ?? error?.response?.status;
const errorMessage = error?.response?.data?.message ?? error?.message;
const isImmutableReleaseAssetUploadFailure = (error: unknown): boolean => {
const errorStatus = getErrorStatus(error);
const message = getResponseData(error)?.message ?? getErrorMessage(error);
return errorStatus === 422 && /immutable release/i.test(String(errorMessage));
return errorStatus === 422 && /immutable release/i.test(String(message));
};
const immutableReleaseAssetUploadMessage = (
@@ -304,11 +422,10 @@ export const upload = async (
url: string,
path: string,
currentAssets: Array<{ id: number; name: string; label?: string | null }>,
releaseId: number,
): Promise<any> => {
const [owner, repo] = config.github_repository.split('/');
const { name, mime, size } = asset(path);
const releaseIdMatch = url.match(/\/releases\/(\d+)\/assets/);
const releaseId = releaseIdMatch ? Number(releaseIdMatch[1]) : undefined;
const currentAsset = currentAssets.find(
// GitHub can rewrite uploaded asset names, so compare against both the raw name
// GitHub returns and the restored label we set when available.
@@ -324,6 +441,7 @@ export const upload = async (
asset_id: currentAsset.id || 1,
owner,
repo,
release_id: releaseId,
});
}
}
@@ -364,7 +482,7 @@ export const upload = async (
size,
mime,
token: config.github_token,
data: fh.readableWebStream({ type: 'bytes' }),
data: fileUploadStream(fh),
});
} finally {
await fh.close();
@@ -396,8 +514,8 @@ export const upload = async (
try {
return await updateAssetLabel(uploadedAsset.id);
} catch (error: any) {
const errorStatus = error?.status ?? error?.response?.status;
} catch (error: unknown) {
const errorStatus = getErrorStatus(error);
if (errorStatus === 404 && releaseId !== undefined) {
try {
@@ -434,9 +552,8 @@ export const upload = async (
try {
return await handleUploadedAsset(await uploadAsset());
} catch (error: any) {
const errorStatus = error?.status ?? error?.response?.status;
const errorData = error?.response?.data;
} catch (error: unknown) {
const errorStatus = getErrorStatus(error);
if (isImmutableReleaseAssetUploadFailure(error)) {
throw new Error(immutableReleaseAssetUploadMessage(name, config.input_prerelease));
@@ -464,7 +581,7 @@ export const upload = async (
if (
config.input_overwrite_files !== false &&
errorStatus === 422 &&
errorData?.errors?.[0]?.code === 'already_exists' &&
hasValidationErrorCode(error, 'already_exists') &&
releaseId !== undefined
) {
console.log(
@@ -482,6 +599,7 @@ export const upload = async (
await releaser.deleteReleaseAsset({
owner,
repo,
release_id: releaseId,
asset_id: latestAsset.id,
});
return await handleUploadedAsset(await uploadAsset());
@@ -514,23 +632,36 @@ export const release = async (
if (generate_release_notes && previous_tag_name) {
console.log(`📝 Generating release notes using previous tag ${previous_tag_name}`);
}
let _release: Release | undefined;
try {
const _release: Release | undefined = await findTagFromReleases(releaser, owner, repo, tag);
if (_release === undefined) {
return await createRelease(
tag,
config,
releaser,
owner,
repo,
discussion_category_name,
generate_release_notes,
maxRetries,
previous_tag_name,
);
_release = await findTagFromReleases(releaser, owner, repo, tag, maxRetries);
} catch (error) {
if (getErrorStatus(error) === 404) {
const diagnostic = releaseLookup404Message(owner, repo, error);
console.log(`⚠️ ${diagnostic}`);
throw new ReleaseAccessError(diagnostic, error);
}
console.log(
`⚠️ Unexpected error fetching GitHub release for tag ${config.github_ref}: ${error}`,
);
throw error;
}
if (_release === undefined) {
return await createRelease(
tag,
config,
releaser,
owner,
repo,
discussion_category_name,
generate_release_notes,
maxRetries,
previous_tag_name,
);
}
try {
let existingRelease: Release = _release!;
console.log(`Found release ${existingRelease.name} (with id=${existingRelease.id})`);
@@ -588,7 +719,10 @@ export const release = async (
created: false,
};
} catch (error) {
if (error.status !== 404) {
if (error instanceof ReleaseCreationError) {
throw error;
}
if (getErrorStatus(error) !== 404) {
console.log(
`⚠️ Unexpected error fetching GitHub release for tag ${config.github_ref}: ${error}`,
);
@@ -641,6 +775,7 @@ export const finalizeRelease = async (
repo,
release_id: release.id,
make_latest: config.input_make_latest,
discussion_category_name: config.input_discussion_category_name,
});
return data;
@@ -715,14 +850,16 @@ export const listReleaseAssets = async (
/**
* Finds a release by tag name.
*
* Uses the direct getReleaseByTag API for O(1) lookup instead of iterating
* through all releases. This also avoids GitHub's API pagination limit of
* 10000 results which would cause failures for repositories with many releases.
* Uses the direct getReleaseByTag API for O(1) lookup. Because GitHub does not
* expose draft releases through that endpoint, a 404 falls back to a bounded
* scan of recent releases and briefly retries in case the listing is not yet
* consistent.
*
* @param releaser - The GitHub API wrapper for release operations
* @param owner - The owner of the repository
* @param repo - The name of the repository
* @param tag - The tag name to search for
* @param listingAttempts - The maximum number of listing attempts after a direct 404
* @returns The release with the given tag name, or undefined if no release with that tag name is found
*/
export async function findTagFromReleases(
@@ -730,18 +867,35 @@ export async function findTagFromReleases(
owner: string,
repo: string,
tag: string,
listingAttempts: number = 1,
): Promise<Release | undefined> {
try {
const { data: release } = await releaser.getReleaseByTag({ owner, repo, tag });
return release;
} catch (error) {
// Release not found (404) or other error - return undefined to allow creation
if (error.status === 404) {
return undefined;
if (getErrorStatus(error) !== 404) {
throw error;
}
// Re-throw unexpected errors
throw error;
}
if (listingAttempts <= 0) {
return undefined;
}
const attempts = Math.max(1, listingAttempts);
for (let attempt = 0; attempt < attempts; attempt += 1) {
const recentReleases = await recentReleasesByTag(releaser, owner, repo, tag);
const canonicalRelease = pickCanonicalRelease(recentReleases, undefined);
if (canonicalRelease) {
return canonicalRelease;
}
if (attempt < attempts - 1) {
await sleep(CREATED_RELEASE_DISCOVERY_RETRY_DELAY_MS);
}
}
return undefined;
}
const CREATED_RELEASE_DISCOVERY_RETRY_DELAY_MS = 1000;
@@ -793,33 +947,31 @@ function pickCanonicalRelease(
})[0];
}
async function cleanupDuplicateDraftReleases(
async function cleanupCreatedDuplicateDraftRelease(
releaser: Releaser,
owner: string,
repo: string,
tag: string,
canonicalReleaseId: number,
releases: Release[],
createdRelease: Release,
): Promise<void> {
const uniqueReleases = Array.from(
new Map(releases.map((release) => [release.id, release])).values(),
);
if (
createdRelease.id === canonicalReleaseId ||
!createdRelease.draft ||
createdRelease.assets.length > 0
) {
return;
}
for (const duplicate of uniqueReleases) {
if (duplicate.id === canonicalReleaseId || !duplicate.draft || duplicate.assets.length > 0) {
continue;
}
try {
console.log(`🧹 Removing duplicate draft release ${duplicate.id} for tag ${tag}...`);
await releaser.deleteRelease({
owner,
repo,
release_id: duplicate.id,
});
} catch (error) {
console.warn(`error deleting duplicate release ${duplicate.id}: ${error}`);
}
try {
console.log(`🧹 Removing duplicate draft release ${createdRelease.id} for tag ${tag}...`);
await releaser.deleteRelease({
owner,
repo,
release_id: createdRelease.id,
});
} catch (error) {
console.warn(`error deleting duplicate release ${createdRelease.id}: ${error}`);
}
}
@@ -836,7 +988,7 @@ async function canonicalizeCreatedRelease(
for (let attempt = 1; attempt <= attempts; attempt += 1) {
let releaseByTag: Release | undefined;
try {
releaseByTag = await findTagFromReleases(releaser, owner, repo, tag);
releaseByTag = await findTagFromReleases(releaser, owner, repo, tag, 0);
} catch (error) {
console.warn(`error reloading release for tag ${tag}: ${error}`);
}
@@ -856,10 +1008,19 @@ async function canonicalizeCreatedRelease(
);
}
await cleanupDuplicateDraftReleases(releaser, owner, repo, tag, canonicalRelease.id, [
createdRelease,
...recentReleases,
]);
const refreshedCreatedRelease = recentReleases.find(
(release) => release.id === createdRelease.id,
);
if (refreshedCreatedRelease) {
await cleanupCreatedDuplicateDraftRelease(
releaser,
owner,
repo,
tag,
canonicalRelease.id,
refreshedCreatedRelease,
);
}
return canonicalRelease;
}
@@ -929,12 +1090,13 @@ async function createRelease(
release: canonicalRelease,
created: canonicalRelease.id === createdRelease.data.id,
};
} catch (error) {
} catch (error: unknown) {
const errorStatus = getErrorStatus(error);
// presume a race with competing matrix runs
console.log(`⚠️ GitHub release failed with status: ${error.status}`);
console.log(`${JSON.stringify(error.response.data)}`);
console.log(`⚠️ GitHub release failed with status: ${errorStatus}`);
console.log(errorMessage(error));
switch (error.status) {
switch (errorStatus) {
case 403:
console.log(
'Skip retry — your GitHub token/PAT does not have the required permission to create a release',
@@ -942,13 +1104,13 @@ async function createRelease(
throw error;
case 404:
console.log('Skip retry - discussion category mismatch');
throw error;
const diagnostic = releaseCreation404Message(owner, repo, discussion_category_name, error);
console.log(`Skip retry — ${diagnostic}`);
throw new ReleaseCreationError(diagnostic, error);
case 422:
// Check if this is a race condition with "already_exists" error
const errorData = error.response?.data;
if (errorData?.errors?.[0]?.code === 'already_exists') {
if (hasValidationErrorCode(error, 'already_exists')) {
console.log(
'⚠️ Release already exists (race condition detected), retrying to find and update existing release...',
);
@@ -965,16 +1127,17 @@ async function createRelease(
}
}
function isTagCreationBlockedError(error: any): boolean {
const errors = error?.response?.data?.errors;
if (!Array.isArray(errors) || error?.status !== 422) {
function isTagCreationBlockedError(error: unknown): boolean {
if (getErrorStatus(error) !== 422) {
return false;
}
return errors.some(
({ field, message }: { field?: string; message?: string }) =>
field === 'pre_receive' &&
typeof message === 'string' &&
message.includes('creations being restricted'),
);
return getValidationErrors(error).some((validationError) => {
const errorRecord = asRecord(validationError);
return (
errorRecord?.field === 'pre_receive' &&
typeof errorRecord.message === 'string' &&
errorRecord.message.includes('creations being restricted')
);
});
}
+2 -113
View File
@@ -1,114 +1,3 @@
import { setFailed, setOutput } from '@actions/core';
import { getOctokit } from '@actions/github';
import { GitHubReleaser, release, finalizeRelease, upload, listReleaseAssets } from './github';
import { isTag, parseConfig, paths, unmatchedPatterns, uploadUrl } from './util';
import { run } from './run';
import { env } from 'process';
async function run() {
try {
const config = parseConfig(env);
if (!config.input_tag_name && !isTag(config.github_ref) && !config.input_draft) {
throw new Error(`⚠️ GitHub Releases requires a tag`);
}
if (config.input_files) {
const patterns = unmatchedPatterns(config.input_files, config.input_working_directory);
patterns.forEach((pattern) => {
if (config.input_fail_on_unmatched_files) {
throw new Error(`⚠️ Pattern '${pattern}' does not match any files.`);
} else {
console.warn(`🤔 Pattern '${pattern}' does not match any files.`);
}
});
if (patterns.length > 0 && config.input_fail_on_unmatched_files) {
throw new Error(`⚠️ There were unmatched files`);
}
}
// const oktokit = GitHub.plugin(
// require("@octokit/plugin-throttling"),
// require("@octokit/plugin-retry")
// );
const gh = getOctokit(config.github_token, {
//new oktokit(
throttle: {
onRateLimit: (retryAfter, options) => {
console.warn(`Request quota exhausted for request ${options.method} ${options.url}`);
if (options.request.retryCount === 0) {
// only retries once
console.log(`Retrying after ${retryAfter} seconds!`);
return true;
}
},
onAbuseLimit: (retryAfter, options) => {
// does not retry, only logs a warning
console.warn(`Abuse detected for request ${options.method} ${options.url}`);
},
},
});
//);
const releaser = new GitHubReleaser(gh);
const releaseResult = await release(config, releaser);
let rel = releaseResult.release;
const releaseWasCreated = releaseResult.created;
let uploadedAssetIds: Set<number> = new Set();
if (config.input_files && config.input_files.length > 0) {
const files = paths(config.input_files, config.input_working_directory);
if (files.length == 0) {
if (config.input_fail_on_unmatched_files) {
throw new Error(`⚠️ ${config.input_files} does not include a valid file.`);
} else {
console.warn(`🤔 ${config.input_files} does not include a valid file.`);
}
}
const currentAssets = rel.assets;
const uploadFile = async (path: string) => {
const json = await upload(config, releaser, uploadUrl(rel.upload_url), path, currentAssets);
return json ? (json.id as number) : undefined;
};
let results: (number | undefined)[];
if (!config.input_preserve_order) {
results = await Promise.all(files.map(uploadFile));
} else {
results = [];
for (const path of files) {
results.push(await uploadFile(path));
}
}
uploadedAssetIds = new Set(results.filter((id): id is number => id !== undefined));
}
console.log('Finalizing release...');
rel = await finalizeRelease(config, releaser, rel, releaseWasCreated);
// Draft releases use temporary "untagged-..." URLs for assets.
// URLs will be changed to correct ones once the release is published.
console.log('Getting assets list...');
{
let assets: any[] = [];
if (uploadedAssetIds.size > 0) {
const updatedAssets = await listReleaseAssets(config, releaser, rel);
assets = updatedAssets
.filter((a) => uploadedAssetIds.has(a.id))
.map((a) => {
const { uploader, ...rest } = a;
return rest;
});
}
setOutput('assets', assets);
}
console.log(`🎉 Release ready at ${rel.html_url}`);
setOutput('url', rel.html_url);
setOutput('id', rel.id.toString());
setOutput('upload_url', rel.upload_url);
} catch (error) {
setFailed(error.message);
}
}
run();
void run();
+104
View File
@@ -0,0 +1,104 @@
import { setFailed, setOutput } from '@actions/core';
import { getOctokit } from '@actions/github';
import { env } from 'process';
import { GitHubReleaser, release, finalizeRelease, upload, listReleaseAssets } from './github';
import { errorMessage, isTag, parseConfig, paths, unmatchedPatterns, uploadUrl } from './util';
export async function run(): Promise<void> {
try {
const config = parseConfig(env);
if (!config.input_tag_name && !isTag(config.github_ref) && !config.input_draft) {
throw new Error(`⚠️ GitHub Releases requires a tag`);
}
if (config.input_files) {
const patterns = unmatchedPatterns(config.input_files, config.input_working_directory);
patterns.forEach((pattern) => {
if (config.input_fail_on_unmatched_files) {
throw new Error(`⚠️ Pattern '${pattern}' does not match any files.`);
} else {
console.warn(`🤔 Pattern '${pattern}' does not match any files.`);
}
});
}
const gh = getOctokit(config.github_token, {
throttle: {
onRateLimit: (retryAfter, options) => {
console.warn(`Request quota exhausted for request ${options.method} ${options.url}`);
if (options.request.retryCount === 0) {
console.log(`Retrying after ${retryAfter} seconds!`);
return true;
}
},
onAbuseLimit: (_retryAfter, options) => {
console.warn(`Abuse detected for request ${options.method} ${options.url}`);
},
},
});
const releaser = new GitHubReleaser(gh);
const releaseResult = await release(config, releaser);
let rel = releaseResult.release;
const releaseWasCreated = releaseResult.created;
let uploadedAssetIds: Set<number> = new Set();
if (config.input_files && config.input_files.length > 0) {
const files = paths(config.input_files, config.input_working_directory);
if (files.length === 0) {
if (config.input_fail_on_unmatched_files) {
throw new Error(`⚠️ ${config.input_files} does not include a valid file.`);
} else {
console.warn(`🤔 ${config.input_files} does not include a valid file.`);
}
}
const currentAssets = rel.assets;
const uploadFile = async (path: string) => {
const json = await upload(
config,
releaser,
uploadUrl(rel.upload_url),
path,
currentAssets,
rel.id,
);
return json ? (json.id as number) : undefined;
};
let results: (number | undefined)[];
if (!config.input_preserve_order) {
results = await Promise.all(files.map(uploadFile));
} else {
results = [];
for (const path of files) {
results.push(await uploadFile(path));
}
}
uploadedAssetIds = new Set(results.filter((id): id is number => id !== undefined));
}
console.log('Finalizing release...');
rel = await finalizeRelease(config, releaser, rel, releaseWasCreated);
// Draft releases use temporary "untagged-..." URLs for assets.
// URLs will be changed to correct ones once the release is published.
console.log('Getting assets list...');
let assets: any[] = [];
if (uploadedAssetIds.size > 0) {
const updatedAssets = await listReleaseAssets(config, releaser, rel);
assets = updatedAssets
.filter((asset) => uploadedAssetIds.has(asset.id))
.map((asset) => {
const { uploader, ...rest } = asset;
return rest;
});
}
setOutput('assets', assets);
console.log(`🎉 Release ready at ${rel.html_url}`);
setOutput('url', rel.html_url);
setOutput('id', rel.id.toString());
setOutput('upload_url', rel.upload_url);
} catch (error: unknown) {
setFailed(errorMessage(error));
}
}
+18
View File
@@ -28,6 +28,24 @@ export interface Config {
input_make_latest: 'true' | 'false' | 'legacy' | undefined;
}
export const errorMessage = (error: unknown): string => {
if (error instanceof Error) {
return error.message;
}
if (
typeof error === 'object' &&
error !== null &&
'message' in error &&
typeof error.message === 'string'
) {
return error.message;
}
if (error === null || error === undefined) {
return 'Unknown error';
}
return String(error);
};
export const uploadUrl = (url: string): string => {
const templateMarkerPos = url.indexOf('{');
if (templateMarkerPos > -1) {
+1 -1
View File
@@ -1,6 +1,6 @@
{
"compilerOptions": {
"useUnknownInCatchVariables": false,
"useUnknownInCatchVariables": true,
/* Basic Options */
// "incremental": true, /* Enable incremental compilation */
"target": "es2022",
+8 -1
View File
@@ -4,7 +4,14 @@ export default defineConfig({
test: {
environment: 'node',
coverage: {
reporter: ['text', 'lcov'],
reporter: ['text', 'json-summary', 'lcov'],
include: ['src/**/*.ts'],
thresholds: {
statements: 94,
branches: 90,
functions: 95,
lines: 94,
},
},
include: ['__tests__/**/*.ts'],
},