Compare commits

...

166 Commits

Author SHA1 Message Date
MaksimZhukov
f4eefdc659 [Beta] Implement the new structure of the match object for the changed-files section (#680)
* Implement the new structure of the match object for changed files section

* Replace inner loops with the find method
2023-09-20 13:43:39 +02:00
MaksimZhukov
4f052778de Merge pull request #574 from MaksimZhukov/v5.0.0-beta.1
fix: correct reading of sync-labels input
2023-05-24 13:03:28 +02:00
MaksimZhukov
26342ba349 fix: correct reading of sync-labels input 2023-05-24 12:21:33 +02:00
MaksimZhukov
e1fcf6fe5b Merge pull request #203 from joshdales/main
Assigns labels based on branch names
2023-05-24 12:01:55 +02:00
dependabot[bot]
2713f7303c Bump @typescript-eslint/eslint-plugin from 5.59.6 to 5.59.7 (#572)
Bumps [@typescript-eslint/eslint-plugin](https://github.com/typescript-eslint/typescript-eslint/tree/HEAD/packages/eslint-plugin) from 5.59.6 to 5.59.7.
- [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/v5.59.7/packages/eslint-plugin)

---
updated-dependencies:
- dependency-name: "@typescript-eslint/eslint-plugin"
  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>
2023-05-23 19:12:09 +02:00
dependabot[bot]
a4eda65d3d Bump @typescript-eslint/parser from 5.59.6 to 5.59.7 (#573)
Bumps [@typescript-eslint/parser](https://github.com/typescript-eslint/typescript-eslint/tree/HEAD/packages/parser) from 5.59.6 to 5.59.7.
- [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/v5.59.7/packages/parser)

---
updated-dependencies:
- dependency-name: "@typescript-eslint/parser"
  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>
2023-05-23 19:07:31 +02:00
MaksimZhukov
5c4deb8a24 Revert "fix: correct reading of sync-labels input. (#480)" (#564)
This reverts commit 751921c443.
2023-05-23 19:06:03 +02:00
dependabot[bot]
61662e8f41 Bump eslint from 8.40.0 to 8.41.0 (#569)
Bumps [eslint](https://github.com/eslint/eslint) from 8.40.0 to 8.41.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.40.0...v8.41.0)

---
updated-dependencies:
- dependency-name: eslint
  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>
2023-05-23 11:49:27 +02:00
dependabot[bot]
6b107e7a7e Bump @typescript-eslint/parser from 5.59.5 to 5.59.6 (#565)
Bumps [@typescript-eslint/parser](https://github.com/typescript-eslint/typescript-eslint/tree/HEAD/packages/parser) from 5.59.5 to 5.59.6.
- [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/v5.59.6/packages/parser)

---
updated-dependencies:
- dependency-name: "@typescript-eslint/parser"
  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>
2023-05-17 15:19:55 +02:00
dependabot[bot]
d93c73a681 Bump @typescript-eslint/eslint-plugin from 5.59.5 to 5.59.6 (#566)
Bumps [@typescript-eslint/eslint-plugin](https://github.com/typescript-eslint/typescript-eslint/tree/HEAD/packages/eslint-plugin) from 5.59.5 to 5.59.6.
- [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/v5.59.6/packages/eslint-plugin)

---
updated-dependencies:
- dependency-name: "@typescript-eslint/eslint-plugin"
  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>
2023-05-17 15:15:42 +02:00
Josh Dales
3352df1f2b Bring test I accidently deleted 2023-05-17 07:26:44 -04:00
Josh Dales
57d34076e0 Better check for empty configs in checkAll 2023-05-17 07:05:19 -04:00
Josh Dales
a256a58edf Add check for empty objects in checkAll 2023-05-15 10:45:56 -04:00
Josh Dales
a5bed11d4d Run the build command 2023-05-11 17:02:27 -04:00
Josh Dales
4ac17648a4 Add a guard clause to stop false changed-files positives 2023-05-11 17:02:05 -04:00
Josh Dales
34a5bf6e83 Update the validation when there are no options in the matchConfigs 2023-05-11 17:01:46 -04:00
Josh Dales
09645fd40d Move the allowed Matchconfig keys into a constant 2023-05-11 16:37:58 -04:00
Josh Dales
51cc5e079c Update text in test descriptions and logging
Co-authored-by: MaksimZhukov <46996400+MaksimZhukov@users.noreply.github.com>
2023-05-11 16:35:05 -04:00
dependabot[bot]
b6f708799c Bump @typescript-eslint/eslint-plugin from 5.59.2 to 5.59.5 (#559)
Bumps [@typescript-eslint/eslint-plugin](https://github.com/typescript-eslint/typescript-eslint/tree/HEAD/packages/eslint-plugin) from 5.59.2 to 5.59.5.
- [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/v5.59.5/packages/eslint-plugin)

---
updated-dependencies:
- dependency-name: "@typescript-eslint/eslint-plugin"
  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>
2023-05-11 12:24:42 +02:00
dependabot[bot]
2d89bd5059 Bump @typescript-eslint/parser from 5.59.2 to 5.59.5 (#560)
Bumps [@typescript-eslint/parser](https://github.com/typescript-eslint/typescript-eslint/tree/HEAD/packages/parser) from 5.59.2 to 5.59.5.
- [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/v5.59.5/packages/parser)

---
updated-dependencies:
- dependency-name: "@typescript-eslint/parser"
  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>
2023-05-10 13:25:33 +02:00
dependabot[bot]
581d1100aa Bump eslint from 8.39.0 to 8.40.0 (#558)
Bumps [eslint](https://github.com/eslint/eslint) from 8.39.0 to 8.40.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.39.0...v8.40.0)

---
updated-dependencies:
- dependency-name: eslint
  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>
2023-05-09 13:07:47 +02:00
dependabot[bot]
8bb4872750 Bump eslint from 8.38.0 to 8.39.0 (#543)
Bumps [eslint](https://github.com/eslint/eslint) from 8.38.0 to 8.39.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.38.0...v8.39.0)

---
updated-dependencies:
- dependency-name: eslint
  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>
2023-05-05 15:52:58 +02:00
dependabot[bot]
9c4ae1e112 Bump @typescript-eslint/eslint-plugin from 5.58.0 to 5.59.2 (#553)
Bumps [@typescript-eslint/eslint-plugin](https://github.com/typescript-eslint/typescript-eslint/tree/HEAD/packages/eslint-plugin) from 5.58.0 to 5.59.2.
- [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/v5.59.2/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>
2023-05-05 15:44:42 +02:00
dependabot[bot]
228fdad71d Bump prettier from 2.8.7 to 2.8.8 (#544)
Bumps [prettier](https://github.com/prettier/prettier) from 2.8.7 to 2.8.8.
- [Release notes](https://github.com/prettier/prettier/releases)
- [Changelog](https://github.com/prettier/prettier/blob/main/CHANGELOG.md)
- [Commits](https://github.com/prettier/prettier/compare/2.8.7...2.8.8)

---
updated-dependencies:
- dependency-name: prettier
  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>
2023-05-05 15:44:04 +02:00
dependabot[bot]
377691d3d6 Bump @typescript-eslint/parser from 5.58.0 to 5.59.2 (#554)
Bumps [@typescript-eslint/parser](https://github.com/typescript-eslint/typescript-eslint/tree/HEAD/packages/parser) from 5.58.0 to 5.59.2.
- [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/v5.59.2/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>
2023-05-05 15:43:18 +02:00
Josh Dales
9cfddd0144 Consolidate the new any change files test into the old one 2023-05-05 09:05:40 -04:00
Josh Dales
3aa0d436e5 Better test description 2023-05-05 09:02:53 -04:00
Josh Dales
9488def29a Update tests and build 2023-05-05 08:58:23 -04:00
Josh Dales
11812c37f6 Revert "Have a single isMatch for checking changed files"
This reverts commit d4d4a104a2.
2023-05-05 08:56:09 -04:00
Josh Dales
68a2598016 Merge branch 'actions:main' into main 2023-04-13 16:07:45 -04:00
Josh Dales
13e75b4361 minor update to the readme 2023-04-13 15:20:47 -04:00
Josh Dales
2a3422a64e Better description for the new test 2023-04-13 15:15:10 -04:00
Josh Dales
c1b0ca76ee Run the build command 2023-04-13 15:02:40 -04:00
Josh Dales
2637d23bca Add test for when not all globs match any changed file 2023-04-13 14:58:52 -04:00
Josh Dales
d4d4a104a2 Have a single isMatch for checking changed files 2023-04-13 14:38:41 -04:00
dependabot[bot]
9471598e3b Bump @typescript-eslint/parser from 5.57.0 to 5.58.0 (#539)
Bumps [@typescript-eslint/parser](https://github.com/typescript-eslint/typescript-eslint/tree/HEAD/packages/parser) from 5.57.0 to 5.58.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/v5.58.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>
2023-04-13 14:13:32 +02:00
dependabot[bot]
b0e65268f8 Bump eslint from 8.37.0 to 8.38.0 (#537)
Bumps [eslint](https://github.com/eslint/eslint) from 8.37.0 to 8.38.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.37.0...v8.38.0)

---
updated-dependencies:
- dependency-name: eslint
  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>
2023-04-13 14:11:16 +02:00
dependabot[bot]
757daa4b3c Bump @typescript-eslint/eslint-plugin from 5.57.0 to 5.58.0 (#540)
Bumps [@typescript-eslint/eslint-plugin](https://github.com/typescript-eslint/typescript-eslint/tree/HEAD/packages/eslint-plugin) from 5.57.0 to 5.58.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/v5.58.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>
2023-04-13 14:10:51 +02:00
Ivan
d8f73a2893 Fix glob bug in package.json scripts section (#528) 2023-04-03 12:49:40 +02:00
Milos Pantic
3c1531c7aa Merge pull request #531 from actions/dependabot/npm_and_yarn/eslint-8.37.0
Bump eslint from 8.36.0 to 8.37.0
2023-03-30 20:00:49 +02:00
dependabot[bot]
2fad4e29df Bump eslint from 8.36.0 to 8.37.0
Bumps [eslint](https://github.com/eslint/eslint) from 8.36.0 to 8.37.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.36.0...v8.37.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-03-30 17:51:01 +00:00
Milos Pantic
656fcaf1a6 Merge pull request #530 from actions/dependabot/npm_and_yarn/typescript-eslint/parser-5.57.0
Bump @typescript-eslint/parser from 5.56.0 to 5.57.0
2023-03-30 19:50:04 +02:00
dependabot[bot]
649bbe91ec Bump @typescript-eslint/parser from 5.56.0 to 5.57.0
Bumps [@typescript-eslint/parser](https://github.com/typescript-eslint/typescript-eslint/tree/HEAD/packages/parser) from 5.56.0 to 5.57.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/v5.57.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-03-30 17:35:26 +00:00
Milos Pantic
dc4d5ad22c Merge pull request #529 from actions/dependabot/npm_and_yarn/typescript-eslint/eslint-plugin-5.57.0
Bump @typescript-eslint/eslint-plugin from 5.56.0 to 5.57.0
2023-03-30 19:34:49 +02:00
Milos Pantic
b5e92d4c4b Merge pull request #527 from actions/dependabot/npm_and_yarn/prettier-2.8.7
Bump prettier from 2.8.6 to 2.8.7
2023-03-30 19:31:44 +02:00
dependabot[bot]
4c60b58719 Bump @typescript-eslint/eslint-plugin from 5.56.0 to 5.57.0
Bumps [@typescript-eslint/eslint-plugin](https://github.com/typescript-eslint/typescript-eslint/tree/HEAD/packages/eslint-plugin) from 5.56.0 to 5.57.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/v5.57.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>
2023-03-28 15:57:02 +00:00
Josh Dales
7f169bc0f2 Merge pull request #4 from joshdales/another-config-setup
Change the structure of the config
2023-03-27 17:25:27 -04:00
Josh Dales
2f1dfd1ef0 Adjust the indenting again 2023-03-27 17:15:14 -04:00
Josh Dales
b1a2f85ed8 Update debugging indentation on the branch checks 2023-03-27 16:37:55 -04:00
Josh Dales
67604ee822 Update more debugging statements 2023-03-27 16:26:58 -04:00
Josh Dales
4be192c7d6 Run the build command 2023-03-27 16:23:04 -04:00
Josh Dales
3ddce51a65 Update the debug values 2023-03-27 16:15:03 -04:00
Josh Dales
938f9c9893 Update the readme a little more 2023-03-26 09:46:29 -04:00
Josh Dales
210043eed1 Run the build command 2023-03-25 19:09:30 -04:00
Josh Dales
fa7f98c785 Yikes, still missed that 2023-03-25 19:09:06 -04:00
Josh Dales
29382eb4ff Build command 2023-03-25 17:42:44 -04:00
Josh Dales
0b2cfb01d7 Im an idiot, bad copy pasta 2023-03-25 17:42:17 -04:00
Josh Dales
62f22bdebe Run the build command 2023-03-25 17:24:52 -04:00
Josh Dales
ef6ab1b64a Add function for checking if any path matches 2023-03-25 17:22:04 -04:00
Josh Dales
5ac9519cbf Update the README 2023-03-25 16:31:45 -04:00
Josh Dales
4554c0d1af Add a bunch more tests 2023-03-25 16:07:56 -04:00
Josh Dales
49676461cb Run the build command 2023-03-24 22:29:57 -04:00
Josh Dales
432b275f71 Get all the tests passings 2023-03-24 22:29:41 -04:00
Josh Dales
3bec9227d1 Add any and all functions for both checks 2023-03-24 21:51:33 -04:00
Josh Dales
a9e07ce8ff Add some new tests 2023-03-24 21:23:51 -04:00
Josh Dales
e51b118725 Change the structure of the config 2023-03-24 21:08:59 -04:00
dependabot[bot]
30f43a6adc Bump prettier from 2.8.6 to 2.8.7
Bumps [prettier](https://github.com/prettier/prettier) from 2.8.6 to 2.8.7.
- [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/2.8.6...2.8.7)

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

Signed-off-by: dependabot[bot] <support@github.com>
2023-03-24 15:56:42 +00:00
Josh Dales
5d0a66ed59 Run the build command again 2023-03-23 09:09:29 -04:00
Josh Dales
9bfc9998ab Run build and fix bad merge 2023-03-23 09:08:08 -04:00
Josh Dales
8e6367ddee Merge branch 'main' into main 2023-03-23 09:02:46 -04:00
Milos Pantic
7012d51fe0 Merge pull request #525 from panticmilos/vmpantic/bump-minimatch
Bump license version
2023-03-23 12:36:22 +01:00
Milos Pantic
9edd2bf941 Bump license version 2023-03-23 12:16:28 +01:00
Milos Pantic
ebf4aac003 Merge pull request #523 from actions/dependabot/npm_and_yarn/prettier-2.8.6
Bump prettier from 2.8.4 to 2.8.6
2023-03-23 12:15:48 +01:00
Adam Azarchs
751921c443 fix: correct reading of sync-labels input. (#480)
* fix: correct reading of sync-labels input.

Contrary to the assumptions made in the unit tests, core.getInput
always returns a string, and !!'false' is true.

Also updates the unit test to reduce changes of regressions by ensuring
that the mocked getInput returns a string, as it would in production.

Fixes https://github.com/actions/labeler/issues/112

Make sure test catches regressions.

* Rebuild dist/index.js.
2023-03-23 10:47:14 +01:00
Milos Pantic
468a5e0250 Rebuild minimatch (#522)
* Rebuild minimatch and adapt changed interface

* Apply formatting

* Update minimatch license
2023-03-23 10:45:05 +01:00
dependabot[bot]
1ed0c2c7a6 Bump prettier from 2.8.4 to 2.8.6
Bumps [prettier](https://github.com/prettier/prettier) from 2.8.4 to 2.8.6.
- [Release notes](https://github.com/prettier/prettier/releases)
- [Changelog](https://github.com/prettier/prettier/blob/main/CHANGELOG.md)
- [Commits](https://github.com/prettier/prettier/compare/2.8.4...2.8.6)

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

Signed-off-by: dependabot[bot] <support@github.com>
2023-03-22 15:56:46 +00:00
Milos Pantic
72bf170dc0 Merge pull request #521 from actions/dependabot/npm_and_yarn/typescript-eslint/eslint-plugin-5.56.0
Bump @typescript-eslint/eslint-plugin from 5.54.0 to 5.56.0
2023-03-22 15:15:44 +01:00
Milos Pantic
e761520c9d Merge pull request #520 from actions/dependabot/npm_and_yarn/eslint-config-prettier-8.8.0
Bump eslint-config-prettier from 8.6.0 to 8.8.0
2023-03-22 15:13:07 +01:00
dependabot[bot]
5ecb1a5c3f Bump @typescript-eslint/eslint-plugin from 5.54.0 to 5.56.0
Bumps [@typescript-eslint/eslint-plugin](https://github.com/typescript-eslint/typescript-eslint/tree/HEAD/packages/eslint-plugin) from 5.54.0 to 5.56.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/v5.56.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>
2023-03-22 14:10:01 +00:00
dependabot[bot]
edfedeeea2 Bump eslint-config-prettier from 8.6.0 to 8.8.0
Bumps [eslint-config-prettier](https://github.com/prettier/eslint-config-prettier) from 8.6.0 to 8.8.0.
- [Release notes](https://github.com/prettier/eslint-config-prettier/releases)
- [Changelog](https://github.com/prettier/eslint-config-prettier/blob/main/CHANGELOG.md)
- [Commits](https://github.com/prettier/eslint-config-prettier/compare/v8.6.0...v8.8.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-03-22 14:08:56 +00:00
Milos Pantic
bf8c2560d4 Merge pull request #519 from actions/dependabot/npm_and_yarn/typescript-eslint/parser-5.56.0
Bump @typescript-eslint/parser from 5.54.0 to 5.56.0
2023-03-22 15:06:45 +01:00
Milos Pantic
113f4f535c Merge pull request #514 from actions/dependabot/npm_and_yarn/eslint-8.36.0
Bump eslint from 8.35.0 to 8.36.0
2023-03-22 15:04:16 +01:00
dependabot[bot]
e22b544e48 Bump @typescript-eslint/parser from 5.54.0 to 5.56.0
Bumps [@typescript-eslint/parser](https://github.com/typescript-eslint/typescript-eslint/tree/HEAD/packages/parser) from 5.54.0 to 5.56.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/v5.56.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-03-21 15:58:11 +00:00
Josh Dales
1c9c27e128 Run the build command 2023-03-20 21:53:16 -04:00
Josh Dales
b25e3a8c27 Better wording for the new test 2023-03-20 17:51:58 -04:00
Josh Dales
d31255f7be Make sure that empty config options don't accidently label things 2023-03-20 17:40:28 -04:00
Josh Dales
92990c0c57 Don't allow empty changed-files objects through 2023-03-20 17:40:28 -04:00
Josh Dales
d0d3628020 Add extra tests and use toEqual matcher.
Turns out that toMatchObject would allow extra properties through
2023-03-20 17:40:28 -04:00
Josh Dales
cc1e02580b Update object assignment in toChangedFilesMatchConfig 2023-03-20 17:40:28 -04:00
Josh Dales
64ce5e9235 Update README with better description for branches
Co-authored-by: MaksimZhukov <46996400+MaksimZhukov@users.noreply.github.com>
2023-03-20 15:38:14 -04:00
Josh Dales
7741e57c6a Run the build command 2023-03-18 17:16:58 -04:00
Josh Dales
65b7640e45 Add unit tests for toMatchConfig 2023-03-18 17:15:18 -04:00
Josh Dales
e9a1777eb0 Fix linting and formatting 2023-03-18 16:46:54 -04:00
Josh Dales
17694aa238 Update the argument type for toMatchConfig 2023-03-18 16:44:50 -04:00
Josh Dales
c31ee1fd86 Add more unit tests for changedFiles.ts 2023-03-18 16:44:50 -04:00
Josh Dales
3af9a47a26 Add unit tests for toChangedFilesMatchConfig 2023-03-18 16:44:49 -04:00
Josh Dales
a988f4eb9d Add todo tests for changedFiles 2023-03-18 16:44:49 -04:00
Josh Dales
ef108a9d83 Convert the yaml output to a matchConfig in getLabelConfigMapFromObject 2023-03-18 16:44:49 -04:00
Josh Dales
1ce9b356f6 Move all changedFiles logic into it's own file 2023-03-18 16:44:49 -04:00
Josh Dales
9f259ee115 Rename checkGlobs to checkMatchConfigs and check each property 2023-03-18 16:44:49 -04:00
Josh Dales
c08f5faa12 Condense assignment of further config options in toChangedFilesMatchConfig 2023-03-18 16:44:49 -04:00
Josh Dales
51b763cbf2 Update comments in getMatchConfigs to represent updated types 2023-03-18 16:44:49 -04:00
Josh Dales
e939550344 Simplfy the conditions in toBranchMatchConfig 2023-03-18 16:44:49 -04:00
Josh Dales
e4486e9ed9 Throw an error if the config is the wrong type 2023-03-18 16:44:49 -04:00
Josh Dales
fc5eb711b0 Revert "reverse the conditions of checkMatch"
This reverts commit 0eb9d49330.
2023-03-18 16:44:49 -04:00
Josh Dales
3eec5d8ccc Update the syntax for checking a match 2023-03-18 16:44:49 -04:00
Josh Dales
90ef37079a Merge branch 'actions:main' into main 2023-03-18 16:44:40 -04:00
Josh Dales
f40b38734d Correct errors and typos in the README
Co-authored-by: Ivan <98037481+IvanZosimov@users.noreply.github.com>
2023-03-17 17:14:59 -04:00
github-actions[bot]
ca88756804 Update configuration files (#513)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2023-03-15 00:45:03 +01:00
dependabot[bot]
2a81921fe4 Bump eslint from 8.35.0 to 8.36.0
Bumps [eslint](https://github.com/eslint/eslint) from 8.35.0 to 8.36.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.35.0...v8.36.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-03-13 15:56:59 +00:00
Marko Zivic
59036c7b95 Merge pull request #509 from akv-platform/reusable-workflow
Turn on automatic update of ESLint and Prettier configuration files
2023-03-10 10:56:35 +01:00
IvanZosimov
a589a5f6e6 Add update-config-files.yml 2023-03-09 14:03:36 +01:00
Ivan
8d81f881dd Add and configure ESLint and update configuration for Prettier (#508)
* Add ESLint and update Prettier

* Rebuild action

* Update package.json
2023-03-09 15:02:17 +02:00
Josh Dales
84e83a9b19 Merge branch 'main' into main 2023-03-08 18:10:37 -05:00
Josh Dales
5e6bdf6d89 update the example workflow in the readme 2023-03-03 11:17:10 -05:00
Josh Dales
394a01bde3 Make getBranchName argument non-optional 2023-03-03 11:15:48 -05:00
Josh Dales
2a5bc55cbf Fix bad test descriptions
Co-authored-by: MaksimZhukov <46996400+MaksimZhukov@users.noreply.github.com>
2023-03-03 09:28:40 -05:00
Josh Dales
2e10ffb6ec Reference minimatch in docs
Co-authored-by: MaksimZhukov <46996400+MaksimZhukov@users.noreply.github.com>
2023-03-03 09:26:43 -05:00
Josh Dales
e5b1bddf5e Update the README with documentation about the new config structure 2023-02-21 11:51:45 -05:00
Josh Dales
8943ca20c9 Merge pull request #3 from joshdales/new-config-structure 2023-02-21 08:38:50 -05:00
Josh Dales
56347d54a1 Add unit tests for toBranchMatchConfig 2023-02-21 08:30:24 -05:00
Josh Dales
da83a1845f Make sure that the changed files config values are an array 2023-02-19 18:10:19 -05:00
Josh Dales
ed31b27f2e Rename some functions and variables to match what they are doing 2023-02-19 16:46:14 -05:00
Josh Dales
09f085373a Fix some typos in the branch checks 2023-02-19 12:17:15 -05:00
Josh Dales
0eb9d49330 reverse the conditions of checkMatch 2023-01-29 15:58:23 -05:00
Josh Dales
b071d82cb8 Run the build command 2023-01-29 15:09:44 -05:00
Josh Dales
7d175313b7 Update the labeler tests 2023-01-29 15:09:06 -05:00
Josh Dales
969899da68 Add the changedFiles key and update logic in labeler 2023-01-29 14:10:07 -05:00
Josh Dales
7a5c525049 Create new interfaces for MatchConfig 2023-01-28 23:14:53 -05:00
Josh Dales
922ffdf5ad Remove deprecated IMinimatch import from labeler.ts 2023-01-28 22:43:56 -05:00
Josh Dales
231de6bc24 Remove the branch option and replace with just head-branch and base-branch 2023-01-28 22:30:05 -05:00
Josh Dales
2daf35ae4b Add an extra test now that we can check the base branch 2023-01-28 18:08:48 -05:00
Josh Dales
0b6e68d75a Add options for getting the head or base branch 2023-01-28 17:57:52 -05:00
Josh Dales
cd3a8df80d Create a test file for branch 2023-01-28 16:45:29 -05:00
Josh Dales
2343710777 Move all the branch checking into its own file 2023-01-28 15:58:00 -05:00
Josh Dales
f2b2513f41 Update the matching to use a regexp rather than minimatch 2023-01-28 15:34:31 -05:00
Josh Dales
8c59eccb9d Rename the getBranchName helper 2023-01-28 15:14:15 -05:00
Josh Dales
7b1327b4c4 Run the build command 2023-01-11 17:12:22 -05:00
Josh Dales
c54c5a2057 Run prettier 2023-01-11 17:09:44 -05:00
Josh Dales
7f8d8e472d Merge branch 'main' into main 2023-01-11 17:02:22 -05:00
Josh Dales
4c74e84461 Fix typo in the README 2022-09-22 09:05:46 -04:00
Josh Dales
0861fa5acc Run the build command 2022-08-30 17:24:00 -04:00
Josh Dales
0ad789cf22 Merge branch 'main' into main 2022-08-29 20:37:19 -04:00
Josh Dales
6e276063fe Update README with reference to branch options 2022-06-11 13:28:58 -04:00
Josh Dales
818399d10f Merge branch 'main' into main 2022-06-11 07:30:44 -04:00
Josh Dales
71fc664414 run the build script 2021-10-28 22:34:51 -04:00
Josh Dales
7aadc17f94 Update the tests for applying multiple branch based labels 2021-10-28 22:33:25 -04:00
Josh Dales
89f6b77325 minor adjustment for successful branch matching.
To better follow the any convention as opposed to all
2021-10-28 22:13:56 -04:00
Josh Dales
2246b667c6 Run build 2021-09-29 10:33:07 -04:00
Josh Dales
ab49f7a2bd Add tests for array branh labelling 2021-09-29 10:32:05 -04:00
Josh Dales
2d63815c83 Allow branch config to be an array as well 2021-09-29 10:31:50 -04:00
Josh Dales
76242143df Merge pull request #1 from bentohq/fix-branch-labeler 2021-09-16 18:40:19 -04:00
Amiel Martin
27a1d89941 Update src/labeler.ts
Safer access of pull_request data.

Co-authored-by: Josh Dales <30500472+joshdales@users.noreply.github.com>
2021-09-16 12:22:00 -08:00
Amiel Martin
79c0cc7c0b Include a test for branching 2021-09-15 10:14:24 -08:00
Amiel Martin
d9ed3e87f6 Format 2021-09-15 09:58:18 -08:00
Amiel Martin
2ced1f3255 Run build 2021-09-15 09:24:05 -08:00
Amiel Martin
cb5f4480b2 Use correct branch name and update tests 2021-09-15 09:23:41 -08:00
Amiel Martin
8aa7614bc1 Run build 2021-09-15 09:16:56 -08:00
Amiel Martin
827e1186a2 Fix PR branch labeler 2021-09-15 09:05:10 -08:00
Josh Dales
765934f274 Run build 2021-08-07 15:26:22 -04:00
Josh Dales
bce88a9ea3 Update new test description 2021-08-07 15:26:13 -04:00
Josh Dales
a01b9aebb2 Add another test to make sure that partial branch naming works 2021-08-07 15:20:20 -04:00
Josh Dales
ee0e0eb513 Add a new fixture and test for the branch checking 2021-08-07 15:12:02 -04:00
Josh Dales
6c50d09410 include checkBranch in checkMatch 2021-08-07 15:09:15 -04:00
Josh Dales
ad73546cad Add function for checking branches 2021-08-07 15:07:47 -04:00
Josh Dales
2bf42e445d Add branch to MatchConfig interface 2021-08-07 15:06:24 -04:00
31 changed files with 5702 additions and 1223 deletions

7
.eslintignore Normal file
View File

@@ -0,0 +1,7 @@
# Ignore list
/*
# Do not ignore these folders:
!__tests__/
!__mocks__/
!src/

50
.eslintrc.js Normal file
View File

@@ -0,0 +1,50 @@
// 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-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}]
},
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
}
};

2
.gitattributes vendored
View File

@@ -1,4 +1,4 @@
* text=auto
* text=auto eol=lf
.licenses/** -diff linguist-generated=true
# don't diff machine generated files

View File

@@ -2,9 +2,9 @@ name: CodeQL analysis
on:
push:
branches: [ main ]
branches: [main]
pull_request:
branches: [ main ]
branches: [main]
schedule:
- cron: '0 3 * * 0'

View File

@@ -0,0 +1,11 @@
name: Update configuration files
on:
schedule:
- cron: '0 3 * * 0'
workflow_dispatch:
jobs:
call-update-configuration-files:
name: Update configuration files
uses: actions/reusable-workflows/.github/workflows/update-config-files.yml@main

View File

@@ -1,6 +1,6 @@
---
name: minimatch
version: 5.1.2
version: 7.4.3
type: npm
summary: a glob matcher in javascript
homepage:

8
.prettierignore Normal file
View File

@@ -0,0 +1,8 @@
# Ignore list
/*
# Do not ignore these folders:
!__tests__/
!__mocks__/
!.github/
!src/

11
.prettierrc.js Normal file
View File

@@ -0,0 +1,11 @@
// 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'
};

View File

@@ -1,12 +0,0 @@
{
"printWidth": 80,
"tabWidth": 2,
"useTabs": false,
"semi": true,
"singleQuote": true,
"trailingComma": "none",
"bracketSpacing": false,
"arrowParens": "avoid",
"parser": "typescript",
"endOfLine": "auto"
}

View File

@@ -2,58 +2,83 @@
[![Basic validation](https://github.com/actions/labeler/actions/workflows/basic-validation.yml/badge.svg?branch=main)](https://github.com/actions/labeler/actions/workflows/basic-validation.yml)
Automatically label new pull requests based on the paths of files being changed.
Automatically label new pull requests based on the paths of files being changed or the branch name.
## Usage
### Create `.github/labeler.yml`
Create a `.github/labeler.yml` file with a list of labels and [minimatch](https://github.com/isaacs/minimatch) globs to match to apply the label.
Create a `.github/labeler.yml` file with a list of labels and config options to match and apply the label.
The key is the name of the label in your repository that you want to add (eg: "merge conflict", "needs-updating") and the value is the path (glob) of the changed files (eg: `src/**/*`, `tests/*.spec.js`) or a match object.
The key is the name of the label in your repository that you want to add (eg: "merge conflict", "needs-updating") and the value is a match object.
#### Match Object
For more control over matching, you can provide a match object instead of a simple path glob. The match object is defined as:
The match object allows control over the matching options, you can specify the label to be applied based on the files that have changed or the name of either the base branch or the head branch. For the changed files options you provide a [path glob](https://github.com/isaacs/minimatch#minimatch), and for the branches you provide a regexp to match against the branch name.
The base match object is defined as:
```yml
- any: ['list', 'of', 'globs']
all: ['list', 'of', 'globs']
- changed-files: ['list', 'of', 'globs']
- base-branch: ['list', 'of', 'regexps']
- head-branch: ['list', 'of', 'regexps']
```
One or both fields can be provided for fine-grained matching. Unlike the top-level list, the list of path globs provided to `any` and `all` must ALL match against a path for the label to be applied.
There are two top level keys of `any` and `all`, which both accept the same config options:
```yml
- any:
- changed-files: ['list', 'of', 'globs']
- base-branch: ['list', 'of', 'regexps']
- head-branch: ['list', 'of', 'regexps']
- all:
- changed-files: ['list', 'of', 'globs']
- base-branch: ['list', 'of', 'regexps']
- head-branch: ['list', 'of', 'regexps']
```
One or all fields can be provided for fine-grained matching.
The fields are defined as follows:
* `any`: match ALL globs against ANY changed path
* `all`: match ALL globs against ALL changed paths
* `all`: all of the provided options must match in order for the label to be applied
* `any`: if any of the provided options match then a label will be applied
* `base-branch`: match regexps against the base branch name
* `changed-files`: match glob patterns against the changed paths
* `head-branch`: match regexps against the head branch name
A simple path glob is the equivalent to `any: ['glob']`. More specifically, the following two configurations are equivalent:
If a base option is provided without a top-level key then it will default to `any`. More specifically, the following two configurations are equivalent:
```yml
label1:
- example1/*
- changed-files: example1/*
```
and
```yml
label1:
- any: ['example1/*']
- any:
- changed-files: ['example1/*']
```
From a boolean logic perspective, top-level match objects are `OR`-ed together and individual match rules within an object are `AND`-ed. Combined with `!` negation, you can write complex matching rules.
From a boolean logic perspective, top-level match objects, and options within `all` are `AND`-ed together and individual match rules within the `any` object are `OR`-ed. If path globs are combined with `!` negation, you can write complex matching rules.
#### Basic Examples
```yml
# Add 'label1' to any changes within 'example' folder or any subfolders
label1:
- example/**/*
- changed-files: example/**/*
# Add 'label2' to any file changes within 'example2' folder
label2: example2/*
label2:
- changed-files: example2/*
# Add label3 to any change to .txt files within the entire repository. Quotation marks are required for the leading asterisk
label3:
- '**/*.txt'
- changed-files: '**/*.txt'
# Add 'label4' to any PR where the head branch name starts with 'example4'
label4:
- head-branch: '^example4'
# Add 'label5' to any PR where the base branch name starts with 'example5'
label5:
- base-branch: '^example5'
```
#### Common Examples
@@ -61,25 +86,37 @@ label3:
```yml
# Add 'repo' label to any root file changes
repo:
- '*'
- changed-files: '*'
# Add '@domain/core' label to any change within the 'core' package
'@domain/core':
- package/core/*
- package/core/**/*
- changed-files:
- package/core/*
- package/core/**/*
# Add 'test' label to any change to *.spec.js files within the source dir
test:
- src/**/*.spec.js
- changed-files: src/**/*.spec.js
# Add 'source' label to any change to src files within the source dir EXCEPT for the docs sub-folder
source:
- any: ['src/**/*', '!src/docs/*']
- changed-files:
- any: ['src/**/*', '!src/docs/*']
# Add 'frontend` label to any change to *.js files as long as the `main.js` hasn't changed
frontend:
- any: ['src/**/*.js']
all: ['!src/main.js']
- any:
- changed-files: ['src/**/*.js']
- all:
- changed-files: ['!src/main.js']
# Add 'feature' label to any PR where the head branch name starts with `feature` or has a `feature` section in the name
feature:
- head-branch: ['^feature', 'feature']
# Add 'release' label to any PR that is opened against the `main` branch
release:
- base-branch: 'main'
```
### Create Workflow
@@ -98,7 +135,7 @@ jobs:
pull-requests: write
runs-on: ubuntu-latest
steps:
- uses: actions/labeler@v4
- uses: actions/labeler@v5
```
#### Inputs

View File

@@ -1,7 +1,13 @@
export const context = {
payload: {
pull_request: {
number: 123
number: 123,
head: {
ref: 'head-branch-name'
},
base: {
ref: 'base-branch-name'
}
}
},
repo: {

210
__tests__/branch.test.ts Normal file
View File

@@ -0,0 +1,210 @@
import {
getBranchName,
checkAnyBranch,
checkAllBranch,
toBranchMatchConfig,
BranchMatchConfig
} from '../src/branch';
import * as github from '@actions/github';
jest.mock('@actions/core');
jest.mock('@actions/github');
describe('getBranchName', () => {
describe('when the pull requests base branch is requested', () => {
it('returns the base branch name', () => {
const result = getBranchName('base');
expect(result).toEqual('base-branch-name');
});
});
describe('when the pull requests head branch is requested', () => {
it('returns the head branch name', () => {
const result = getBranchName('head');
expect(result).toEqual('head-branch-name');
});
});
});
describe('checkAllBranch', () => {
beforeEach(() => {
github.context.payload.pull_request!.head = {
ref: 'test/feature/123'
};
github.context.payload.pull_request!.base = {
ref: 'main'
};
});
describe('when a single pattern is provided', () => {
describe('and the pattern matches the head branch', () => {
it('returns true', () => {
const result = checkAllBranch(['^test'], 'head');
expect(result).toBe(true);
});
});
describe('and the pattern does not match the head branch', () => {
it('returns false', () => {
const result = checkAllBranch(['^feature/'], 'head');
expect(result).toBe(false);
});
});
});
describe('when multiple patterns are provided', () => {
describe('and not all patterns matched', () => {
it('returns false', () => {
const result = checkAllBranch(['^test/', '^feature/'], 'head');
expect(result).toBe(false);
});
});
describe('and all patterns match', () => {
it('returns true', () => {
const result = checkAllBranch(['^test/', '/feature/'], 'head');
expect(result).toBe(true);
});
});
describe('and no patterns match', () => {
it('returns false', () => {
const result = checkAllBranch(['^feature/', '/test$'], 'head');
expect(result).toBe(false);
});
});
});
describe('when the branch to check is specified as the base branch', () => {
describe('and the pattern matches the base branch', () => {
it('returns true', () => {
const result = checkAllBranch(['^main$'], 'base');
expect(result).toBe(true);
});
});
});
});
describe('checkAnyBranch', () => {
beforeEach(() => {
github.context.payload.pull_request!.head = {
ref: 'test/feature/123'
};
github.context.payload.pull_request!.base = {
ref: 'main'
};
});
describe('when a single pattern is provided', () => {
describe('and the pattern matches the head branch', () => {
it('returns true', () => {
const result = checkAnyBranch(['^test'], 'head');
expect(result).toBe(true);
});
});
describe('and the pattern does not match the head branch', () => {
it('returns false', () => {
const result = checkAnyBranch(['^feature/'], 'head');
expect(result).toBe(false);
});
});
});
describe('when multiple patterns are provided', () => {
describe('and at least one pattern matches', () => {
it('returns true', () => {
const result = checkAnyBranch(['^test/', '^feature/'], 'head');
expect(result).toBe(true);
});
});
describe('and all patterns match', () => {
it('returns true', () => {
const result = checkAnyBranch(['^test/', '/feature/'], 'head');
expect(result).toBe(true);
});
});
describe('and no patterns match', () => {
it('returns false', () => {
const result = checkAnyBranch(['^feature/', '/test$'], 'head');
expect(result).toBe(false);
});
});
});
describe('when the branch to check is specified as the base branch', () => {
describe('and the pattern matches the base branch', () => {
it('returns true', () => {
const result = checkAnyBranch(['^main$'], 'base');
expect(result).toBe(true);
});
});
});
});
describe('toBranchMatchConfig', () => {
describe('when there are no branch keys in the config', () => {
const config = {'changed-files': [{any: ['testing']}]};
it('returns an empty object', () => {
const result = toBranchMatchConfig(config);
expect(result).toEqual({});
});
});
describe('when the config contains a head-branch option', () => {
const config = {'head-branch': ['testing']};
it('sets headBranch in the matchConfig', () => {
const result = toBranchMatchConfig(config);
expect(result).toEqual<BranchMatchConfig>({
headBranch: ['testing']
});
});
describe('and the matching option is a string', () => {
const stringConfig = {'head-branch': 'testing'};
it('sets headBranch in the matchConfig', () => {
const result = toBranchMatchConfig(stringConfig);
expect(result).toEqual<BranchMatchConfig>({
headBranch: ['testing']
});
});
});
});
describe('when the config contains a base-branch option', () => {
const config = {'base-branch': ['testing']};
it('sets baseBranch in the matchConfig', () => {
const result = toBranchMatchConfig(config);
expect(result).toEqual<BranchMatchConfig>({
baseBranch: ['testing']
});
});
describe('and the matching option is a string', () => {
const stringConfig = {'base-branch': 'testing'};
it('sets baseBranch in the matchConfig', () => {
const result = toBranchMatchConfig(stringConfig);
expect(result).toEqual<BranchMatchConfig>({
baseBranch: ['testing']
});
});
});
});
describe('when the config contains both a base-branch and head-branch option', () => {
const config = {'base-branch': ['testing'], 'head-branch': ['testing']};
it('sets headBranch and baseBranch in the matchConfig', () => {
const result = toBranchMatchConfig(config);
expect(result).toEqual<BranchMatchConfig>({
baseBranch: ['testing'],
headBranch: ['testing']
});
});
});
});

View File

@@ -0,0 +1,220 @@
import {
ChangedFilesMatchConfig,
checkAllChangedFiles,
checkAnyChangedFiles,
toChangedFilesMatchConfig,
checkIfAnyGlobMatchesAnyFile,
checkIfAllGlobsMatchAnyFile,
checkIfAnyGlobMatchesAllFiles,
checkIfAllGlobsMatchAllFiles
} from '../src/changedFiles';
jest.mock('@actions/core');
jest.mock('@actions/github');
describe('checkAllChangedFiles', () => {
const changedFiles = ['foo.txt', 'bar.txt'];
describe('when all given glob pattern configs matched', () => {
const globPatternsConfigs = [
{AnyGlobToAnyFile: ['foo.txt']},
{AnyGlobToAllFiles: ['*.txt']},
{AllGlobsToAllFiles: ['**']}
];
it('returns true', () => {
const result = checkAllChangedFiles(changedFiles, globPatternsConfigs);
expect(result).toBe(true);
});
});
describe(`when some given glob pattern config did not match`, () => {
const globPatternsConfigs = [
{AnyGlobToAnyFile: ['*.md']},
{AnyGlobToAllFiles: ['*.txt']},
{AllGlobsToAllFiles: ['**']}
];
it('returns false', () => {
const result = checkAllChangedFiles(changedFiles, globPatternsConfigs);
expect(result).toBe(false);
});
});
});
describe('checkAnyChangedFiles', () => {
const changedFiles = ['foo.txt', 'bar.txt'];
describe('when any given glob pattern config matched', () => {
const globPatternsConfigs = [
{AnyGlobToAnyFile: ['*.md']},
{AnyGlobToAllFiles: ['*.txt']}
];
it('returns true', () => {
const result = checkAnyChangedFiles(changedFiles, globPatternsConfigs);
expect(result).toBe(true);
});
});
describe('when none of the given glob pattern configs matched', () => {
const globPatternsConfigs = [
{AnyGlobToAnyFile: ['*.md']},
{AnyGlobToAllFiles: ['!*.txt']}
];
it('returns false', () => {
const result = checkAnyChangedFiles(changedFiles, globPatternsConfigs);
expect(result).toBe(false);
});
});
});
describe('toChangedFilesMatchConfig', () => {
describe(`when there is no 'changed-files' key in the config`, () => {
const config = {'head-branch': 'test'};
it('returns an empty object', () => {
const result = toChangedFilesMatchConfig(config);
expect(result).toEqual<ChangedFilesMatchConfig>({});
});
});
describe(`when there is a 'changed-files' key in the config`, () => {
describe('but the glob pattern config key is not provided', () => {
const config = {'changed-files': ['bar']};
it('throws the error', () => {
expect(() => {
toChangedFilesMatchConfig(config);
}).toThrow(
`The "changed-files" section must have a valid config structure. Please read the action documentation for more information`
);
});
});
describe('but the glob pattern config key is not valid', () => {
const config = {'changed-files': [{NotValidConfigKey: ['bar']}]};
it('throws the error', () => {
expect(() => {
toChangedFilesMatchConfig(config);
}).toThrow(
`Unknown config options were under "changed-files": NotValidConfigKey`
);
});
});
describe('and the glob pattern config key is provided', () => {
describe('and the value is an array of strings', () => {
const config = {'changed-files': [{AnyGlobToAnyFile: ['testing']}]};
it('sets the value in the config object', () => {
const result = toChangedFilesMatchConfig(config);
expect(result).toEqual<ChangedFilesMatchConfig>({
changedFiles: [{AnyGlobToAnyFile: ['testing']}]
});
});
});
describe('and the value is a string', () => {
const config = {'changed-files': [{AnyGlobToAnyFile: 'testing'}]};
it(`sets the string as an array in the config object`, () => {
const result = toChangedFilesMatchConfig(config);
expect(result).toEqual<ChangedFilesMatchConfig>({
changedFiles: [{AnyGlobToAnyFile: ['testing']}]
});
});
});
});
});
});
describe('checkIfAnyGlobMatchesAnyFile', () => {
const changedFiles = ['foo.txt', 'bar.txt'];
describe('when any given glob pattern matched any file', () => {
const globPatterns = ['*.md', 'foo.txt'];
it('returns true', () => {
const result = checkIfAnyGlobMatchesAnyFile(changedFiles, globPatterns);
expect(result).toBe(true);
});
});
describe('when none of the given glob pattern matched any file', () => {
const globPatterns = ['*.md', '!*.txt'];
it('returns false', () => {
const result = checkIfAnyGlobMatchesAnyFile(changedFiles, globPatterns);
expect(result).toBe(false);
});
});
});
describe('checkIfAllGlobsMatchAnyFile', () => {
const changedFiles = ['foo.txt', 'bar.txt'];
describe('when all given glob patterns matched any file', () => {
const globPatterns = ['**/bar.txt', 'bar.txt'];
it('returns true', () => {
const result = checkIfAllGlobsMatchAnyFile(changedFiles, globPatterns);
expect(result).toBe(true);
});
});
describe('when some of the given glob patterns did not match any file', () => {
const globPatterns = ['*.txt', '*.md'];
it('returns false', () => {
const result = checkIfAllGlobsMatchAnyFile(changedFiles, globPatterns);
expect(result).toBe(false);
});
});
});
describe('checkIfAnyGlobMatchesAllFiles', () => {
const changedFiles = ['foo.txt', 'bar.txt'];
describe('when any given glob pattern matched all files', () => {
const globPatterns = ['*.md', '*.txt'];
it('returns true', () => {
const result = checkIfAnyGlobMatchesAllFiles(changedFiles, globPatterns);
expect(result).toBe(true);
});
});
describe('when none of the given glob patterns matched all files', () => {
const globPatterns = ['*.md', 'bar.txt', 'foo.txt'];
it('returns false', () => {
const result = checkIfAnyGlobMatchesAllFiles(changedFiles, globPatterns);
expect(result).toBe(false);
});
});
});
describe('checkIfAllGlobsMatchAllFiles', () => {
const changedFiles = ['foo.txt', 'bar.txt'];
describe('when all given glob patterns matched all files', () => {
const globPatterns = ['*.txt', '**'];
it('returns true', () => {
const result = checkIfAllGlobsMatchAllFiles(changedFiles, globPatterns);
expect(result).toBe(true);
});
});
describe('when some of the given glob patterns did not match all files', () => {
const globPatterns = ['**', 'foo.txt'];
it('returns false', () => {
const result = checkIfAllGlobsMatchAllFiles(changedFiles, globPatterns);
expect(result).toBe(false);
});
});
});

View File

@@ -0,0 +1,17 @@
label1:
- any:
- changed-files:
- AnyGlobToAnyFile: ['glob']
- head-branch: ['regexp']
- base-branch: ['regexp']
- all:
- changed-files:
- AllGlobsToAllFiles: ['glob']
- head-branch: ['regexp']
- base-branch: ['regexp']
label2:
- changed-files:
- AnyGlobToAnyFile: ['glob']
- head-branch: ['regexp']
- base-branch: ['regexp']

View File

@@ -0,0 +1,8 @@
tests:
- any:
- head-branch: ['^tests/', '^test/']
- changed-files:
- AnyGlobToAnyFile: ['tests/**/*']
- all:
- changed-files:
- AllGlobsToAllFiles: ['!tests/requirements.txt']

View File

@@ -0,0 +1,11 @@
test-branch:
- head-branch: '^test/'
feature-branch:
- head-branch: '/feature/'
bug-branch:
- head-branch: '^bug/|fix/'
array-branch:
- head-branch: ['^array/']

View File

@@ -0,0 +1,3 @@
label:
- all:
- unknown: 'this-is-not-supported'

View File

@@ -1,2 +1,3 @@
touched-a-pdf-file:
- any: ['*.pdf']
- changed-files:
- AnyGlobToAnyFile: ['*.pdf']

View File

@@ -1,6 +1,13 @@
import {checkGlobs} from '../src/labeler';
import {
checkMatchConfigs,
MatchConfig,
toMatchConfig,
getLabelConfigMapFromObject,
BaseMatchConfig
} from '../src/labeler';
import * as yaml from 'js-yaml';
import * as core from '@actions/core';
import * as fs from 'fs';
jest.mock('@actions/core');
@@ -10,20 +17,131 @@ beforeAll(() => {
});
});
const matchConfig = [{any: ['*.txt']}];
const loadYaml = (filepath: string) => {
const loadedFile = fs.readFileSync(filepath);
const content = Buffer.from(loadedFile).toString();
return yaml.load(content);
};
describe('getLabelConfigMapFromObject', () => {
const yamlObject = loadYaml('__tests__/fixtures/all_options.yml');
const expected = new Map<string, MatchConfig[]>();
expected.set('label1', [
{
any: [
{changedFiles: [{AnyGlobToAnyFile: ['glob']}]},
{baseBranch: undefined, headBranch: ['regexp']},
{baseBranch: ['regexp'], headBranch: undefined}
]
},
{
all: [
{changedFiles: [{AllGlobsToAllFiles: ['glob']}]},
{baseBranch: undefined, headBranch: ['regexp']},
{baseBranch: ['regexp'], headBranch: undefined}
]
}
]);
expected.set('label2', [
{
any: [
{changedFiles: [{AnyGlobToAnyFile: ['glob']}]},
{baseBranch: undefined, headBranch: ['regexp']},
{baseBranch: ['regexp'], headBranch: undefined}
]
}
]);
it('returns a MatchConfig', () => {
const result = getLabelConfigMapFromObject(yamlObject);
expect(result).toEqual(expected);
});
});
describe('toMatchConfig', () => {
describe('when all expected config options are present', () => {
const config = {
'changed-files': [{AnyGlobToAnyFile: ['testing-files']}],
'head-branch': ['testing-head'],
'base-branch': ['testing-base']
};
const expected: BaseMatchConfig = {
changedFiles: [{AnyGlobToAnyFile: ['testing-files']}],
headBranch: ['testing-head'],
baseBranch: ['testing-base']
};
it('returns a MatchConfig object with all options', () => {
const result = toMatchConfig(config);
expect(result).toEqual(expected);
});
describe('and there are also unexpected options present', () => {
config['test-test'] = 'testing';
it('does not include the unexpected items in the returned MatchConfig object', () => {
const result = toMatchConfig(config);
expect(result).toEqual(expected);
});
});
});
});
describe('checkMatchConfigs', () => {
describe('when a single match config is provided', () => {
const matchConfig: MatchConfig[] = [
{any: [{changedFiles: [{AnyGlobToAnyFile: ['*.txt']}]}]}
];
describe('checkGlobs', () => {
it('returns true when our pattern does match changed files', () => {
const changedFiles = ['foo.txt', 'bar.txt'];
const result = checkGlobs(changedFiles, matchConfig);
const result = checkMatchConfigs(changedFiles, matchConfig);
expect(result).toBeTruthy();
});
it('returns false when our pattern does not match changed files', () => {
const changedFiles = ['foo.docx'];
const result = checkGlobs(changedFiles, matchConfig);
const result = checkMatchConfigs(changedFiles, matchConfig);
expect(result).toBeFalsy();
});
it('returns true when either the branch or changed files patter matches', () => {
const matchConfig: MatchConfig[] = [
{
any: [
{changedFiles: [{AnyGlobToAnyFile: ['*.txt']}]},
{headBranch: ['some-branch']}
]
}
];
const changedFiles = ['foo.txt', 'bar.txt'];
const result = checkMatchConfigs(changedFiles, matchConfig);
expect(result).toBe(true);
});
});
describe('when multiple MatchConfigs are supplied', () => {
const matchConfig: MatchConfig[] = [
{any: [{changedFiles: [{AnyGlobToAnyFile: ['*.txt']}]}]},
{any: [{headBranch: ['some-branch']}]}
];
const changedFiles = ['foo.txt', 'bar.md'];
it('returns false when only one config matches', () => {
const result = checkMatchConfigs(changedFiles, matchConfig);
expect(result).toBe(false);
});
it('returns true when only both config matches', () => {
const matchConfig: MatchConfig[] = [
{any: [{changedFiles: [{AnyGlobToAnyFile: ['*.txt']}]}]},
{any: [{headBranch: ['head-branch']}]}
];
const result = checkMatchConfigs(changedFiles, matchConfig);
expect(result).toBe(true);
});
});
});

View File

@@ -15,7 +15,10 @@ const paginateMock = jest.spyOn(gh, 'paginate');
const getPullMock = jest.spyOn(gh.rest.pulls, 'get');
const yamlFixtures = {
'only_pdfs.yml': fs.readFileSync('__tests__/fixtures/only_pdfs.yml')
'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')
};
afterAll(() => jest.restoreAllMocks());
@@ -47,16 +50,29 @@ describe('run', () => {
expect(addLabelsMock).toHaveBeenCalledTimes(0);
});
it('does not add a label when the match config options are not supported', async () => {
usingLabelerConfigYaml('not_supported.yml');
await run();
expect(addLabelsMock).toHaveBeenCalledTimes(0);
expect(removeLabelMock).toHaveBeenCalledTimes(0);
});
it('(with sync-labels: true) it deletes preexisting PR labels that no longer match the glob pattern', async () => {
let mockInput = {
const mockInput = {
'repo-token': 'foo',
'configuration-path': 'bar',
'sync-labels': true
'sync-labels': 'true'
};
jest
.spyOn(core, 'getInput')
.mockImplementation((name: string, ...opts) => mockInput[name]);
jest
.spyOn(core, 'getBooleanInput')
.mockImplementation(
(name: string, ...opts) => mockInput[name] === 'true'
);
usingLabelerConfigYaml('only_pdfs.yml');
mockGitHubResponseChangedFiles('foo.txt');
@@ -79,15 +95,20 @@ describe('run', () => {
});
it('(with sync-labels: false) it issues no delete calls even when there are preexisting PR labels that no longer match the glob pattern', async () => {
let mockInput = {
const mockInput = {
'repo-token': 'foo',
'configuration-path': 'bar',
'sync-labels': false
'sync-labels': 'false'
};
jest
.spyOn(core, 'getInput')
.mockImplementation((name: string, ...opts) => mockInput[name]);
jest
.spyOn(core, 'getBooleanInput')
.mockImplementation(
(name: string, ...opts) => mockInput[name] === 'true'
);
usingLabelerConfigYaml('only_pdfs.yml');
mockGitHubResponseChangedFiles('foo.txt');
@@ -102,6 +123,87 @@ describe('run', () => {
expect(addLabelsMock).toHaveBeenCalledTimes(0);
expect(removeLabelMock).toHaveBeenCalledTimes(0);
});
it('adds labels based on the branch names that match the regexp pattern', async () => {
github.context.payload.pull_request!.head = {ref: 'test/testing-time'};
usingLabelerConfigYaml('branches.yml');
await run();
expect(addLabelsMock).toHaveBeenCalledTimes(1);
expect(addLabelsMock).toHaveBeenCalledWith({
owner: 'monalisa',
repo: 'helloworld',
issue_number: 123,
labels: ['test-branch']
});
});
it('adds multiple labels based on branch names that match different regexp patterns', async () => {
github.context.payload.pull_request!.head = {
ref: 'test/feature/123'
};
usingLabelerConfigYaml('branches.yml');
await run();
expect(addLabelsMock).toHaveBeenCalledTimes(1);
expect(addLabelsMock).toHaveBeenCalledWith({
owner: 'monalisa',
repo: 'helloworld',
issue_number: 123,
labels: ['test-branch', 'feature-branch']
});
});
it('can support multiple branches by batching', async () => {
github.context.payload.pull_request!.head = {ref: 'fix/123'};
usingLabelerConfigYaml('branches.yml');
await run();
expect(addLabelsMock).toHaveBeenCalledTimes(1);
expect(addLabelsMock).toHaveBeenCalledWith({
owner: 'monalisa',
repo: 'helloworld',
issue_number: 123,
labels: ['bug-branch']
});
});
it('can support multiple branches by providing an array', async () => {
github.context.payload.pull_request!.head = {ref: 'array/123'};
usingLabelerConfigYaml('branches.yml');
await run();
expect(addLabelsMock).toHaveBeenCalledTimes(1);
expect(addLabelsMock).toHaveBeenCalledWith({
owner: 'monalisa',
repo: 'helloworld',
issue_number: 123,
labels: ['array-branch']
});
});
it('adds a label when matching any and all patterns are provided', async () => {
usingLabelerConfigYaml('any_and_all.yml');
mockGitHubResponseChangedFiles('tests/test.ts');
await run();
expect(addLabelsMock).toHaveBeenCalledTimes(1);
expect(addLabelsMock).toHaveBeenCalledWith({
owner: 'monalisa',
repo: 'helloworld',
issue_number: 123,
labels: ['tests']
});
});
it('does not add a label when not all any and all patterns are matched', async () => {
usingLabelerConfigYaml('any_and_all.yml');
mockGitHubResponseChangedFiles('tests/requirements.txt');
await run();
expect(addLabelsMock).toHaveBeenCalledTimes(0);
expect(removeLabelMock).toHaveBeenCalledTimes(0);
});
});
function usingLabelerConfigYaml(fixtureName: keyof typeof yamlFixtures): void {

3040
dist/index.js vendored

File diff suppressed because it is too large Load Diff

2147
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@@ -5,9 +5,10 @@
"main": "lib/main.js",
"scripts": {
"build": "tsc && ncc build lib/main.js",
"format": "prettier --write **/*.ts",
"format-check": "prettier --check **/*.ts",
"lint": "echo \"Fake command that does nothing. It is used in reusable workflows\"",
"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"
},
"repository": {
@@ -26,16 +27,21 @@
"@actions/core": "^1.10.0",
"@actions/github": "^5.1.1",
"js-yaml": "^4.1.0",
"minimatch": "^5.1.2"
"minimatch": "^7.4.3"
},
"devDependencies": {
"@types/jest": "^27.4.1",
"@types/node": "^16.11.7",
"@types/minimatch": "^5.1.2",
"@types/js-yaml": "^4.0.5",
"@types/minimatch": "^5.1.2",
"@types/node": "^16.11.7",
"@typescript-eslint/eslint-plugin": "^5.59.7",
"@typescript-eslint/parser": "^5.59.7",
"@vercel/ncc": "^0.36.1",
"eslint": "^8.41.0",
"eslint-config-prettier": "^8.8.0",
"eslint-plugin-jest": "^27.2.1",
"jest": "^27.5.1",
"prettier": "^2.8.4",
"prettier": "^2.8.8",
"ts-jest": "^27.1.3",
"typescript": "^4.9.5"
}

98
src/branch.ts Normal file
View File

@@ -0,0 +1,98 @@
import * as core from '@actions/core';
import * as github from '@actions/github';
export interface BranchMatchConfig {
headBranch?: string[];
baseBranch?: string[];
}
type BranchBase = 'base' | 'head';
export function toBranchMatchConfig(config: any): BranchMatchConfig {
if (!config['head-branch'] && !config['base-branch']) {
return {};
}
const branchConfig = {
headBranch: config['head-branch'],
baseBranch: config['base-branch']
};
for (const branchName in branchConfig) {
if (typeof branchConfig[branchName] === 'string') {
branchConfig[branchName] = [branchConfig[branchName]];
}
}
return branchConfig;
}
export function getBranchName(branchBase: BranchBase): string | undefined {
const pullRequest = github.context.payload.pull_request;
if (!pullRequest) {
return undefined;
}
if (branchBase === 'base') {
return pullRequest.base?.ref;
} else {
return pullRequest.head?.ref;
}
}
export function checkAnyBranch(
regexps: string[],
branchBase: BranchBase
): boolean {
const branchName = getBranchName(branchBase);
if (!branchName) {
core.debug(` no branch name`);
return false;
}
core.debug(` checking "branch" pattern against ${branchName}`);
const matchers = regexps.map(regexp => new RegExp(regexp));
for (const matcher of matchers) {
if (matchBranchPattern(matcher, branchName)) {
core.debug(` "branch" patterns matched against ${branchName}`);
return true;
}
}
core.debug(` "branch" patterns did not match against ${branchName}`);
return false;
}
export function checkAllBranch(
regexps: string[],
branchBase: BranchBase
): boolean {
const branchName = getBranchName(branchBase);
if (!branchName) {
core.debug(` cannot fetch branch name from the pull request`);
return false;
}
core.debug(` checking "branch" pattern against ${branchName}`);
const matchers = regexps.map(regexp => new RegExp(regexp));
for (const matcher of matchers) {
if (!matchBranchPattern(matcher, branchName)) {
core.debug(` "branch" patterns did not match against ${branchName}`);
return false;
}
}
core.debug(` "branch" patterns matched against ${branchName}`);
return true;
}
function matchBranchPattern(matcher: RegExp, branchName: string): boolean {
core.debug(` - ${matcher}`);
if (matcher.test(branchName)) {
core.debug(` "branch" pattern matched`);
return true;
}
core.debug(` ${matcher} did not match`);
return false;
}

353
src/changedFiles.ts Normal file
View File

@@ -0,0 +1,353 @@
import * as core from '@actions/core';
import * as github from '@actions/github';
import {Minimatch} from 'minimatch';
export interface ChangedFilesMatchConfig {
changedFiles?: ChangedFilesGlobPatternsConfig[];
}
interface ChangedFilesGlobPatternsConfig {
AnyGlobToAnyFile?: string[];
AnyGlobToAllFiles?: string[];
AllGlobsToAnyFile?: string[];
AllGlobsToAllFiles?: string[];
}
type ClientType = ReturnType<typeof github.getOctokit>;
const ALLOWED_FILES_CONFIG_KEYS = [
'AnyGlobToAnyFile',
'AnyGlobToAllFiles',
'AllGlobsToAnyFile',
'AllGlobsToAllFiles'
];
export async function getChangedFiles(
client: ClientType,
prNumber: number
): Promise<string[]> {
const listFilesOptions = client.rest.pulls.listFiles.endpoint.merge({
owner: github.context.repo.owner,
repo: github.context.repo.repo,
pull_number: prNumber
});
const listFilesResponse = await client.paginate(listFilesOptions);
const changedFiles = listFilesResponse.map((f: any) => f.filename);
core.debug('found changed files:');
for (const file of changedFiles) {
core.debug(' ' + file);
}
return changedFiles;
}
export function toChangedFilesMatchConfig(
config: any
): ChangedFilesMatchConfig {
if (!config['changed-files'] || !config['changed-files'].length) {
return {};
}
const changedFilesConfigs = Array.isArray(config['changed-files'])
? config['changed-files']
: [config['changed-files']];
const validChangedFilesConfigs: ChangedFilesGlobPatternsConfig[] = [];
changedFilesConfigs.forEach(changedFilesConfig => {
if (!isObject(changedFilesConfig)) {
throw new Error(
`The "changed-files" section must have a valid config structure. Please read the action documentation for more information`
);
}
const changedFilesConfigKeys = Object.keys(changedFilesConfig);
const invalidKeys = changedFilesConfigKeys.filter(
key => !ALLOWED_FILES_CONFIG_KEYS.includes(key)
);
if (invalidKeys.length) {
throw new Error(
`Unknown config options were under "changed-files": ${invalidKeys.join(
', '
)}`
);
}
changedFilesConfigKeys.forEach(key => {
validChangedFilesConfigs.push({
[key]: Array.isArray(changedFilesConfig[key])
? changedFilesConfig[key]
: [changedFilesConfig[key]]
});
});
});
return {
changedFiles: validChangedFilesConfigs
};
}
function isObject(obj: unknown): obj is object {
return obj !== null && typeof obj === 'object' && !Array.isArray(obj);
}
function printPattern(matcher: Minimatch): string {
return (matcher.negate ? '!' : '') + matcher.pattern;
}
export function checkAnyChangedFiles(
changedFiles: string[],
globPatternsConfigs: ChangedFilesGlobPatternsConfig[]
): boolean {
core.debug(` checking "changed-files" patterns`);
for (const globPatternsConfig of globPatternsConfigs) {
if (globPatternsConfig.AnyGlobToAnyFile) {
if (
checkIfAnyGlobMatchesAnyFile(
changedFiles,
globPatternsConfig.AnyGlobToAnyFile
)
) {
core.debug(` "changed-files" matched`);
return true;
}
}
if (globPatternsConfig.AnyGlobToAllFiles) {
if (
checkIfAnyGlobMatchesAllFiles(
changedFiles,
globPatternsConfig.AnyGlobToAllFiles
)
) {
core.debug(` "changed-files" matched`);
return true;
}
}
if (globPatternsConfig.AllGlobsToAnyFile) {
if (
checkIfAllGlobsMatchAnyFile(
changedFiles,
globPatternsConfig.AllGlobsToAnyFile
)
) {
core.debug(` "changed-files" matched`);
return true;
}
}
if (globPatternsConfig.AllGlobsToAllFiles) {
if (
checkIfAllGlobsMatchAllFiles(
changedFiles,
globPatternsConfig.AllGlobsToAllFiles
)
) {
core.debug(` "changed-files" matched`);
return true;
}
}
}
core.debug(` "changed-files" did not match`);
return false;
}
export function checkAllChangedFiles(
changedFiles: string[],
globPatternsConfigs: ChangedFilesGlobPatternsConfig[]
): boolean {
core.debug(` checking "changed-files" patterns`);
for (const globPatternsConfig of globPatternsConfigs) {
if (globPatternsConfig.AnyGlobToAnyFile) {
if (
!checkIfAnyGlobMatchesAnyFile(
changedFiles,
globPatternsConfig.AnyGlobToAnyFile
)
) {
core.debug(` "changed-files" did not match`);
return false;
}
}
if (globPatternsConfig.AnyGlobToAllFiles) {
if (
!checkIfAnyGlobMatchesAllFiles(
changedFiles,
globPatternsConfig.AnyGlobToAllFiles
)
) {
core.debug(` "changed-files" did not match`);
return false;
}
}
if (globPatternsConfig.AllGlobsToAnyFile) {
if (
!checkIfAllGlobsMatchAnyFile(
changedFiles,
globPatternsConfig.AllGlobsToAnyFile
)
) {
core.debug(` "changed-files" did not match`);
return false;
}
}
if (globPatternsConfig.AllGlobsToAllFiles) {
if (
!checkIfAllGlobsMatchAllFiles(
changedFiles,
globPatternsConfig.AllGlobsToAllFiles
)
) {
core.debug(` "changed-files" did not match`);
return false;
}
}
}
core.debug(` "changed-files" patterns matched`);
return true;
}
export function checkIfAnyGlobMatchesAnyFile(
changedFiles: string[],
globs: string[]
): boolean {
core.debug(` checking "AnyGlobToAnyFile" config patterns`);
const matchers = globs.map(g => new Minimatch(g));
for (const matcher of matchers) {
const matchedFile = changedFiles.find(changedFile => {
core.debug(
` checking "${printPattern(
matcher
)}" pattern against ${changedFile}`
);
return matcher.match(changedFile);
});
if (matchedFile) {
core.debug(
` "${printPattern(matcher)}" pattern matched ${matchedFile}`
);
return true;
}
}
core.debug(` none of the patterns matched any of the files`);
return false;
}
export function checkIfAllGlobsMatchAnyFile(
changedFiles: string[],
globs: string[]
): boolean {
core.debug(` checking "AllGlobsToAnyFile" config patterns`);
const matchers = globs.map(g => new Minimatch(g));
for (const changedFile of changedFiles) {
const mismatchedGlob = matchers.find(matcher => {
core.debug(
` checking "${printPattern(
matcher
)}" pattern against ${changedFile}`
);
return !matcher.match(changedFile);
});
if (mismatchedGlob) {
core.debug(
` "${printPattern(
mismatchedGlob
)}" pattern did not match ${changedFile}`
);
continue;
}
core.debug(` all patterns matched ${changedFile}`);
return true;
}
core.debug(` none of the files matched all patterns`);
return false;
}
export function checkIfAnyGlobMatchesAllFiles(
changedFiles: string[],
globs: string[]
): boolean {
core.debug(` checking "AnyGlobToAllFiles" config patterns`);
const matchers = globs.map(g => new Minimatch(g));
for (const matcher of matchers) {
const mismatchedFile = changedFiles.find(changedFile => {
core.debug(
` checking "${printPattern(
matcher
)}" pattern against ${changedFile}`
);
return !matcher.match(changedFile);
});
if (mismatchedFile) {
core.debug(
` "${printPattern(
matcher
)}" pattern did not match ${mismatchedFile}`
);
continue;
}
core.debug(` "${printPattern(matcher)}" pattern matched all files`);
return true;
}
core.debug(` none of the patterns matched all files`);
return false;
}
export function checkIfAllGlobsMatchAllFiles(
changedFiles: string[],
globs: string[]
): boolean {
core.debug(` checking "AllGlobsToAllFiles" config patterns`);
const matchers = globs.map(g => new Minimatch(g));
for (const changedFile of changedFiles) {
const mismatchedGlob = matchers.find(matcher => {
core.debug(
` checking "${printPattern(
matcher
)}" pattern against ${changedFile}`
);
return !matcher.match(changedFile);
});
if (mismatchedGlob) {
core.debug(
` "${printPattern(
mismatchedGlob
)}" pattern did not match ${changedFile}`
);
return false;
}
}
core.debug(` all patterns matched all files`);
return true;
}

View File

@@ -1,25 +1,41 @@
import * as core from '@actions/core';
import * as github from '@actions/github';
import * as yaml from 'js-yaml';
import {Minimatch, IMinimatch} from 'minimatch';
interface MatchConfig {
all?: string[];
any?: string[];
}
import {
ChangedFilesMatchConfig,
getChangedFiles,
toChangedFilesMatchConfig,
checkAllChangedFiles,
checkAnyChangedFiles
} from './changedFiles';
import {
checkAnyBranch,
checkAllBranch,
toBranchMatchConfig,
BranchMatchConfig
} from './branch';
export type BaseMatchConfig = BranchMatchConfig & ChangedFilesMatchConfig;
export type MatchConfig = {
any?: BaseMatchConfig[];
all?: BaseMatchConfig[];
};
type StringOrMatchConfig = string | MatchConfig;
type ClientType = ReturnType<typeof github.getOctokit>;
const ALLOWED_CONFIG_KEYS = ['changed-files', 'head-branch', 'base-branch'];
export async function run() {
try {
const token = core.getInput('repo-token');
const configPath = core.getInput('configuration-path', {required: true});
const syncLabels = !!core.getInput('sync-labels', {required: false});
const syncLabels = core.getBooleanInput('sync-labels');
const prNumber = getPrNumber();
if (!prNumber) {
console.log('Could not get pull request number from context, exiting');
core.info('Could not get pull request number from context, exiting');
return;
}
@@ -33,16 +49,16 @@ export async function run() {
core.debug(`fetching changed files for pr #${prNumber}`);
const changedFiles: string[] = await getChangedFiles(client, prNumber);
const labelGlobs: Map<string, StringOrMatchConfig[]> = await getLabelGlobs(
const labelConfigs: Map<string, MatchConfig[]> = await getMatchConfigs(
client,
configPath
);
const labels: string[] = [];
const labelsToRemove: string[] = [];
for (const [label, globs] of labelGlobs.entries()) {
for (const [label, configs] of labelConfigs.entries()) {
core.debug(`processing ${label}`);
if (checkGlobs(changedFiles, globs)) {
if (checkMatchConfigs(changedFiles, configs)) {
labels.push(label);
} else if (pullRequest.labels.find(l => l.name === label)) {
labelsToRemove.push(label);
@@ -71,41 +87,20 @@ function getPrNumber(): number | undefined {
return pullRequest.number;
}
async function getChangedFiles(
client: ClientType,
prNumber: number
): Promise<string[]> {
const listFilesOptions = client.rest.pulls.listFiles.endpoint.merge({
owner: github.context.repo.owner,
repo: github.context.repo.repo,
pull_number: prNumber
});
const listFilesResponse = await client.paginate(listFilesOptions);
const changedFiles = listFilesResponse.map((f: any) => f.filename);
core.debug('found changed files:');
for (const file of changedFiles) {
core.debug(' ' + file);
}
return changedFiles;
}
async function getLabelGlobs(
async function getMatchConfigs(
client: ClientType,
configurationPath: string
): Promise<Map<string, StringOrMatchConfig[]>> {
): Promise<Map<string, MatchConfig[]>> {
const configurationContent: string = await fetchContent(
client,
configurationPath
);
// loads (hopefully) a `{[label:string]: string | StringOrMatchConfig[]}`, but is `any`:
// loads (hopefully) a `{[label:string]: MatchConfig[]}`, but is `any`:
const configObject: any = yaml.load(configurationContent);
// transform `any` => `Map<string,StringOrMatchConfig[]>` or throw if yaml is malformed:
return getLabelGlobMapFromObject(configObject);
// transform `any` => `Map<string,MatchConfig[]>` or throw if yaml is malformed:
return getLabelConfigMapFromObject(configObject);
}
async function fetchContent(
@@ -122,106 +117,101 @@ async function fetchContent(
return Buffer.from(response.data.content, response.data.encoding).toString();
}
function getLabelGlobMapFromObject(
export function getLabelConfigMapFromObject(
configObject: any
): Map<string, StringOrMatchConfig[]> {
const labelGlobs: Map<string, StringOrMatchConfig[]> = new Map();
): Map<string, MatchConfig[]> {
const labelMap: Map<string, MatchConfig[]> = new Map();
for (const label in configObject) {
if (typeof configObject[label] === 'string') {
labelGlobs.set(label, [configObject[label]]);
} else if (configObject[label] instanceof Array) {
labelGlobs.set(label, configObject[label]);
} else {
const configOptions = configObject[label];
if (
!Array.isArray(configOptions) ||
!configOptions.every(opts => typeof opts === 'object')
) {
throw Error(
`found unexpected type for label ${label} (should be string or array of globs)`
`found unexpected type for label '${label}' (should be array of config options)`
);
}
const matchConfigs = configOptions.reduce<MatchConfig[]>(
(updatedConfig, configValue) => {
if (!configValue) {
return updatedConfig;
}
return labelGlobs;
Object.entries(configValue).forEach(([key, value]) => {
// If the top level `any` or `all` keys are provided then set them, and convert their values to
// our config objects.
if (key === 'any' || key === 'all') {
if (Array.isArray(value)) {
const newConfigs = value.map(toMatchConfig);
updatedConfig.push({[key]: newConfigs});
}
} else if (ALLOWED_CONFIG_KEYS.includes(key)) {
const newMatchConfig = toMatchConfig({[key]: value});
// Find or set the `any` key so that we can add these properties to that rule,
// Or create a new `any` key and add that to our array of configs.
const indexOfAny = updatedConfig.findIndex(mc => !!mc['any']);
if (indexOfAny >= 0) {
updatedConfig[indexOfAny].any?.push(newMatchConfig);
} else {
updatedConfig.push({any: [newMatchConfig]});
}
} else {
// Log the key that we don't know what to do with.
core.info(`An unknown config option was under ${label}: ${key}`);
}
});
return updatedConfig;
},
[]
);
if (matchConfigs.length) {
labelMap.set(label, matchConfigs);
}
}
return labelMap;
}
function toMatchConfig(config: StringOrMatchConfig): MatchConfig {
if (typeof config === 'string') {
export function toMatchConfig(config: any): BaseMatchConfig {
const changedFilesConfig = toChangedFilesMatchConfig(config);
const branchConfig = toBranchMatchConfig(config);
return {
any: [config]
...changedFilesConfig,
...branchConfig
};
}
return config;
}
function printPattern(matcher: IMinimatch): string {
return (matcher.negate ? '!' : '') + matcher.pattern;
}
export function checkGlobs(
export function checkMatchConfigs(
changedFiles: string[],
globs: StringOrMatchConfig[]
matchConfigs: MatchConfig[]
): boolean {
for (const glob of globs) {
core.debug(` checking pattern ${JSON.stringify(glob)}`);
const matchConfig = toMatchConfig(glob);
if (checkMatch(changedFiles, matchConfig)) {
return true;
}
}
return false;
}
function isMatch(changedFile: string, matchers: IMinimatch[]): boolean {
core.debug(` matching patterns against file ${changedFile}`);
for (const matcher of matchers) {
core.debug(` - ${printPattern(matcher)}`);
if (!matcher.match(changedFile)) {
core.debug(` ${printPattern(matcher)} did not match`);
for (const config of matchConfigs) {
core.debug(` checking config ${JSON.stringify(config)}`);
if (!checkMatch(changedFiles, config)) {
return false;
}
}
core.debug(` all patterns matched`);
return true;
}
// equivalent to "Array.some()" but expanded for debugging and clarity
function checkAny(changedFiles: string[], globs: string[]): boolean {
const matchers = globs.map(g => new Minimatch(g));
core.debug(` checking "any" patterns`);
for (const changedFile of changedFiles) {
if (isMatch(changedFile, matchers)) {
core.debug(` "any" patterns matched against ${changedFile}`);
return true;
}
}
core.debug(` "any" patterns did not match any files`);
return false;
}
// equivalent to "Array.every()" but expanded for debugging and clarity
function checkAll(changedFiles: string[], globs: string[]): boolean {
const matchers = globs.map(g => new Minimatch(g));
core.debug(` checking "all" patterns`);
for (const changedFile of changedFiles) {
if (!isMatch(changedFile, matchers)) {
core.debug(` "all" patterns did not match against ${changedFile}`);
return false;
}
}
core.debug(` "all" patterns matched all files`);
return true;
}
function checkMatch(changedFiles: string[], matchConfig: MatchConfig): boolean {
if (matchConfig.all !== undefined) {
if (!checkAll(changedFiles, matchConfig.all)) {
if (!Object.keys(matchConfig).length) {
core.debug(` no "any" or "all" patterns to check`);
return false;
}
if (matchConfig.all) {
if (!checkAll(matchConfig.all, changedFiles)) {
return false;
}
}
if (matchConfig.any !== undefined) {
if (!checkAny(changedFiles, matchConfig.any)) {
if (matchConfig.any) {
if (!checkAny(matchConfig.any, changedFiles)) {
return false;
}
}
@@ -229,6 +219,93 @@ function checkMatch(changedFiles: string[], matchConfig: MatchConfig): boolean {
return true;
}
// equivalent to "Array.some()" but expanded for debugging and clarity
export function checkAny(
matchConfigs: BaseMatchConfig[],
changedFiles: string[]
): boolean {
core.debug(` checking "any" patterns`);
if (
!matchConfigs.length ||
!matchConfigs.some(configOption => Object.keys(configOption).length)
) {
core.debug(` no "any" patterns to check`);
return false;
}
for (const matchConfig of matchConfigs) {
if (matchConfig.baseBranch) {
if (checkAnyBranch(matchConfig.baseBranch, 'base')) {
core.debug(` "any" patterns matched`);
return true;
}
}
if (matchConfig.changedFiles) {
if (checkAnyChangedFiles(changedFiles, matchConfig.changedFiles)) {
core.debug(` "any" patterns matched`);
return true;
}
}
if (matchConfig.headBranch) {
if (checkAnyBranch(matchConfig.headBranch, 'head')) {
core.debug(` "any" patterns matched`);
return true;
}
}
}
core.debug(` "any" patterns did not match any configs`);
return false;
}
// equivalent to "Array.every()" but expanded for debugging and clarity
export function checkAll(
matchConfigs: BaseMatchConfig[],
changedFiles: string[]
): boolean {
core.debug(` checking "all" patterns`);
if (
!matchConfigs.length ||
!matchConfigs.some(configOption => Object.keys(configOption).length)
) {
core.debug(` no "all" patterns to check`);
return false;
}
for (const matchConfig of matchConfigs) {
if (matchConfig.baseBranch) {
if (!checkAllBranch(matchConfig.baseBranch, 'base')) {
core.debug(` "all" patterns did not match`);
return false;
}
}
if (matchConfig.changedFiles) {
if (!changedFiles.length) {
core.debug(` no files to check "changed-files" patterns against`);
return false;
}
if (!checkAllChangedFiles(changedFiles, matchConfig.changedFiles)) {
core.debug(` "all" patterns did not match`);
return false;
}
}
if (matchConfig.headBranch) {
if (!checkAllBranch(matchConfig.headBranch, 'head')) {
core.debug(` "all" patterns did not match`);
return false;
}
}
}
core.debug(` "all" patterns matched all configs`);
return true;
}
async function addLabels(
client: ClientType,
prNumber: number,