Skip to content

Add 'changed-files-labels-limit' and 'max-files-changed' configs to allow capping number of labels added#923

Merged
HarithaVattikuti merged 3 commits into
actions:mainfrom
bluca:label_limit
Mar 26, 2026
Merged

Add 'changed-files-labels-limit' and 'max-files-changed' configs to allow capping number of labels added#923
HarithaVattikuti merged 3 commits into
actions:mainfrom
bluca:label_limit

Conversation

@bluca

@bluca bluca commented Feb 10, 2026

Copy link
Copy Markdown
Contributor

Description:
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-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.

Check list:

  • Mark if documentation changes are required.
  • Mark if tests were added or updated to cover the changes.

Copilot AI review requested due to automatic review settings February 10, 2026 23:31
@bluca bluca requested a review from a team as a code owner February 10, 2026 23:31
@bluca

bluca commented Feb 10, 2026

Copy link
Copy Markdown
Contributor Author

Example of a PR where the labeling gets out of hands and spams the discussion page: systemd/systemd#40624

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR adds a changed-files-limit configuration option to the labeler action to prevent label spam when large refactors touch many components. When the number of new changed-files labels exceeds the configured limit, all new changed-files labels are skipped, while branch-based labels and preexisting labels remain unaffected.

Changes:

  • Added changed-files-limit top-level configuration option to cap the number of changed-files labels
  • Implemented logic to track and differentiate between changed-files labels and branch-based labels
  • Added comprehensive test coverage with 8 new test cases covering various limit scenarios

Reviewed changes

Copilot reviewed 9 out of 10 changed files in this pull request and generated 1 comment.

