Compare commits

..
54 Commits
Author SHA1 Message Date
Chiranjib SwainandGitHub bf12e9b00b feat: migrate to ESM and update dependencies (#949)
* feat: migrate to ESM and update dependencies

- Migrated the project to ESM to support the latest `@actions/*` package versions.
- Updated dependencies to their latest versions, including `@actions/core`, `@actions/github`, and others.
- Replaced `.prettierrc.js` with `.prettierrc.json` for configuration.
- Updated ESLint configuration to use ESM and added new rules.
- Refactored test files to use `jest` with ESM imports.
- Removed deprecated files and updated import paths to use `.js` extensions.
- Added new files for improved configuration and removed unnecessary mocks.
- Updated README to reflect breaking changes in version 7.

* docs: update README to clarify ESM migration details and adjust TypeScript configuration
2026-07-16 11:04:03 -05:00
dependabot[bot]GitHubdependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
b8dd2d9be0 Bump @typescript-eslint/eslint-plugin from 8.59.1 to 8.61.1 (#942)
Bumps [@typescript-eslint/eslint-plugin](https://github.com/typescript-eslint/typescript-eslint/tree/HEAD/packages/eslint-plugin) from 8.59.1 to 8.61.1.
- [Release notes](https://github.com/typescript-eslint/typescript-eslint/releases)
- [Changelog](https://github.com/typescript-eslint/typescript-eslint/blob/main/packages/eslint-plugin/CHANGELOG.md)
- [Commits](https://github.com/typescript-eslint/typescript-eslint/commits/v8.61.1/packages/eslint-plugin)

---
updated-dependencies:
- dependency-name: "@typescript-eslint/eslint-plugin"
  dependency-version: 8.61.1
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-07-06 11:58:15 -05:00
dependabot[bot]GitHubdependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>chiranjib-swain
53affe8ca4 Bump js-yaml to 4.2.0, apply npm audit fix, and add undici override for 0 vulnerabilities (#943)
* Bump js-yaml from 4.1.1 to 4.2.0

Bumps [js-yaml](https://github.com/nodeca/js-yaml) from 4.1.1 to 4.2.0.
- [Changelog](https://github.com/nodeca/js-yaml/blob/master/CHANGELOG.md)
- [Commits](https://github.com/nodeca/js-yaml/commits)

---
updated-dependencies:
- dependency-name: js-yaml
  dependency-version: 4.2.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

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

* Bump js-yaml to version 4.2.0

* chore: update package.json and package-lock.json with undici override and bump js-yaml to 4.2.0

* chore: remove obsolete license files for busboy and undici, add undici license file

* chore: update version to 6.2.0 in package.json and regenerate package-lock.json

---------

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: chiranjib-swain <chiranjib-swain@github.com>
2026-07-06 11:54:28 -05:00
Chiranjib SwainandGitHub f612d9ad18 Fix: Improve PR number validation and warning messages in input handling (#939)
* Fix: Improve PR number validation and warning messages in input handling

* Fix: Enhance PR number validation with improved sanitization and warning messages

* Fix: Change sanitizeForWarning to a local function for better encapsulation
2026-06-22 16:16:37 -05:00
CopilotGitHubchiranjib-swaincopilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
f27b608878 chore: upgrade dependencies (@actions/core, @actions/github, js-yaml, minimatch, @typescript-eslint) (#934)
* chore: upgrade dependencies and update license cache

Agent-Logs-Url: https://github.com/actions/labeler/sessions/b9db86f9-e9cd-4c8a-a1a1-84e33ef84437

Co-authored-by: chiranjib-swain <196914770+chiranjib-swain@users.noreply.github.com>

* fix: remove unused error variable in catch block to fix lint

Agent-Logs-Url: https://github.com/actions/labeler/sessions/7a6c6978-c912-4278-be03-f22f98e28f71

Co-authored-by: chiranjib-swain <196914770+chiranjib-swain@users.noreply.github.com>

* build: update dist/index.js with latest source changes

Agent-Logs-Url: https://github.com/actions/labeler/sessions/a5e02d2e-473f-4106-9227-2b5b25b15b81

Co-authored-by: chiranjib-swain <196914770+chiranjib-swain@users.noreply.github.com>

* chore: bump version to 6.1.0, update lockfile, and rebuild dist/index.js

Agent-Logs-Url: https://github.com/actions/labeler/sessions/08c6ea0c-fa19-47d8-a4fd-bbdaf444071f

Co-authored-by: chiranjib-swain <196914770+chiranjib-swain@users.noreply.github.com>

---------

Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: chiranjib-swain <196914770+chiranjib-swain@users.noreply.github.com>
2026-05-05 21:37:09 -05:00
Luca BoccassiandGitHub c5dadc2a45 Add 'changed-files-labels-limit' and 'max-files-changed' configs to allow capping number of labels added (#923)
* README.md: drop trailing whitespace

* Add 'changed-files-labels-limit' config to allow capping number of labels added

When a repository has many components, each with a changed-files label,
a large refactor ends up with the labeler spamming the pull request
with label changes. The end result is not very useful as it's not
very readable, and due to how github automatically hides comments
when label changes overflow the discussion tab, it means useful
information is hidden and one has to manually click "Load more..."
dozens of time every time the page is loaded.

Add a changed-files-labels-limit top level config knob. If more than the
configured limit of labels is set to be added, none are added.
This only affects changed-files labels.

* Add 'max-files-changed' config to allow capping number of files for labelling

When a PR modifies a very large number of files (e.g., tree-wide
refactors, automated code formatting), this new options allows
skipping file-based labeling entirely when the number of files
that are changed hits the configured limit.

Fixes https://github.com/actions/labeler/issues/486
2026-03-26 10:03:12 -05:00
dependabot[bot]GitHubdependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>chiranjib-swain
e52e4fb63e Bump minimatch from 10.0.1 to 10.2.3 (#926)
* Bump minimatch from 10.0.1 to 10.2.1

Bumps [minimatch](https://github.com/isaacs/minimatch) from 10.0.1 to 10.2.1.
- [Changelog](https://github.com/isaacs/minimatch/blob/main/changelog.md)
- [Commits](https://github.com/isaacs/minimatch/compare/v10.0.1...v10.2.1)

---
updated-dependencies:
- dependency-name: minimatch
  dependency-version: 10.2.1
  dependency-type: direct:production
...

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

* Update license configurations and add new dependencies for Octokit packages

---------

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: chiranjib-swain <chiranjib-swain@github.com>
2026-03-11 16:56:45 -05:00
Chiranjib SwainandGitHub 77a4082b84 Fix: Preserve manually added labels during workflow run and refine label sync logic (#917)
* Refactor labeler function to improve label management and deduplication logic

* Refactor labeler function to improve label handling and ensure manual labels are prioritized
2026-01-22 13:13:24 -06:00
Chiranjib SwainandGitHub 25abb3cad4 Improve Labeler Action Documentation and Error Handling for Permissions (#897)
* Update README.md and labeler.ts to clarify permissions for GitHub Labeler Action

* Update dist/index.js with latest build changes

* Update README.md to clarify manual label creation as an alternative to granting issues write permission

* Fix labeler error handling to ensure case-insensitive check for unauthorized access

* Refactor error handling in labeler to throw an error for unauthorized access instead of logging

* Add tests for labeler error handling and improve error reporting
2025-09-19 14:46:04 -05:00
dependabot[bot]GitHubdependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>Aparna Jyothi
395c8cfdb1 Bump brace-expansion from 1.1.11 to 1.1.12 and document breaking changes in v6 (#877)
* Bump brace-expansion from 1.1.11 to 1.1.12

Bumps [brace-expansion](https://github.com/juliangruber/brace-expansion) from 1.1.11 to 1.1.12.
- [Release notes](https://github.com/juliangruber/brace-expansion/releases)
- [Commits](https://github.com/juliangruber/brace-expansion/compare/1.1.11...v1.1.12)

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

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

* documentation update and check failure fix

* doc update

* doc updates

---------

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Aparna Jyothi <aparnajyothi-y@github.com>
2025-09-16 13:25:22 -05:00
aparnajyothi-yandGitHub 634933edcd publish-action upgrade to 0.4.0 from 0.2.2 (#901) 2025-09-04 12:20:23 -05:00
f1a63e87db Update Node.js version to 24 in action and dependencies (#891)
* Update Node.js version to 24 in action and dependencies

Bump the required Node.js version to 24 in action.yml and package.json. Update @types/node to ^24.1.0 to match the new Node.js version.

* package.json version update

* update to the latest versions

---------

Co-authored-by: Aparna Jyothi <aparnajyothi-y@github.com>
2025-09-03 22:24:18 -05:00
dependabot[bot]GitHubdependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>Aparna Jyothi
b0a1180683 Bump @octokit/request-error from 5.0.1 to 5.1.1 (#846)
* Bump @octokit/request-error from 5.0.1 to 5.1.1

Bumps [@octokit/request-error](https://github.com/octokit/request-error.js) from 5.0.1 to 5.1.1.
- [Release notes](https://github.com/octokit/request-error.js/releases)
- [Commits](https://github.com/octokit/request-error.js/compare/v5.0.1...v5.1.1)

---
updated-dependencies:
- dependency-name: "@octokit/request-error"
  dependency-type: indirect
...

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

* check failures fix

---------

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Aparna Jyothi <aparnajyothi-y@github.com>
2025-07-29 12:08:39 -05:00
suyashgaonkarandGitHub 110d44140c Update README.md (#871) 2025-07-14 14:59:24 -05:00
dependabot[bot]GitHubdependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>HarithaVattikuti
bee50fefe1 Bump undici from 5.28.4 to 5.28.5 (#842)
* Bump undici from 5.28.4 to 5.28.5

Bumps [undici](https://github.com/nodejs/undici) from 5.28.4 to 5.28.5.
- [Release notes](https://github.com/nodejs/undici/releases)
- [Commits](https://github.com/nodejs/undici/compare/v5.28.4...v5.28.5)

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

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

* Fix Failures

---------

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: HarithaVattikuti <73516759+HarithaVattikuti@users.noreply.github.com>
2025-06-10 15:29:08 -05:00
dependabot[bot]GitHubdependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
6463cdb00e Bump eslint-plugin-jest from 28.9.0 to 28.11.0 (#839)
Bumps [eslint-plugin-jest](https://github.com/jest-community/eslint-plugin-jest) from 28.9.0 to 28.11.0.
- [Release notes](https://github.com/jest-community/eslint-plugin-jest/releases)
- [Changelog](https://github.com/jest-community/eslint-plugin-jest/blob/main/CHANGELOG.md)
- [Commits](https://github.com/jest-community/eslint-plugin-jest/compare/v28.9.0...v28.11.0)

---
updated-dependencies:
- dependency-name: eslint-plugin-jest
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-02-19 17:08:51 -06:00
dependabot[bot]GitHubdependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
c209686724 Bump typescript from 5.7.2 to 5.7.3 (#835)
Bumps [typescript](https://github.com/microsoft/TypeScript) from 5.7.2 to 5.7.3.
- [Release notes](https://github.com/microsoft/TypeScript/releases)
- [Changelog](https://github.com/microsoft/TypeScript/blob/main/azure-pipelines.release.yml)
- [Commits](https://github.com/microsoft/TypeScript/compare/v5.7.2...v5.7.3)

---
updated-dependencies:
- dependency-name: typescript
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-02-13 14:39:42 -06:00
dependabot[bot]GitHubdependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>Aparna Jyothi
5184940b54 Bump @vercel/ncc from 0.38.1 to 0.38.3 (#830)
* Bump @vercel/ncc from 0.38.1 to 0.38.3

Bumps [@vercel/ncc](https://github.com/vercel/ncc) from 0.38.1 to 0.38.3.
- [Release notes](https://github.com/vercel/ncc/releases)
- [Commits](https://github.com/vercel/ncc/compare/0.38.1...0.38.3)

---
updated-dependencies:
- dependency-name: "@vercel/ncc"
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

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

* fix-check failures also

---------

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Aparna Jyothi <aparnajyothi-y@github.com>
2025-02-13 14:38:51 -06:00
HarithaVattikutiandGitHub 3629d5568b Document update - permission section (#840)
* Update Section

* Update warning
2025-01-16 08:46:55 -06:00
dependabot[bot]GitHubdependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
d24f7f3731 Bump ts-jest from 29.1.2 to 29.2.5 (#831)
Bumps [ts-jest](https://github.com/kulshekhar/ts-jest) from 29.1.2 to 29.2.5.
- [Release notes](https://github.com/kulshekhar/ts-jest/releases)
- [Changelog](https://github.com/kulshekhar/ts-jest/blob/main/CHANGELOG.md)
- [Commits](https://github.com/kulshekhar/ts-jest/compare/v29.1.2...v29.2.5)

---
updated-dependencies:
- dependency-name: ts-jest
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-12-19 11:38:22 -06:00
dependabot[bot]GitHubdependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
425a1f1422 Bump eslint-plugin-jest from 27.9.0 to 28.9.0 (#832)
Bumps [eslint-plugin-jest](https://github.com/jest-community/eslint-plugin-jest) from 27.9.0 to 28.9.0.
- [Release notes](https://github.com/jest-community/eslint-plugin-jest/releases)
- [Changelog](https://github.com/jest-community/eslint-plugin-jest/blob/main/CHANGELOG.md)
- [Commits](https://github.com/jest-community/eslint-plugin-jest/compare/v27.9.0...v28.9.0)

---
updated-dependencies:
- dependency-name: eslint-plugin-jest
  dependency-type: direct:development
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-12-19 11:37:31 -06:00
dependabot[bot]GitHubdependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2755f92612 Bump @types/jest from 29.5.12 to 29.5.14 (#827)
Bumps [@types/jest](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/jest) from 29.5.12 to 29.5.14.
- [Release notes](https://github.com/DefinitelyTyped/DefinitelyTyped/releases)
- [Commits](https://github.com/DefinitelyTyped/DefinitelyTyped/commits/HEAD/types/jest)

---
updated-dependencies:
- dependency-name: "@types/jest"
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-12-17 11:54:18 -06:00
dependabot[bot]GitHubdependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
31efb45c79 Bump prettier from 3.2.5 to 3.4.2 (#825)
Bumps [prettier](https://github.com/prettier/prettier) from 3.2.5 to 3.4.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.2.5...3.4.2)

---
updated-dependencies:
- dependency-name: prettier
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-12-17 11:40:17 -06:00
dependabot[bot]GitHubdependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
deb1c03ec1 Bump @typescript-eslint/parser from 7.3.1 to 8.17.0 (#824)
Bumps [@typescript-eslint/parser](https://github.com/typescript-eslint/typescript-eslint/tree/HEAD/packages/parser) from 7.3.1 to 8.17.0.
- [Release notes](https://github.com/typescript-eslint/typescript-eslint/releases)
- [Changelog](https://github.com/typescript-eslint/typescript-eslint/blob/main/packages/parser/CHANGELOG.md)
- [Commits](https://github.com/typescript-eslint/typescript-eslint/commits/v8.17.0/packages/parser)

---
updated-dependencies:
- dependency-name: "@typescript-eslint/parser"
  dependency-type: direct:development
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-12-17 11:30:47 -06:00
dependabot[bot]GitHubdependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>Aparna Jyothi
a261db4c87 Bump typescript from 5.4.3 to 5.7.2 (#819)
* Bump typescript from 5.4.3 to 5.7.2

Bumps [typescript](https://github.com/microsoft/TypeScript) from 5.4.3 to 5.7.2.
- [Release notes](https://github.com/microsoft/TypeScript/releases)
- [Changelog](https://github.com/microsoft/TypeScript/blob/main/azure-pipelines.release.yml)
- [Commits](https://github.com/microsoft/TypeScript/compare/v5.4.3...v5.7.2)

---
updated-dependencies:
- dependency-name: typescript
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

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

* npm run build

---------

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Aparna Jyothi <aparnajyothi-y@github.com>
2024-12-17 11:23:00 -06:00
dependabot[bot]GitHubdependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>Aparna Jyothi
5838aad63e Bump @actions/core from 1.10.1 to 1.11.1 (#811)
* Bump @actions/core from 1.10.1 to 1.11.1

Bumps [@actions/core](https://github.com/actions/toolkit/tree/HEAD/packages/core) from 1.10.1 to 1.11.1.
- [Changelog](https://github.com/actions/toolkit/blob/main/packages/core/RELEASES.md)
- [Commits](https://github.com/actions/toolkit/commits/HEAD/packages/core)

---
updated-dependencies:
- dependency-name: "@actions/core"
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

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

* npm run build

* licensed cache

* licensed cache

* licensed

* licensed check failure fix

---------

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Aparna Jyothi <aparnajyothi-y@github.com>
2024-12-16 08:39:04 -06:00
dependabot[bot]GitHubdependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>Aparna Jyothi
98d12e7f87 Bump minimatch from 9.0.3 to 10.0.1 (#805)
* Bump minimatch from 9.0.3 to 10.0.1

Bumps [minimatch](https://github.com/isaacs/minimatch) from 9.0.3 to 10.0.1.
- [Changelog](https://github.com/isaacs/minimatch/blob/main/changelog.md)
- [Commits](https://github.com/isaacs/minimatch/compare/v9.0.3...v10.0.1)

---
updated-dependencies:
- dependency-name: minimatch
  dependency-type: direct:production
  update-type: version-update:semver-major
...

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

* check failues fix

---------

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Aparna Jyothi <aparnajyothi-y@github.com>
2024-12-12 21:22:05 -06:00
suyashgaonkarandGitHub 857d8ca96a Update README.md (#822) 2024-12-10 14:36:38 -06:00
Joel AmbassandGitHub bb8f002e4f Merge pull request #802 from actions/Jcambass-patch-1
Add workflow file for publishing releases to immutable action package
2024-09-26 08:24:34 +02:00
dependabot[bot]GitHubdependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>HarithaVattikuti
70db055cd5 Bump braces from 3.0.2 to 3.0.3 (#789)
* Bump braces from 3.0.2 to 3.0.3

Bumps [braces](https://github.com/micromatch/braces) from 3.0.2 to 3.0.3.
- [Changelog](https://github.com/micromatch/braces/blob/master/CHANGELOG.md)
- [Commits](https://github.com/micromatch/braces/compare/3.0.2...3.0.3)

---
updated-dependencies:
- dependency-name: braces
  dependency-type: indirect
...

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

* Bump undici from 5.28.3 to 5.28.4.

* License update

---------

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: HarithaVattikuti <73516759+HarithaVattikuti@users.noreply.github.com>
2024-09-17 09:45:00 -05:00
Joel AmbassandGitHub 2e99c4dc10 Add workflow file for publishing releases to immutable action package
This workflow file publishes new action releases to the immutable action package of the same name as this repo.

This is part of the Immutable Actions project which is not yet fully released to the public. First party actions like this one are part of our initial testing of this feature.
2024-09-16 17:56:39 +02:00
dependabot[bot]GitHubdependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>HarithaVattikuti
506e1a00c6 Bump undici from 5.26.5 to 5.28.3 (#757)
* Bump undici from 5.26.5 to 5.28.3

Bumps [undici](https://github.com/nodejs/undici) from 5.26.5 to 5.28.3.
- [Release notes](https://github.com/nodejs/undici/releases)
- [Commits](https://github.com/nodejs/undici/compare/v5.26.5...v5.28.3)

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

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

* fix check failures

---------

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: HarithaVattikuti <73516759+HarithaVattikuti@users.noreply.github.com>
2024-04-04 11:04:15 -05:00
dependabot[bot]GitHubdependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
83720bce86 Bump prettier from 3.1.1 to 3.2.5 (#752)
Bumps [prettier](https://github.com/prettier/prettier) from 3.1.1 to 3.2.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.1.1...3.2.5)

---
updated-dependencies:
- dependency-name: prettier
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-02-28 10:18:06 -06:00
dependabot[bot]GitHubdependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
e5bd067930 Bump @typescript-eslint/eslint-plugin from 6.9.0 to 6.20.0 (#750)
Bumps [@typescript-eslint/eslint-plugin](https://github.com/typescript-eslint/typescript-eslint/tree/HEAD/packages/eslint-plugin) from 6.9.0 to 6.20.0.
- [Release notes](https://github.com/typescript-eslint/typescript-eslint/releases)
- [Changelog](https://github.com/typescript-eslint/typescript-eslint/blob/main/packages/eslint-plugin/CHANGELOG.md)
- [Commits](https://github.com/typescript-eslint/typescript-eslint/commits/v6.20.0/packages/eslint-plugin)

---
updated-dependencies:
- dependency-name: "@typescript-eslint/eslint-plugin"
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-02-01 14:31:19 -06:00
dependabot[bot]GitHubdependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
b2b2c20d44 Bump eslint-plugin-jest from 27.4.3 to 27.6.3 (#744)
Bumps [eslint-plugin-jest](https://github.com/jest-community/eslint-plugin-jest) from 27.4.3 to 27.6.3.
- [Release notes](https://github.com/jest-community/eslint-plugin-jest/releases)
- [Changelog](https://github.com/jest-community/eslint-plugin-jest/blob/main/CHANGELOG.md)
- [Commits](https://github.com/jest-community/eslint-plugin-jest/compare/v27.4.3...v27.6.3)

---
updated-dependencies:
- dependency-name: eslint-plugin-jest
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-01-23 13:40:36 -06:00
dependabot[bot]GitHubdependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
02180c4758 Bump @typescript-eslint/parser from 6.14.0 to 6.19.0 (#745)
Bumps [@typescript-eslint/parser](https://github.com/typescript-eslint/typescript-eslint/tree/HEAD/packages/parser) from 6.14.0 to 6.19.0.
- [Release notes](https://github.com/typescript-eslint/typescript-eslint/releases)
- [Changelog](https://github.com/typescript-eslint/typescript-eslint/blob/main/packages/parser/CHANGELOG.md)
- [Commits](https://github.com/typescript-eslint/typescript-eslint/commits/v6.19.0/packages/parser)

---
updated-dependencies:
- dependency-name: "@typescript-eslint/parser"
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-01-22 13:46:43 -06:00
MaksimZhukovandGitHub 17086b7743 Merge pull request #725 from actions/dependabot/npm_and_yarn/eslint-8.56.0
Bump eslint from 8.55.0 to 8.56.0
2023-12-18 17:19:56 +01:00
dependabot[bot]andGitHub 5e969e09f0 Bump eslint from 8.55.0 to 8.56.0
Bumps [eslint](https://github.com/eslint/eslint) from 8.55.0 to 8.56.0.
- [Release notes](https://github.com/eslint/eslint/releases)
- [Changelog](https://github.com/eslint/eslint/blob/main/CHANGELOG.md)
- [Commits](https://github.com/eslint/eslint/compare/v8.55.0...v8.56.0)

---
updated-dependencies:
- dependency-name: eslint
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-12-18 15:53:54 +00:00
MaksimZhukovandGitHub 035de5e30d Merge pull request #726 from actions/dependabot/npm_and_yarn/prettier-3.1.1
Bump prettier from 3.0.3 to 3.1.1
2023-12-18 16:52:28 +01:00
dependabot[bot]andGitHub 73e8e27589 Bump prettier from 3.0.3 to 3.1.1
Bumps [prettier](https://github.com/prettier/prettier) from 3.0.3 to 3.1.1.
- [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.0.3...3.1.1)

---
updated-dependencies:
- dependency-name: prettier
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-12-18 15:48:47 +00:00
MaksimZhukovandGitHub ccee68d6cf Merge pull request #717 from actions/dependabot/npm_and_yarn/typescript-eslint/parser-6.14.0
Bump @typescript-eslint/parser from 6.9.0 to 6.14.0
2023-12-18 16:48:25 +01:00
MaksimZhukovandGitHub 2b7003274c Merge pull request #718 from actions/dependabot/npm_and_yarn/types/js-yaml-4.0.9
Bump @types/js-yaml from 4.0.8 to 4.0.9
2023-12-18 16:47:50 +01:00
dependabot[bot]andGitHub 90cc4c2623 Bump @types/js-yaml from 4.0.8 to 4.0.9
Bumps [@types/js-yaml](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/js-yaml) from 4.0.8 to 4.0.9.
- [Release notes](https://github.com/DefinitelyTyped/DefinitelyTyped/releases)
- [Commits](https://github.com/DefinitelyTyped/DefinitelyTyped/commits/HEAD/types/js-yaml)

---
updated-dependencies:
- dependency-name: "@types/js-yaml"
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-12-18 14:34:19 +00:00
dependabot[bot]andGitHub 4a56a41318 Bump @typescript-eslint/parser from 6.9.0 to 6.14.0
Bumps [@typescript-eslint/parser](https://github.com/typescript-eslint/typescript-eslint/tree/HEAD/packages/parser) from 6.9.0 to 6.14.0.
- [Release notes](https://github.com/typescript-eslint/typescript-eslint/releases)
- [Changelog](https://github.com/typescript-eslint/typescript-eslint/blob/main/packages/parser/CHANGELOG.md)
- [Commits](https://github.com/typescript-eslint/typescript-eslint/commits/v6.14.0/packages/parser)

---
updated-dependencies:
- dependency-name: "@typescript-eslint/parser"
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-12-18 14:33:47 +00:00
MaksimZhukovandGitHub aa18a3cacc Merge pull request #719 from actions/dependabot/npm_and_yarn/types/jest-29.5.11
Bump @types/jest from 29.5.6 to 29.5.11
2023-12-18 15:33:01 +01:00
MaksimZhukovandGitHub dea3f9b186 Merge pull request #720 from actions/dependabot/npm_and_yarn/eslint-8.55.0
Bump eslint from 8.52.0 to 8.55.0
2023-12-18 15:32:34 +01:00
IvanandGitHub 0ad0ff974e Update readme with additional examples and important note about pull_request_target event (#721)
* docs: add note about pull_request_target event trigger

* docs: change note from being caution to important

* docs: fix typos

* docs: add examples to the examples chapter

* docs: fix typos
2023-12-18 13:34:14 +01:00
dependabot[bot]andGitHub 4b5201e562 Bump eslint from 8.52.0 to 8.55.0
Bumps [eslint](https://github.com/eslint/eslint) from 8.52.0 to 8.55.0.
- [Release notes](https://github.com/eslint/eslint/releases)
- [Changelog](https://github.com/eslint/eslint/blob/main/CHANGELOG.md)
- [Commits](https://github.com/eslint/eslint/compare/v8.52.0...v8.55.0)

---
updated-dependencies:
- dependency-name: eslint
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-12-14 15:30:33 +00:00
dependabot[bot]andGitHub ccaeba86e2 Bump @types/jest from 29.5.6 to 29.5.11
Bumps [@types/jest](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/jest) from 29.5.6 to 29.5.11.
- [Release notes](https://github.com/DefinitelyTyped/DefinitelyTyped/releases)
- [Commits](https://github.com/DefinitelyTyped/DefinitelyTyped/commits/HEAD/types/jest)

---
updated-dependencies:
- dependency-name: "@types/jest"
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-12-14 15:30:21 +00:00
MaksimZhukovandGitHub 08bb101f04 Merge pull request #711 from actions/dependabot/npm_and_yarn/eslint-config-prettier-9.1.0
Bump eslint-config-prettier from 9.0.0 to 9.1.0
2023-12-14 16:03:34 +01:00
MaksimZhukovandGitHub f9ea084de7 Merge pull request #669 from silverwind/patch-1
Add note regarding `pull_request_target` to README.md
2023-12-13 16:27:02 +01:00
dependabot[bot]andGitHub 587debe10c Bump eslint-config-prettier from 9.0.0 to 9.1.0
Bumps [eslint-config-prettier](https://github.com/prettier/eslint-config-prettier) from 9.0.0 to 9.1.0.
- [Changelog](https://github.com/prettier/eslint-config-prettier/blob/main/CHANGELOG.md)
- [Commits](https://github.com/prettier/eslint-config-prettier/compare/v9.0.0...v9.1.0)

---
updated-dependencies:
- dependency-name: eslint-config-prettier
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-12-04 15:50:37 +00:00
silverwindandGitHub 92c8874170 Update README.md 2023-09-08 11:46:17 +02:00
silverwindandGitHub c3a152eec1 Add note regarding pull_request_target to README.md
I think this is a big gotcha that should be called out in the documentation. I've been trying to debug why the workflow did not run for a long time, until I finally understood the underlying issue.
2023-09-08 11:43:56 +02:00
74 changed files with 33670 additions and 26191 deletions
-7
View File
@@ -1,7 +0,0 @@
# Ignore list
/*
# Do not ignore these folders:
!__tests__/
!__mocks__/
!src/
-51
View File
@@ -1,51 +0,0 @@
// This is a reusable configuration file copied from https://github.com/actions/reusable-workflows/tree/main/reusable-configurations. Please don't make changes to this file as it's the subject of an automatic update.
module.exports = {
extends: [
'eslint:recommended',
'plugin:@typescript-eslint/recommended',
'plugin:eslint-plugin-jest/recommended',
'eslint-config-prettier'
],
parser: '@typescript-eslint/parser',
plugins: ['@typescript-eslint', 'eslint-plugin-node', 'eslint-plugin-jest'],
rules: {
'@typescript-eslint/no-require-imports': 'error',
'@typescript-eslint/no-non-null-assertion': 'off',
'@typescript-eslint/no-explicit-any': 'off',
'@typescript-eslint/no-empty-function': 'off',
'@typescript-eslint/ban-ts-comment': [
'error',
{
'ts-ignore': 'allow-with-description'
}
],
'no-console': 'error',
'yoda': 'error',
'prefer-const': [
'error',
{
destructuring: 'all'
}
],
'no-control-regex': 'off',
'no-constant-condition': ['error', {checkLoops: false}],
'node/no-extraneous-import': 'error'
},
overrides: [
{
files: ['**/*{test,spec}.ts'],
rules: {
'@typescript-eslint/no-unused-vars': 'off',
'jest/no-standalone-expect': 'off',
'jest/no-conditional-expect': 'off',
'no-console': 'off',
}
}
],
env: {
node: true,
es6: true,
'jest/globals': true
}
};
+1 -1
View File
@@ -16,4 +16,4 @@ jobs:
name: Basic validation
uses: actions/reusable-workflows/.github/workflows/basic-validation.yml@main
with:
node-version: '20.x'
node-version: '24.x'
+1 -1
View File
@@ -16,4 +16,4 @@ jobs:
name: Check dist/
uses: actions/reusable-workflows/.github/workflows/check-dist.yml@main
with:
node-version: '20.x'
node-version: '24.x'
@@ -0,0 +1,20 @@
name: 'Publish Immutable Action Version'
on:
release:
types: [published]
jobs:
publish:
runs-on: ubuntu-latest
permissions:
contents: read
id-token: write
packages: write
steps:
- name: Checking out
uses: actions/checkout@v5
- name: Publish
id: publish
uses: actions/publish-immutable-action@0.0.3
@@ -22,7 +22,7 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Update the ${{ env.TAG_NAME }} tag
uses: actions/publish-action@v0.2.2
uses: actions/publish-action@v0.4.0
with:
source-tag: ${{ env.TAG_NAME }}
slack-webhook: ${{ secrets.SLACK_WEBHOOK }}
+5 -1
View File
@@ -11,4 +11,8 @@ allowed:
- unlicense
reviewed:
npm:
npm:
- "@actions/http-client"
- balanced-match
- brace-expansion
- minimatch
+1 -1
View File
@@ -1,6 +1,6 @@
---
name: "@actions/core"
version: 1.10.1
version: 3.0.1
type: npm
summary: Actions core lib
homepage: https://github.com/actions/toolkit/tree/main/packages/core
+20
View File
@@ -0,0 +1,20 @@
---
name: "@actions/exec"
version: 3.0.0
type: npm
summary: Actions exec lib
homepage: https://github.com/actions/toolkit/tree/main/packages/exec
license: mit
licenses:
- sources: LICENSE.md
text: |-
The MIT License (MIT)
Copyright 2019 GitHub
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
notices: []
+1 -1
View File
@@ -1,6 +1,6 @@
---
name: "@actions/github"
version: 6.0.0
version: 9.1.1
type: npm
summary: Actions github lib
homepage: https://github.com/actions/toolkit/tree/main/packages/github
@@ -1,10 +1,10 @@
---
name: "@actions/http-client"
version: 2.2.0
version: 3.0.2
type: npm
summary: Actions Http Client
homepage: https://github.com/actions/toolkit/tree/main/packages/http-client
license: mit
license: other
licenses:
- sources: LICENSE
text: |
+32
View File
@@ -0,0 +1,32 @@
---
name: "@actions/http-client"
version: 4.0.1
type: npm
summary: Actions Http Client
homepage: https://github.com/actions/toolkit/tree/main/packages/http-client
license: other
licenses:
- sources: LICENSE
text: |
Actions Http Client for Node.js
Copyright (c) GitHub, Inc.
All rights reserved.
MIT License
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and
associated documentation files (the "Software"), to deal in the Software without restriction,
including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense,
and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so,
subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT
LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
notices: []
@@ -1,16 +1,16 @@
---
name: uuid
version: 8.3.2
name: "@actions/io"
version: 3.0.2
type: npm
summary: RFC4122 (v1, v4, and v5) UUIDs
homepage:
summary: Actions io lib
homepage: https://github.com/actions/toolkit/tree/main/packages/io
license: mit
licenses:
- sources: LICENSE.md
text: |
text: |-
The MIT License (MIT)
Copyright (c) 2010-2020 Robert Kieffer and other contributors
Copyright 2019 GitHub
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
-30
View File
@@ -1,30 +0,0 @@
---
name: "@fastify/busboy"
version: 2.0.0
type: npm
summary: A streaming parser for HTML form data for node.js
homepage:
license: mit
licenses:
- sources: LICENSE
text: |-
Copyright Brian White. All rights reserved.
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to
deal in the Software without restriction, including without limitation the
rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
sell copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
IN THE SOFTWARE.
notices: []
+2 -2
View File
@@ -1,9 +1,9 @@
---
name: "@octokit/auth-token"
version: 4.0.0
version: 6.0.0
type: npm
summary: GitHub API token authentication for browsers and Node.js
homepage:
homepage:
license: mit
licenses:
- sources: LICENSE
+2 -2
View File
@@ -1,9 +1,9 @@
---
name: "@octokit/core"
version: 5.0.1
version: 7.0.6
type: npm
summary: Extendable client for GitHub's REST & GraphQL APIs
homepage:
homepage:
license: mit
licenses:
- sources: LICENSE
+2 -2
View File
@@ -1,9 +1,9 @@
---
name: "@octokit/endpoint"
version: 9.0.1
version: 11.0.3
type: npm
summary: Turns REST API endpoints into generic request options
homepage:
homepage:
license: mit
licenses:
- sources: LICENSE
+2 -2
View File
@@ -1,9 +1,9 @@
---
name: "@octokit/graphql"
version: 7.0.2
version: 9.0.3
type: npm
summary: GitHub GraphQL API client for browsers and Node
homepage:
homepage:
license: mit
licenses:
- sources: LICENSE
+4 -4
View File
@@ -1,14 +1,14 @@
---
name: "@octokit/openapi-types"
version: 19.0.1
version: 27.0.0
type: npm
summary: Generated TypeScript definitions based on GitHub's OpenAPI spec for api.github.com
homepage:
homepage:
license: mit
licenses:
- sources: LICENSE
text: |-
Copyright 2020 Gregor Martynus
text: |
Copyright (c) GitHub 2025 - Licensed as MIT.
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
+2 -2
View File
@@ -1,9 +1,9 @@
---
name: "@octokit/plugin-paginate-rest"
version: 9.1.0
version: 14.0.0
type: npm
summary: Octokit plugin to paginate REST API endpoint responses
homepage:
homepage:
license: mit
licenses:
- sources: LICENSE
+2 -2
View File
@@ -1,9 +1,9 @@
---
name: "@octokit/plugin-rest-endpoint-methods"
version: 10.1.0
version: 17.0.0
type: npm
summary: Octokit plugin adding one method for all of api.github.com REST API endpoints
homepage:
homepage:
license: mit
licenses:
- sources: LICENSE
+2 -2
View File
@@ -1,9 +1,9 @@
---
name: "@octokit/plugin-retry"
version: 6.0.1
version: 8.1.0
type: npm
summary: Automatic retry plugin for octokit
homepage:
homepage:
license: mit
licenses:
- sources: LICENSE
+2 -2
View File
@@ -1,9 +1,9 @@
---
name: "@octokit/request-error"
version: 5.0.1
version: 7.1.0
type: npm
summary: Error class for Octokit request errors
homepage:
homepage:
license: mit
licenses:
- sources: LICENSE
+2 -2
View File
@@ -1,10 +1,10 @@
---
name: "@octokit/request"
version: 8.1.4
version: 10.0.10
type: npm
summary: Send parameterized requests to GitHub's APIs with sensible defaults in browsers
and Node
homepage:
homepage:
license: mit
licenses:
- sources: LICENSE
+2 -2
View File
@@ -1,9 +1,9 @@
---
name: "@octokit/types"
version: 12.1.0
version: 16.0.0
type: npm
summary: Shared TypeScript definitions for Octokit projects
homepage:
homepage:
license: mit
licenses:
- sources: LICENSE
+5 -26
View File
@@ -1,39 +1,18 @@
---
name: balanced-match
version: 1.0.2
version: 4.0.4
type: npm
summary: Match balanced character pairs, like "{" and "}"
homepage: https://github.com/juliangruber/balanced-match
license: mit
homepage:
license: other
licenses:
- sources: LICENSE.md
text: |
(MIT)
Copyright (c) 2013 Julian Gruber &lt;julian@juliangruber.com&gt;
Original code Copyright Julian Gruber <julian@juliangruber.com>
Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal in
the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
of the Software, and to permit persons to whom the Software is furnished to do
so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
- sources: README.md
text: |-
(MIT)
Copyright (c) 2013 Julian Gruber &lt;julian@juliangruber.com&gt;
Port to TypeScript Copyright Isaac Z. Schlueter <i@izs.me>
Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal in
+2 -2
View File
@@ -1,9 +1,9 @@
---
name: before-after-hook
version: 2.2.3
version: 4.0.0
type: npm
summary: asynchronous before/error/after hooks for internal functionality
homepage:
homepage:
license: apache-2.0
licenses:
- sources: LICENSE
+6 -27
View File
@@ -1,16 +1,18 @@
---
name: brace-expansion
version: 2.0.1
version: 5.0.6
type: npm
summary: Brace expansion as known from sh/bash
homepage: https://github.com/juliangruber/brace-expansion
license: mit
homepage:
license: other
licenses:
- sources: LICENSE
text: |
MIT License
Copyright (c) 2013 Julian Gruber <julian@juliangruber.com>
Copyright Julian Gruber <julian@juliangruber.com>
TypeScript port Copyright Isaac Z. Schlueter <i@izs.me>
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
@@ -22,29 +24,6 @@ licenses:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
- sources: README.md
text: |-
(MIT)
Copyright (c) 2013 Julian Gruber &lt;julian@juliangruber.com&gt;
Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal in
the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
of the Software, and to permit persons to whom the Software is furnished to do
so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+47
View File
@@ -0,0 +1,47 @@
---
name: content-type
version: 2.0.0
type: npm
summary: Create and parse HTTP Content-Type header
homepage:
license: mit
licenses:
- sources: LICENSE
text: |
(The MIT License)
Copyright (c) 2015 Douglas Christopher Wilson
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
'Software'), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to
the following conditions:
The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- sources: README.md
text: |-
[MIT](LICENSE)
[npm-image]: https://img.shields.io/npm/v/content-type
[npm-url]: https://npmjs.org/package/content-type
[downloads-image]: https://img.shields.io/npm/dm/content-type
[downloads-url]: https://npmjs.org/package/content-type
[build-image]: https://img.shields.io/github/actions/workflow/status/jshttp/content-type/ci.yml?branch=master
[build-url]: https://github.com/jshttp/content-type/actions/workflows/ci.yml?query=branch%3Amaster
[coverage-image]: https://img.shields.io/codecov/c/gh/jshttp/content-type
[coverage-url]: https://codecov.io/gh/jshttp/content-type
[license-image]: http://img.shields.io/npm/l/content-type.svg?style=flat
[license-url]: LICENSE
notices: []
-28
View File
@@ -1,28 +0,0 @@
---
name: deprecation
version: 2.3.1
type: npm
summary: Log a deprecation message with stack
homepage:
license: isc
licenses:
- sources: LICENSE
text: |
The ISC License
Copyright (c) Gregor Martynus and contributors
Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted, provided that the above
copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR
IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- sources: README.md
text: "[ISC](LICENSE)"
notices: []
+2 -2
View File
@@ -1,9 +1,9 @@
---
name: js-yaml
version: 4.1.0
version: 5.1.0
type: npm
summary: YAML 1.2 parser and serializer
homepage: https://github.com/nodeca/js-yaml
homepage:
license: mit
licenses:
- sources: LICENSE
@@ -1,16 +1,17 @@
---
name: is-plain-object
version: 5.0.0
name: json-with-bigint
version: 3.5.8
type: npm
summary: Returns true if an object was created by the `Object` constructor, or Object.create(null).
homepage: https://github.com/jonschlinkert/is-plain-object
summary: JS library that allows you to easily serialize and deserialize data with
BigInt values
homepage:
license: mit
licenses:
- sources: LICENSE
text: |
The MIT License (MIT)
MIT License
Copyright (c) 2014-2017, Jon Schlinkert.
Copyright (c) 2023 Ivan Korolenko
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
@@ -19,22 +20,14 @@ licenses:
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
- sources: README.md
text: |-
Copyright © 2019, [Jon Schlinkert](https://github.com/jonschlinkert).
Released under the [MIT License](LICENSE).
***
_This file was generated by [verb-generate-readme](https://github.com/verbose/verb-generate-readme), v0.8.0, on April 28, 2019._
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
notices: []
+56 -16
View File
@@ -1,26 +1,66 @@
---
name: minimatch
version: 9.0.3
version: 10.2.5
type: npm
summary: a glob matcher in javascript
homepage:
license: isc
homepage:
license: blueoak-1.0.0
licenses:
- sources: LICENSE
- sources: LICENSE.md
text: |
The ISC License
# Blue Oak Model License
Copyright (c) 2011-2022 Isaac Z. Schlueter and Contributors
Version 1.0.0
Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted, provided that the above
copyright notice and this permission notice appear in all copies.
## Purpose
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR
IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
This license gives everyone as much permission to work with
this software as possible, while protecting contributors
from liability.
## Acceptance
In order to receive this license, you must agree to its
rules. The rules of this license are both obligations
under that agreement and conditions to your license.
You must not do anything with this software that triggers
a rule that you cannot or will not follow.
## Copyright
Each contributor licenses you to do everything with this
software that would otherwise infringe that contributor's
copyright in it.
## Notices
You must ensure that everyone who gets a copy of
any part of this software from you, with or without
changes, also gets the text of this license or a link to
<https://blueoakcouncil.org/license/1.0.0>.
## Excuse
If anyone notifies you in writing that you have not
complied with [Notices](#notices), you can keep your
license by taking all practical steps to comply within 30
days after the notice. If you do not do so, your license
ends immediately.
## Patent
Each contributor licenses you to do everything with this
software that would otherwise infringe any patent claims
they can license or become able to license.
## Reliability
No contributor can revoke this license.
## No Liability
**_As far as the law allows, this software comes as is,
without any warranty or condition, and no contributor
will be liable to anyone for any damages related to this
software or this license, under any kind of legal claim._**
notices: []
-26
View File
@@ -1,26 +0,0 @@
---
name: once
version: 1.4.0
type: npm
summary: Run a function exactly one time
homepage:
license: isc
licenses:
- sources: LICENSE
text: |
The ISC License
Copyright (c) Isaac Z. Schlueter and Contributors
Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted, provided that the above
copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR
IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
notices: []
+1 -1
View File
@@ -1,6 +1,6 @@
---
name: undici
version: 5.26.5
version: 6.27.0
type: npm
summary: An HTTP/1.1 client, written from scratch for Node.js
homepage: https://undici.nodejs.org
+4 -4
View File
@@ -1,16 +1,16 @@
---
name: universal-user-agent
version: 6.0.0
version: 7.0.3
type: npm
summary: Get a user agent string in both browser and node
homepage:
summary: Get a user agent string across all JavaScript Runtime Environments
homepage:
license: isc
licenses:
- sources: LICENSE.md
text: |
# [ISC License](https://spdx.org/licenses/ISC)
Copyright (c) 2018, Gregor Martynus (https://github.com/gr2m)
Copyright (c) 2018-2021, Gregor Martynus (https://github.com/gr2m)
Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided that the above copyright notice and this permission notice appear in all copies.
-26
View File
@@ -1,26 +0,0 @@
---
name: wrappy
version: 1.0.2
type: npm
summary: Callback wrapping utility
homepage: https://github.com/npm/wrappy
license: isc
licenses:
- sources: LICENSE
text: |
The ISC License
Copyright (c) Isaac Z. Schlueter and Contributors
Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted, provided that the above
copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR
IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
notices: []
-11
View File
@@ -1,11 +0,0 @@
// This is a reusable configuration file copied from https://github.com/actions/reusable-workflows/tree/main/reusable-configurations. Please don't make changes to this file as it's the subject of an automatic update.
module.exports = {
printWidth: 80,
tabWidth: 2,
useTabs: false,
semi: true,
singleQuote: true,
trailingComma: 'none',
bracketSpacing: false,
arrowParens: 'avoid'
};
+10
View File
@@ -0,0 +1,10 @@
{
"printWidth": 80,
"tabWidth": 2,
"useTabs": false,
"semi": true,
"singleQuote": true,
"trailingComma": "none",
"bracketSpacing": false,
"arrowParens": "avoid"
}
+184 -19
View File
@@ -4,6 +4,17 @@
Automatically label new pull requests based on the paths of files being changed or the branch name.
## What's changed in V7
- **Migrated to ESM** internally to support the latest `@actions/*` package versions. No changes to action inputs, outputs, or behavior.
## Breaking changes in V6
- Upgraded action from node20 to node24.
> Make sure your runner is on version v2.327.1 or later to ensure compatibility with this release. [Release Notes](https://github.com/actions/runner/releases/tag/v2.327.1)
For more details, see the full release notes on the [release page](https://github.com/actions/labeler/releases/tag/v6.0.0)
## Breaking changes in V5
1) The ability to apply labels based on the names of base and/or head branches was added ([#186](https://github.com/actions/labeler/issues/186) and [#54](https://github.com/actions/labeler/issues/54)). The match object for changed files was expanded with new combinations in order to make it more intuitive and flexible ([#423](https://github.com/actions/labeler/issues/423) and [#101](https://github.com/actions/labeler/issues/101)). As a result, the configuration file structure was significantly redesigned and is not compatible with the structure of the previous version. Please read the documentation below to find out how to adapt your configuration files for use with the new action version.
@@ -13,6 +24,9 @@ Automatically label new pull requests based on the paths of files being changed
4) Version 5 of this action updated the [runtime to Node.js 20](https://docs.github.com/en/actions/creating-actions/metadata-syntax-for-github-actions#runs-for-javascript-actions). All scripts are now run with Node.js 20 instead of Node.js 16 and are affected by any breaking changes between Node.js 16 and 20.
> [!IMPORTANT]
> Before the update to the v5, please check out [this information](#notes-regarding-pull_request_target-event) about the `pull_request_target` event trigger.
## Usage
### Create `.github/labeler.yml`
@@ -27,7 +41,7 @@ The match object allows control over the matching options. You can specify the l
The base match object is defined as:
```yml
- changed-files:
- changed-files:
- any-glob-to-any-file: ['list', 'of', 'globs']
- any-glob-to-all-files: ['list', 'of', 'globs']
- all-globs-to-any-file: ['list', 'of', 'globs']
@@ -110,7 +124,19 @@ Documentation:
- changed-files:
- any-glob-to-any-file: docs/*
# Add 'Documentation' label to any change to .md files within the entire repository
# Add 'Documentation' label to any file changes within 'docs' or 'guides' folders
Documentation:
- changed-files:
- any-glob-to-any-file:
- docs/*
- guides/*
## Equivalent of the above mentioned configuration using another syntax
Documentation:
- changed-files:
- any-glob-to-any-file: ['docs/*', 'guides/*']
# Add 'Documentation' label to any change to .md files within the entire repository
Documentation:
- changed-files:
- any-glob-to-any-file: '**/*.md'
@@ -126,14 +152,104 @@ source:
feature:
- head-branch: ['^feature', 'feature']
# Add 'release' label to any PR that is opened against the `main` branch
# Add 'release' label to any PR that is opened against the `main` branch
release:
- base-branch: 'main'
```
#### Configuration Options
The labeler configuration file (`.github/labeler.yml`) supports the following top-level options:
| Name | Description |
|------------------------------|---------------------------------------------------------------------------------------------------------------------------------------------------------------|
| `changed-files-labels-limit` | Maximum number of new labels to apply based on changed files (must be a non-negative integer). If exceeded, no changed-files labels are applied for that run. |
| `max-files-changed` | Maximum number of total changed files (must be a non-negative integer). If exceeded, all file-based labeling is skipped. |
##### Limiting changed-files labels
When working with large PRs (e.g., tree-wide refactors) that touch many components, you may want to prevent the labeler from adding too many labels. Set `changed-files-labels-limit` in your `.github/labeler.yml` configuration file to limit the number of labels that can be applied based on changed files patterns.
**Important behaviors:**
- The limit counts only **new** labels that would be added by changed-files rules. Labels already present on the PR are not counted toward the limit.
- If the number of new changed-files labels **exceeds** the limit, **all** new changed-files labels are skipped for that run.
- If the number of new changed-files labels **equals** the limit, labels are still applied normally.
- Labels based on branch conditions (`head-branch`, `base-branch`) are **not affected** by the limit.
- **Any label definition that includes a `changed-files` rule is considered a changed-files label** and is subject to the limit, regardless of which condition caused the label to match. For example, a label with both `head-branch` and `changed-files` rules will be subject to the limit even if it matches via the branch rule.
- If both `max-files-changed` and `changed-files-labels-limit` are configured at the same time, `max-files-changed` is evaluated first, and if it triggers, `changed-files-labels-limit` is not evaluated.
##### Example
```yml
# .github/labeler.yml
# Limit changed-files based labels to 5
changed-files-labels-limit: 5
# Label definitions - these are subject to the limit
frontend:
- changed-files:
- any-glob-to-any-file: 'src/frontend/**'
backend:
- changed-files:
- any-glob-to-any-file: 'src/backend/**'
docs:
- changed-files:
- any-glob-to-any-file: 'docs/**'
# This label has both branch and changed-files rules.
# It is still subject to the limit because it includes changed-files.
mixed:
- any:
- head-branch: '^feature/'
- changed-files:
- any-glob-to-any-file: 'src/mixed/**'
# Branch-based labels are NOT affected by the limit
feature:
- head-branch: '^feature/'
```
##### Skipping labeling for large PRs
When a PR modifies a very large number of files (e.g., tree-wide refactors, automated code formatting), you may want to skip file-based labeling entirely. Set `max-files-changed` in your `.github/labeler.yml` configuration file to skip all file-based labeling when the total number of changed files exceeds the threshold.
**Important behaviors:**
- If the total number of changed files **exceeds** the limit, all file-based labeling is skipped entirely.
- If the total number of changed files **equals** the limit, labels are still applied normally.
- Labels based **only** on branch conditions (`head-branch`, `base-branch`) are **not affected** by the limit.
- **Any label definition that includes a `changed-files` rule is considered a file-based label** and will be skipped, regardless of which condition caused the label to match. For example, a label with both `head-branch` and `changed-files` rules will be skipped even if it would match via the branch rule.
- Pre-existing labels on the PR are **preserved** — changed-files configs are not evaluated at all, so `sync-labels` will not remove them.
##### Example
```yml
# .github/labeler.yml
# Skip file-based labeling if more than 100 files changed
max-files-changed: 100
# These labels will be skipped if > 100 files changed
frontend:
- changed-files:
- any-glob-to-any-file: 'src/frontend/**'
backend:
- changed-files:
- any-glob-to-any-file: 'src/backend/**'
# Branch-based labels are NOT affected
release:
- base-branch: 'main'
```
### Create Workflow
Create a workflow (e.g. `.github/workflows/labeler.yml` see [Creating a Workflow file](https://help.github.com/en/articles/configuring-a-workflow#creating-a-workflow-file)) to utilize the labeler action with content:
Create a workflow (e.g. `.github/workflows/labeler.yml` see [Creating a Workflow file](https://docs.github.com/en/actions/writing-workflows/quickstart#creating-your-first-workflow)) to utilize the labeler action with content:
```yml
name: "Pull Request Labeler"
@@ -147,7 +263,7 @@ jobs:
pull-requests: write
runs-on: ubuntu-latest
steps:
- uses: actions/labeler@v5
- uses: actions/labeler@v6
```
#### Inputs
@@ -167,10 +283,10 @@ You might want to use action called [@actions/checkout](https://github.com/actio
```yml
steps:
- uses: actions/checkout@v4 # Uploads repository content to the runner
- uses: actions/checkout@v5 # Uploads repository content to the runner
with:
repository: "owner/repositoryName" # The one of the available inputs, visit https://github.com/actions/checkout#readme to find more
- uses: actions/labeler@v5
- uses: actions/labeler@v6
with:
configuration-path: 'path/to/the/uploaded/configuration/file'
@@ -191,10 +307,10 @@ jobs:
pull-requests: write
runs-on: ubuntu-latest
steps:
# Label PRs 1, 2, and 3
- uses: actions/labeler@v5
with:
- uses: actions/labeler@v6
with:
pr-number: |
1
2
@@ -203,9 +319,9 @@ jobs:
**Note:** in normal usage the `pr-number` input is not required as the action will detect the PR number from the workflow context.
#### Outputs
#### Outputs
Labeler provides the following outputs:
Labeler provides the following outputs:
| Name | Description |
|--------------|-----------------------------------------------------------|
@@ -226,14 +342,14 @@ jobs:
runs-on: ubuntu-latest
steps:
- id: label-the-PR
uses: actions/labeler@v5
uses: actions/labeler@v6
- id: run-frontend-tests
if: contains(steps.label-the-PR.outputs.all-labels, 'frontend')
run: |
echo "Running frontend tests..."
# Put your commands for running frontend tests here
- id: run-backend-tests
if: contains(steps.label-the-PR.outputs.all-labels, 'backend')
run: |
@@ -241,11 +357,60 @@ jobs:
# Put your commands for running backend tests here
```
## Permissions
## Recommended Permissions
In order to add labels to pull requests, the GitHub labeler action requires write permissions on the pull-request. However, when the action runs on a pull request from a forked repository, GitHub only grants read access tokens for `pull_request` events, at most. If you encounter an `Error: HttpError: Resource not accessible by integration`, it's likely due to these permission constraints. To resolve this issue, you can modify the `on:` section of your workflow to use
[`pull_request_target`](https://docs.github.com/en/actions/using-workflows/events-that-trigger-workflows#pull_request_target) instead of `pull_request` (see example [above](#create-workflow)). This change allows the action to have write access, because `pull_request_target` alters the [context of the action](https://docs.github.com/en/actions/using-workflows/events-that-trigger-workflows#pull_request_target) and safely grants additional permissions. Refer to the [GitHub token permissions documentation](https://docs.github.com/en/actions/security-guides/automatic-token-authentication#permissions-for-the-github_token) for more details about access levels and event contexts.
To successfully add labels to pull requests using the GitHub Labeler Action, specific permissions must be granted based on your use case:
1. **Adding Existing Labels**:
- Requires: `pull-requests: write`
- Use this if all labels already exist in the repository (i.e., pre-defined in `.github/labeler.yml`).
2. **Creating New Labels**:
- Requires: `issues: write`
- This is necessary if the action needs to create labels that do not already exist in the repository.
However, when the action runs on a pull request from a forked repository, GitHub only grants read access tokens for `pull_request` events, at most. If you encounter an `Error: HttpError: Resource not accessible by integration`, it's likely due to these permission constraints. To resolve this issue, you can modify the `on:` section of your workflow to use
[`pull_request_target`](https://docs.github.com/en/actions/using-workflows/events-that-trigger-workflows#pull_request_target) instead of `pull_request` (see example [above](#create-workflow)). This change allows the action to have write access, because `pull_request_target` alters the [context of the action](https://docs.github.com/en/actions/using-workflows/events-that-trigger-workflows#pull_request_target) and safely grants additional permissions.
There exists a potentially dangerous misuse of the `pull_request_target` workflow trigger that may lead to malicious PR authors (i.e. attackers) being able to obtain repository write permissions or stealing repository secrets. Hence, it is advisable that `pull_request_target` should only be used in workflows that are carefully designed to avoid executing untrusted code and to also ensure that workflows using `pull_request_target` limit access to sensitive resources. Refer to the [GitHub token permissions documentation](https://docs.github.com/en/actions/security-guides/automatic-token-authentication#permissions-for-the-github_token) for more details about access levels and event contexts.
### Example Workflow Permissions
To ensure the action works correctly, include the following permissions in your workflow file:
```yml
permissions:
contents: read
pull-requests: write
issues: write
```
### Manual Label Creation as an Alternative to Granting issues write Permission
If you prefer not to grant the `issues: write` permission in your workflow, you can manually create all required labels in the repository before the action runs.
## Notes regarding `pull_request_target` event
Using the `pull_request_target` event trigger involves several peculiarities related to initial set up of the labeler or updating version of the labeler.
### Initial set up of the labeler action
When submitting an initial pull request to a repository using the `pull_request_target` event, the labeler workflow will not run on that pull request because the `pull_request_target` execution runs off the base branch instead of the pull request's branch. Unfortunately this means the introduction of the labeler can not be verified during that pull request and it needs to be committed blindly.
### Updating major version of the labeler
When submitting a pull request that includes updates of the labeler action version and associated configuration files, using the `pull_request_target` event may result in a failed workflow. This is due to the nature of `pull_request_target`, which uses the code from the base branch rather than the branch linked to the pull request — so, potentially outdated configuration files may not be compatible with the updated labeler action.
To prevent this issue, you can switch to using the `pull_request` event temporarily, before merging. This event execution draws from the code within the branch of your pull request, allowing you to verify the new configuration's compatibility with the updated labeler action.
```yml
name: "Pull Request Labeler"
on:
- pull_request
```
Once you confirm that the updated configuration files function as intended, you can then revert to using the `pull_request_target` event before merging the pull request. Following this step ensures that your workflow is robust and free from disruptions.
## Contributions
Contributions are welcome! See the [Contributor's Guide](CONTRIBUTING.md).
Contributions are welcome! See the [Contributor's Guide](CONTRIBUTING.md).
-43
View File
@@ -1,43 +0,0 @@
export const context = {
payload: {
pull_request: {
number: 123,
head: {
ref: 'head-branch-name'
},
base: {
ref: 'base-branch-name'
}
}
},
repo: {
owner: 'monalisa',
repo: 'helloworld'
}
};
const mockApi = {
rest: {
issues: {
setLabels: jest.fn()
},
pulls: {
get: jest.fn().mockResolvedValue({
data: {
labels: []
}
}),
listFiles: {
endpoint: {
merge: jest.fn().mockReturnValue({})
}
}
},
repos: {
getContent: jest.fn()
}
},
paginate: jest.fn()
};
export const getOctokit = jest.fn().mockImplementation(() => mockApi);
+36 -19
View File
@@ -1,14 +1,31 @@
import {
getBranchName,
checkAnyBranch,
checkAllBranch,
toBranchMatchConfig,
BranchMatchConfig
} from '../src/branch';
import * as github from '@actions/github';
import {jest, describe, beforeEach, it, expect} from '@jest/globals';
import type {BranchMatchConfig} from '../src/branch.js';
jest.mock('@actions/core');
jest.mock('@actions/github');
jest.unstable_mockModule('@actions/core', () => ({
debug: jest.fn(),
info: jest.fn(),
warning: jest.fn(),
error: jest.fn()
}));
const mockGithubContext = {
payload: {
pull_request: {
number: 123,
head: {ref: 'head-branch-name'},
base: {ref: 'base-branch-name'}
}
},
repo: {owner: 'monalisa', repo: 'helloworld'}
} as any;
jest.unstable_mockModule('@actions/github', () => ({
context: mockGithubContext,
getOctokit: jest.fn()
}));
const {getBranchName, checkAnyBranch, checkAllBranch, toBranchMatchConfig} =
await import('../src/branch.js');
describe('getBranchName', () => {
describe('when the pull requests base branch is requested', () => {
@@ -28,10 +45,10 @@ describe('getBranchName', () => {
describe('checkAllBranch', () => {
beforeEach(() => {
github.context.payload.pull_request!.head = {
mockGithubContext.payload.pull_request.head = {
ref: 'test/feature/123'
};
github.context.payload.pull_request!.base = {
mockGithubContext.payload.pull_request.base = {
ref: 'main'
};
});
@@ -87,10 +104,10 @@ describe('checkAllBranch', () => {
describe('checkAnyBranch', () => {
beforeEach(() => {
github.context.payload.pull_request!.head = {
mockGithubContext.payload.pull_request.head = {
ref: 'test/feature/123'
};
github.context.payload.pull_request!.base = {
mockGithubContext.payload.pull_request.base = {
ref: 'main'
};
});
@@ -159,7 +176,7 @@ describe('toBranchMatchConfig', () => {
it('sets headBranch in the matchConfig', () => {
const result = toBranchMatchConfig(config);
expect(result).toEqual<BranchMatchConfig>({
expect(result).toEqual({
headBranch: ['testing']
});
});
@@ -169,7 +186,7 @@ describe('toBranchMatchConfig', () => {
it('sets headBranch in the matchConfig', () => {
const result = toBranchMatchConfig(stringConfig);
expect(result).toEqual<BranchMatchConfig>({
expect(result).toEqual({
headBranch: ['testing']
});
});
@@ -180,7 +197,7 @@ describe('toBranchMatchConfig', () => {
const config = {'base-branch': ['testing']};
it('sets baseBranch in the matchConfig', () => {
const result = toBranchMatchConfig(config);
expect(result).toEqual<BranchMatchConfig>({
expect(result).toEqual({
baseBranch: ['testing']
});
});
@@ -190,7 +207,7 @@ describe('toBranchMatchConfig', () => {
it('sets baseBranch in the matchConfig', () => {
const result = toBranchMatchConfig(stringConfig);
expect(result).toEqual<BranchMatchConfig>({
expect(result).toEqual({
baseBranch: ['testing']
});
});
@@ -201,7 +218,7 @@ describe('toBranchMatchConfig', () => {
const config = {'base-branch': ['testing'], 'head-branch': ['testing']};
it('sets headBranch and baseBranch in the matchConfig', () => {
const result = toBranchMatchConfig(config);
expect(result).toEqual<BranchMatchConfig>({
expect(result).toEqual({
baseBranch: ['testing'],
headBranch: ['testing']
});
+25 -9
View File
@@ -1,5 +1,24 @@
import {
ChangedFilesMatchConfig,
import {jest, describe, it, expect} from '@jest/globals';
import type {ChangedFilesMatchConfig} from '../src/changedFiles.js';
jest.unstable_mockModule('@actions/core', () => ({
debug: jest.fn(),
info: jest.fn(),
warning: jest.fn(),
error: jest.fn()
}));
jest.unstable_mockModule('@actions/github', () => ({
context: {
payload: {
pull_request: {number: 123, head: {ref: 'head'}, base: {ref: 'base'}}
},
repo: {owner: 'monalisa', repo: 'helloworld'}
},
getOctokit: jest.fn()
}));
const {
checkAllChangedFiles,
checkAnyChangedFiles,
toChangedFilesMatchConfig,
@@ -7,10 +26,7 @@ import {
checkIfAllGlobsMatchAnyFile,
checkIfAnyGlobMatchesAllFiles,
checkIfAllGlobsMatchAllFiles
} from '../src/changedFiles';
jest.mock('@actions/core');
jest.mock('@actions/github');
} = await import('../src/changedFiles.js');
describe('checkAllChangedFiles', () => {
const changedFiles = ['foo.txt', 'bar.txt'];
@@ -92,7 +108,7 @@ describe('toChangedFilesMatchConfig', () => {
it('returns an empty object', () => {
const result = toChangedFilesMatchConfig(config);
expect(result).toEqual<ChangedFilesMatchConfig>({});
expect(result).toEqual({});
});
});
@@ -129,7 +145,7 @@ describe('toChangedFilesMatchConfig', () => {
it('sets the value in the config object', () => {
const result = toChangedFilesMatchConfig(config);
expect(result).toEqual<ChangedFilesMatchConfig>({
expect(result).toEqual({
changedFiles: [{anyGlobToAnyFile: ['testing']}]
});
});
@@ -140,7 +156,7 @@ describe('toChangedFilesMatchConfig', () => {
it(`sets the string as an array in the config object`, () => {
const result = toChangedFilesMatchConfig(config);
expect(result).toEqual<ChangedFilesMatchConfig>({
expect(result).toEqual({
changedFiles: [{anyGlobToAnyFile: ['testing']}]
});
});
+18
View File
@@ -0,0 +1,18 @@
# Limit to 0 changed-files labels (none allowed)
changed-files-labels-limit: 0
# Labels based on changed files
component-a:
- changed-files:
- any-glob-to-any-file: ['components/a/**']
component-b:
- changed-files:
- any-glob-to-any-file: ['components/b/**']
# Labels based on branch patterns only
test-branch:
- head-branch: '^test/'
feature-branch:
- head-branch: '/feature/'
+26
View File
@@ -0,0 +1,26 @@
# Limit to 1 changed-files label
changed-files-labels-limit: 1
# Labels based on changed files
component-a:
- changed-files:
- any-glob-to-any-file: ['components/a/**']
component-b:
- changed-files:
- any-glob-to-any-file: ['components/b/**']
component-c:
- changed-files:
- any-glob-to-any-file: ['components/c/**']
component-d:
- changed-files:
- any-glob-to-any-file: ['components/d/**']
# Labels based on branch patterns only
test-branch:
- head-branch: '^test/'
feature-branch:
- head-branch: '/feature/'
+26
View File
@@ -0,0 +1,26 @@
# Limit to 2 changed-files labels
changed-files-labels-limit: 2
# Labels based on changed files
component-a:
- changed-files:
- any-glob-to-any-file: ['components/a/**']
component-b:
- changed-files:
- any-glob-to-any-file: ['components/b/**']
component-c:
- changed-files:
- any-glob-to-any-file: ['components/c/**']
component-d:
- changed-files:
- any-glob-to-any-file: ['components/d/**']
# Labels based on branch patterns only
test-branch:
- head-branch: '^test/'
feature-branch:
- head-branch: '/feature/'
+26
View File
@@ -0,0 +1,26 @@
# Limit to 3 changed-files labels
changed-files-labels-limit: 3
# Labels based on changed files
component-a:
- changed-files:
- any-glob-to-any-file: ['components/a/**']
component-b:
- changed-files:
- any-glob-to-any-file: ['components/b/**']
component-c:
- changed-files:
- any-glob-to-any-file: ['components/c/**']
component-d:
- changed-files:
- any-glob-to-any-file: ['components/d/**']
# Labels based on branch patterns only
test-branch:
- head-branch: '^test/'
feature-branch:
- head-branch: '/feature/'
+15
View File
@@ -0,0 +1,15 @@
# Skip file-based labeling if more than 5 files changed
max-files-changed: 5
# Labels based on changed files
component-a:
- changed-files:
- any-glob-to-any-file: ['components/a/**']
component-b:
- changed-files:
- any-glob-to-any-file: ['components/b/**']
component-c:
- changed-files:
- any-glob-to-any-file: ['components/c/**']
@@ -0,0 +1,15 @@
# Skip file-based labeling if more than 3 files changed
max-files-changed: 3
# Labels based on changed files
component-a:
- changed-files:
- any-glob-to-any-file: ['components/a/**']
component-b:
- changed-files:
- any-glob-to-any-file: ['components/b/**']
# Branch-based label (should not be affected)
test-branch:
- head-branch: ['^test/']
+23
View File
@@ -0,0 +1,23 @@
# Labels based on changed files
component-a:
- changed-files:
- any-glob-to-any-file: ['components/a/**']
component-b:
- changed-files:
- any-glob-to-any-file: ['components/b/**']
component-c:
- changed-files:
- any-glob-to-any-file: ['components/c/**']
component-d:
- changed-files:
- any-glob-to-any-file: ['components/d/**']
# Labels based on branch patterns only
test-branch:
- head-branch: '^test/'
feature-branch:
- head-branch: '/feature/'
+16
View File
@@ -0,0 +1,16 @@
# Test fixture for mixed rules behavior
# A label with both branch and changed-files rules is considered a "changed-files label"
# and is subject to the limit, even if it matches via the branch rule
changed-files-labels-limit: 0
# This label has both branch and changed-files rules
# It should be subject to the limit even if matched via branch
mixed-label:
- any:
- head-branch: '^test/'
- changed-files:
- any-glob-to-any-file: ['components/a/**']
# Pure branch-based label - not subject to limit
pure-branch-label:
- head-branch: '^test/'
+370 -10
View File
@@ -1,20 +1,65 @@
import {jest, describe, it, expect, beforeEach, beforeAll} from '@jest/globals';
import * as yaml from 'js-yaml';
import * as core from '@actions/core';
import * as fs from 'fs';
import {checkMatchConfigs} from '../src/labeler';
import {
import type {
MatchConfig,
BaseMatchConfig
} from '../src/api/get-label-configs.js';
// Define API mock functions at module level
const getPullRequestsMock = jest.fn<any>();
const getLabelConfigsMock = jest.fn<any>();
const setLabelsMock = jest.fn<any>();
const getChangedFilesMock = jest.fn<any>();
const getContentMock = jest.fn<any>();
jest.unstable_mockModule('@actions/core', () => ({
getInput: jest.fn(),
getMultilineInput: jest.fn(),
getBooleanInput: jest.fn(),
setOutput: jest.fn(),
setFailed: jest.fn(),
error: jest.fn(),
warning: jest.fn(),
info: jest.fn(),
debug: jest.fn()
}));
jest.unstable_mockModule('@actions/github', () => ({
context: {
payload: {
pull_request: {
number: 123,
head: {ref: 'head-branch'},
base: {ref: 'base-branch'}
}
},
repo: {owner: 'monalisa', repo: 'helloworld'}
},
getOctokit: jest.fn()
}));
jest.unstable_mockModule('../src/api/index.js', () => ({
getPullRequests: getPullRequestsMock,
getLabelConfigs: getLabelConfigsMock,
setLabels: setLabelsMock,
getChangedFiles: getChangedFilesMock,
getContent: getContentMock
}));
const core = await import('@actions/core');
const github = await import('@actions/github');
const api = await import('../src/api/index.js');
const {labeler, checkMatchConfigs} = await import('../src/labeler.js');
const {
toMatchConfig,
getLabelConfigMapFromObject,
BaseMatchConfig
} from '../src/api/get-label-configs';
jest.mock('@actions/core');
getLabelConfigResultFromObject,
configUsesChangedFiles
} = await import('../src/api/get-label-configs.js');
beforeAll(() => {
jest.spyOn(core, 'getInput').mockImplementation((name, options) => {
return jest.requireActual('@actions/core').getInput(name, options);
});
(core.getInput as jest.Mock).mockImplementation(() => undefined);
});
const loadYaml = (filepath: string) => {
@@ -56,6 +101,204 @@ describe('getLabelConfigMapFromObject', () => {
const result = getLabelConfigMapFromObject(yamlObject);
expect(result).toEqual(expected);
});
it('ignores top-level options like changed-files-labels-limit and max-files-changed', () => {
const configWithLimit = {
'changed-files-labels-limit': 5,
'max-files-changed': 100,
label1: [{'changed-files': [{'any-glob-to-any-file': ['*.txt']}]}]
};
const result = getLabelConfigMapFromObject(configWithLimit);
expect(result.has('changed-files-labels-limit')).toBe(false);
expect(result.has('max-files-changed')).toBe(false);
expect(result.has('label1')).toBe(true);
});
});
describe('getLabelConfigResultFromObject', () => {
it('extracts changed-files-labels-limit as a number', () => {
const config = {
'changed-files-labels-limit': 5,
label1: [{'changed-files': [{'any-glob-to-any-file': ['*.txt']}]}]
};
const result = getLabelConfigResultFromObject(config);
expect(result.changedFilesLimit).toBe(5);
expect(result.labelConfigs.has('label1')).toBe(true);
});
it('parses changed-files-labels-limit from string', () => {
const config = {
'changed-files-labels-limit': '10',
label1: [{'changed-files': [{'any-glob-to-any-file': ['*.txt']}]}]
};
const result = getLabelConfigResultFromObject(config);
expect(result.changedFilesLimit).toBe(10);
});
it('trims whitespace when parsing string values', () => {
const config = {
'changed-files-labels-limit': ' 5 ',
label1: [{'changed-files': [{'any-glob-to-any-file': ['*.txt']}]}]
};
const result = getLabelConfigResultFromObject(config);
expect(result.changedFilesLimit).toBe(5);
});
it('returns undefined changedFilesLimit when not set', () => {
const config = {
label1: [{'changed-files': [{'any-glob-to-any-file': ['*.txt']}]}]
};
const result = getLabelConfigResultFromObject(config);
expect(result.changedFilesLimit).toBeUndefined();
});
it('throws error for invalid changed-files-labels-limit value', () => {
const config = {
'changed-files-labels-limit': 'invalid',
label1: [{'changed-files': [{'any-glob-to-any-file': ['*.txt']}]}]
};
expect(() => getLabelConfigResultFromObject(config)).toThrow(
/Invalid value for 'changed-files-labels-limit'/
);
});
it('throws error for negative changed-files-labels-limit value', () => {
const config = {
'changed-files-labels-limit': -1,
label1: [{'changed-files': [{'any-glob-to-any-file': ['*.txt']}]}]
};
expect(() => getLabelConfigResultFromObject(config)).toThrow(
/must be a non-negative integer/
);
});
it('throws error for string with trailing characters', () => {
const config = {
'changed-files-labels-limit': '10abc',
label1: [{'changed-files': [{'any-glob-to-any-file': ['*.txt']}]}]
};
expect(() => getLabelConfigResultFromObject(config)).toThrow(
/must be a non-negative integer/
);
});
it('throws error for decimal string', () => {
const config = {
'changed-files-labels-limit': '3.2',
label1: [{'changed-files': [{'any-glob-to-any-file': ['*.txt']}]}]
};
expect(() => getLabelConfigResultFromObject(config)).toThrow(
/must be a non-negative integer/
);
});
it('throws error for float number', () => {
const config = {
'changed-files-labels-limit': 3.2,
label1: [{'changed-files': [{'any-glob-to-any-file': ['*.txt']}]}]
};
expect(() => getLabelConfigResultFromObject(config)).toThrow(
/must be a non-negative integer/
);
});
it('accepts zero as a valid changed-files-labels-limit', () => {
const config = {
'changed-files-labels-limit': 0,
label1: [{'changed-files': [{'any-glob-to-any-file': ['*.txt']}]}]
};
const result = getLabelConfigResultFromObject(config);
expect(result.changedFilesLimit).toBe(0);
});
it('extracts max-files-changed as a number', () => {
const config = {
'max-files-changed': 100,
label1: [{'changed-files': [{'any-glob-to-any-file': ['*.txt']}]}]
};
const result = getLabelConfigResultFromObject(config);
expect(result.maxFilesChanged).toBe(100);
expect(result.labelConfigs.has('label1')).toBe(true);
});
it('parses max-files-changed from string', () => {
const config = {
'max-files-changed': '50',
label1: [{'changed-files': [{'any-glob-to-any-file': ['*.txt']}]}]
};
const result = getLabelConfigResultFromObject(config);
expect(result.maxFilesChanged).toBe(50);
});
it('returns undefined maxFilesChanged when not set', () => {
const config = {
label1: [{'changed-files': [{'any-glob-to-any-file': ['*.txt']}]}]
};
const result = getLabelConfigResultFromObject(config);
expect(result.maxFilesChanged).toBeUndefined();
});
it('throws error for invalid max-files-changed value', () => {
const config = {
'max-files-changed': 'invalid',
label1: [{'changed-files': [{'any-glob-to-any-file': ['*.txt']}]}]
};
expect(() => getLabelConfigResultFromObject(config)).toThrow(
/Invalid value for 'max-files-changed'/
);
});
it('throws error for negative max-files-changed value', () => {
const config = {
'max-files-changed': -1,
label1: [{'changed-files': [{'any-glob-to-any-file': ['*.txt']}]}]
};
expect(() => getLabelConfigResultFromObject(config)).toThrow(
/must be a non-negative integer/
);
});
it('accepts zero as a valid max-files-changed', () => {
const config = {
'max-files-changed': 0,
label1: [{'changed-files': [{'any-glob-to-any-file': ['*.txt']}]}]
};
const result = getLabelConfigResultFromObject(config);
expect(result.maxFilesChanged).toBe(0);
});
it('supports both options together', () => {
const config = {
'changed-files-labels-limit': 5,
'max-files-changed': 100,
label1: [{'changed-files': [{'any-glob-to-any-file': ['*.txt']}]}]
};
const result = getLabelConfigResultFromObject(config);
expect(result.changedFilesLimit).toBe(5);
expect(result.maxFilesChanged).toBe(100);
});
it('throws a clear error when max-files-changed is used as a label', () => {
const config = {
'max-files-changed': [
{'changed-files': [{'any-glob-to-any-file': ['*.txt']}]}
]
};
expect(() => getLabelConfigResultFromObject(config)).toThrow(
/reserved top-level option and cannot be used as a label name/
);
});
it('throws a clear error when changed-files-labels-limit is used as a label', () => {
const config = {
'changed-files-labels-limit': [
{'changed-files': [{'any-glob-to-any-file': ['*.txt']}]}
]
};
expect(() => getLabelConfigResultFromObject(config)).toThrow(
/reserved top-level option and cannot be used as a label name/
);
});
});
describe('toMatchConfig', () => {
@@ -159,3 +402,120 @@ describe('checkMatchConfigs', () => {
});
});
});
describe('configUsesChangedFiles', () => {
it('returns true when config has changed-files in any block', () => {
const matchConfig: MatchConfig[] = [
{any: [{changedFiles: [{anyGlobToAnyFile: ['*.txt']}]}]}
];
expect(configUsesChangedFiles(matchConfig)).toBe(true);
});
it('returns true when config has changed-files in all block', () => {
const matchConfig: MatchConfig[] = [
{all: [{changedFiles: [{allGlobsToAllFiles: ['*.txt']}]}]}
];
expect(configUsesChangedFiles(matchConfig)).toBe(true);
});
it('returns false when config only has branch patterns', () => {
const matchConfig: MatchConfig[] = [
{any: [{headBranch: ['^test/']}]},
{any: [{baseBranch: ['main']}]}
];
expect(configUsesChangedFiles(matchConfig)).toBe(false);
});
it('returns false when config has empty changed-files array', () => {
const matchConfig: MatchConfig[] = [{any: [{changedFiles: []}]}];
expect(configUsesChangedFiles(matchConfig)).toBe(false);
});
it('returns false when config has changed-files with empty objects', () => {
const matchConfig: MatchConfig[] = [{any: [{changedFiles: [{}]}]}];
expect(configUsesChangedFiles(matchConfig)).toBe(false);
});
it('returns true when config has mixed branch and changed-files patterns', () => {
const matchConfig: MatchConfig[] = [
{
any: [
{changedFiles: [{anyGlobToAnyFile: ['*.txt']}]},
{headBranch: ['^feature/']}
]
}
];
expect(configUsesChangedFiles(matchConfig)).toBe(true);
});
});
describe('labeler error handling', () => {
const mockClient = {} as any;
const mockPullRequest = {
number: 123,
data: {labels: []},
changedFiles: []
};
beforeEach(() => {
jest.resetAllMocks();
(github.getOctokit as jest.Mock).mockReturnValue(mockClient);
getPullRequestsMock.mockReturnValue([
{
...mockPullRequest,
data: {labels: [{name: 'old-label'}]}
}
]);
getLabelConfigsMock.mockResolvedValue({
labelConfigs: new Map([['new-label', ['dummy-config']]]),
changedFilesLimit: undefined
});
// Force match so "new-label" is always added
jest.spyOn({checkMatchConfigs}, 'checkMatchConfigs').mockReturnValue(true);
});
it('throws a custom error for HttpError 403 with "unauthorized" message', async () => {
setLabelsMock.mockRejectedValue({
name: 'HttpError',
status: 403,
message: 'Request failed with status code 403: Unauthorized'
});
await expect(labeler()).rejects.toThrow(
/does not have permission to create labels/
);
});
it('rethrows unexpected HttpError', async () => {
const unexpectedError = {
name: 'HttpError',
status: 404,
message: 'Not Found'
};
setLabelsMock.mockRejectedValue(unexpectedError);
// NOTE: In the current implementation, labeler rethrows the raw error object (not an Error instance).
// `rejects.toThrow` only works with real Error objects, so here we must use `rejects.toEqual`.
// If labeler is updated to always wrap errors in `Error`, this test can be changed to use `rejects.toThrow`.
await expect(labeler()).rejects.toEqual(unexpectedError);
});
it('handles "Resource not accessible by integration" gracefully', async () => {
const error = {
name: 'HttpError',
message: 'Resource not accessible by integration'
};
setLabelsMock.mockRejectedValue(error);
await labeler();
expect(core.warning).toHaveBeenCalledWith(
expect.stringContaining("requires 'issues: write'"),
expect.any(Object)
);
expect(core.setFailed).toHaveBeenCalledWith(error.message);
});
});
+624 -29
View File
@@ -1,23 +1,75 @@
import {run} from '../src/labeler';
import * as github from '@actions/github';
import * as core from '@actions/core';
import {
jest,
describe,
it,
test,
expect,
afterAll,
beforeEach
} from '@jest/globals';
import path from 'path';
import {fileURLToPath} from 'url';
import fs from 'fs';
jest.mock('@actions/core');
jest.mock('@actions/github');
const __dirname = path.dirname(fileURLToPath(import.meta.url));
// Define mock functions before mocking modules
const setLabelsMock = jest.fn<any>();
const reposMock = jest.fn<any>();
const paginateMock = jest.fn<any>();
const getPullMock = jest.fn<any>().mockResolvedValue({data: {labels: []}});
const listFilesMergeMock = jest.fn<any>().mockReturnValue({});
const coreGetInputMock = jest.fn<any>();
const coreGetMultilineInputMock = jest.fn<any>();
const coreGetBooleanInputMock = jest.fn<any>();
const coreErrorMock = jest.fn<any>();
const coreWarningMock = jest.fn<any>();
const coreSetFailedMock = jest.fn<any>();
const setOutputSpy = jest.fn<any>();
const mockGithubContext: any = {
payload: {
pull_request: {
number: 123,
head: {ref: 'head-branch-name'},
base: {ref: 'base-branch-name'}
}
},
repo: {owner: 'monalisa', repo: 'helloworld'}
};
jest.unstable_mockModule('@actions/core', () => ({
getInput: coreGetInputMock,
getMultilineInput: coreGetMultilineInputMock,
getBooleanInput: coreGetBooleanInputMock,
setOutput: setOutputSpy,
setFailed: coreSetFailedMock,
error: coreErrorMock,
warning: coreWarningMock,
info: jest.fn(),
debug: jest.fn()
}));
jest.unstable_mockModule('@actions/github', () => ({
context: mockGithubContext,
getOctokit: jest.fn(() => ({
rest: {
issues: {setLabels: setLabelsMock},
repos: {getContent: reposMock},
pulls: {
get: getPullMock,
listFiles: {endpoint: {merge: listFilesMergeMock}}
}
},
paginate: paginateMock
}))
}));
const {run} = await import('../src/labeler.js');
const gh = github.getOctokit('_');
const setLabelsMock = jest.spyOn(gh.rest.issues, 'setLabels');
const reposMock = jest.spyOn(gh.rest.repos, 'getContent');
const paginateMock = jest.spyOn(gh, 'paginate');
const getPullMock = jest.spyOn(gh.rest.pulls, 'get');
const readFileSyncMock = jest.spyOn(fs, 'readFileSync');
const existsSyncMock = jest.spyOn(fs, 'existsSync');
const coreErrorMock = jest.spyOn(core, 'error');
const coreWarningMock = jest.spyOn(core, 'warning');
const coreSetFailedMock = jest.spyOn(core, 'setFailed');
const setOutputSpy = jest.spyOn(core, 'setOutput');
class HttpError extends Error {
constructor(message: string) {
@@ -37,7 +89,17 @@ const yamlFixtures = {
'branches.yml': fs.readFileSync('__tests__/fixtures/branches.yml'),
'only_pdfs.yml': fs.readFileSync('__tests__/fixtures/only_pdfs.yml'),
'not_supported.yml': fs.readFileSync('__tests__/fixtures/not_supported.yml'),
'any_and_all.yml': fs.readFileSync('__tests__/fixtures/any_and_all.yml')
'any_and_all.yml': fs.readFileSync('__tests__/fixtures/any_and_all.yml'),
'mixed_labels.yml': fs.readFileSync('__tests__/fixtures/mixed_labels.yml'),
'limit_0.yml': fs.readFileSync('__tests__/fixtures/limit_0.yml'),
'limit_1.yml': fs.readFileSync('__tests__/fixtures/limit_1.yml'),
'limit_2.yml': fs.readFileSync('__tests__/fixtures/limit_2.yml'),
'limit_3.yml': fs.readFileSync('__tests__/fixtures/limit_3.yml'),
'mixed_rules.yml': fs.readFileSync('__tests__/fixtures/mixed_rules.yml'),
'max_files_5.yml': fs.readFileSync('__tests__/fixtures/max_files_5.yml'),
'max_files_with_branch.yml': fs.readFileSync(
'__tests__/fixtures/max_files_with_branch.yml'
)
};
const configureInput = (
@@ -49,20 +111,27 @@ const configureInput = (
'pr-number': string[];
}>
) => {
jest
.spyOn(core, 'getInput')
.mockImplementation((name: string, ...opts) => mockInput[name]);
jest
.spyOn(core, 'getMultilineInput')
.mockImplementation((name: string, ...opts) => mockInput[name]);
jest
.spyOn(core, 'getBooleanInput')
.mockImplementation((name: string, ...opts) => mockInput[name]);
coreGetInputMock.mockImplementation(
(name: unknown) => mockInput[name as keyof typeof mockInput]
);
coreGetMultilineInputMock.mockImplementation(
(name: unknown) => mockInput[name as keyof typeof mockInput]
);
coreGetBooleanInputMock.mockImplementation(
(name: unknown) => mockInput[name as keyof typeof mockInput]
);
};
afterAll(() => jest.restoreAllMocks());
afterAll(async () => {
jest.restoreAllMocks();
});
describe('run', () => {
beforeEach(() => {
getPullMock.mockResolvedValue({data: {labels: []}} as any);
mockGithubContext.payload.pull_request.head = {ref: 'head-branch-name'};
mockGithubContext.payload.pull_request.base = {ref: 'base-branch-name'};
});
it('(with dot: false) adds labels to PRs that match our glob patterns', async () => {
configureInput({});
usingLabelerConfigYaml('only_pdfs.yml');
@@ -159,7 +228,7 @@ describe('run', () => {
it('adds labels based on the branch names that match the regexp pattern', async () => {
configureInput({});
github.context.payload.pull_request!.head = {ref: 'test/testing-time'};
mockGithubContext.payload.pull_request.head = {ref: 'test/testing-time'};
usingLabelerConfigYaml('branches.yml');
await run();
@@ -177,7 +246,7 @@ describe('run', () => {
it('adds multiple labels based on branch names that match different regexp patterns', async () => {
configureInput({});
github.context.payload.pull_request!.head = {
mockGithubContext.payload.pull_request.head = {
ref: 'test/feature/123'
};
usingLabelerConfigYaml('branches.yml');
@@ -203,7 +272,7 @@ describe('run', () => {
it('can support multiple branches by batching', async () => {
configureInput({});
github.context.payload.pull_request!.head = {ref: 'fix/123'};
mockGithubContext.payload.pull_request.head = {ref: 'fix/123'};
usingLabelerConfigYaml('branches.yml');
await run();
@@ -221,7 +290,7 @@ describe('run', () => {
it('can support multiple branches by providing an array', async () => {
configureInput({});
github.context.payload.pull_request!.head = {ref: 'array/123'};
mockGithubContext.payload.pull_request.head = {ref: 'array/123'};
usingLabelerConfigYaml('branches.yml');
await run();
@@ -431,6 +500,197 @@ describe('run', () => {
);
});
it('(with pr-number: non-numeric string) warns and makes no API call', async () => {
configureInput({
'repo-token': 'foo',
'configuration-path': 'bar',
'pr-number': ['abc']
});
usingLabelerConfigYaml('only_pdfs.yml');
await run();
expect(coreWarningMock).toHaveBeenCalledWith(
"'abc' is not a valid pull request number"
);
expect(getPullMock).not.toHaveBeenCalled();
expect(setLabelsMock).not.toHaveBeenCalled();
});
it('(with pr-number: negative number) warns and makes no API call', async () => {
configureInput({
'repo-token': 'foo',
'configuration-path': 'bar',
'pr-number': ['-1']
});
usingLabelerConfigYaml('only_pdfs.yml');
await run();
expect(coreWarningMock).toHaveBeenCalledWith(
"'-1' is not a valid pull request number"
);
expect(getPullMock).not.toHaveBeenCalled();
expect(setLabelsMock).not.toHaveBeenCalled();
});
it('(with pr-number: zero) warns and makes no API call', async () => {
configureInput({
'repo-token': 'foo',
'configuration-path': 'bar',
'pr-number': ['0']
});
usingLabelerConfigYaml('only_pdfs.yml');
await run();
expect(coreWarningMock).toHaveBeenCalledWith(
"'0' is not a valid pull request number"
);
expect(getPullMock).not.toHaveBeenCalled();
expect(setLabelsMock).not.toHaveBeenCalled();
});
it('(with pr-number: number with internal space) warns and makes no API call', async () => {
configureInput({
'repo-token': 'foo',
'configuration-path': 'bar',
'pr-number': ['10 4']
});
usingLabelerConfigYaml('only_pdfs.yml');
await run();
expect(coreWarningMock).toHaveBeenCalledWith(
"'10 4' is not a valid pull request number"
);
expect(getPullMock).not.toHaveBeenCalled();
expect(setLabelsMock).not.toHaveBeenCalled();
});
it('(with pr-number: number with trailing non-numeric chars) warns and makes no API call', async () => {
configureInput({
'repo-token': 'foo',
'configuration-path': 'bar',
'pr-number': ['104abc']
});
usingLabelerConfigYaml('only_pdfs.yml');
await run();
expect(coreWarningMock).toHaveBeenCalledWith(
"'104abc' is not a valid pull request number"
);
expect(getPullMock).not.toHaveBeenCalled();
expect(setLabelsMock).not.toHaveBeenCalled();
});
it('(with pr-number: valid number with surrounding whitespace) trims and processes correctly', async () => {
configureInput({
'repo-token': 'foo',
'configuration-path': 'bar',
'pr-number': [' 104 ']
});
usingLabelerConfigYaml('only_pdfs.yml');
mockGitHubResponseChangedFiles('foo.pdf');
getPullMock.mockResolvedValue(<any>{data: {labels: []}});
await run();
expect(getPullMock).toHaveBeenCalled();
expect(coreWarningMock).not.toHaveBeenCalledWith(
expect.stringContaining('is not a valid pull request number')
);
});
it('(with pr-number: string with carriage return) sanitizes CR as \\x0d in warning', async () => {
configureInput({
'repo-token': 'foo',
'configuration-path': 'bar',
'pr-number': ['abc\rdef']
});
usingLabelerConfigYaml('only_pdfs.yml');
await run();
expect(coreWarningMock).toHaveBeenCalledWith(
"'abc\\x0ddef' is not a valid pull request number (non-printable characters were escaped as \\xNN)"
);
expect(getPullMock).not.toHaveBeenCalled();
expect(setLabelsMock).not.toHaveBeenCalled();
});
it('(with pr-number: string with tab) sanitizes tab as \\x09 in warning', async () => {
configureInput({
'repo-token': 'foo',
'configuration-path': 'bar',
'pr-number': ['abc\tdef']
});
usingLabelerConfigYaml('only_pdfs.yml');
await run();
expect(coreWarningMock).toHaveBeenCalledWith(
"'abc\\x09def' is not a valid pull request number (non-printable characters were escaped as \\xNN)"
);
expect(getPullMock).not.toHaveBeenCalled();
expect(setLabelsMock).not.toHaveBeenCalled();
});
it('(with pr-number: string with ANSI escape sequence) sanitizes ESC byte as \\x1b in warning', async () => {
configureInput({
'repo-token': 'foo',
'configuration-path': 'bar',
'pr-number': ['abc\x1b[31mINJECTED\x1b[0m']
});
usingLabelerConfigYaml('only_pdfs.yml');
await run();
expect(coreWarningMock).toHaveBeenCalledWith(
"'abc\\x1b[31mINJECTED\\x1b[0m' is not a valid pull request number (non-printable characters were escaped as \\xNN)"
);
expect(getPullMock).not.toHaveBeenCalled();
expect(setLabelsMock).not.toHaveBeenCalled();
});
it('(with pr-number: mix of valid and invalid) processes valid, skips invalid with warning', async () => {
configureInput({
'repo-token': 'foo',
'configuration-path': 'bar',
'pr-number': ['104', 'abc']
});
usingLabelerConfigYaml('only_pdfs.yml');
mockGitHubResponseChangedFiles('foo.pdf');
getPullMock.mockResolvedValue(<any>{
data: {labels: []}
});
await run();
expect(coreWarningMock).toHaveBeenCalledWith(
"'abc' is not a valid pull request number"
);
expect(setLabelsMock).toHaveBeenCalledTimes(1);
expect(setLabelsMock).toHaveBeenCalledWith({
owner: 'monalisa',
repo: 'helloworld',
issue_number: 104,
labels: ['touched-a-pdf-file']
});
});
it('does not add labels to PRs that have no changed files', async () => {
usingLabelerConfigYaml('only_pdfs.yml');
mockGitHubResponseChangedFiles();
@@ -440,6 +700,341 @@ describe('run', () => {
expect(setLabelsMock).toHaveBeenCalledTimes(0);
});
describe('changed-files-labels-limit', () => {
it('applies all labels when count is within limit', async () => {
configureInput({});
mockGithubContext.payload.pull_request.head = {ref: 'main'};
usingLabelerConfigYaml('limit_3.yml');
mockGitHubResponseChangedFiles(
'components/a/file.ts',
'components/b/file.ts'
);
getPullMock.mockResolvedValue(<any>{
data: {labels: []}
});
await run();
expect(setLabelsMock).toHaveBeenCalledTimes(1);
expect(setLabelsMock).toHaveBeenCalledWith({
owner: 'monalisa',
repo: 'helloworld',
issue_number: 123,
labels: ['component-a', 'component-b']
});
});
it('skips changed-files labels when count exceeds limit', async () => {
configureInput({});
mockGithubContext.payload.pull_request.head = {ref: 'main'};
usingLabelerConfigYaml('limit_2.yml');
mockGitHubResponseChangedFiles(
'components/a/file.ts',
'components/b/file.ts',
'components/c/file.ts'
);
getPullMock.mockResolvedValue(<any>{
data: {labels: []}
});
await run();
// No labels should be applied since changed-files labels exceed limit
expect(setLabelsMock).toHaveBeenCalledTimes(0);
});
it('still applies branch-based labels when changed-files limit is exceeded', async () => {
configureInput({});
mockGithubContext.payload.pull_request.head = {ref: 'test/some-feature'};
usingLabelerConfigYaml('limit_1.yml');
mockGitHubResponseChangedFiles(
'components/a/file.ts',
'components/b/file.ts',
'components/c/file.ts'
);
getPullMock.mockResolvedValue(<any>{
data: {labels: []}
});
await run();
// Only the branch-based label should be applied
expect(setLabelsMock).toHaveBeenCalledTimes(1);
expect(setLabelsMock).toHaveBeenCalledWith({
owner: 'monalisa',
repo: 'helloworld',
issue_number: 123,
labels: ['test-branch']
});
});
it('applies all labels when no limit is set', async () => {
configureInput({});
mockGithubContext.payload.pull_request.head = {ref: 'main'};
usingLabelerConfigYaml('mixed_labels.yml');
mockGitHubResponseChangedFiles(
'components/a/file.ts',
'components/b/file.ts',
'components/c/file.ts',
'components/d/file.ts'
);
getPullMock.mockResolvedValue(<any>{
data: {labels: []}
});
await run();
expect(setLabelsMock).toHaveBeenCalledTimes(1);
expect(setLabelsMock).toHaveBeenCalledWith({
owner: 'monalisa',
repo: 'helloworld',
issue_number: 123,
labels: ['component-a', 'component-b', 'component-c', 'component-d']
});
});
it('does not count preexisting labels toward the limit', async () => {
configureInput({});
mockGithubContext.payload.pull_request.head = {ref: 'main'};
usingLabelerConfigYaml('limit_2.yml');
mockGitHubResponseChangedFiles(
'components/a/file.ts',
'components/b/file.ts',
'components/c/file.ts',
'components/d/file.ts'
);
getPullMock.mockResolvedValue(<any>{
data: {labels: [{name: 'component-a'}, {name: 'component-b'}]}
});
await run();
// component-a and component-b are preexisting, so only 2 new labels (c, d) would be added
// which equals the limit of 2, so labels should be applied
expect(setLabelsMock).toHaveBeenCalledTimes(1);
expect(setLabelsMock).toHaveBeenCalledWith({
owner: 'monalisa',
repo: 'helloworld',
issue_number: 123,
labels: ['component-a', 'component-b', 'component-c', 'component-d']
});
});
it('skips new labels when new count exceeds limit even with preexisting', async () => {
configureInput({});
mockGithubContext.payload.pull_request.head = {ref: 'main'};
usingLabelerConfigYaml('limit_2.yml');
mockGitHubResponseChangedFiles(
'components/a/file.ts',
'components/b/file.ts',
'components/c/file.ts',
'components/d/file.ts'
);
getPullMock.mockResolvedValue(<any>{
data: {labels: [{name: 'component-a'}]}
});
await run();
// component-a is preexisting, so 3 new labels (b, c, d) would be added
// which exceeds the limit of 2, so no new changed-files labels are applied
expect(setLabelsMock).toHaveBeenCalledTimes(0);
});
it('applies labels when new count equals the limit', async () => {
configureInput({});
mockGithubContext.payload.pull_request.head = {ref: 'main'};
usingLabelerConfigYaml('limit_2.yml');
mockGitHubResponseChangedFiles(
'components/a/file.ts',
'components/b/file.ts'
);
getPullMock.mockResolvedValue(<any>{
data: {labels: []}
});
await run();
expect(setLabelsMock).toHaveBeenCalledTimes(1);
expect(setLabelsMock).toHaveBeenCalledWith({
owner: 'monalisa',
repo: 'helloworld',
issue_number: 123,
labels: ['component-a', 'component-b']
});
});
it('skips all changed-files labels when limit is 0', async () => {
configureInput({});
mockGithubContext.payload.pull_request.head = {ref: 'test/some-feature'};
usingLabelerConfigYaml('limit_0.yml');
mockGitHubResponseChangedFiles('components/a/file.ts');
getPullMock.mockResolvedValue(<any>{
data: {labels: []}
});
await run();
// With limit 0, only branch-based labels should be applied
expect(setLabelsMock).toHaveBeenCalledTimes(1);
expect(setLabelsMock).toHaveBeenCalledWith({
owner: 'monalisa',
repo: 'helloworld',
issue_number: 123,
labels: ['test-branch']
});
});
it('treats labels with mixed rules as changed-files labels', async () => {
// A label that has both branch and changed-files rules is considered
// a "changed-files label" and subject to the limit, even if it matches
// via the branch rule
configureInput({});
mockGithubContext.payload.pull_request.head = {ref: 'test/some-feature'};
usingLabelerConfigYaml('mixed_rules.yml');
mockGitHubResponseChangedFiles('unrelated/file.ts');
getPullMock.mockResolvedValue(<any>{
data: {labels: []}
});
await run();
// The mixed-label matches via branch rule but is still subject to limit
// because it contains a changed-files rule in its definition.
// Only pure-branch-label should be applied.
expect(setLabelsMock).toHaveBeenCalledTimes(1);
expect(setLabelsMock).toHaveBeenCalledWith({
owner: 'monalisa',
repo: 'helloworld',
issue_number: 123,
labels: ['pure-branch-label']
});
});
});
describe('max-files-changed', () => {
it('applies labels when changed files count is within limit', async () => {
configureInput({});
mockGithubContext.payload.pull_request.head = {ref: 'main'};
usingLabelerConfigYaml('max_files_5.yml');
mockGitHubResponseChangedFiles(
'components/a/file.ts',
'components/b/file.ts',
'components/c/file.ts'
);
getPullMock.mockResolvedValue(<any>{
data: {labels: []}
});
await run();
expect(setLabelsMock).toHaveBeenCalledTimes(1);
expect(setLabelsMock).toHaveBeenCalledWith({
owner: 'monalisa',
repo: 'helloworld',
issue_number: 123,
labels: ['component-a', 'component-b', 'component-c']
});
});
it('skips file-based labels when changed files exceed limit', async () => {
configureInput({});
mockGithubContext.payload.pull_request.head = {ref: 'main'};
usingLabelerConfigYaml('max_files_5.yml');
mockGitHubResponseChangedFiles(
'components/a/file1.ts',
'components/a/file2.ts',
'components/b/file1.ts',
'components/b/file2.ts',
'components/c/file1.ts',
'components/c/file2.ts' // 6 files > limit of 5
);
getPullMock.mockResolvedValue(<any>{
data: {labels: []}
});
await run();
// No labels should be applied since changed files exceed limit
expect(setLabelsMock).toHaveBeenCalledTimes(0);
});
it('applies labels when changed files count equals limit', async () => {
configureInput({});
mockGithubContext.payload.pull_request.head = {ref: 'main'};
usingLabelerConfigYaml('max_files_5.yml');
mockGitHubResponseChangedFiles(
'components/a/file1.ts',
'components/a/file2.ts',
'components/b/file1.ts',
'components/b/file2.ts',
'components/c/file.ts' // exactly 5 files = limit
);
getPullMock.mockResolvedValue(<any>{
data: {labels: []}
});
await run();
expect(setLabelsMock).toHaveBeenCalledTimes(1);
expect(setLabelsMock).toHaveBeenCalledWith({
owner: 'monalisa',
repo: 'helloworld',
issue_number: 123,
labels: ['component-a', 'component-b', 'component-c']
});
});
it('still applies branch-based labels when max-files-changed is exceeded', async () => {
configureInput({});
mockGithubContext.payload.pull_request.head = {ref: 'test/some-feature'};
usingLabelerConfigYaml('max_files_with_branch.yml');
mockGitHubResponseChangedFiles(
'components/a/file1.ts',
'components/a/file2.ts',
'components/b/file1.ts',
'components/b/file2.ts' // 4 files > limit of 3
);
getPullMock.mockResolvedValue(<any>{
data: {labels: []}
});
await run();
// Only the branch-based label should be applied
expect(setLabelsMock).toHaveBeenCalledTimes(1);
expect(setLabelsMock).toHaveBeenCalledWith({
owner: 'monalisa',
repo: 'helloworld',
issue_number: 123,
labels: ['test-branch']
});
});
it('preserves preexisting changed-files labels with sync-labels when max-files-changed is exceeded', async () => {
configureInput({'sync-labels': true});
mockGithubContext.payload.pull_request.head = {ref: 'main'};
usingLabelerConfigYaml('max_files_5.yml');
mockGitHubResponseChangedFiles(
'unrelated/file1.ts',
'unrelated/file2.ts',
'unrelated/file3.ts',
'unrelated/file4.ts',
'unrelated/file5.ts',
'unrelated/file6.ts' // 6 files > limit of 5
);
getPullMock.mockResolvedValue(<any>{
data: {labels: [{name: 'component-a'}]} // preexisting label
});
await run();
// No setLabels call because labels should remain unchanged
// (component-a is preserved, not removed by sync-labels)
expect(setLabelsMock).toHaveBeenCalledTimes(0);
});
});
it('should use local configuration file if it exists', async () => {
const configFile = 'only_pdfs.yml';
const configFilePath = path.join(__dirname, 'fixtures', configFile);
+1 -1
View File
@@ -28,5 +28,5 @@ outputs:
all-labels:
description: 'A comma-separated list of all labels that the PR contains'
runs:
using: 'node20'
using: 'node24'
main: 'dist/index.js'
+28554 -23346
View File
File diff suppressed because one or more lines are too long
+3
View File
@@ -0,0 +1,3 @@
{
"type": "module"
}
+74
View File
@@ -0,0 +1,74 @@
// This is a reusable configuration file copied from https://github.com/actions/reusable-workflows/tree/main/reusable-configurations. Please don't make changes to this file as it's the subject of an automatic update.
import js from '@eslint/js';
import tsParser from '@typescript-eslint/parser';
import tsPlugin from '@typescript-eslint/eslint-plugin';
import jest from 'eslint-plugin-jest';
import n from 'eslint-plugin-n';
import prettier from 'eslint-config-prettier';
import globals from 'globals';
export default [
{
ignores: ['**/*', '!src/**', '!__tests__/**']
},
js.configs.recommended,
{
files: ['**/*.ts'],
languageOptions: {
parser: tsParser,
ecmaVersion: 2022,
sourceType: 'module',
globals: {
...globals.node,
...globals.es2015
}
},
plugins: {
'@typescript-eslint': tsPlugin,
n
},
rules: {
...tsPlugin.configs.recommended.rules,
'@typescript-eslint/no-require-imports': 'error',
'@typescript-eslint/no-non-null-assertion': 'off',
'@typescript-eslint/no-explicit-any': 'off',
'@typescript-eslint/no-empty-function': 'off',
'@typescript-eslint/ban-ts-comment': [
'error',
{
'ts-ignore': 'allow-with-description'
}
],
'no-console': 'error',
yoda: 'error',
'prefer-const': [
'error',
{
destructuring: 'all'
}
],
'no-control-regex': 'off',
'no-constant-condition': ['error', {checkLoops: false}],
'no-undef': 'off',
'no-useless-assignment': 'off',
'n/no-extraneous-import': 'error'
}
},
{
files: ['**/*{test,spec}.ts'],
plugins: {jest},
languageOptions: {
globals: {
...globals.jest
}
},
rules: {
...jest.configs['flat/recommended'].rules,
'@typescript-eslint/no-unused-vars': 'off',
'jest/no-standalone-expect': 'off',
'jest/no-conditional-expect': 'off',
'no-console': 'off'
}
},
prettier
];
-10
View File
@@ -1,10 +0,0 @@
module.exports = {
clearMocks: true,
moduleFileExtensions: ['js', 'ts'],
testEnvironment: 'node',
testMatch: ['**/*.test.ts'],
transform: {
'^.+\\.ts$': 'ts-jest'
},
verbose: true
}
+23
View File
@@ -0,0 +1,23 @@
export default {
clearMocks: true,
moduleFileExtensions: ['js', 'ts'],
testEnvironment: 'node',
testMatch: ['**/*.test.ts'],
transform: {
'^.+\\.ts$': [
'ts-jest',
{
useESM: true,
diagnostics: {
ignoreCodes: [151002]
}
}
]
},
extensionsToTreatAsEsm: ['.ts'],
transformIgnorePatterns: ['node_modules/(?!(@actions|@octokit)/)'],
moduleNameMapper: {
'^(\\.{1,2}/.*)\\.js$': '$1'
},
verbose: true
}
+3074 -2317
View File
File diff suppressed because it is too large Load Diff
+31 -27
View File
@@ -1,15 +1,19 @@
{
"name": "labeler",
"version": "5.0.0",
"version": "7.0.0",
"description": "Labels pull requests by files altered",
"type": "module",
"main": "lib/main.js",
"engines": {
"node": ">=24"
},
"scripts": {
"build": "tsc && ncc build lib/main.js",
"format": "prettier --no-error-on-unmatched-pattern --config ./.prettierrc.js --write \"**/*.{ts,yml,yaml}\"",
"format-check": "prettier --no-error-on-unmatched-pattern --config ./.prettierrc.js --check \"**/*.{ts,yml,yaml}\"",
"lint": "eslint --config ./.eslintrc.js \"**/*.ts\"",
"lint:fix": "eslint --config ./.eslintrc.js \"**/*.ts\" --fix",
"test": "jest"
"format": "prettier --no-error-on-unmatched-pattern --write \"**/*.{ts,yml,yaml}\"",
"format-check": "prettier --no-error-on-unmatched-pattern --check \"**/*.{ts,yml,yaml}\"",
"lint": "eslint \"**/*.ts\"",
"lint:fix": "eslint \"**/*.ts\" --fix",
"test": "node --experimental-vm-modules ./node_modules/jest/bin/jest.js --runInBand"
},
"repository": {
"type": "git",
@@ -24,29 +28,29 @@
"author": "GitHub",
"license": "MIT",
"dependencies": {
"@actions/core": "^1.10.0",
"@actions/github": "^6.0.0",
"@octokit/plugin-retry": "^6.0.0",
"js-yaml": "^4.1.0",
"@actions/core": "^3.0.1",
"@actions/github": "^9.1.1",
"@octokit/plugin-retry": "^8.1.0",
"js-yaml": "^5.1.0",
"lodash.isequal": "^4.5.0",
"minimatch": "^9.0.3"
"minimatch": "^10.2.5"
},
"devDependencies": {
"@types/jest": "^29.5.6",
"@types/js-yaml": "^4.0.6",
"@types/lodash.isequal": "^4.5.6",
"@types/minimatch": "^5.1.2",
"@types/node": "^20.8.8",
"@typescript-eslint/eslint-plugin": "^6.7.4",
"@typescript-eslint/parser": "^6.7.2",
"@vercel/ncc": "^0.38.1",
"eslint": "^8.51.0",
"eslint-config-prettier": "^9.0.0",
"eslint-plugin-jest": "^27.4.2",
"eslint-plugin-node": "^11.1.0",
"jest": "^29.7.0",
"prettier": "^3.0.3",
"ts-jest": "^29.1.1",
"typescript": "^5.2.2"
"@eslint/js": "^10.0.1",
"@jest/globals": "^30.4.1",
"@types/lodash.isequal": "^4.5.8",
"@types/node": "^24.13.2",
"@typescript-eslint/eslint-plugin": "^8.62.0",
"@typescript-eslint/parser": "^8.62.0",
"@vercel/ncc": "^0.44.0",
"eslint": "^10.5.0",
"eslint-config-prettier": "^10.1.8",
"eslint-plugin-jest": "^29.15.2",
"eslint-plugin-n": "^18.1.0",
"globals": "^17.7.0",
"jest": "^30.4.2",
"prettier": "^3.8.4",
"ts-jest": "^29.4.11",
"typescript": "^6.0.3"
}
}
+1 -1
View File
@@ -1,6 +1,6 @@
import * as core from '@actions/core';
import * as github from '@actions/github';
import {ClientType} from './types';
import {ClientType} from './types.js';
export const getChangedFiles = async (
client: ClientType,
+3 -3
View File
@@ -1,7 +1,7 @@
import * as core from '@actions/core';
import * as github from '@actions/github';
import {getChangedFiles} from './get-changed-files';
import {ClientType} from './types';
import {getChangedFiles} from './get-changed-files.js';
import {ClientType} from './types.js';
export async function* getPullRequests(
client: ClientType,
@@ -17,7 +17,7 @@ export async function* getPullRequests(
pull_number: prNumber
});
prData = result.data;
} catch (error: any) {
} catch {
core.warning(`Could not find pull request #${prNumber}, skipping`);
continue;
}
+1 -1
View File
@@ -1,5 +1,5 @@
import * as github from '@actions/github';
import {ClientType} from './types';
import {ClientType} from './types.js';
export const getContent = async (
client: ClientType,
+112 -7
View File
@@ -1,15 +1,15 @@
import * as core from '@actions/core';
import * as yaml from 'js-yaml';
import fs from 'fs';
import {ClientType} from './types';
import {getContent} from './get-content';
import {ClientType} from './types.js';
import {getContent} from './get-content.js';
import {
ChangedFilesMatchConfig,
toChangedFilesMatchConfig
} from '../changedFiles';
} from '../changedFiles.js';
import {toBranchMatchConfig, BranchMatchConfig} from '../branch';
import {toBranchMatchConfig, BranchMatchConfig} from '../branch.js';
export interface MatchConfig {
all?: BaseMatchConfig[];
@@ -18,12 +18,53 @@ export interface MatchConfig {
export type BaseMatchConfig = BranchMatchConfig & ChangedFilesMatchConfig;
export interface LabelConfigResult {
labelConfigs: Map<string, MatchConfig[]>;
changedFilesLimit?: number;
maxFilesChanged?: number;
}
const ALLOWED_CONFIG_KEYS = ['changed-files', 'head-branch', 'base-branch'];
const TOP_LEVEL_OPTIONS = ['changed-files-labels-limit', 'max-files-changed'];
/**
* Parses and validates a non-negative integer value from the configuration.
*/
function parseNonNegativeInteger(value: unknown, optionName: string): number {
if (typeof value === 'number') {
if (!Number.isFinite(value) || !Number.isInteger(value) || value < 0) {
throw new Error(
`Invalid value for '${optionName}': must be a non-negative integer (got ${value})`
);
}
return value;
}
if (typeof value === 'string') {
const trimmed = value.trim();
if (!/^\d+$/.test(trimmed)) {
throw new Error(
`Invalid value for '${optionName}': must be a non-negative integer (got '${value}')`
);
}
return Number(trimmed);
}
if (Array.isArray(value)) {
throw new Error(
`'${optionName}' is a reserved top-level option and cannot be used as a label name. Please rename it.`
);
}
throw new Error(
`Invalid value for '${optionName}': expected a non-negative integer`
);
}
export const getLabelConfigs = (
client: ClientType,
configurationPath: string
): Promise<Map<string, MatchConfig[]>> =>
): Promise<LabelConfigResult> =>
Promise.resolve()
.then(() => {
if (!fs.existsSync(configurationPath)) {
@@ -54,15 +95,49 @@ export const getLabelConfigs = (
// loads (hopefully) a `{[label:string]: MatchConfig[]}`, but is `any`:
const configObject: any = yaml.load(configuration);
// transform `any` => `Map<string,MatchConfig[]>` or throw if yaml is malformed:
return getLabelConfigMapFromObject(configObject);
// transform `any` => `LabelConfigResult` or throw if yaml is malformed:
return getLabelConfigResultFromObject(configObject);
});
export function getLabelConfigResultFromObject(
configObject: any
): LabelConfigResult {
// Extract top-level options
let changedFilesLimit: number | undefined;
let maxFilesChanged: number | undefined;
const limitValue = configObject?.['changed-files-labels-limit'];
if (limitValue !== undefined) {
changedFilesLimit = parseNonNegativeInteger(
limitValue,
'changed-files-labels-limit'
);
}
const maxFilesValue = configObject?.['max-files-changed'];
if (maxFilesValue !== undefined) {
maxFilesChanged = parseNonNegativeInteger(
maxFilesValue,
'max-files-changed'
);
}
return {
labelConfigs: getLabelConfigMapFromObject(configObject),
changedFilesLimit,
maxFilesChanged
};
}
export function getLabelConfigMapFromObject(
configObject: any
): Map<string, MatchConfig[]> {
const labelMap: Map<string, MatchConfig[]> = new Map();
for (const label in configObject) {
// Skip top-level options
if (TOP_LEVEL_OPTIONS.includes(label)) {
continue;
}
const configOptions = configObject[label];
if (
!Array.isArray(configOptions) ||
@@ -124,3 +199,33 @@ export function toMatchConfig(config: any): BaseMatchConfig {
...branchConfig
};
}
/**
* Checks if any of the match configs for a label use changed-files patterns.
* This is used to determine if a label should be counted toward the changed-files limit.
*/
export function configUsesChangedFiles(matchConfigs: MatchConfig[]): boolean {
for (const config of matchConfigs) {
if (config.all) {
for (const baseConfig of config.all) {
if (
baseConfig.changedFiles &&
baseConfig.changedFiles.some(cf => Object.keys(cf).length > 0)
) {
return true;
}
}
}
if (config.any) {
for (const baseConfig of config.any) {
if (
baseConfig.changedFiles &&
baseConfig.changedFiles.some(cf => Object.keys(cf).length > 0)
) {
return true;
}
}
}
}
return false;
}
+6 -6
View File
@@ -1,6 +1,6 @@
export * from './get-changed-files';
export * from './get-changed-pull-requests';
export * from './get-content';
export * from './get-label-configs';
export * from './set-labels';
export * from './types';
export * from './get-changed-files.js';
export * from './get-changed-pull-requests.js';
export * from './get-content.js';
export * from './get-label-configs.js';
export * from './set-labels.js';
export * from './types.js';
+1 -1
View File
@@ -1,5 +1,5 @@
import * as github from '@actions/github';
import {ClientType} from './types';
import {ClientType} from './types.js';
export const setLabels = async (
client: ClientType,
+1 -1
View File
@@ -1,7 +1,7 @@
import * as core from '@actions/core';
import * as github from '@actions/github';
import {Minimatch} from 'minimatch';
import {printPattern, isObject, kebabToCamel} from './utils';
import {printPattern, isObject, kebabToCamel} from './utils.js';
export interface ChangedFilesMatchConfig {
changedFiles?: ChangedFilesGlobPatternsConfig[];
+1 -1
View File
@@ -1,5 +1,5 @@
import * as core from '@actions/core';
import {getPrNumbers} from './get-pr-numbers';
import {getPrNumbers} from './get-pr-numbers.js';
export const getInputs = () => ({
token: core.getInput('repo-token'),
+16 -3
View File
@@ -4,6 +4,13 @@ import * as github from '@actions/github';
const getPrNumberFromContext = () =>
github.context.payload.pull_request?.number;
const sanitizeForWarning = (value: string): string => {
return value.replace(
/[\x00-\x1F\x7F-\x9F]/g,
c => `\\x${c.charCodeAt(0).toString(16).padStart(2, '0')}`
);
};
export const getPrNumbers = (): number[] => {
const prInput = core.getMultilineInput('pr-number');
@@ -14,10 +21,16 @@ export const getPrNumbers = (): number[] => {
const result: number[] = [];
for (const line of prInput) {
const prNumber = parseInt(line, 10);
const trimmed = line.trim();
const prNumber = parseInt(trimmed, 10);
if (isNaN(prNumber) && prNumber <= 0) {
core.warning(`'${prNumber}' is not a valid pull request number`);
if (isNaN(prNumber) || prNumber <= 0 || String(prNumber) !== trimmed) {
const sanitized = sanitizeForWarning(line);
const hint =
sanitized !== line
? ' (non-printable characters were escaped as \\xNN)'
: '';
core.warning(`'${sanitized}' is not a valid pull request number${hint}`);
continue;
}
+1 -1
View File
@@ -1 +1 @@
export * from './get-inputs';
export * from './get-inputs.js';
+99 -17
View File
@@ -1,15 +1,19 @@
import * as core from '@actions/core';
import * as github from '@actions/github';
import * as pluginRetry from '@octokit/plugin-retry';
import * as api from './api';
import * as api from './api/index.js';
import isEqual from 'lodash.isequal';
import {getInputs} from './get-inputs';
import {getInputs} from './get-inputs/index.js';
import {BaseMatchConfig, MatchConfig} from './api/get-label-configs';
import {
BaseMatchConfig,
MatchConfig,
configUsesChangedFiles
} from './api/get-label-configs.js';
import {checkAllChangedFiles, checkAnyChangedFiles} from './changedFiles';
import {checkAllChangedFiles, checkAnyChangedFiles} from './changedFiles.js';
import {checkAnyBranch, checkAllBranch} from './branch';
import {checkAnyBranch, checkAllBranch} from './branch.js';
type ClientType = ReturnType<typeof github.getOctokit>;
@@ -22,7 +26,7 @@ export const run = () =>
core.setFailed(error.message);
});
async function labeler() {
export async function labeler() {
const {token, configPath, syncLabels, dot, prNumbers} = getInputs();
if (!prNumbers.length) {
@@ -35,36 +39,113 @@ async function labeler() {
const pullRequests = api.getPullRequests(client, prNumbers);
for await (const pullRequest of pullRequests) {
const labelConfigs: Map<string, MatchConfig[]> = await api.getLabelConfigs(
client,
configPath
);
const {labelConfigs, changedFilesLimit, maxFilesChanged} =
await api.getLabelConfigs(client, configPath);
// Check if total changed files exceeds the max-files-changed threshold
const skipChangedFilesLabeling =
maxFilesChanged !== undefined &&
pullRequest.changedFiles.length > maxFilesChanged;
if (skipChangedFilesLabeling) {
core.info(
`Total changed files (${pullRequest.changedFiles.length}) exceeds max-files-changed (${maxFilesChanged}), skipping file-based labeling`
);
}
const preexistingLabels = pullRequest.data.labels.map(l => l.name);
const allLabels: Set<string> = new Set<string>(preexistingLabels);
// Track labels that would be added based on changed-files patterns
const changedFilesLabels: Set<string> = new Set<string>();
for (const [label, configs] of labelConfigs.entries()) {
core.debug(`processing ${label}`);
// If this config uses changed-files and we're skipping file-based labeling,
// don't evaluate it at all (skip add/remove) to preserve preexisting labels
const usesChangedFiles = configUsesChangedFiles(configs);
if (skipChangedFilesLabeling && usesChangedFiles) {
core.debug(
`skipping ${label} (uses changed-files and max-files-changed exceeded)`
);
continue;
}
if (checkMatchConfigs(pullRequest.changedFiles, configs, dot)) {
allLabels.add(label);
// Track if this label uses changed-files patterns
if (usesChangedFiles) {
changedFilesLabels.add(label);
}
} else if (syncLabels) {
allLabels.delete(label);
}
}
const labelsToAdd = [...allLabels].slice(0, GITHUB_MAX_LABELS);
// Check if changed-files labels should be skipped due to labels limit
const newChangedFilesLabels = [...changedFilesLabels].filter(
l => !preexistingLabels.includes(l)
);
if (
changedFilesLimit !== undefined &&
newChangedFilesLabels.length > changedFilesLimit
) {
core.info(
`Changed-files labels (${newChangedFilesLabels.length}) exceed limit (${changedFilesLimit}), skipping: ${newChangedFilesLabels.join(', ')}`
);
// Remove all new changed-files labels
for (const label of newChangedFilesLabels) {
allLabels.delete(label);
}
}
const labelsToApply = [...allLabels].slice(0, GITHUB_MAX_LABELS);
const excessLabels = [...allLabels].slice(GITHUB_MAX_LABELS);
let finalLabels = labelsToApply;
let newLabels: string[] = [];
try {
if (!isEqual(labelsToAdd, preexistingLabels)) {
await api.setLabels(client, pullRequest.number, labelsToAdd);
newLabels = labelsToAdd.filter(
label => !preexistingLabels.includes(label)
if (!isEqual(labelsToApply, preexistingLabels)) {
// Fetch the latest labels for the PR
const latestLabels: string[] = [];
// Skip fetching real labels when running tests (uses mock data instead)
if (process.env.NODE_ENV !== 'test') {
const pr = await client.rest.pulls.get({
...github.context.repo,
pull_number: pullRequest.number
});
latestLabels.push(...pr.data.labels.map(l => l.name).filter(Boolean));
}
// Labels added manually during the run (not in first snapshot)
const manualAddedDuringRun = latestLabels.filter(
l => !preexistingLabels.includes(l)
);
// Preserve manual labels first, then apply config-based labels, respecting GitHub's 100-label limit
finalLabels = [
...new Set([...manualAddedDuringRun, ...labelsToApply])
].slice(0, GITHUB_MAX_LABELS);
await api.setLabels(client, pullRequest.number, finalLabels);
newLabels = finalLabels.filter(l => !preexistingLabels.includes(l));
}
} catch (error: any) {
if (
error.name === 'HttpError' &&
error.status === 403 &&
error.message.toLowerCase().includes('unauthorized')
) {
throw new Error(
`Failed to set labels for PR #${pullRequest.number}. The workflow does not have permission to create labels. ` +
`Ensure the 'issues: write' permission is granted in the workflow file or manually create the missing labels in the repository before running the action.`,
{cause: error}
);
} else if (
error.name !== 'HttpError' ||
error.message !== 'Resource not accessible by integration'
) {
@@ -72,7 +153,8 @@ async function labeler() {
}
core.warning(
`The action requires write permission to add labels to pull requests. For more information please refer to the action documentation: https://github.com/actions/labeler#permissions`,
`The action requires 'issues: write' permission to create new labels or 'pull-requests: write' permission to add existing labels to pull requests. ` +
`For more information, refer to the action documentation: https://github.com/actions/labeler#recommended-permissions`,
{
title: `${process.env['GITHUB_ACTION_REPOSITORY']} running under '${github.context.eventName}' is misconfigured`
}
@@ -84,7 +166,7 @@ async function labeler() {
}
core.setOutput('new-labels', newLabels.join(','));
core.setOutput('all-labels', labelsToAdd.join(','));
core.setOutput('all-labels', finalLabels.join(','));
if (excessLabels.length) {
core.warning(
+1 -1
View File
@@ -1,3 +1,3 @@
import {run} from './labeler';
import {run} from './labeler.js';
run();
+5 -5
View File
@@ -2,8 +2,9 @@
"compilerOptions": {
/* Basic Options */
// "incremental": true, /* Enable incremental compilation */
"target": "es6", /* Specify ECMAScript target version: 'ES3' (default), 'ES5', 'ES2015', 'ES2016', 'ES2017', 'ES2018', 'ES2019' or 'ESNEXT'. */
"module": "commonjs", /* Specify module code generation: 'none', 'commonjs', 'amd', 'system', 'umd', 'es2015', or 'ESNext'. */
"target": "ES2022", /* Emit ES2022-compatible JavaScript. */
"module": "NodeNext", /* Use Node.js ESM module semantics. */
"moduleResolution": "NodeNext", /* Resolve modules using Node.js ESM rules. */
// "allowJs": true, /* Allow javascript files to be compiled. */
// "checkJs": true, /* Report errors in .js files. */
// "jsx": "preserve", /* Specify JSX code generation: 'preserve', 'react-native', or 'react'. */
@@ -38,7 +39,7 @@
// "noFallthroughCasesInSwitch": true, /* Report errors for fallthrough cases in switch statement. */
/* Module Resolution Options */
// "moduleResolution": "node", /* Specify module resolution strategy: 'node' (Node.js) or 'classic' (TypeScript pre-1.6). */
// "moduleResolution": "node", /* Specify module resolution strategy: 'node16' or 'NodeNext'. */
// "baseUrl": "./", /* Base directory to resolve non-absolute module names. */
// "paths": {}, /* A series of entries which re-map imports to lookup locations relative to the 'baseUrl'. */
// "rootDirs": [], /* List of root folders whose combined content represents the structure of the project at runtime. */
@@ -46,7 +47,6 @@
// "types": [], /* Type declaration files to be included in compilation. */
// "allowSyntheticDefaultImports": true, /* Allow default imports from modules with no default export. This does not affect code emit, just typechecking. */
"esModuleInterop": true /* Enables emit interoperability between CommonJS and ES Modules via creation of namespace objects for all imports. Implies 'allowSyntheticDefaultImports'. */
// "preserveSymlinks": true, /* Do not resolve the real path of symlinks. */
// "allowUmdGlobalAccess": true, /* Allow accessing UMD globals from modules. */
/* Source Map Options */
@@ -59,5 +59,5 @@
// "experimentalDecorators": true, /* Enables experimental support for ES7 decorators. */
// "emitDecoratorMetadata": true, /* Enables experimental support for emitting type metadata for decorators. */
},
"exclude": ["node_modules", "__tests__", "__mocks__"]
"exclude": ["node_modules", "__tests__", "__mocks__", "jest.config.ts"]
}