Show a summary per file
File Description
src/labeler.ts Implements limit checking logic that tracks changed-files labels and removes them if the limit is exceeded
src/api/get-label-configs.ts Adds parsing and validation for the new changed-files-limit config option and a helper function to identify changed-files labels
dist/index.js Compiled JavaScript output reflecting the TypeScript changes
tests/main.test.ts Adds 8 integration test cases covering various limit scenarios including edge cases with preexisting labels
tests/labeler.test.ts Adds unit tests for the new parsing logic and configUsesChangedFiles helper function
tests/fixtures/*.yml Four new YAML test fixtures with different limit configurations
README.md Comprehensive documentation of the new feature with examples and usage guidance

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread src/api/get-label-configs.ts Outdated

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 10 out of 11 changed files in this pull request and generated no new comments.


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

@chiranjib-swain

Copy link
Copy Markdown
Contributor

Hi 👋 thanks again for working on this — the option added in #923 to cap how many changed-files labels get applied is very useful for preventing label spam in large PRs.

One nuance though: it seems to address a slightly different problem than the original request in #486.

changed-files-limit currently limits how many labels are applied, while #486 was more about limiting labeling based on the overall size of the change (e.g., only apply file-based labels if fewer than N files changed).

Would you be open to extending this PR or adding a follow-up to support something like:

max-files-changed: N

If the total changed files exceed N, file-based labeling could be skipped entirely. This would align more closely with the original goal in #486 and also avoid unnecessary pattern scanning on very large PRs.

While reviewing the implementation and README, I also noted a few smaller suggestions:

1. Naming & Semantics

The name changed-files-limit can be somewhat ambiguous since it sounds like it limits the number of changed files, while it actually limits the number of labels generated by changed-files rules.

Suggestion

Consider renaming to something clearer like changed-files-labels-limit.

If renaming could break configs, we could support both names and treat changed-files-limit as a deprecated alias.

2. Stricter Configuration Parsing

The current parsing uses parseInt, which can silently accept invalid inputs.

Examples:

  • "10abc" → interpreted as 10
  • "3.2" → interpreted as 3

To make configuration validation stricter and safer:

  • If the value is a string, require it to match /^\d+$/ before parsing.
  • If the value is a number, validate with:
  • Number.isInteger(value)
  • Number.isFinite(value)

Potential tests:

  • "10abc" → should throw an error
  • "3.2" → should throw an error
  • 3.2 (float) → should throw an error

3. Clarifying the Definition of a “Changed-Files Label”

One subtle behavior worth documenting is how the limit interacts with mixed rules.

Example:

changed-files-limit: 0

mixed-label:
 - any:
     - head-branch: "^test/"
     - changed-files:
         - any-glob-to-any-file: ["components/a/**"]

Even if the label matches via the branch rule, the presence of a `changed-files` rule causes it to be treated as a changed-files label and therefore subject to the limit.

It might help to document something like:

Any label definition that includes a `changed-files` rule is considered a changed-files label and is subject to changed-files-limit, regardless of which condition caused the label to match.

Adding a small dedicated test fixture could also help make this behavior explicit.

4. README Documentation

The new Configuration Options section is a great addition 👍. It might help to explicitly mention:

  • The limit counts only new labels derived from changed-files rules (labels already present on the PR are ignored).
  • Labels are skipped only when newChangedFilesLabels > limit. If newChangedFilesLabels === limit, they are still applied.
  • If the limit is exceeded, all new changed-files labels are skipped for that run.
  • Labels based on branch conditions (head-branch, base-branch) are not affected.

@bluca bluca changed the title Add 'changed-files-limit' config to allow capping number of labels added Add 'changed-files-labels-limit' and 'changed-files-labels-limit' configs to allow capping number of labels added Mar 11, 2026
@bluca

bluca commented Mar 11, 2026

Copy link
Copy Markdown
Contributor Author

@chiranjib-swain thanks for the review, applied all suggestions and requests

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 13 out of 14 changed files in this pull request and generated 3 comments.


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

You can also share your feedback on Copilot code review. Take the survey.

Comment thread src/labeler.ts
Comment thread src/api/get-label-configs.ts
Comment thread README.md

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 13 out of 14 changed files in this pull request and generated 2 comments.


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

You can also share your feedback on Copilot code review. Take the survey.

Comment thread src/api/get-label-configs.ts
Comment thread __tests__/fixtures/max_files_with_branch.yml Outdated
@bluca bluca force-pushed the label_limit branch 2 times, most recently from a07363b to ce49779 Compare March 12, 2026 11:04
@bluca

bluca commented Mar 12, 2026

Copy link
Copy Markdown
Contributor Author

Fixes the formatting issue (hopefully)

@bluca

bluca commented Mar 13, 2026

Copy link
Copy Markdown
Contributor Author

@chiranjib-swain anything else I can do here? Thanks

@chiranjib-swain

chiranjib-swain commented Mar 19, 2026

Copy link
Copy Markdown
Contributor

Hi @bluca ,Really nice work on this 👏 — the addition of max-files-changed is a great improvement and should help a lot in reducing label noise on large PRs.

🔹 Suggestion: Improve parseNonNegativeInteger

One small suggestion regarding parseNonNegativeInteger used here: https://github.com/bluca/labeler/blob/a07363b7e377762584a79fe87e6a744d5a385058/src/api/get-label-configs.ts#L33

Currently the regex check runs directly on the raw string value. This means inputs like " 30 " would be rejected even though they represent a valid integer. It might be worth trimming the string before applying the regex so that common whitespace cases are handled more gracefully.

Since the regex already guarantees that the string contains only digits, we could also use Number(trimmed) instead of parseInt. That avoids relying on parseInt’s permissive behavior while keeping the logic clear.

Finally, the non-negativity check (value < 0) could potentially be included directly in the numeric branch condition to simplify the validation flow slightly.

Something along these lines could work:

const trimmed = value.trim()

if (!/^\d+$/.test(trimmed)) {
  throw new Error(
    `Invalid value for '${optionName}': must be a non-negative integer (got '${value}')`
  )
}

parsed = Number(trimmed)

This is a fairly small refinement, but it could make the validation a bit more robust while keeping the current behavior intact.

🔹 Suggestion: Clarify Threshold Semantics

Additionally, one small suggestion regarding threshold semantics:

If both limits are introduced/configured (e.g., max-files-changed and changed-files-labels-limit), it might help to clearly define their interaction. For example:

When both are configured, max-files-changed is evaluated first. If it triggers, changed-files-labels-limit is not evaluated.

Documenting this precedence explicitly could help avoid confusion and make the behavior more predictable.

🔹 Suggestion: Reserved Keys Clarification

Using keys like max-files-changed as labels in .github/labeler.yml causes failures because they are treated as reserved config options and parsed as integers.

Currently, this results in an error like:

Invalid value for 'max-files-changed': expected a non-negative integer

We should either document these as reserved keys or improve the error message, e.g.:

'max-files-changed' is a reserved top-level option and cannot be used as a label. Please rename it.

🔹 Suggestion: PR Title Improvement

Your current title:
Add 'changed-files-labels-limit' and 'changed-files-labels-limit' configs to allow capping number of labels added

has a typo (the same option is repeated) and it doesn’t mention max-files-changed.

bluca added 2 commits March 19, 2026 10:41
…bels 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.
@bluca bluca changed the title Add 'changed-files-labels-limit' and 'changed-files-labels-limit' configs to allow capping number of labels added Add 'changed-files-labels-limit' and 'max-files-changed' configs to allow capping number of labels added Mar 19, 2026
@bluca

bluca commented Mar 19, 2026

Copy link
Copy Markdown
Contributor Author

@chiranjib-swain thank you, updated as requested, PTAL

@bluca

bluca commented Mar 23, 2026

Copy link
Copy Markdown
Contributor Author

CI failures look to be unrelated (dependencies audit)

@chiranjib-swain

Copy link
Copy Markdown
Contributor

Thanks for the improvements here — the new caps for changed-files labeling look really useful, especially for large refactors.

One thing before we can proceed: the dist check is currently failing on this PR. Could you please re-run the build step that generates the dist/ artifacts and commit the updated output so the check passes?

Also, small docs nits for clarity:

  • Could we use “Pre-existing labels” (hyphenated) instead of “Preexisting”?
  • Could we add a NOTE clarifying that when both max-files-changed and changed-files-labels-limit are set, max-files-changed is evaluated first, and if it triggers then changed-files-labels-limit is not evaluated?

Thanks again!

@bluca

bluca commented Mar 23, 2026

Copy link
Copy Markdown
Contributor Author

Hi - I've ran npm run build but it generates no diff for me? The file stays the same

@bluca

bluca commented Mar 23, 2026

Copy link
Copy Markdown
Contributor Author

Could we use “Pre-existing labels” (hyphenated) instead of “Preexisting”?

Changed

Could we add a NOTE clarifying that when both max-files-changed and changed-files-labels-limit are set, max-files-changed is evaluated first, and if it triggers then changed-files-labels-limit is not evaluated?

There already is:

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.

Would you like me to reword it or move it?

@bluca

bluca commented Mar 23, 2026

Copy link
Copy Markdown
Contributor Author

Hi - I've ran npm run build but it generates no diff for me? The file stays the same

This is on Debian unstable with NPM 9.2.0

@HarithaVattikuti

Copy link
Copy Markdown
Contributor

Hi @bluca

The Labeler repository now officially runs on Node.js 24, as reflected in its workflows and documentation.

Please use Node.js version 24 / npm version 11+ when running the command to ensure the check dist workflow passes.

…abelling

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 actions#486
@bluca

bluca commented Mar 23, 2026

Copy link
Copy Markdown
Contributor Author

Hi @bluca

The Labeler repository now officially runs on Node.js 24, as reflected in its workflows and documentation.

Please use Node.js version 24 / npm version 11+ when running the command to ensure the check dist workflow passes.

@HarithaVattikuti got it thanks, rerun with npm 11.12.0 and now it did update it, pushed it

@HarithaVattikuti HarithaVattikuti merged commit c5dadc2 into actions:main Mar 26, 2026
4 of 10 checks passed
@bluca bluca deleted the label_limit branch March 26, 2026 15:04
eleboucher pushed a commit to eleboucher/homelab that referenced this pull request May 6, 2026
…v6.0.1 → v6.1.0) (#384)

This PR contains the following updates:

| Package | Type | Update | Change |
|---|---|---|---|
| [https://github.com/actions/labeler](https://github.com/actions/labeler) | action | minor | `v6.0.1` → `v6.1.0` |

---

### Release Notes

<details>
<summary>actions/labeler (https://github.com/actions/labeler)</summary>

### [`v6.1.0`](https://github.com/actions/labeler/releases/tag/v6.1.0)

[Compare Source](actions/labeler@v6.0.1...v6.1.0)

#### Enhancements

- Add changed-files-labels-limit and max-files-changed configuration options to cap the number of labels added by [@&#8203;bluca](https://github.com/bluca) in [#&#8203;923](actions/labeler#923)

#### Bug Fixes

- Improve Labeler Action documentation and permission error handling by [@&#8203;chiranjib-swain](https://github.com/chiranjib-swain) in [#&#8203;897](actions/labeler#897)
- Preserve manually added labels during workflow runs and refine label synchronization logic by [@&#8203;chiranjib-swain](https://github.com/chiranjib-swain) in [#&#8203;917](actions/labeler#917)

#### Dependency Updates

- Upgrade brace-expansion from 1.1.11 to 1.1.12 and document breaking changes in v6 by [@&#8203;dependabot](https://github.com/dependabot) in [#&#8203;877](actions/labeler#877)
- Upgrade minimatch from 10.0.1 to 10.2.3 by [@&#8203;dependabot](https://github.com/dependabot) in [#&#8203;926](actions/labeler#926)
- Upgrade dependencies ([@&#8203;actions/core](https://github.com/actions/core), [@&#8203;actions/github](https://github.com/actions/github), js-yaml, minimatch, [@&#8203;typescript-eslint](https://github.com/typescript-eslint)) by [@&#8203;Copilot](https://github.com/Copilot) in [#&#8203;934](actions/labeler#934)

#### New Contributors

- [@&#8203;chiranjib-swain](https://github.com/chiranjib-swain) made their first contribution in [#&#8203;897](actions/labeler#897)
- [@&#8203;bluca](https://github.com/bluca) made their first contribution in [#&#8203;923](actions/labeler#923)
- [@&#8203;Copilot](https://github.com/Copilot) made their first contribution in [#&#8203;934](actions/labeler#934)

**Full Changelog**: <actions/labeler@v6...v6.1.0>

</details>

---

### Configuration

📅 **Schedule**: Branch creation - At any time (no schedule defined), Automerge - At any time (no schedule defined).

🚦 **Automerge**: Disabled by config. Please merge this manually once you are satisfied.

♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox.

🔕 **Ignore**: Close this PR and you won't be reminded about this update again.

---

 - [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check this box

---

This PR has been generated by [Renovate Bot](https://github.com/renovatebot/renovate).
<!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiI0My4xMDEuMSIsInVwZGF0ZWRJblZlciI6IjQzLjEwMS4xIiwidGFyZ2V0QnJhbmNoIjoibWFpbiIsImxhYmVscyI6WyJyZW5vdmF0ZS9naXRodWItYWN0aW9uIiwidHlwZS9taW5vciJdfQ==-->

Reviewed-on: https://git.erwanleboucher.dev/eleboucher/homelab/pulls/384
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants