Compare commits
422 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
af292f1e84 | ||
|
|
2ddcb04986 | ||
|
|
3ce5a2970f | ||
|
|
d898dd09e4 | ||
|
|
0e08afd95d | ||
|
|
955cdc8d81 | ||
|
|
e48cacbca5 | ||
|
|
5aee572571 | ||
|
|
c83cb31f5b | ||
|
|
fea790cb66 | ||
|
|
794c26fb9f | ||
|
|
0f6525cd7d | ||
|
|
28cf22057f | ||
|
|
faedee1163 | ||
|
|
4a7ca97de0 | ||
|
|
cef68eee2e | ||
|
|
40e81cc72b | ||
|
|
4d1f5becef | ||
|
|
c82b7e2992 | ||
|
|
02eb5a78aa | ||
|
|
2cee40ea93 | ||
|
|
5b02f7c186 | ||
|
|
2e7f228016 | ||
|
|
8a78ebb29f | ||
|
|
95690f9ece | ||
|
|
97266423db | ||
|
|
af4b210111 | ||
|
|
2a10bef1b4 | ||
|
|
5c45808ea0 | ||
|
|
a82ffc67b3 | ||
|
|
44225688bb | ||
|
|
f144a9e6da | ||
|
|
d08f64adf6 | ||
|
|
2d0db8be9e | ||
|
|
408093d9ff | ||
|
|
a8fcc78511 | ||
|
|
49e754c81d | ||
|
|
3b9406ef82 | ||
|
|
1d9d8f4a76 | ||
|
|
6777efe3ca | ||
|
|
2b4a057e15 | ||
|
|
1e88b750d4 | ||
|
|
57421690e0 | ||
|
|
1c14cc7ff3 | ||
|
|
54864d4c3b | ||
|
|
8f6e85fcdf | ||
|
|
6cd5b66101 | ||
|
|
3729bf289f | ||
|
|
db153baf73 | ||
|
|
344b35fc53 | ||
|
|
f318653745 | ||
|
|
3415b43780 | ||
|
|
15f38d6693 | ||
|
|
2160c8e998 | ||
|
|
39084f937a | ||
|
|
22a6a7dedc | ||
|
|
8f93691a81 | ||
|
|
c5c7d8163f | ||
|
|
e061de58da | ||
|
|
6f90eecfe8 | ||
|
|
4daaa8171d | ||
|
|
cbff9146e3 | ||
|
|
2d7c10954b | ||
|
|
6e74c9dbbb | ||
|
|
44827f39da | ||
|
|
2ba385a5e1 | ||
|
|
7d9358afc1 | ||
|
|
cf03855076 | ||
|
|
877b5ce98c | ||
|
|
428220b7f4 | ||
|
|
914e0223cf | ||
|
|
b79cd45602 | ||
|
|
19107de46c | ||
|
|
29dd1b9c76 | ||
|
|
dac82b0e15 | ||
|
|
4595c4c56b | ||
|
|
39000e536b | ||
|
|
181ee9b66b | ||
|
|
9053f9ea11 | ||
|
|
8238a41032 | ||
|
|
aaf4339aa1 | ||
|
|
d2486b470f | ||
|
|
e7fd9e59a4 | ||
|
|
e3cc088a96 | ||
|
|
72d7089b72 | ||
|
|
e94da5a065 | ||
|
|
a721d001dd | ||
|
|
8af3110d4d | ||
|
|
a351a301d2 | ||
|
|
62a23f82b1 | ||
|
|
ef42e5ad18 | ||
|
|
cd1e384723 | ||
|
|
a52f8621d2 | ||
|
|
920856cfdd | ||
|
|
08906b3254 | ||
|
|
cd35eace22 | ||
|
|
8296c33fd0 | ||
|
|
0ad71b9855 | ||
|
|
c98e6d20fc | ||
|
|
2398551415 | ||
|
|
060b3b9b03 | ||
|
|
ff65504325 | ||
|
|
543c1a25c6 | ||
|
|
1be42003d7 | ||
|
|
2325baada3 | ||
|
|
e6ce728d79 | ||
|
|
0b947ed818 | ||
|
|
e8dbf6d670 | ||
|
|
41c232aad8 | ||
|
|
4196030939 | ||
|
|
bbe796033e | ||
|
|
159562dc02 | ||
|
|
a21a533a0c | ||
|
|
eeb169a9f9 | ||
|
|
951140b94a | ||
|
|
dbf0700c7a | ||
|
|
dacbaebcaf | ||
|
|
36ab2fe9c2 | ||
|
|
7e3a4bac80 | ||
|
|
dcbe9805f4 | ||
|
|
fd73c1248c | ||
|
|
8e79ba7ab9 | ||
|
|
5db7b578d5 | ||
|
|
a17e8c5252 | ||
|
|
d1e9506b19 | ||
|
|
1fdfe0928a | ||
|
|
76c4d81a6a | ||
|
|
d8904df6c5 | ||
|
|
662c03ea61 | ||
|
|
c8b7da7226 | ||
|
|
249c1698c5 | ||
|
|
17352b2176 | ||
|
|
e8e6614779 | ||
|
|
ad4b06d999 | ||
|
|
b1a34eb336 | ||
|
|
d9a6ccb099 | ||
|
|
090eb05f17 | ||
|
|
690bef673a | ||
|
|
fb8d2c9c29 | ||
|
|
bb3b39cd33 | ||
|
|
001f56257c | ||
|
|
57245a9721 | ||
|
|
6ee9cdc581 | ||
|
|
dc40835d4d | ||
|
|
7e3122dc95 | ||
|
|
073479583b | ||
|
|
d76ddeeeaa | ||
|
|
7cdc56dd7a | ||
|
|
246636f5fa | ||
|
|
fe0fb71961 | ||
|
|
e60a7a9173 | ||
|
|
81bb5d8954 | ||
|
|
523e8b6f11 | ||
|
|
4a0a3c4aa5 | ||
|
|
9dfd3f686b | ||
|
|
796ac2d08f | ||
|
|
534262e0b2 | ||
|
|
673189f77b | ||
|
|
89cb9ea919 | ||
|
|
7113206187 | ||
|
|
926a3fd777 | ||
|
|
de23f62d1e | ||
|
|
afbabc4364 | ||
|
|
eda0811ed2 | ||
|
|
bda67fc879 | ||
|
|
5a5d398e5f | ||
|
|
f699bde5ad | ||
|
|
48566bbcc2 | ||
|
|
d68a6666be | ||
|
|
07660d51a9 | ||
|
|
632c84dcca | ||
|
|
1aee3621b1 | ||
|
|
8d335b7b7d | ||
|
|
fd460fa3ba | ||
|
|
5b84ed26a3 | ||
|
|
e03c026bf4 | ||
|
|
5704310356 | ||
|
|
c922361eb2 | ||
|
|
48576e6584 | ||
|
|
79d644d1a2 | ||
|
|
2f7246cb26 | ||
|
|
8476756ae3 | ||
|
|
d90c240f2a | ||
|
|
3be651e99d | ||
|
|
4fac98a656 | ||
|
|
bed56b29b8 | ||
|
|
2338e28eef | ||
|
|
d4eb53db66 | ||
|
|
8f777bbc0d | ||
|
|
7d256b941a | ||
|
|
c3ceccf9bc | ||
|
|
c89928824f | ||
|
|
047f654646 | ||
|
|
0fc9663aa7 | ||
|
|
50f623482f | ||
|
|
2e0f79f8b6 | ||
|
|
308cb3daf9 | ||
|
|
f1b3c2fa8b | ||
|
|
2f6d66af9d | ||
|
|
ef21b84507 | ||
|
|
c9dd6721cf | ||
|
|
428519788b | ||
|
|
522df62704 | ||
|
|
d35b677f4b | ||
|
|
b1c183b83c | ||
|
|
7555f14f91 | ||
|
|
bc2a793022 | ||
|
|
a40e52b504 | ||
|
|
c860b5c47f | ||
|
|
2f8b80270f | ||
|
|
d01e38ae60 | ||
|
|
eed6844f8b | ||
|
|
f6e73eb5b6 | ||
|
|
3034ed7851 | ||
|
|
34c9fcc96a | ||
|
|
b7f1b7347f | ||
|
|
fc4a224c47 | ||
|
|
b86b5055c6 | ||
|
|
c0d418d2f4 | ||
|
|
2cd89433de | ||
|
|
6cb2857ef0 | ||
|
|
716bc48e21 | ||
|
|
6afd248b18 | ||
|
|
8e62bee92f | ||
|
|
02ce009f42 | ||
|
|
88a8df65a2 | ||
|
|
5c42e98b8f | ||
|
|
fd5abe1ac5 | ||
|
|
088d89c918 | ||
|
|
8299ae07ec | ||
|
|
fd8ad0b934 | ||
|
|
2fc6aa80df | ||
|
|
1c26215f3f | ||
|
|
7b1e1540e2 | ||
|
|
02010edac3 | ||
|
|
e4e76943d6 | ||
|
|
569361586a | ||
|
|
785218258b | ||
|
|
0b45bc64c2 | ||
|
|
17f3fec1ed | ||
|
|
52dbf3e3cf | ||
|
|
0a814e4372 | ||
|
|
fc63326544 | ||
|
|
18bacaab15 | ||
|
|
e8f12786b4 | ||
|
|
8789204f97 | ||
|
|
819fb64520 | ||
|
|
31003b45e6 | ||
|
|
1f04b16682 | ||
|
|
0a8b04e3e3 | ||
|
|
f8b4039d96 | ||
|
|
6da496e2f9 | ||
|
|
68d38a3f16 | ||
|
|
0e8eddfd8c | ||
|
|
3645cf9fc3 | ||
|
|
a0585ff990 | ||
|
|
ec3a2a3b3b | ||
|
|
24e2a6fb86 | ||
|
|
1144bc6587 | ||
|
|
fa84d9471e | ||
|
|
71dfd0dc2e | ||
|
|
b941520afb | ||
|
|
be110124f6 | ||
|
|
927363397d | ||
|
|
9dc097cfe5 | ||
|
|
e3b0c8a681 | ||
|
|
a62be95af3 | ||
|
|
a2e707696a | ||
|
|
f267068b02 | ||
|
|
7f0849be06 | ||
|
|
87697c0dca | ||
|
|
0acc1c308e | ||
|
|
312a3d8003 | ||
|
|
701bae514b | ||
|
|
8bffb974e4 | ||
|
|
d4e6e22e93 | ||
|
|
1e9cd5f299 | ||
|
|
29022e81a4 | ||
|
|
6b028b6303 | ||
|
|
f76208237d | ||
|
|
b61db7817f | ||
|
|
6a48a0a018 | ||
|
|
3415802ae9 | ||
|
|
20a19b977f | ||
|
|
10228bf07b | ||
|
|
24ac45c74e | ||
|
|
85c8b8252f | ||
|
|
948fd1aec0 | ||
|
|
213a6fbf71 | ||
|
|
c089e392a9 | ||
|
|
387fa91a19 | ||
|
|
bde04d3ec6 | ||
|
|
ce7dceac93 | ||
|
|
18832c2f0d | ||
|
|
3fdcd6b1fa | ||
|
|
2b564ea543 | ||
|
|
6b62acfc40 | ||
|
|
62411c0bbf | ||
|
|
c10ebdc85f | ||
|
|
1b00b76bc1 | ||
|
|
8ffb34e4db | ||
|
|
81ce706243 | ||
|
|
a96679dfee | ||
|
|
0c659577d4 | ||
|
|
ea41e77287 | ||
|
|
ca51c3f430 | ||
|
|
5716c6246f | ||
|
|
f6edf885b4 | ||
|
|
4acaa728bb | ||
|
|
331d2daf96 | ||
|
|
174b246d44 | ||
|
|
0bf83955a9 | ||
|
|
69c6091ee4 | ||
|
|
cf02ab960f | ||
|
|
b50d1ab2d1 | ||
|
|
ba9054e8d5 | ||
|
|
7e9cc01c54 | ||
|
|
0f52c861db | ||
|
|
920e7b9ae1 | ||
|
|
b8e577a274 | ||
|
|
fc3c551a67 | ||
|
|
797a722244 | ||
|
|
44790ad9d8 | ||
|
|
73d266fe29 | ||
|
|
e1ddf02aff | ||
|
|
66d62c97d5 | ||
|
|
d44a61ef33 | ||
|
|
ef59201f02 | ||
|
|
f5439803c2 | ||
|
|
a0a0be0376 | ||
|
|
48ce5846c9 | ||
|
|
de0eba3279 | ||
|
|
bc262c2f61 | ||
|
|
d4389f0f4f | ||
|
|
79984462e1 | ||
|
|
c6dcc2a013 | ||
|
|
e6dde3c065 | ||
|
|
39283171ce | ||
|
|
33288d37e7 | ||
|
|
b60277dde9 | ||
|
|
68b429ddc6 | ||
|
|
ec0b6d0e4c | ||
|
|
e3ea6b7948 | ||
|
|
8c8be234b2 | ||
|
|
029d6cd6b8 | ||
|
|
8fc95ea175 | ||
|
|
3e2a2ce2d0 | ||
|
|
4aebdafc0b | ||
|
|
2aadab2297 | ||
|
|
2a968ff601 | ||
|
|
ef327f98b5 | ||
|
|
5c1cab8429 | ||
|
|
60e7ac7c28 | ||
|
|
fe91ab72f6 | ||
|
|
cc23ede837 | ||
|
|
76dc7bcd3f | ||
|
|
c7072f0969 | ||
|
|
032079bf7f | ||
|
|
21ccb43669 | ||
|
|
038a51af80 | ||
|
|
a5f4b54b5f | ||
|
|
61e9ed7dab | ||
|
|
c6c396f2fe | ||
|
|
7f05b89187 | ||
|
|
139cb86a77 | ||
|
|
97365f6cd2 | ||
|
|
1f20fb83f0 | ||
|
|
51647add79 | ||
|
|
6c6532459a | ||
|
|
f53b75ef58 | ||
|
|
732c1a14e7 | ||
|
|
3ab0d43f2c | ||
|
|
de17e6cdf2 | ||
|
|
c7bb50a40c | ||
|
|
fe12e8f13f | ||
|
|
87e23c4c79 | ||
|
|
2f49eb9ee1 | ||
|
|
00b3d3d9e7 | ||
|
|
19193bdb26 | ||
|
|
d12b5fc2ab | ||
|
|
338f354106 | ||
|
|
626a6b7213 | ||
|
|
090f90127a | ||
|
|
598640f3be | ||
|
|
7ee3290f25 | ||
|
|
e9eccdd473 | ||
|
|
6dc8c796c9 | ||
|
|
d1028b2eb8 | ||
|
|
0e24cebad0 | ||
|
|
d8f8ad9a74 | ||
|
|
47a703e935 | ||
|
|
742b6417b4 | ||
|
|
af9376f801 | ||
|
|
adaff22ded | ||
|
|
2cd4de3431 | ||
|
|
b199521773 | ||
|
|
aecc5ebeee | ||
|
|
630aa37bbd | ||
|
|
c060576a37 | ||
|
|
54849deb96 | ||
|
|
034e423c9c | ||
|
|
89c31817b2 | ||
|
|
e42f43b67b | ||
|
|
6fdb8b53b3 | ||
|
|
3323f78bb4 | ||
|
|
fe20777b56 | ||
|
|
89890d6f77 | ||
|
|
927a8c5ba3 | ||
|
|
5e7542fc4b | ||
|
|
bb3376162b | ||
|
|
6d350523ea | ||
|
|
8838901b21 | ||
|
|
eb59803836 | ||
|
|
bdf73bf6ae | ||
|
|
4cddd28d4b | ||
|
|
89f014aed9 | ||
|
|
4904bb2843 | ||
|
|
13e016d7c4 | ||
|
|
709c71af5f | ||
|
|
8c58d60f5b | ||
|
|
e6e128a1c4 | ||
|
|
358ff4f347 |
@@ -187,6 +187,16 @@
|
||||
"contributions": [
|
||||
"doc"
|
||||
]
|
||||
},
|
||||
{
|
||||
"login": "V0lantis",
|
||||
"name": "Arthur",
|
||||
"avatar_url": "https://avatars.githubusercontent.com/u/37664438?v=4",
|
||||
"profile": "https://arthurvolant.com",
|
||||
"contributions": [
|
||||
"bug",
|
||||
"code"
|
||||
]
|
||||
}
|
||||
],
|
||||
"contributorsPerLine": 7,
|
||||
@@ -195,5 +205,6 @@
|
||||
"repoType": "github",
|
||||
"repoHost": "https://github.com",
|
||||
"skipCi": true,
|
||||
"commitConvention": "angular"
|
||||
"commitConvention": "angular",
|
||||
"commitType": "docs"
|
||||
}
|
||||
|
||||
4
.codacy.yml
Normal file
4
.codacy.yml
Normal file
@@ -0,0 +1,4 @@
|
||||
---
|
||||
exclude_paths:
|
||||
- "*.md"
|
||||
- "dist/**"
|
||||
@@ -1,4 +1,5 @@
|
||||
dist/
|
||||
lib/
|
||||
node_modules/
|
||||
jest.config.js
|
||||
jest.config.js
|
||||
coverage/
|
||||
@@ -1,10 +1,12 @@
|
||||
{
|
||||
"plugins": [
|
||||
"jest",
|
||||
"@typescript-eslint"
|
||||
"@typescript-eslint",
|
||||
"github"
|
||||
],
|
||||
"extends": [
|
||||
"plugin:github/recommended"
|
||||
"plugin:github/recommended",
|
||||
"plugin:prettier/recommended"
|
||||
],
|
||||
"parser": "@typescript-eslint/parser",
|
||||
"parserOptions": {
|
||||
|
||||
12
.github/FUNDING.yml
vendored
12
.github/FUNDING.yml
vendored
@@ -1,12 +0,0 @@
|
||||
# These are supported funding model platforms
|
||||
|
||||
github: jackton1
|
||||
patreon: # Replace with a single Patreon username
|
||||
open_collective: tj-actions
|
||||
ko_fi: # Replace with a single Ko-fi username
|
||||
tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel
|
||||
community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry
|
||||
liberapay: # Replace with a single Liberapay username
|
||||
issuehunt: # Replace with a single IssueHunt username
|
||||
otechie: # Replace with a single Otechie username
|
||||
custom: []
|
||||
98
.github/ISSUE_TEMPLATE/bug_report.yaml
vendored
98
.github/ISSUE_TEMPLATE/bug_report.yaml
vendored
@@ -1,98 +0,0 @@
|
||||
name: 🐞 Bug
|
||||
description: Create a report to help us improve
|
||||
title: "[BUG] <title>"
|
||||
labels: [bug, needs triage]
|
||||
|
||||
body:
|
||||
- type: markdown
|
||||
attributes:
|
||||
value: |
|
||||
Thanks for taking the time to fill out this bug report!
|
||||
- type: checkboxes
|
||||
attributes:
|
||||
label: Is there an existing issue for this?
|
||||
description: Please search to see if an issue already exists for the bug you encountered.
|
||||
options:
|
||||
- label: I have searched the existing issues
|
||||
required: true
|
||||
- type: checkboxes
|
||||
attributes:
|
||||
label: Does this issue exist in the latest version?
|
||||
description: Please view all releases to confirm that this issue hasn't already been fixed.
|
||||
options:
|
||||
- label: I'm using the latest release
|
||||
required: true
|
||||
- type: textarea
|
||||
id: what-happened
|
||||
attributes:
|
||||
label: Describe the bug?
|
||||
description: A clear and concise description of what the bug is
|
||||
placeholder: Tell us what you see!
|
||||
validations:
|
||||
required: true
|
||||
- type: textarea
|
||||
id: reproduce
|
||||
attributes:
|
||||
label: To Reproduce
|
||||
description: Steps to reproduce the behavior?
|
||||
placeholder: |
|
||||
1. In this environment...
|
||||
2. With this config...
|
||||
3. Run '...'
|
||||
4. See error...
|
||||
validations:
|
||||
required: true
|
||||
- type: dropdown
|
||||
id: os
|
||||
attributes:
|
||||
label: What OS are you seeing the problem on?
|
||||
multiple: true
|
||||
options:
|
||||
- all
|
||||
- ubuntu-latest or ubuntu-20.04
|
||||
- ubuntu-18.04
|
||||
- macos-latest or macos-10.15
|
||||
- macos-11
|
||||
- windows-latest or windows-2019
|
||||
- windows-2016
|
||||
validations:
|
||||
required: true
|
||||
- type: textarea
|
||||
id: expected
|
||||
attributes:
|
||||
label: Expected behavior?
|
||||
description: A clear and concise description of what you expected to happen.
|
||||
placeholder: Tell us what you expected!
|
||||
validations:
|
||||
required: true
|
||||
- type: textarea
|
||||
id: logs
|
||||
attributes:
|
||||
label: Relevant log output
|
||||
description: Please copy and paste any relevant log output which is obtained after enabling debug logging. This will be automatically formatted into code, so no need for backticks.
|
||||
placeholder: |
|
||||
1. Re-running the workflow with debug logging enabled.
|
||||
2. Copy or download the log archive.
|
||||
3. Paste the contents here or upload the file in a subsequent comment.
|
||||
render: shell
|
||||
validations:
|
||||
required: true
|
||||
- type: textarea
|
||||
attributes:
|
||||
label: Anything else?
|
||||
description: |
|
||||
Links? or References?
|
||||
|
||||
Anything that will give us more context about the issue you are encountering!
|
||||
|
||||
Tip: You can attach images or log files by clicking this area to highlight it and then dragging files in.
|
||||
validations:
|
||||
required: false
|
||||
- type: checkboxes
|
||||
id: terms
|
||||
attributes:
|
||||
label: Code of Conduct
|
||||
description: By submitting this issue, you agree to follow our [Code of Conduct](../blob/main/CODE_OF_CONDUCT.md)
|
||||
options:
|
||||
- label: I agree to follow this project's Code of Conduct
|
||||
required: true
|
||||
59
.github/ISSUE_TEMPLATE/feature_request.yaml
vendored
59
.github/ISSUE_TEMPLATE/feature_request.yaml
vendored
@@ -1,59 +0,0 @@
|
||||
name: Feature request
|
||||
description: Suggest an idea for this project
|
||||
title: "[Feature] <title>"
|
||||
labels: [enhancement]
|
||||
|
||||
body:
|
||||
- type: markdown
|
||||
attributes:
|
||||
value: |
|
||||
Thanks for taking the time to fill out this feature request!
|
||||
- type: checkboxes
|
||||
attributes:
|
||||
label: Is this feature missing in the latest version?
|
||||
description: Please upgrade to the latest version to verify that this feature is still missing.
|
||||
options:
|
||||
- label: I'm using the latest release
|
||||
required: true
|
||||
- type: textarea
|
||||
id: what-happened
|
||||
attributes:
|
||||
label: Is your feature request related to a problem? Please describe.
|
||||
description: |
|
||||
A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]
|
||||
placeholder: Tell us what you see!
|
||||
validations:
|
||||
required: true
|
||||
- type: textarea
|
||||
id: requests
|
||||
attributes:
|
||||
label: Describe the solution you'd like?
|
||||
description: A clear and concise description of what you want to happen.
|
||||
validations:
|
||||
required: true
|
||||
- type: textarea
|
||||
id: alternative
|
||||
attributes:
|
||||
label: Describe alternatives you've considered?
|
||||
description: A clear and concise description of any alternative solutions or features you've considered.
|
||||
validations:
|
||||
required: false
|
||||
- type: textarea
|
||||
attributes:
|
||||
label: Anything else?
|
||||
description: |
|
||||
Links? or References?
|
||||
|
||||
Add any other context or screenshots about the feature request here.
|
||||
|
||||
Tip: You can attach images or log files by clicking this area to highlight it and then dragging files in.
|
||||
validations:
|
||||
required: false
|
||||
- type: checkboxes
|
||||
id: terms
|
||||
attributes:
|
||||
label: Code of Conduct
|
||||
description: By submitting this issue, you agree to follow our [Code of Conduct](../blob/main/CODE_OF_CONDUCT.md)
|
||||
options:
|
||||
- label: I agree to follow this project's Code of Conduct
|
||||
required: true
|
||||
17
.github/dependabot.yml
vendored
17
.github/dependabot.yml
vendored
@@ -1,7 +1,24 @@
|
||||
version: 2
|
||||
updates:
|
||||
- package-ecosystem: npm
|
||||
directory: "/"
|
||||
schedule:
|
||||
interval: daily
|
||||
open-pull-requests-limit: 10
|
||||
versioning-strategy: widen
|
||||
labels:
|
||||
- "merge when passing"
|
||||
- package-ecosystem: github-actions
|
||||
directory: "/"
|
||||
schedule:
|
||||
interval: daily
|
||||
open-pull-requests-limit: 10
|
||||
labels:
|
||||
- "merge when passing"
|
||||
- package-ecosystem: gitsubmodule
|
||||
directory: /
|
||||
schedule:
|
||||
interval: daily
|
||||
open-pull-requests-limit: 10
|
||||
labels:
|
||||
- "merge when passing"
|
||||
|
||||
26
.github/workflows/auto-merge.yml
vendored
26
.github/workflows/auto-merge.yml
vendored
@@ -1,26 +0,0 @@
|
||||
name: automerge
|
||||
on:
|
||||
check_suite:
|
||||
types:
|
||||
- completed
|
||||
|
||||
jobs:
|
||||
automerge:
|
||||
runs-on: ubuntu-latest
|
||||
if: |
|
||||
github.actor == 'dependabot[bot]' ||
|
||||
github.actor == 'dependabot' ||
|
||||
github.actor == 'dependabot-preview[bot]' ||
|
||||
github.actor == 'dependabot-preview' ||
|
||||
github.actor == 'renovate[bot]' ||
|
||||
github.actor == 'renovate'
|
||||
steps:
|
||||
- name: automerge
|
||||
uses: pascalgn/automerge-action@v0.15.6
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.PAT_TOKEN }}
|
||||
MERGE_METHOD: "rebase"
|
||||
UPDATE_METHOD: "rebase"
|
||||
MERGE_RETRIES: "6"
|
||||
MERGE_RETRY_SLEEP: "100000"
|
||||
MERGE_LABELS: ""
|
||||
2
.github/workflows/codacy-analysis.yml
vendored
2
.github/workflows/codacy-analysis.yml
vendored
@@ -29,7 +29,7 @@ jobs:
|
||||
steps:
|
||||
# Checkout the repository to the GitHub Actions runner
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v3
|
||||
uses: actions/checkout@v4
|
||||
|
||||
# Execute Codacy Analysis CLI and generate a SARIF output with the security issues identified during the analysis
|
||||
- name: Run Codacy Analysis CLI
|
||||
|
||||
2
.github/workflows/codeql.yml
vendored
2
.github/workflows/codeql.yml
vendored
@@ -38,7 +38,7 @@ jobs:
|
||||
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v3
|
||||
uses: actions/checkout@v4
|
||||
|
||||
# Initializes the CodeQL tools for scanning.
|
||||
- name: Initialize CodeQL
|
||||
|
||||
174
.github/workflows/issue-comment-test.yml
vendored
Normal file
174
.github/workflows/issue-comment-test.yml
vendored
Normal file
@@ -0,0 +1,174 @@
|
||||
name: Issue Comment Test
|
||||
on:
|
||||
issue_comment:
|
||||
|
||||
jobs:
|
||||
pr_commented:
|
||||
# This job only runs for pull request comments
|
||||
name: PR comment
|
||||
if: ${{ github.event.issue.pull_request }}
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- run: |
|
||||
echo A comment on PR $NUMBER
|
||||
env:
|
||||
NUMBER: ${{ github.event.issue.number }}
|
||||
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
submodules: true
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Dump GitHub context
|
||||
env:
|
||||
GITHUB_CONTEXT: ${{ toJson(github) }}
|
||||
run: echo "$GITHUB_CONTEXT"
|
||||
|
||||
- name: Run changed-files with defaults
|
||||
id: changed-files
|
||||
uses: ./
|
||||
|
||||
- name: Show output
|
||||
run: |
|
||||
echo '${{ toJSON(steps.changed-files.outputs) }}'
|
||||
shell:
|
||||
bash
|
||||
|
||||
- name: Run changed-files for old new filenames test rename
|
||||
id: changed-files-all-old-new-renamed-files
|
||||
uses: ./
|
||||
with:
|
||||
base_sha: d1c0ee4
|
||||
sha: 4d04215
|
||||
fetch_depth: 60000
|
||||
include_all_old_new_renamed_files: true
|
||||
|
||||
- name: Show output
|
||||
run: |
|
||||
echo '${{ toJSON(steps.changed-files-all-old-new-renamed-files.outputs) }}'
|
||||
shell:
|
||||
bash
|
||||
|
||||
- name: Show output
|
||||
run: |
|
||||
echo '${{ toJSON(steps.changed-files-all-old-new-renamed-files.outputs) }}'
|
||||
shell:
|
||||
bash
|
||||
|
||||
- name: Check all_old_new_renamed_files output on non windows platform
|
||||
if: "!contains(steps.changed-files-all-old-new-renamed-files.outputs.all_old_new_renamed_files, 'test/test rename 1.txt,test/test rename-1.txt') && runner.os != 'Windows'"
|
||||
run: |
|
||||
echo "Invalid output: Expected to include (test/test rename 1.txt,test/test rename-1.txt) got (${{ steps.changed-files-all-old-new-renamed-files.outputs.all_old_new_renamed_files }})"
|
||||
exit 1
|
||||
shell:
|
||||
bash
|
||||
|
||||
- name: Check all_old_new_renamed_files output on windows platform
|
||||
if: "!contains(steps.changed-files-all-old-new-renamed-files.outputs.all_old_new_renamed_files, 'test\\test rename 1.txt,test\\test rename-1.txt') && runner.os == 'Windows'"
|
||||
run: |
|
||||
echo "Invalid output: Expected to not include (test\\test rename 1.txt,test\\test rename-1.txt) got (${{ steps.changed-files-all-old-new-renamed-files.outputs.all_old_new_renamed_files }})"
|
||||
exit 1
|
||||
shell:
|
||||
bash
|
||||
|
||||
- name: Check the renamed_files output on non windows platform
|
||||
if: "!contains(steps.changed-files-all-old-new-renamed-files.outputs.renamed_files, 'test/test rename-1.txt') && runner.os != 'Windows'"
|
||||
run: |
|
||||
echo "Invalid output: Expected to include (test/test rename-1.txt) got (${{ steps.changed-files-all-old-new-renamed-files.outputs.renamed_files }})"
|
||||
exit 1
|
||||
shell:
|
||||
bash
|
||||
|
||||
- name: Check the renamed_files output on windows platform
|
||||
if: "!contains(steps.changed-files-all-old-new-renamed-files.outputs.renamed_files, 'test\\test rename-1.txt') && runner.os == 'Windows'"
|
||||
run: |
|
||||
echo "Invalid output: Expected to not include (test\\test rename-1.txt) got (${{ steps.changed-files-all-old-new-renamed-files.outputs.renamed_files }})"
|
||||
exit 1
|
||||
shell:
|
||||
bash
|
||||
|
||||
issue_commented:
|
||||
# This job only runs for issue comments
|
||||
name: Issue comment
|
||||
if: ${{ !github.event.issue.pull_request }}
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- run: |
|
||||
echo A comment on issue $NUMBER
|
||||
env:
|
||||
NUMBER: ${{ github.event.issue.number }}
|
||||
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
submodules: true
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Dump GitHub context
|
||||
env:
|
||||
GITHUB_CONTEXT: ${{ toJson(github) }}
|
||||
run: echo "$GITHUB_CONTEXT"
|
||||
|
||||
- name: Run changed-files with defaults
|
||||
id: changed-files
|
||||
uses: ./
|
||||
|
||||
- name: Show output
|
||||
run: |
|
||||
echo '${{ toJSON(steps.changed-files.outputs) }}'
|
||||
shell:
|
||||
bash
|
||||
|
||||
- name: Run changed-files for old new filenames test rename
|
||||
id: changed-files-all-old-new-renamed-files
|
||||
uses: ./
|
||||
with:
|
||||
base_sha: d1c0ee4
|
||||
sha: 4d04215
|
||||
fetch_depth: 60000
|
||||
include_all_old_new_renamed_files: true
|
||||
|
||||
- name: Show output
|
||||
run: |
|
||||
echo '${{ toJSON(steps.changed-files-all-old-new-renamed-files.outputs) }}'
|
||||
shell:
|
||||
bash
|
||||
|
||||
- name: Show output
|
||||
run: |
|
||||
echo '${{ toJSON(steps.changed-files-all-old-new-renamed-files.outputs) }}'
|
||||
shell:
|
||||
bash
|
||||
|
||||
- name: Check all_old_new_renamed_files output on non windows platform
|
||||
if: "!contains(steps.changed-files-all-old-new-renamed-files.outputs.all_old_new_renamed_files, 'test/test rename 1.txt,test/test rename-1.txt') && runner.os != 'Windows'"
|
||||
run: |
|
||||
echo "Invalid output: Expected to include (test/test rename 1.txt,test/test rename-1.txt) got (${{ steps.changed-files-all-old-new-renamed-files.outputs.all_old_new_renamed_files }})"
|
||||
exit 1
|
||||
shell:
|
||||
bash
|
||||
|
||||
- name: Check all_old_new_renamed_files output on windows platform
|
||||
if: "!contains(steps.changed-files-all-old-new-renamed-files.outputs.all_old_new_renamed_files, 'test\\test rename 1.txt,test\\test rename-1.txt') && runner.os == 'Windows'"
|
||||
run: |
|
||||
echo "Invalid output: Expected to not include (test\\test rename 1.txt,test\\test rename-1.txt) got (${{ steps.changed-files-all-old-new-renamed-files.outputs.all_old_new_renamed_files }})"
|
||||
exit 1
|
||||
shell:
|
||||
bash
|
||||
|
||||
- name: Check the renamed_files output on non windows platform
|
||||
if: "!contains(steps.changed-files-all-old-new-renamed-files.outputs.renamed_files, 'test/test rename-1.txt') && runner.os != 'Windows'"
|
||||
run: |
|
||||
echo "Invalid output: Expected to include (test/test rename-1.txt) got (${{ steps.changed-files-all-old-new-renamed-files.outputs.renamed_files }})"
|
||||
exit 1
|
||||
shell:
|
||||
bash
|
||||
|
||||
- name: Check the renamed_files output on windows platform
|
||||
if: "!contains(steps.changed-files-all-old-new-renamed-files.outputs.renamed_files, 'test\\test rename-1.txt') && runner.os == 'Windows'"
|
||||
run: |
|
||||
echo "Invalid output: Expected to not include (test\\test rename-1.txt) got (${{ steps.changed-files-all-old-new-renamed-files.outputs.renamed_files }})"
|
||||
exit 1
|
||||
shell:
|
||||
bash
|
||||
2
.github/workflows/manual-test.yml
vendored
2
.github/workflows/manual-test.yml
vendored
@@ -16,7 +16,7 @@ jobs:
|
||||
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v3
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
submodules: true
|
||||
fetch-depth: 0
|
||||
|
||||
4
.github/workflows/matrix-test.yml
vendored
4
.github/workflows/matrix-test.yml
vendored
@@ -14,7 +14,7 @@ jobs:
|
||||
matrix: ${{ steps.set-matrix.outputs.matrix }}
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v3
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
fetch-depth: 0
|
||||
- name: Get changed files
|
||||
@@ -38,7 +38,7 @@ jobs:
|
||||
fail-fast: false
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v3
|
||||
uses: actions/checkout@v4
|
||||
- name: Test
|
||||
run: |
|
||||
echo ${{ matrix.files }}
|
||||
|
||||
29
.github/workflows/submodule-sync.yml
vendored
29
.github/workflows/submodule-sync.yml
vendored
@@ -1,29 +0,0 @@
|
||||
on:
|
||||
workflow_dispatch:
|
||||
|
||||
jobs:
|
||||
sync:
|
||||
name: Submodule Sync
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v3
|
||||
with:
|
||||
fetch-depth: 0
|
||||
submodules: recursive
|
||||
|
||||
- name: Git Sumbodule Update
|
||||
run: |
|
||||
git pull --recurse-submodules
|
||||
git submodule update --remote --recursive
|
||||
|
||||
- name: Create Pull Request
|
||||
uses: peter-evans/create-pull-request@v5.0.2
|
||||
with:
|
||||
title: "Updated submodule"
|
||||
labels: "merge when passing"
|
||||
branch: "chore/update-submodule"
|
||||
commit-message: "Updated submodule"
|
||||
body: "Updated submodule"
|
||||
token: ${{ secrets.PAT_TOKEN }}
|
||||
12
.github/workflows/sync-release-version.yml
vendored
12
.github/workflows/sync-release-version.yml
vendored
@@ -8,11 +8,11 @@ jobs:
|
||||
update-version:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
fetch-depth: 0
|
||||
- name: Run release-tagger
|
||||
uses: tj-actions/release-tagger@v3
|
||||
uses: tj-actions/release-tagger@v4
|
||||
- name: Sync release version.
|
||||
uses: tj-actions/sync-release-version@v13
|
||||
id: sync-release-version
|
||||
@@ -21,6 +21,14 @@ jobs:
|
||||
only_major: true
|
||||
paths: |
|
||||
README.md
|
||||
- name: Sync release package version.
|
||||
uses: tj-actions/sync-release-version@v13
|
||||
id: sync-release-package-version
|
||||
with:
|
||||
pattern: '"version": "'
|
||||
strip_prefix: "v"
|
||||
paths: |
|
||||
package.json
|
||||
- name: Run git-cliff
|
||||
uses: tj-actions/git-cliff@v1
|
||||
- name: Create Pull Request
|
||||
|
||||
661
.github/workflows/test.yml
vendored
661
.github/workflows/test.yml
vendored
File diff suppressed because it is too large
Load Diff
4
.github/workflows/update-readme.yml
vendored
4
.github/workflows/update-readme.yml
vendored
@@ -9,12 +9,12 @@ jobs:
|
||||
sync-assets:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Run auto-doc
|
||||
uses: tj-actions/auto-doc@v2
|
||||
uses: tj-actions/auto-doc@v3
|
||||
|
||||
- name: Run remark
|
||||
uses: tj-actions/remark@v3
|
||||
|
||||
1040
HISTORY.md
1040
HISTORY.md
File diff suppressed because it is too large
Load Diff
587
README.md
587
README.md
@@ -9,44 +9,53 @@
|
||||
|
||||
<!-- ALL-CONTRIBUTORS-BADGE:START - Do not remove or modify this section -->
|
||||
|
||||
[](#contributors-)
|
||||
[](#contributors-)
|
||||
|
||||
<!-- ALL-CONTRIBUTORS-BADGE:END -->
|
||||
|
||||
<div align="center">
|
||||
<img width="auto" alt="Screen Shot 2021-11-19 at 4 59 21 PM" src="https://user-images.githubusercontent.com/17484350/229027815-eee0bf22-f3e5-444d-9d90-6409c68a0dc9.png">
|
||||
</div>
|
||||
|
||||
## changed-files
|
||||
|
||||
Effortlessly track all changed files and directories relative to a target branch, preceding commit or the last remote commit returning **relative paths** from the project root.
|
||||
Effortlessly track all changed files and directories relative to a target branch, preceding commit or the last remote commit returning **relative paths** from the project root using this GitHub action.
|
||||
|
||||
> **Note**
|
||||
>
|
||||
> * This action solely identifies files that have undergone changes within the context of events such as `pull_request*`, `push`, and more. However, it doesn't detect pending uncommitted changes created during the workflow execution.
|
||||
>
|
||||
> See: https://github.com/tj-actions/verify-changed-files instead
|
||||
|
||||
## Table of contents
|
||||
|
||||
* [Features](#features)
|
||||
* [Usage](#usage)
|
||||
* [Useful Acronyms](#useful-acronyms)
|
||||
* [Outputs](#outputs)
|
||||
* [Inputs](#inputs)
|
||||
* [Versioning](#versioning)
|
||||
* [Examples](#examples)
|
||||
* [Real world usage](#real-world-usage)
|
||||
* [Known Limitation](#known-limitation)
|
||||
* [Migration guide](#migration-guide)
|
||||
* [Credits](#credits)
|
||||
* [Report Bugs](#report-bugs)
|
||||
* [Features 🚀](#features-)
|
||||
* [Usage 💻](#usage-)
|
||||
* [On `pull_request` 🔀](#on-pull_request-)
|
||||
* [Using local .git history 📁](#using-local-git-history-)
|
||||
* [Using Github's API :octocat:](#using-githubs-api-octocat)
|
||||
* [On `push` ⬆️](#on-push-️)
|
||||
* [Useful Acronyms 🧮](#useful-acronyms-)
|
||||
* [Outputs 📤](#outputs-)
|
||||
* [Inputs ⚙️](#inputs-️)
|
||||
* [Versioning 🏷️](#versioning-️)
|
||||
* [Examples 📄](#examples-)
|
||||
* [Real-world usage 🌐](#real-world-usage-)
|
||||
* [Open source projects 📦](#open-source-projects-)
|
||||
* [Scalability Example 📈](#scalability-example-)
|
||||
* [Important Notice ⚠️](#important-notice-️)
|
||||
* [Migration guide 🔄](#migration-guide-)
|
||||
* [Credits 👏](#credits-)
|
||||
* [Report Bugs 🐛](#report-bugs-)
|
||||
* [Contributors ✨](#contributors-)
|
||||
|
||||
## Features
|
||||
## Features 🚀
|
||||
|
||||
* Provides fast execution, averaging 0-10 seconds.
|
||||
* Fast execution, averaging 0-10 seconds.
|
||||
* Leverages either [Github's REST API](https://docs.github.com/en/rest/reference/repos#list-commits) or [Git's native diff](https://git-scm.com/docs/git-diff) to determine changed files.
|
||||
* Facilitates easy debugging.
|
||||
* Scales to handle large repositories.
|
||||
* Supports Git submodules.
|
||||
* Generates escaped JSON output for running matrix jobs based on changed files.
|
||||
* Supports [merge queues](https://docs.github.com/en/repositories/configuring-branches-and-merges-in-your-repository/configuring-pull-request-merges/managing-a-merge-queue) for pull requests.
|
||||
* Generates escaped [JSON output for running matrix jobs](https://github.com/tj-actions/changed-files/blob/main/.github/workflows/matrix-test.yml) based on changed files.
|
||||
* Lists changed directories.
|
||||
* Allows limiting the matching changed directories to a specified maximum depth.
|
||||
* Limits matching changed directories to a specified maximum depth.
|
||||
* Optionally excludes the current directory.
|
||||
* Writes outputs to a designated `.txt` or `.json` file for further processing.
|
||||
* Restores deleted files to their previous location or a newly specified location.
|
||||
@@ -61,76 +70,58 @@ Effortlessly track all changed files and directories relative to a target branch
|
||||
* Between the last remote branch commit and the current HEAD.
|
||||
* Restricts change detection to a subset of files and directories:
|
||||
* Provides boolean output indicating changes in specific files.
|
||||
* Uses [Glob pattern](https://docs.github.com/en/actions/learn-github-actions/workflow-syntax-for-github-actions#filter-pattern-cheat-sheet) matching.
|
||||
* Uses [Glob pattern](https://codepen.io/mrmlnc/pen/OXQjMe) matching.
|
||||
* Supports Globstar.
|
||||
* Supports brace expansion.
|
||||
* Supports negation.
|
||||
* Uses [YAML](https://yaml.org/) syntax for specifying patterns.
|
||||
* Supports [YAML anchors & aliases](https://www.educative.io/blog/advanced-yaml-syntax-cheatsheet#anchors).
|
||||
* Supports [YAML multi-line strings](https://learnxinyminutes.com/docs/yaml/).
|
||||
* Supports [YAML anchors & aliases](https://github.com/tj-actions/changed-files/blob/main/test/changed-files.yml#L8-L12).
|
||||
* Supports [YAML multi-line strings](https://github.com/tj-actions/changed-files/blob/main/test/changed-files.yml#L13-L16).
|
||||
|
||||
And many more.
|
||||
And many more...
|
||||
|
||||
## Usage
|
||||
## Usage 💻
|
||||
|
||||
> **Warning**:
|
||||
> **Important**
|
||||
>
|
||||
> * **IMPORTANT:** For `push` events when configuring [`actions/checkout`](https://github.com/actions/checkout#usage) the `fetch-depth` should be set to either `fetch-depth: 0` **OR** `fetch-depth: 2` depending on your use case.
|
||||
> * For monorepos where pulling all the branch history might not be desired, you can omit [`actions/checkout`](https://github.com/actions/checkout#usage) - `fetch-depth` for `pull_request` events.
|
||||
> * All multiline inputs should not use double or single quotes since the value is already a string separated by a newline character. See [Examples](#examples) for more information.
|
||||
> * Ensure that `persist-credentials` is set to `true` when configuring [`actions/checkout`](https://github.com/actions/checkout#usage) if `fetch-depth` isn't set to `0`.
|
||||
> * For repositories that have PRs generated from forks when configuring [`actions/checkout`](https://github.com/actions/checkout#usage) set the `repository` to `${{ github.event.pull_request.head.repo.full_name }}`. See: [Example](https://github.com/tj-actions/changed-files/blob/main/.github/workflows/test.yml#L47-L51)
|
||||
> * For `push` events: When configuring [`actions/checkout`](https://github.com/actions/checkout#usage), make sure to set [`fetch-depth`](https://github.com/actions/checkout#usage) to either `0` or `2`, depending on your use case.
|
||||
> * For mono repositories where pulling all branch history might not be desired, you can still use the default [`fetch-depth`](https://github.com/actions/checkout#usage), which is set to `1` for `pull_request` events.
|
||||
> * Avoid using single or double quotes for multiline inputs, as the value is already a string separated by a newline character. See [Examples](#examples) for more information.
|
||||
> * If [`fetch-depth`](https://github.com/actions/checkout#usage) isn't set to `0`, ensure that [`persist-credentials`](https://github.com/actions/checkout#usage) is set to `true` when configuring [`actions/checkout`](https://github.com/actions/checkout#usage).
|
||||
> * For matching all files and folders under a directory you'll need to use `dir_name/**`
|
||||
|
||||
Visit the [discussions for more information](https://github.com/tj-actions/changed-files/discussions) or [create a new discussion](https://github.com/tj-actions/changed-files/discussions/new/choose) for usage-related questions.
|
||||
|
||||
### On `pull_request` 🔀
|
||||
|
||||
Detect changes to all files in a Pull request relative to the target branch or since the last pushed commit.
|
||||
|
||||
#### Using local .git history 📁
|
||||
|
||||
```yaml
|
||||
name: CI
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- main
|
||||
pull_request:
|
||||
branches:
|
||||
- main
|
||||
|
||||
jobs:
|
||||
# -------------------------------------------------------------
|
||||
# Event `pull_request`: Returns all changed pull request files.
|
||||
# --------------------------------------------------------------
|
||||
job1: # Example 1 - Using GitHub's API
|
||||
# NOTE:
|
||||
# - This is limited to pull_request* events and would raise an error for other events.
|
||||
# - A maximum of 3000 files can be returned.
|
||||
runs-on: ubuntu-latest # windows-latest | macos-latest
|
||||
name: Test changed-files
|
||||
if: github.event_name != 'push'
|
||||
permissions:
|
||||
pull-requests: read
|
||||
steps:
|
||||
- name: Get changed files
|
||||
id: changed-files
|
||||
uses: tj-actions/changed-files@v37
|
||||
|
||||
- name: List all changed files
|
||||
run: |
|
||||
for file in ${{ steps.changed-files.outputs.all_changed_files }}; do
|
||||
echo "$file was changed"
|
||||
done
|
||||
|
||||
# ------------------------------------------------------------------------------------------------------------
|
||||
# Event `push`: Compare the preceding commit -> to the current commit of the main branch.
|
||||
# Event `pull_request`: Compare the last commit of main -> to the current commit of a Pull Request branch.
|
||||
# ------------------------------------------------------------------------------------------------------------
|
||||
job2: # Example 2 - Using local .git directory
|
||||
runs-on: ubuntu-latest # windows-latest | macos-latest
|
||||
# ------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
# Event `pull_request`: Compare the last commit of the main branch or last remote commit of the PR branch -> to the current commit of a PR branch.
|
||||
# ------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
changed_files:
|
||||
runs-on: ubuntu-latest # windows-latest || macos-latest
|
||||
name: Test changed-files
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
fetch-depth: 0 # OR "2" -> To retrieve the preceding commit.
|
||||
|
||||
# Example 1
|
||||
- name: Get changed files
|
||||
id: changed-files
|
||||
uses: tj-actions/changed-files@v37
|
||||
uses: tj-actions/changed-files@v39
|
||||
|
||||
# To compare changes between the current commit and the last pushed remote commit set `since_last_remote_commit: true`. e.g
|
||||
# with:
|
||||
@@ -142,75 +133,26 @@ jobs:
|
||||
echo "$file was changed"
|
||||
done
|
||||
|
||||
job3: # Example 3 - Using local .git directory
|
||||
runs-on: ubuntu-latest # windows-latest | macos-latest
|
||||
name: Test changed-files
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
with:
|
||||
fetch-depth: 0 # OR "2" -> To retrieve the preceding commit.
|
||||
|
||||
- name: Get changed files in the docs folder
|
||||
id: changed-files-specific
|
||||
uses: tj-actions/changed-files@v37
|
||||
with:
|
||||
files: docs/*.{js,html} # Alternatively using: `docs/**` or `docs`
|
||||
|
||||
- name: Run step if any file(s) in the docs folder change
|
||||
if: steps.changed-files-specific.outputs.any_changed == 'true'
|
||||
run: |
|
||||
echo "One or more files in the docs folder has changed."
|
||||
echo "List all the files that have changed: ${{ steps.changed-files-specific.outputs.all_changed_files }}"
|
||||
|
||||
job4: # Example 4 - Using local .git directory
|
||||
runs-on: ubuntu-latest # windows-latest | macos-latest
|
||||
name: Test changed-files
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
with:
|
||||
fetch-depth: 0 # OR "2" -> To retrieve the preceding commit.
|
||||
|
||||
- name: Get all changed .js file(s) or any file in the static folder excluding the docs folder
|
||||
id: changed-files-excluded
|
||||
uses: tj-actions/changed-files@v37
|
||||
with:
|
||||
files: |
|
||||
**.js
|
||||
static
|
||||
files_ignore: docs
|
||||
|
||||
- name: Run step if any .js file(s) or any file in the static folder change
|
||||
if: steps.changed-files-excluded.outputs.any_changed == 'true'
|
||||
run: |
|
||||
echo "One or more .js file(s) or any file in the static folder but not in the doc folder has changed."
|
||||
echo "List all the files that have changed: ${{ steps.changed-files-excluded.outputs.all_changed_files }}"
|
||||
|
||||
job5: # Example 5 - Using local .git directory
|
||||
runs-on: ubuntu-latest # windows-latest | macos-latest
|
||||
name: Test changed-files
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
with:
|
||||
fetch-depth: 0 # OR "2" -> To retrieve the preceding commit.
|
||||
|
||||
# Example 2
|
||||
- name: Get all test, doc and src files that have changed
|
||||
id: changed-files-yaml
|
||||
uses: tj-actions/changed-files@v37
|
||||
uses: tj-actions/changed-files@v39
|
||||
with:
|
||||
files_yaml: |
|
||||
doc:
|
||||
- *.md
|
||||
- '**/*.md'
|
||||
- docs/**
|
||||
- !docs/README.md
|
||||
- README.md
|
||||
test:
|
||||
- test/**
|
||||
- !test/README.md
|
||||
- '!test/**.md'
|
||||
src:
|
||||
- src/**
|
||||
# Optionally set `files_yaml_from_source_file` to read the YAML from a file. e.g `files_yaml_from_source_file: .github/changed-files.yml`
|
||||
|
||||
- name: Run step if test file(s) change
|
||||
if: steps.changed-files-yaml.outputs.test_any_changed == 'true'
|
||||
# NOTE: Ensure all outputs are prefixed by the same key used above e.g. `test_(...)` | `doc_(...)` | `src_(...)` when trying to access the `any_changed` output.
|
||||
if: steps.changed-files-yaml.outputs.test_any_changed == 'true'
|
||||
run: |
|
||||
echo "One or more test file(s) has changed."
|
||||
echo "List all the files that have changed: ${{ steps.changed-files-yaml.outputs.test_all_changed_files }}"
|
||||
@@ -220,9 +162,124 @@ jobs:
|
||||
run: |
|
||||
echo "One or more doc file(s) has changed."
|
||||
echo "List all the files that have changed: ${{ steps.changed-files-yaml.outputs.doc_all_changed_files }}"
|
||||
|
||||
# Example 3
|
||||
- name: Get changed files in the docs folder
|
||||
id: changed-files-specific
|
||||
uses: tj-actions/changed-files@v39
|
||||
with:
|
||||
files: docs/*.{js,html} # Alternatively using: `docs/**`
|
||||
files_ignore: docs/static.js
|
||||
|
||||
- name: Run step if any file(s) in the docs folder change
|
||||
if: steps.changed-files-specific.outputs.any_changed == 'true'
|
||||
run: |
|
||||
echo "One or more files in the docs folder has changed."
|
||||
echo "List all the files that have changed: ${{ steps.changed-files-specific.outputs.all_changed_files }}"
|
||||
```
|
||||
|
||||
To access more examples, navigate to the [Examples](#examples) section.
|
||||
#### Using Github's API :octocat:
|
||||
|
||||
```yaml
|
||||
name: CI
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
branches:
|
||||
- main
|
||||
|
||||
jobs:
|
||||
# -------------------------------------------------------------
|
||||
# Event `pull_request`: Returns all changed pull request files.
|
||||
# --------------------------------------------------------------
|
||||
changed_files:
|
||||
# NOTE:
|
||||
# - This is limited to pull_request* events and would raise an error for other events.
|
||||
# - A maximum of 3000 files can be returned.
|
||||
# - For more flexibility and no limitations see "Using local .git history" above.
|
||||
|
||||
runs-on: ubuntu-latest # windows-latest || macos-latest
|
||||
name: Test changed-files
|
||||
permissions:
|
||||
pull-requests: read
|
||||
|
||||
steps:
|
||||
- name: Get changed files
|
||||
id: changed-files
|
||||
uses: tj-actions/changed-files@v39
|
||||
|
||||
- name: List all changed files
|
||||
run: |
|
||||
for file in ${{ steps.changed-files.outputs.all_changed_files }}; do
|
||||
echo "$file was changed"
|
||||
done
|
||||
```
|
||||
|
||||
### On `push` ⬆️
|
||||
|
||||
Detect changes to files made since the last pushed commit.
|
||||
|
||||
```yaml
|
||||
name: CI
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- main
|
||||
|
||||
# -------------------------------
|
||||
# Optionally run on other events
|
||||
# -------------------------------
|
||||
# schedule:
|
||||
# - cron: '0 0 * * *'
|
||||
#
|
||||
# release:
|
||||
# types: [...]
|
||||
#
|
||||
# workflow_dispatch:
|
||||
#
|
||||
# push:
|
||||
# tags:
|
||||
# - '**'
|
||||
#
|
||||
# merge_group:
|
||||
#
|
||||
# ...and many more
|
||||
|
||||
|
||||
jobs:
|
||||
# -------------------------------------------------------------
|
||||
# Using GitHub's API is not supported for push events
|
||||
# -------------------------------------------------------------
|
||||
#
|
||||
# ----------------------------------------------------------------------------------------------
|
||||
# Using local .git history
|
||||
# ----------------------------------------------------------------------------------------------
|
||||
# Event `push`: Compare the preceding remote commit -> to the current commit of the main branch
|
||||
# ----------------------------------------------------------------------------------------------
|
||||
changed_files:
|
||||
runs-on: ubuntu-latest # windows-latest || macos-latest
|
||||
name: Test changed-files
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
fetch-depth: 0 # OR "2" -> To retrieve the preceding commit.
|
||||
|
||||
- name: Get changed files
|
||||
id: changed-files
|
||||
uses: tj-actions/changed-files@v39
|
||||
|
||||
# NOTE: `since_last_remote_commit: true` is implied by default and falls back to the previous local commit.
|
||||
|
||||
- name: List all changed files
|
||||
run: |
|
||||
for file in ${{ steps.changed-files.outputs.all_changed_files }}; do
|
||||
echo "$file was changed"
|
||||
done
|
||||
...
|
||||
```
|
||||
|
||||
To access more examples, navigate to the [Examples](#examples-) section.
|
||||
|
||||
If you feel generous and want to show some extra appreciation:
|
||||
|
||||
@@ -234,7 +291,7 @@ Support this project with a :star:
|
||||
|
||||
[buymeacoffee-shield]: https://www.buymeacoffee.com/assets/img/custom_images/orange_img.png
|
||||
|
||||
## Useful Acronyms
|
||||
## Useful Acronyms 🧮
|
||||
|
||||
| Acronym | Meaning |
|
||||
|:---------:|:------------:|
|
||||
@@ -247,100 +304,118 @@ Support this project with a :star:
|
||||
| U | Unmerged |
|
||||
| X | Unknown |
|
||||
|
||||
## Outputs
|
||||
> **Warning**
|
||||
>
|
||||
> * When using `files_yaml*` inputs ensure all outputs are prefixed by the key `test_{...}` e.g. `test_added_files`, `test_any_changed`
|
||||
> * All keys must start with a letter or \_ and contain only alphanumeric characters, -, or \_.
|
||||
|
||||
## Outputs 📤
|
||||
|
||||
<!-- AUTO-DOC-OUTPUT:START - Do not remove or modify this section -->
|
||||
|
||||
| OUTPUT | TYPE | DESCRIPTION |
|
||||
|--------------------------------------|--------|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
|
||||
| added\_files | string | Returns only files that are <br>Added (A). |
|
||||
| added\_files\_count | string | Returns the number of `added_files` |
|
||||
| all\_changed\_and\_modified\_files | string | Returns all changed and modified <br>files i.e. *a combination of (ACMRDTUX)* |
|
||||
| all\_changed\_and\_modified\_files\_count | string | Returns the number of `all_changed_and_modified_files` |
|
||||
| all\_changed\_files | string | Returns all changed files i.e. <br>*a combination of all added, copied, modified and renamed files (ACMR)* |
|
||||
| all\_changed\_files\_count | string | Returns the number of `all_changed_files` |
|
||||
| all\_modified\_files | string | Returns all changed files i.e. <br>*a combination of all added, copied, modified, renamed and deleted files (ACMRD)*. |
|
||||
| all\_modified\_files\_count | string | Returns the number of `all_modified_files` |
|
||||
| all\_old\_new\_renamed\_files | string | Returns only files that are <br>Renamed and lists their old <br>and new names. **NOTE:** This <br>requires setting `include_all_old_new_renamed_files` to `true`. <br>Also, keep in mind that <br>this output is global and <br>wouldn't be nested in outputs <br>generated when the `*_yaml_*` input <br>is used. (R) |
|
||||
| all\_old\_new\_renamed\_files\_count | string | Returns the number of `all_old_new_renamed_files` |
|
||||
| any\_changed | string | Returns `true` when any of <br>the filenames provided using the <br>`files*` or `files_ignore*` inputs has changed. i.e. <br>*using a combination of all added, copied, modified and renamed files (ACMR)*. |
|
||||
| any\_deleted | string | Returns `true` when any of <br>the filenames provided using the <br>`files*` or `files_ignore*` inputs has been deleted. <br>(D) |
|
||||
| any\_modified | string | Returns `true` when any of <br>the filenames provided using the <br>`files*` or `files_ignore*` inputs has been modified. <br>i.e. *using a combination of all added, copied, modified, renamed, and deleted files (ACMRD)*. |
|
||||
| copied\_files | string | Returns only files that are <br>Copied (C). |
|
||||
| copied\_files\_count | string | Returns the number of `copied_files` |
|
||||
| deleted\_files | string | Returns only files that are <br>Deleted (D). |
|
||||
| deleted\_files\_count | string | Returns the number of `deleted_files` |
|
||||
| modified\_files | string | Returns only files that are <br>Modified (M). |
|
||||
| modified\_files\_count | string | Returns the number of `modified_files` |
|
||||
| only\_changed | string | Returns `true` when only files <br>provided using the `files*` or `files_ignore*` inputs <br>has changed. i.e. *using a combination of all added, copied, modified and renamed files (ACMR)*. |
|
||||
| only\_deleted | string | Returns `true` when only files <br>provided using the `files*` or `files_ignore*` inputs <br>has been deleted. (D) |
|
||||
| only\_modified | string | Returns `true` when only files <br>provided using the `files*` or `files_ignore*` inputs <br>has been modified. (ACMRD). |
|
||||
| other\_changed\_files | string | Returns all other changed files <br>not listed in the files <br>input i.e. *using a combination of all added, copied, modified and renamed files (ACMR)*. |
|
||||
| other\_changed\_files\_count | string | Returns the number of `other_changed_files` |
|
||||
| other\_deleted\_files | string | Returns all other deleted files <br>not listed in the files <br>input i.e. *a combination of all deleted files (D)* |
|
||||
| other\_deleted\_files\_count | string | Returns the number of `other_deleted_files` |
|
||||
| other\_modified\_files | string | Returns all other modified files <br>not listed in the files <br>input i.e. *a combination of all added, copied, modified, and deleted files (ACMRD)* |
|
||||
| other\_modified\_files\_count | string | Returns the number of `other_modified_files` |
|
||||
| renamed\_files | string | Returns only files that are <br>Renamed (R). |
|
||||
| renamed\_files\_count | string | Returns the number of `renamed_files` |
|
||||
| type\_changed\_files | string | Returns only files that have <br>their file type changed (T). |
|
||||
| type\_changed\_files\_count | string | Returns the number of `type_changed_files` |
|
||||
| unknown\_files | string | Returns only files that are <br>Unknown (X). |
|
||||
| unknown\_files\_count | string | Returns the number of `unknown_files` |
|
||||
| unmerged\_files | string | Returns only files that are <br>Unmerged (U). |
|
||||
| unmerged\_files\_count | string | Returns the number of `unmerged_files` |
|
||||
| OUTPUT | TYPE | DESCRIPTION |
|
||||
|------------------------------------------------------------------------------------------------------------------------------------------------|--------|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
|
||||
| <a name="output_added_files"></a>[added\_files](#output_added_files) | string | Returns only files that are <br>Added (A). |
|
||||
| <a name="output_added_files_count"></a>[added\_files\_count](#output_added_files_count) | string | Returns the number of `added_files` |
|
||||
| <a name="output_all_changed_and_modified_files"></a>[all\_changed\_and\_modified\_files](#output_all_changed_and_modified_files) | string | Returns all changed and modified <br>files i.e. *a combination of (ACMRDTUX)* |
|
||||
| <a name="output_all_changed_and_modified_files_count"></a>[all\_changed\_and\_modified\_files\_count](#output_all_changed_and_modified_files_count) | string | Returns the number of `all_changed_and_modified_files` |
|
||||
| <a name="output_all_changed_files"></a>[all\_changed\_files](#output_all_changed_files) | string | Returns all changed files i.e. <br>*a combination of all added, copied, modified and renamed files (ACMR)* |
|
||||
| <a name="output_all_changed_files_count"></a>[all\_changed\_files\_count](#output_all_changed_files_count) | string | Returns the number of `all_changed_files` |
|
||||
| <a name="output_all_modified_files"></a>[all\_modified\_files](#output_all_modified_files) | string | Returns all changed files i.e. <br>*a combination of all added, copied, modified, renamed and deleted files (ACMRD)*. |
|
||||
| <a name="output_all_modified_files_count"></a>[all\_modified\_files\_count](#output_all_modified_files_count) | string | Returns the number of `all_modified_files` |
|
||||
| <a name="output_all_old_new_renamed_files"></a>[all\_old\_new\_renamed\_files](#output_all_old_new_renamed_files) | string | Returns only files that are <br>Renamed and lists their old <br>and new names. **NOTE:** This <br>requires setting `include_all_old_new_renamed_files` to `true`. <br>Also, keep in mind that <br>this output is global and <br>wouldn't be nested in outputs <br>generated when the `*_yaml_*` input <br>is used. (R) |
|
||||
| <a name="output_all_old_new_renamed_files_count"></a>[all\_old\_new\_renamed\_files\_count](#output_all_old_new_renamed_files_count) | string | Returns the number of `all_old_new_renamed_files` |
|
||||
| <a name="output_any_changed"></a>[any\_changed](#output_any_changed) | string | Returns `true` when any of <br>the filenames provided using the <br>`files*` or `files_ignore*` inputs has changed. i.e. <br>*includes a combination of all added, copied, modified and renamed files (ACMR)*. |
|
||||
| <a name="output_any_deleted"></a>[any\_deleted](#output_any_deleted) | string | Returns `true` when any of <br>the filenames provided using the <br>`files*` or `files_ignore*` inputs has been deleted. <br>(D) |
|
||||
| <a name="output_any_modified"></a>[any\_modified](#output_any_modified) | string | Returns `true` when any of <br>the filenames provided using the <br>`files*` or `files_ignore*` inputs has been modified. <br>i.e. *includes a combination of all added, copied, modified, renamed, and deleted files (ACMRD)*. |
|
||||
| <a name="output_changed_keys"></a>[changed\_keys](#output_changed_keys) | string | Returns all changed YAML keys <br>when the `files_yaml` input is <br>used. i.e. *key that contains any path that has either been added, copied, modified, and renamed (ACMR)* |
|
||||
| <a name="output_copied_files"></a>[copied\_files](#output_copied_files) | string | Returns only files that are <br>Copied (C). |
|
||||
| <a name="output_copied_files_count"></a>[copied\_files\_count](#output_copied_files_count) | string | Returns the number of `copied_files` |
|
||||
| <a name="output_deleted_files"></a>[deleted\_files](#output_deleted_files) | string | Returns only files that are <br>Deleted (D). |
|
||||
| <a name="output_deleted_files_count"></a>[deleted\_files\_count](#output_deleted_files_count) | string | Returns the number of `deleted_files` |
|
||||
| <a name="output_modified_files"></a>[modified\_files](#output_modified_files) | string | Returns only files that are <br>Modified (M). |
|
||||
| <a name="output_modified_files_count"></a>[modified\_files\_count](#output_modified_files_count) | string | Returns the number of `modified_files` |
|
||||
| <a name="output_modified_keys"></a>[modified\_keys](#output_modified_keys) | string | Returns all modified YAML keys <br>when the `files_yaml` input is <br>used. i.e. *key that contains any path that has either been added, copied, modified, and deleted (ACMRD)* |
|
||||
| <a name="output_only_changed"></a>[only\_changed](#output_only_changed) | string | Returns `true` when only files <br>provided using the `files*` or `files_ignore*` inputs <br>has changed. i.e. *includes a combination of all added, copied, modified and renamed files (ACMR)*. |
|
||||
| <a name="output_only_deleted"></a>[only\_deleted](#output_only_deleted) | string | Returns `true` when only files <br>provided using the `files*` or `files_ignore*` inputs <br>has been deleted. (D) |
|
||||
| <a name="output_only_modified"></a>[only\_modified](#output_only_modified) | string | Returns `true` when only files <br>provided using the `files*` or `files_ignore*` inputs <br>has been modified. (ACMRD). |
|
||||
| <a name="output_other_changed_files"></a>[other\_changed\_files](#output_other_changed_files) | string | Returns all other changed files <br>not listed in the files <br>input i.e. *includes a combination of all added, copied, modified and renamed files (ACMR)*. |
|
||||
| <a name="output_other_changed_files_count"></a>[other\_changed\_files\_count](#output_other_changed_files_count) | string | Returns the number of `other_changed_files` |
|
||||
| <a name="output_other_deleted_files"></a>[other\_deleted\_files](#output_other_deleted_files) | string | Returns all other deleted files <br>not listed in the files <br>input i.e. *a combination of all deleted files (D)* |
|
||||
| <a name="output_other_deleted_files_count"></a>[other\_deleted\_files\_count](#output_other_deleted_files_count) | string | Returns the number of `other_deleted_files` |
|
||||
| <a name="output_other_modified_files"></a>[other\_modified\_files](#output_other_modified_files) | string | Returns all other modified files <br>not listed in the files <br>input i.e. *a combination of all added, copied, modified, and deleted files (ACMRD)* |
|
||||
| <a name="output_other_modified_files_count"></a>[other\_modified\_files\_count](#output_other_modified_files_count) | string | Returns the number of `other_modified_files` |
|
||||
| <a name="output_renamed_files"></a>[renamed\_files](#output_renamed_files) | string | Returns only files that are <br>Renamed (R). |
|
||||
| <a name="output_renamed_files_count"></a>[renamed\_files\_count](#output_renamed_files_count) | string | Returns the number of `renamed_files` |
|
||||
| <a name="output_type_changed_files"></a>[type\_changed\_files](#output_type_changed_files) | string | Returns only files that have <br>their file type changed (T). |
|
||||
| <a name="output_type_changed_files_count"></a>[type\_changed\_files\_count](#output_type_changed_files_count) | string | Returns the number of `type_changed_files` |
|
||||
| <a name="output_unknown_files"></a>[unknown\_files](#output_unknown_files) | string | Returns only files that are <br>Unknown (X). |
|
||||
| <a name="output_unknown_files_count"></a>[unknown\_files\_count](#output_unknown_files_count) | string | Returns the number of `unknown_files` |
|
||||
| <a name="output_unmerged_files"></a>[unmerged\_files](#output_unmerged_files) | string | Returns only files that are <br>Unmerged (U). |
|
||||
| <a name="output_unmerged_files_count"></a>[unmerged\_files\_count](#output_unmerged_files_count) | string | Returns the number of `unmerged_files` |
|
||||
|
||||
<!-- AUTO-DOC-OUTPUT:END -->
|
||||
|
||||
## Inputs
|
||||
## Inputs ⚙️
|
||||
|
||||
<!-- AUTO-DOC-INPUT:START - Do not remove or modify this section -->
|
||||
|
||||
| INPUT | TYPE | REQUIRED | DEFAULT | DESCRIPTION |
|
||||
|----------------------------------------------|--------|----------|---------------------------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
|
||||
| api\_url | string | false | `"${{ github.api_url }}"` | Github API URL. |
|
||||
| base\_sha | string | false | | Specify a different base commit <br>SHA used for comparing changes |
|
||||
| diff\_relative | string | false | `"true"` | Exclude changes outside the current <br>directory and show path names <br>relative to it. **NOTE:** This <br>requires you to specify the <br>top level directory via the <br>`path` input. |
|
||||
| dir\_names | string | false | `"false"` | Output unique changed directories instead <br>of filenames. **NOTE:** This returns <br>`.` for changed files located <br>in the current working directory <br>which defaults to `$GITHUB_WORKSPACE`. |
|
||||
| dir\_names\_exclude\_current\_dir | string | false | `"false"` | Exclude the current directory represented <br>by `.` from the output <br>when `dir_names` is set to <br>`true`. |
|
||||
| dir\_names\_max\_depth | string | false | | Limit the directory output to <br>a maximum depth e.g `test/test1/test2` <br>with max depth of `2` <br>returns `test/test1`. |
|
||||
| escape\_json | string | false | `"true"` | Escape JSON output. |
|
||||
| fetch\_depth | string | false | `"50"` | Depth of additional branch history <br>fetched. **NOTE**: This can be <br>adjusted to resolve errors with <br>insufficient history. |
|
||||
| files | string | false | | File and directory patterns used <br>to detect changes (Defaults to the entire repo if unset) **NOTE:** <br>Multiline file/directory patterns should not <br>include quotes. |
|
||||
| files\_from\_source\_file | string | false | | Source file(s) used to populate <br>the `files` input. |
|
||||
| files\_from\_source\_file\_separator | string | false | `"\n"` | Separator used to split the <br>`files_from_source_file` input |
|
||||
| files\_ignore | string | false | | Ignore changes to these file(s) <br>**NOTE:** Multiline file/directory patterns should <br>not include quotes. |
|
||||
| files\_ignore\_from\_source\_file | string | false | | Source file(s) used to populate <br>the `files_ignore` input |
|
||||
| files\_ignore\_from\_source\_file\_separator | string | false | `"\n"` | Separator used to split the <br>`files_ignore_from_source_file` input |
|
||||
| files\_ignore\_separator | string | false | `"\n"` | Separator used to split the <br>`files_ignore` input |
|
||||
| files\_ignore\_yaml | string | false | | YAML used to define a <br>set of file patterns to <br>ignore changes |
|
||||
| files\_ignore\_yaml\_from\_source\_file | string | false | | Source file(s) used to populate <br>the `files_ignore_yaml` input. [Example](https://github.com/tj-actions/changed-files/blob/main/test/changed-files.yml) |
|
||||
| files\_ignore\_yaml\_from\_source\_file\_separator | string | false | `"\n"` | Separator used to split the <br>`files_ignore_yaml_from_source_file` input |
|
||||
| files\_separator | string | false | `"\n"` | Separator used to split the <br>`files` input |
|
||||
| files\_yaml | string | false | | YAML used to define a <br>set of file patterns to <br>detect changes |
|
||||
| files\_yaml\_from\_source\_file | string | false | | Source file(s) used to populate <br>the `files_yaml` input. [Example](https://github.com/tj-actions/changed-files/blob/main/test/changed-files.yml) |
|
||||
| files\_yaml\_from\_source\_file\_separator | string | false | `"\n"` | Separator used to split the <br>`files_yaml_from_source_file` input |
|
||||
| include\_all\_old\_new\_renamed\_files | string | false | `"false"` | Include `all_old_new_renamed_files` output. Note this <br>can generate a large output <br>See: [#501](https://github.com/tj-actions/changed-files/issues/501). |
|
||||
| json | string | false | `"false"` | Output list of changed files <br>in a JSON formatted string <br>which can be used for <br>matrix jobs. |
|
||||
| old\_new\_files\_separator | string | false | `" "` | Split character for old and <br>new renamed filename pairs. |
|
||||
| old\_new\_separator | string | false | `","` | Split character for old and <br>new filename pairs. |
|
||||
| output\_dir | string | false | `".github/outputs"` | Directory to store output files. |
|
||||
| output\_renamed\_files\_as\_deleted\_and\_added | string | false | `"false"` | Output renamed files as deleted <br>and added files. |
|
||||
| path | string | false | `"."` | Specify a relative path under <br>`$GITHUB_WORKSPACE` to locate the repository. |
|
||||
| quotepath | string | false | `"true"` | Use non-ascii characters to match <br>files and output the filenames <br>completely verbatim by setting this <br>to `false` |
|
||||
| recover\_deleted\_files | string | false | `"false"` | Recover deleted files. |
|
||||
| recover\_deleted\_files\_to\_destination | string | false | | Recover deleted files to a <br>new destination directory, defaults to <br>the original location. |
|
||||
| separator | string | false | `" "` | Split character for output strings |
|
||||
| sha | string | false | | Specify a different commit SHA <br>used for comparing changes |
|
||||
| since | string | false | | Get changed files for commits <br>whose timestamp is older than <br>the given time. |
|
||||
| since\_last\_remote\_commit | string | false | `"false"` | Use the last commit on <br>the remote branch as the <br>`base_sha`. Defaults to the last <br>non-merge commit on the target <br>branch for pull request events <br>and the previous remote commit <br>of the current branch for <br>push events. |
|
||||
| token | string | false | `"${{ github.token }}"` | Github token used to fetch <br>changed files from Github's API. |
|
||||
| until | string | false | | Get changed files for commits <br>whose timestamp is earlier than <br>the given time. |
|
||||
| write\_output\_files | string | false | `"false"` | Write outputs to the `output_dir` <br>defaults to `.github/outputs` folder. **NOTE:** <br>This creates a `.txt` file <br>by default and a `.json` <br>file if `json` is set <br>to `true`. |
|
||||
| INPUT | TYPE | REQUIRED | DEFAULT | DESCRIPTION |
|
||||
|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|--------|----------|---------------------------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
|
||||
| <a name="input_api_url"></a>[api\_url](#input_api_url) | string | false | `"${{ github.api_url }}"` | Github API URL. |
|
||||
| <a name="input_base_sha"></a>[base\_sha](#input_base_sha) | string | false | | Specify a different base commit <br>SHA used for comparing changes |
|
||||
| <a name="input_diff_relative"></a>[diff\_relative](#input_diff_relative) | string | false | `"true"` | Exclude changes outside the current <br>directory and show path names <br>relative to it. **NOTE:** This <br>requires you to specify the <br>top level directory via the <br>`path` input. |
|
||||
| <a name="input_dir_names"></a>[dir\_names](#input_dir_names) | string | false | `"false"` | Output unique changed directories instead <br>of filenames. **NOTE:** This returns <br>`.` for changed files located <br>in the current working directory <br>which defaults to `$GITHUB_WORKSPACE`. |
|
||||
| <a name="input_dir_names_deleted_files_include_only_deleted_dirs"></a>[dir\_names\_deleted\_files\_include\_only\_deleted\_dirs](#input_dir_names_deleted_files_include_only_deleted_dirs) | string | false | `"false"` | Include only directories that have <br>been deleted as opposed to <br>directory names of files that <br>have been deleted in the <br>`deleted_files` output when `dir_names` is <br>set to `true`. |
|
||||
| <a name="input_dir_names_exclude_current_dir"></a>[dir\_names\_exclude\_current\_dir](#input_dir_names_exclude_current_dir) | string | false | `"false"` | Exclude the current directory represented <br>by `.` from the output <br>when `dir_names` is set to <br>`true`. |
|
||||
| <a name="input_dir_names_include_files"></a>[dir\_names\_include\_files](#input_dir_names_include_files) | string | false | | Include files in the output <br>when `dir_names` is set to <br>`true`. **NOTE:** This returns only <br>the matching files and also <br>the directory names. |
|
||||
| <a name="input_dir_names_include_files_separator"></a>[dir\_names\_include\_files\_separator](#input_dir_names_include_files_separator) | string | false | `"\n"` | Separator used to split the <br>`dir_names_include_files` input |
|
||||
| <a name="input_dir_names_max_depth"></a>[dir\_names\_max\_depth](#input_dir_names_max_depth) | string | false | | Limit the directory output to <br>a maximum depth e.g `test/test1/test2` <br>with max depth of `2` <br>returns `test/test1`. |
|
||||
| <a name="input_escape_json"></a>[escape\_json](#input_escape_json) | string | false | `"true"` | Escape JSON output. |
|
||||
| <a name="input_fail_on_initial_diff_error"></a>[fail\_on\_initial\_diff\_error](#input_fail_on_initial_diff_error) | string | false | `"false"` | Fail when the initial diff <br>fails. |
|
||||
| <a name="input_fail_on_submodule_diff_error"></a>[fail\_on\_submodule\_diff\_error](#input_fail_on_submodule_diff_error) | string | false | `"false"` | Fail when the submodule diff <br>fails. |
|
||||
| <a name="input_fetch_additional_submodule_history"></a>[fetch\_additional\_submodule\_history](#input_fetch_additional_submodule_history) | string | false | `"false"` | Fetch additional history for submodules. |
|
||||
| <a name="input_fetch_depth"></a>[fetch\_depth](#input_fetch_depth) | string | false | `"50"` | Depth of additional branch history <br>fetched. **NOTE**: This can be <br>adjusted to resolve errors with <br>insufficient history. |
|
||||
| <a name="input_files"></a>[files](#input_files) | string | false | | File and directory patterns used <br>to detect changes (Defaults to the entire repo if unset) **NOTE:** <br>Multiline file/directory patterns should not <br>include quotes. |
|
||||
| <a name="input_files_from_source_file"></a>[files\_from\_source\_file](#input_files_from_source_file) | string | false | | Source file(s) used to populate <br>the `files` input. |
|
||||
| <a name="input_files_from_source_file_separator"></a>[files\_from\_source\_file\_separator](#input_files_from_source_file_separator) | string | false | `"\n"` | Separator used to split the <br>`files_from_source_file` input |
|
||||
| <a name="input_files_ignore"></a>[files\_ignore](#input_files_ignore) | string | false | | Ignore changes to these file(s) <br>**NOTE:** Multiline file/directory patterns should <br>not include quotes. |
|
||||
| <a name="input_files_ignore_from_source_file"></a>[files\_ignore\_from\_source\_file](#input_files_ignore_from_source_file) | string | false | | Source file(s) used to populate <br>the `files_ignore` input |
|
||||
| <a name="input_files_ignore_from_source_file_separator"></a>[files\_ignore\_from\_source\_file\_separator](#input_files_ignore_from_source_file_separator) | string | false | `"\n"` | Separator used to split the <br>`files_ignore_from_source_file` input |
|
||||
| <a name="input_files_ignore_separator"></a>[files\_ignore\_separator](#input_files_ignore_separator) | string | false | `"\n"` | Separator used to split the <br>`files_ignore` input |
|
||||
| <a name="input_files_ignore_yaml"></a>[files\_ignore\_yaml](#input_files_ignore_yaml) | string | false | | YAML used to define a <br>set of file patterns to <br>ignore changes |
|
||||
| <a name="input_files_ignore_yaml_from_source_file"></a>[files\_ignore\_yaml\_from\_source\_file](#input_files_ignore_yaml_from_source_file) | string | false | | Source file(s) used to populate <br>the `files_ignore_yaml` input. [Example](https://github.com/tj-actions/changed-files/blob/main/test/changed-files.yml) |
|
||||
| <a name="input_files_ignore_yaml_from_source_file_separator"></a>[files\_ignore\_yaml\_from\_source\_file\_separator](#input_files_ignore_yaml_from_source_file_separator) | string | false | `"\n"` | Separator used to split the <br>`files_ignore_yaml_from_source_file` input |
|
||||
| <a name="input_files_separator"></a>[files\_separator](#input_files_separator) | string | false | `"\n"` | Separator used to split the <br>`files` input |
|
||||
| <a name="input_files_yaml"></a>[files\_yaml](#input_files_yaml) | string | false | | YAML used to define a <br>set of file patterns to <br>detect changes |
|
||||
| <a name="input_files_yaml_from_source_file"></a>[files\_yaml\_from\_source\_file](#input_files_yaml_from_source_file) | string | false | | Source file(s) used to populate <br>the `files_yaml` input. [Example](https://github.com/tj-actions/changed-files/blob/main/test/changed-files.yml) |
|
||||
| <a name="input_files_yaml_from_source_file_separator"></a>[files\_yaml\_from\_source\_file\_separator](#input_files_yaml_from_source_file_separator) | string | false | `"\n"` | Separator used to split the <br>`files_yaml_from_source_file` input |
|
||||
| <a name="input_include_all_old_new_renamed_files"></a>[include\_all\_old\_new\_renamed\_files](#input_include_all_old_new_renamed_files) | string | false | `"false"` | Include `all_old_new_renamed_files` output. Note this <br>can generate a large output <br>See: [#501](https://github.com/tj-actions/changed-files/issues/501). |
|
||||
| <a name="input_json"></a>[json](#input_json) | string | false | `"false"` | Output list of changed files <br>in a JSON formatted string <br>which can be used for <br>matrix jobs. [Example](https://github.com/tj-actions/changed-files/blob/main/.github/workflows/matrix-test.yml) |
|
||||
| <a name="input_old_new_files_separator"></a>[old\_new\_files\_separator](#input_old_new_files_separator) | string | false | `" "` | Split character for old and <br>new renamed filename pairs. |
|
||||
| <a name="input_old_new_separator"></a>[old\_new\_separator](#input_old_new_separator) | string | false | `","` | Split character for old and <br>new filename pairs. |
|
||||
| <a name="input_output_dir"></a>[output\_dir](#input_output_dir) | string | false | `".github/outputs"` | Directory to store output files. |
|
||||
| <a name="input_output_renamed_files_as_deleted_and_added"></a>[output\_renamed\_files\_as\_deleted\_and\_added](#input_output_renamed_files_as_deleted_and_added) | string | false | `"false"` | Output renamed files as deleted <br>and added files. |
|
||||
| <a name="input_path"></a>[path](#input_path) | string | false | `"."` | Specify a relative path under <br>`$GITHUB_WORKSPACE` to locate the repository. |
|
||||
| <a name="input_quotepath"></a>[quotepath](#input_quotepath) | string | false | `"true"` | Use non-ascii characters to match <br>files and output the filenames <br>completely verbatim by setting this <br>to `false` |
|
||||
| <a name="input_recover_deleted_files"></a>[recover\_deleted\_files](#input_recover_deleted_files) | string | false | `"false"` | Recover deleted files. |
|
||||
| <a name="input_recover_deleted_files_to_destination"></a>[recover\_deleted\_files\_to\_destination](#input_recover_deleted_files_to_destination) | string | false | | Recover deleted files to a <br>new destination directory, defaults to <br>the original location. |
|
||||
| <a name="input_recover_files"></a>[recover\_files](#input_recover_files) | string | false | | File and directory patterns used <br>to recover deleted files, defaults <br>to the patterns provided via <br>the `files`, `files_from_source_file`, `files_ignore` and <br>`files_ignore_from_source_file` inputs or all deleted <br>files if no patterns are <br>provided. |
|
||||
| <a name="input_recover_files_ignore"></a>[recover\_files\_ignore](#input_recover_files_ignore) | string | false | | File and directory patterns to <br>ignore when recovering deleted files. |
|
||||
| <a name="input_recover_files_ignore_separator"></a>[recover\_files\_ignore\_separator](#input_recover_files_ignore_separator) | string | false | `"\n"` | Separator used to split the <br>`recover_files_ignore` input |
|
||||
| <a name="input_recover_files_separator"></a>[recover\_files\_separator](#input_recover_files_separator) | string | false | `"\n"` | Separator used to split the <br>`recover_files` input |
|
||||
| <a name="input_separator"></a>[separator](#input_separator) | string | false | `" "` | Split character for output strings |
|
||||
| <a name="input_sha"></a>[sha](#input_sha) | string | false | | Specify a different commit SHA <br>used for comparing changes |
|
||||
| <a name="input_since"></a>[since](#input_since) | string | false | | Get changed files for commits <br>whose timestamp is older than <br>the given time. |
|
||||
| <a name="input_since_last_remote_commit"></a>[since\_last\_remote\_commit](#input_since_last_remote_commit) | string | false | `"false"` | Use the last commit on <br>the remote branch as the <br>`base_sha`. Defaults to the last <br>non-merge commit on the target <br>branch for pull request events <br>and the previous remote commit <br>of the current branch for <br>push events. |
|
||||
| <a name="input_skip_initial_fetch"></a>[skip\_initial\_fetch](#input_skip_initial_fetch) | string | false | `"false"` | Skip the initial fetch to <br>improve performance for shallow repositories. <br>**NOTE**: This could lead to <br>errors with missing history and <br>the intended use is limited <br>to when you've fetched the <br>history necessary to perform the <br>diff. |
|
||||
| <a name="input_token"></a>[token](#input_token) | string | false | `"${{ github.token }}"` | Github token used to fetch <br>changed files from Github's API. |
|
||||
| <a name="input_until"></a>[until](#input_until) | string | false | | Get changed files for commits <br>whose timestamp is earlier than <br>the given time. |
|
||||
| <a name="input_write_output_files"></a>[write\_output\_files](#input_write_output_files) | string | false | `"false"` | Write outputs to the `output_dir` <br>defaults to `.github/outputs` folder. **NOTE:** <br>This creates a `.txt` file <br>by default and a `.json` <br>file if `json` is set <br>to `true`. |
|
||||
|
||||
<!-- AUTO-DOC-INPUT:END -->
|
||||
|
||||
## Versioning
|
||||
## Versioning 🏷️
|
||||
|
||||
This GitHub Action follows the principles of [Semantic Versioning](https://semver.org) for versioning releases.
|
||||
|
||||
@@ -352,7 +427,7 @@ The format of the version string is as follows:
|
||||
|
||||
* patch: indicates bug fixes or other small changes that are backward compatible.
|
||||
|
||||
## Examples
|
||||
## Examples 📄
|
||||
|
||||
<details>
|
||||
<summary>Get all changed files in the current branch</summary>
|
||||
@@ -361,20 +436,20 @@ The format of the version string is as follows:
|
||||
...
|
||||
- name: Get changed files
|
||||
id: changed-files
|
||||
uses: tj-actions/changed-files@v37
|
||||
uses: tj-actions/changed-files@v39
|
||||
...
|
||||
```
|
||||
|
||||
</details>
|
||||
|
||||
<details>
|
||||
<summary>Get all changed files and using a comma separator</summary>
|
||||
<summary>Get all changed files and use a comma separator</summary>
|
||||
|
||||
```yaml
|
||||
...
|
||||
- name: Get all changed files and use a comma separator in the output
|
||||
id: changed-files
|
||||
uses: tj-actions/changed-files@v37
|
||||
uses: tj-actions/changed-files@v39
|
||||
with:
|
||||
separator: ","
|
||||
...
|
||||
@@ -391,7 +466,7 @@ See [inputs](#inputs) for more information.
|
||||
...
|
||||
- name: Get changed files
|
||||
id: changed-files
|
||||
uses: tj-actions/changed-files@v37
|
||||
uses: tj-actions/changed-files@v39
|
||||
|
||||
- name: List all added files
|
||||
run: |
|
||||
@@ -412,7 +487,7 @@ See [outputs](#outputs) for a list of all available outputs.
|
||||
...
|
||||
- name: Get changed files
|
||||
id: changed-files
|
||||
uses: tj-actions/changed-files@v37
|
||||
uses: tj-actions/changed-files@v39
|
||||
|
||||
- name: Run a step if my-file.txt was modified
|
||||
if: contains(steps.changed-files.outputs.modified_files, 'my-file.txt')
|
||||
@@ -431,7 +506,7 @@ See [outputs](#outputs) for a list of all available outputs.
|
||||
```yaml
|
||||
...
|
||||
|
||||
- name: Get changed files and write the outputs to a txt file
|
||||
- name: Get changed files and write the outputs to a Txt file
|
||||
id: changed-files-write-output-files-txt
|
||||
uses: ./
|
||||
with:
|
||||
@@ -450,7 +525,7 @@ See [outputs](#outputs) for a list of all available outputs.
|
||||
|
||||
```yaml
|
||||
...
|
||||
- name: Get changed files and write the outputs to a json file
|
||||
- name: Get changed files and write the outputs to a JSON file
|
||||
id: changed-files-write-output-files-json
|
||||
uses: ./
|
||||
with:
|
||||
@@ -472,14 +547,14 @@ See [outputs](#outputs) for a list of all available outputs.
|
||||
...
|
||||
- name: Get changed files
|
||||
id: changed-files
|
||||
uses: tj-actions/changed-files@v37
|
||||
uses: tj-actions/changed-files@v39
|
||||
with:
|
||||
files: |
|
||||
my-file.txt
|
||||
*.sh
|
||||
*.png
|
||||
!*.md
|
||||
test_directory
|
||||
test_directory/**
|
||||
**/*.sql
|
||||
...
|
||||
```
|
||||
@@ -495,14 +570,14 @@ See [inputs](#inputs) for more information.
|
||||
...
|
||||
- name: Get changed files
|
||||
id: changed-files-specific
|
||||
uses: tj-actions/changed-files@v37
|
||||
uses: tj-actions/changed-files@v39
|
||||
with:
|
||||
files: |
|
||||
my-file.txt
|
||||
*.sh
|
||||
*.png
|
||||
!*.md
|
||||
test_directory
|
||||
test_directory/**
|
||||
**/*.sql
|
||||
|
||||
- name: Run step if any of the listed files above change
|
||||
@@ -542,7 +617,7 @@ See [outputs](#outputs) for a list of all available outputs.
|
||||
...
|
||||
- name: Get changed files using a source file or list of file(s) to populate to files input.
|
||||
id: changed-files-specific-source-file
|
||||
uses: tj-actions/changed-files@v37
|
||||
uses: tj-actions/changed-files@v39
|
||||
with:
|
||||
files_from_source_file: test/changed-files-list.txt
|
||||
...
|
||||
@@ -559,7 +634,7 @@ See [inputs](#inputs) for more information.
|
||||
...
|
||||
- name: Get changed files using a source file or list of file(s) to populate to files input and optionally specify more files.
|
||||
id: changed-files-specific-source-file-and-specify-files
|
||||
uses: tj-actions/changed-files@v37
|
||||
uses: tj-actions/changed-files@v39
|
||||
with:
|
||||
files_from_source_file: |
|
||||
test/changed-files-list.txt
|
||||
@@ -580,7 +655,7 @@ See [inputs](#inputs) for more information.
|
||||
...
|
||||
- name: Get changed files using a different SHA
|
||||
id: changed-files
|
||||
uses: tj-actions/changed-files@v37
|
||||
uses: tj-actions/changed-files@v39
|
||||
with:
|
||||
sha: ${{ github.event.pull_request.head.sha }}
|
||||
...
|
||||
@@ -597,7 +672,7 @@ See [inputs](#inputs) for more information.
|
||||
...
|
||||
- name: Get changed files using a different base SHA
|
||||
id: changed-files
|
||||
uses: tj-actions/changed-files@v37
|
||||
uses: tj-actions/changed-files@v39
|
||||
with:
|
||||
base_sha: ${{ github.event.pull_request.base.sha }}
|
||||
...
|
||||
@@ -623,17 +698,17 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v3
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Get changed files
|
||||
id: changed-files
|
||||
uses: tj-actions/changed-files@v37
|
||||
uses: tj-actions/changed-files@v39
|
||||
|
||||
- name: Get changed files in the .github folder
|
||||
id: changed-files-specific
|
||||
uses: tj-actions/changed-files@v37
|
||||
uses: tj-actions/changed-files@v39
|
||||
with:
|
||||
base_sha: ${{ steps.get-base-sha.outputs.base_sha }}
|
||||
files: .github/**
|
||||
@@ -656,14 +731,14 @@ See [inputs](#inputs) for more information.
|
||||
```yaml
|
||||
...
|
||||
- name: Checkout into dir1
|
||||
uses: actions/checkout@v3
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
fetch-depth: 0
|
||||
path: dir1
|
||||
|
||||
- name: Run changed-files with defaults in dir1
|
||||
id: changed-files-for-dir1
|
||||
uses: tj-actions/changed-files@v37
|
||||
uses: tj-actions/changed-files@v39
|
||||
with:
|
||||
path: dir1
|
||||
|
||||
@@ -680,13 +755,13 @@ See [inputs](#inputs) for more information.
|
||||
</details>
|
||||
|
||||
<details>
|
||||
<summary>Get all changed files with non äšćįí characters i.e (Filename in other languages)</summary>
|
||||
<summary>Get all changed files with non-äšćįí characters i.e (Filename in other languages)</summary>
|
||||
|
||||
```yaml
|
||||
...
|
||||
- name: Run changed-files with quotepath disabled
|
||||
id: changed-files-quotepath
|
||||
uses: tj-actions/changed-files@v37
|
||||
uses: tj-actions/changed-files@v39
|
||||
with:
|
||||
quotepath: "false"
|
||||
|
||||
@@ -725,7 +800,7 @@ See [inputs](#inputs) for more information.
|
||||
|
||||
- name: Run changed-files with the commit of the last successful test workflow run
|
||||
id: changed-files-base-sha-push
|
||||
uses: tj-actions/changed-files@v37
|
||||
uses: tj-actions/changed-files@v39
|
||||
with:
|
||||
base_sha: ${{ steps.last_successful_commit_push.outputs.base }}
|
||||
...
|
||||
@@ -747,12 +822,12 @@ See [inputs](#inputs) for more information.
|
||||
- uses: nrwl/nx-set-shas@v3
|
||||
id: last_successful_commit_pull_request
|
||||
with:
|
||||
main-branch-name: ${{ steps.branch-name.outputs.base_ref_branch }} # Get the last successful commit on master or main branch
|
||||
main-branch-name: ${{ steps.branch-name.outputs.base_ref_branch }} # Get the last successful commit on the master or main branch
|
||||
workflow_id: 'test.yml'
|
||||
|
||||
- name: Run changed-files with the commit of the last successful test workflow run on main
|
||||
- name: Run changed-files with the commit of the last successful test workflow run on the main branch
|
||||
id: changed-files-base-sha-pull-request
|
||||
uses: tj-actions/changed-files@v37
|
||||
uses: tj-actions/changed-files@v39
|
||||
with:
|
||||
base_sha: ${{ steps.last_successful_commit_pull_request.outputs.base }}
|
||||
...
|
||||
@@ -762,7 +837,9 @@ See [inputs](#inputs) for more information.
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
> **Warning**: This setting overrides the commit sha used by setting `since_last_remote_commit` to true.
|
||||
> **Warning**
|
||||
>
|
||||
> This setting overrides the commit sha used by setting `since_last_remote_commit` to true.
|
||||
> It is recommended to use either solution that works for your use case.
|
||||
|
||||
See [inputs](#inputs) for more information.
|
||||
@@ -776,7 +853,7 @@ See [inputs](#inputs) for more information.
|
||||
...
|
||||
- name: Run changed-files with dir_names
|
||||
id: changed-files-dir-names
|
||||
uses: tj-actions/changed-files@v37
|
||||
uses: tj-actions/changed-files@v39
|
||||
with:
|
||||
dir_names: "true"
|
||||
...
|
||||
@@ -791,9 +868,9 @@ See [inputs](#inputs) for more information.
|
||||
|
||||
```yaml
|
||||
...
|
||||
- name: Run changed-files with json output
|
||||
- name: Run changed-files with JSON output
|
||||
id: changed-files-json
|
||||
uses: tj-actions/changed-files@v37
|
||||
uses: tj-actions/changed-files@v39
|
||||
with:
|
||||
json: "true"
|
||||
...
|
||||
@@ -810,13 +887,13 @@ See [inputs](#inputs) for more information.
|
||||
...
|
||||
- name: Get changed-files since 2022-08-19
|
||||
id: changed-files-since
|
||||
uses: tj-actions/changed-files@v37
|
||||
uses: tj-actions/changed-files@v39
|
||||
with:
|
||||
since: "2022-08-19"
|
||||
|
||||
- name: Get changed-files until 2022-08-20
|
||||
id: changed-files-until
|
||||
uses: tj-actions/changed-files@v37
|
||||
uses: tj-actions/changed-files@v39
|
||||
with:
|
||||
until: "2022-08-20"
|
||||
...
|
||||
@@ -826,7 +903,9 @@ See [inputs](#inputs) for more information.
|
||||
|
||||
</details>
|
||||
|
||||
## Real world usage
|
||||
## Real-world usage 🌐
|
||||
|
||||
### Open source projects 📦
|
||||
|
||||
* [vitejs/vite: uses tj-actions/changed-files to automate testing](https://github.com/vitejs/vite/blob/8da04227d6f818a8ad9efc0056101968037c2e36/.github/workflows/ci.yml#L61)
|
||||
|
||||
@@ -842,20 +921,26 @@ See [inputs](#inputs) for more information.
|
||||
|
||||
* [aws-doc-sdk-examples: uses tj-actions/changed-files to automate testing](https://github.com/awsdocs/aws-doc-sdk-examples/blob/2393723ef6b0cad9502f4852f5c72f7be58ca89d/.github/workflows/javascript.yml#L22)
|
||||
|
||||

|
||||
* [nhost: uses tj-actions/changed-files to automate testing based on changes detected](https://github.com/nhost/nhost/blob/main/.github/workflows/ci.yaml#L44-L48)
|
||||
|
||||
* [qmk\_firmware uses tj-actions/changed-files to run linters](https://github.com/qmk/qmk_firmware/blob/7a737235ffd49c32d2c5561e8fe53fd96baa7f96/.github/workflows/lint.yml#L30)
|
||||
|
||||
And many more...
|
||||
|
||||
## Known Limitation
|
||||
### Scalability Example 📈
|
||||
|
||||
> **Warning**:
|
||||

|
||||
|
||||
## Important Notice ⚠️
|
||||
|
||||
> **Important**
|
||||
>
|
||||
> * Spaces in file names can introduce bugs when using bash loops. See: [#216](https://github.com/tj-actions/changed-files/issues/216)
|
||||
> However, this action will handle spaces in file names, with a recommendation of using a separator to prevent hidden issues.
|
||||
> However, this action will handle spaces in file names, with a recommendation of using a separator to prevent any hidden issues.
|
||||
>
|
||||
> 
|
||||
|
||||
## Migration guide
|
||||
## Migration guide 🔄
|
||||
|
||||
With the switch from using grep's Extended regex to match files to the natively supported workflow glob pattern matching syntax introduced in [v13](https://github.com/tj-actions/changed-files/releases/tag/v13) you'll need to modify patterns used to match `files`.
|
||||
|
||||
@@ -869,14 +954,13 @@ With the switch from using grep's Extended regex to match files to the natively
|
||||
- \.sh$
|
||||
- .(sql|py)$
|
||||
- ^(dir1|dir2)
|
||||
+ *.{sh,sql,py}
|
||||
+ dir1
|
||||
+ dir2
|
||||
+ **/*.{sh,sql,py}
|
||||
+ {dir1,dir2}/**
|
||||
```
|
||||
|
||||
* Free software: [MIT license](LICENSE)
|
||||
|
||||
## Credits
|
||||
## Credits 👏
|
||||
|
||||
This package was created with [cookiecutter-action](https://github.com/tj-actions/cookiecutter-action).
|
||||
|
||||
@@ -887,7 +971,7 @@ This package was created with [cookiecutter-action](https://github.com/tj-action
|
||||
* [tj-actions/demo3](https://github.com/tj-actions/demo3)
|
||||
* [tj-actions/release-tagger](https://github.com/tj-actions/release-tagger)
|
||||
|
||||
## Report Bugs
|
||||
## Report Bugs 🐛
|
||||
|
||||
Report bugs at https://github.com/tj-actions/changed-files/issues.
|
||||
|
||||
@@ -934,6 +1018,7 @@ Thanks goes to these wonderful people ([emoji key](https://allcontributors.org/d
|
||||
<td align="center" valign="top" width="14.28%"><a href="https://github.com/adonisgarciac"><img src="https://avatars.githubusercontent.com/u/71078987?v=4?s=100" width="100px;" alt="adonisgarciac"/><br /><sub><b>adonisgarciac</b></sub></a><br /><a href="https://github.com/tj-actions/changed-files/commits?author=adonisgarciac" title="Code">💻</a> <a href="https://github.com/tj-actions/changed-files/commits?author=adonisgarciac" title="Documentation">📖</a></td>
|
||||
<td align="center" valign="top" width="14.28%"><a href="https://github.com/cfernhout"><img src="https://avatars.githubusercontent.com/u/22294606?v=4?s=100" width="100px;" alt="Chiel Fernhout"/><br /><sub><b>Chiel Fernhout</b></sub></a><br /><a href="https://github.com/tj-actions/changed-files/commits?author=cfernhout" title="Documentation">📖</a></td>
|
||||
<td align="center" valign="top" width="14.28%"><a href="https://github.com/albertoperdomo2"><img src="https://avatars.githubusercontent.com/u/62241095?v=4?s=100" width="100px;" alt="Alberto Perdomo"/><br /><sub><b>Alberto Perdomo</b></sub></a><br /><a href="https://github.com/tj-actions/changed-files/commits?author=albertoperdomo2" title="Documentation">📖</a></td>
|
||||
<td align="center" valign="top" width="14.28%"><a href="https://arthurvolant.com"><img src="https://avatars.githubusercontent.com/u/37664438?v=4?s=100" width="100px;" alt="Arthur"/><br /><sub><b>Arthur</b></sub></a><br /><a href="https://github.com/tj-actions/changed-files/issues?q=author%3AV0lantis" title="Bug reports">🐛</a> <a href="https://github.com/tj-actions/changed-files/commits?author=V0lantis" title="Code">💻</a></td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
62
action.yml
62
action.yml
@@ -112,8 +112,20 @@ inputs:
|
||||
description: "Exclude the current directory represented by `.` from the output when `dir_names` is set to `true`."
|
||||
required: false
|
||||
default: "false"
|
||||
dir_names_include_files:
|
||||
description: "Include files in the output when `dir_names` is set to `true`. **NOTE:** This returns only the matching files and also the directory names."
|
||||
required: false
|
||||
default: ""
|
||||
dir_names_include_files_separator:
|
||||
description: "Separator used to split the `dir_names_include_files` input"
|
||||
default: "\n"
|
||||
required: false
|
||||
dir_names_deleted_files_include_only_deleted_dirs:
|
||||
description: "Include only directories that have been deleted as opposed to directory names of files that have been deleted in the `deleted_files` output when `dir_names` is set to `true`."
|
||||
required: false
|
||||
default: "false"
|
||||
json:
|
||||
description: "Output list of changed files in a JSON formatted string which can be used for matrix jobs."
|
||||
description: "Output list of changed files in a JSON formatted string which can be used for matrix jobs. [Example](https://github.com/tj-actions/changed-files/blob/main/.github/workflows/matrix-test.yml)"
|
||||
required: false
|
||||
default: "false"
|
||||
escape_json:
|
||||
@@ -124,6 +136,14 @@ inputs:
|
||||
description: "Depth of additional branch history fetched. **NOTE**: This can be adjusted to resolve errors with insufficient history."
|
||||
required: false
|
||||
default: "50"
|
||||
skip_initial_fetch:
|
||||
description: "Skip the initial fetch to improve performance for shallow repositories. **NOTE**: This could lead to errors with missing history and the intended use is limited to when you've fetched the history necessary to perform the diff."
|
||||
required: false
|
||||
default: "false"
|
||||
fetch_additional_submodule_history:
|
||||
description: "Fetch additional history for submodules."
|
||||
required: false
|
||||
default: "false"
|
||||
since_last_remote_commit:
|
||||
description: "Use the last commit on the remote branch as the `base_sha`. Defaults to the last non-merge commit on the target branch for pull request events and the previous remote commit of the current branch for push events."
|
||||
required: false
|
||||
@@ -148,6 +168,22 @@ inputs:
|
||||
description: "Recover deleted files to a new destination directory, defaults to the original location."
|
||||
required: false
|
||||
default: ""
|
||||
recover_files:
|
||||
description: "File and directory patterns used to recover deleted files, defaults to the patterns provided via the `files`, `files_from_source_file`, `files_ignore` and `files_ignore_from_source_file` inputs or all deleted files if no patterns are provided."
|
||||
required: false
|
||||
default: ""
|
||||
recover_files_separator:
|
||||
description: "Separator used to split the `recover_files` input"
|
||||
default: "\n"
|
||||
required: false
|
||||
recover_files_ignore:
|
||||
description: "File and directory patterns to ignore when recovering deleted files."
|
||||
required: false
|
||||
default: ""
|
||||
recover_files_ignore_separator:
|
||||
description: "Separator used to split the `recover_files_ignore` input"
|
||||
default: "\n"
|
||||
required: false
|
||||
token:
|
||||
description: "Github token used to fetch changed files from Github's API."
|
||||
required: false
|
||||
@@ -156,6 +192,14 @@ inputs:
|
||||
description: "Github API URL."
|
||||
required: false
|
||||
default: ${{ github.api_url }}
|
||||
fail_on_initial_diff_error:
|
||||
description: "Fail when the initial diff fails."
|
||||
required: false
|
||||
default: "false"
|
||||
fail_on_submodule_diff_error:
|
||||
description: "Fail when the submodule diff fails."
|
||||
required: false
|
||||
default: "false"
|
||||
|
||||
outputs:
|
||||
added_files:
|
||||
@@ -203,11 +247,11 @@ outputs:
|
||||
all_changed_files_count:
|
||||
description: "Returns the number of `all_changed_files`"
|
||||
any_changed:
|
||||
description: "Returns `true` when any of the filenames provided using the `files*` or `files_ignore*` inputs has changed. i.e. *using a combination of all added, copied, modified and renamed files (ACMR)*."
|
||||
description: "Returns `true` when any of the filenames provided using the `files*` or `files_ignore*` inputs has changed. i.e. *includes a combination of all added, copied, modified and renamed files (ACMR)*."
|
||||
only_changed:
|
||||
description: "Returns `true` when only files provided using the `files*` or `files_ignore*` inputs has changed. i.e. *using a combination of all added, copied, modified and renamed files (ACMR)*."
|
||||
description: "Returns `true` when only files provided using the `files*` or `files_ignore*` inputs has changed. i.e. *includes a combination of all added, copied, modified and renamed files (ACMR)*."
|
||||
other_changed_files:
|
||||
description: "Returns all other changed files not listed in the files input i.e. *using a combination of all added, copied, modified and renamed files (ACMR)*."
|
||||
description: "Returns all other changed files not listed in the files input i.e. *includes a combination of all added, copied, modified and renamed files (ACMR)*."
|
||||
other_changed_files_count:
|
||||
description: "Returns the number of `other_changed_files`"
|
||||
all_modified_files:
|
||||
@@ -215,11 +259,11 @@ outputs:
|
||||
all_modified_files_count:
|
||||
description: "Returns the number of `all_modified_files`"
|
||||
any_modified:
|
||||
description: "Returns `true` when any of the filenames provided using the `files*` or `files_ignore*` inputs has been modified. i.e. *using a combination of all added, copied, modified, renamed, and deleted files (ACMRD)*."
|
||||
description: "Returns `true` when any of the filenames provided using the `files*` or `files_ignore*` inputs has been modified. i.e. *includes a combination of all added, copied, modified, renamed, and deleted files (ACMRD)*."
|
||||
only_modified:
|
||||
description: "Returns `true` when only files provided using the `files*` or `files_ignore*` inputs has been modified. (ACMRD)."
|
||||
other_modified_files:
|
||||
description: "Returns all other modified files not listed in the files input i.e. *a combination of all added, copied, modified, and deleted files (ACMRD)*"
|
||||
description: "Returns all other modified files not listed in the files input i.e. *a combination of all added, copied, modified, and deleted files (ACMRD)*"
|
||||
other_modified_files_count:
|
||||
description: "Returns the number of `other_modified_files`"
|
||||
any_deleted:
|
||||
@@ -230,9 +274,13 @@ outputs:
|
||||
description: "Returns all other deleted files not listed in the files input i.e. *a combination of all deleted files (D)*"
|
||||
other_deleted_files_count:
|
||||
description: "Returns the number of `other_deleted_files`"
|
||||
modified_keys:
|
||||
description: "Returns all modified YAML keys when the `files_yaml` input is used. i.e. *key that contains any path that has either been added, copied, modified, and deleted (ACMRD)*"
|
||||
changed_keys:
|
||||
description: "Returns all changed YAML keys when the `files_yaml` input is used. i.e. *key that contains any path that has either been added, copied, modified, and renamed (ACMR)*"
|
||||
|
||||
runs:
|
||||
using: 'node16'
|
||||
using: 'node20'
|
||||
main: 'dist/index.js'
|
||||
|
||||
branding:
|
||||
|
||||
33738
dist/index.js
generated
vendored
33738
dist/index.js
generated
vendored
File diff suppressed because one or more lines are too long
2
dist/index.js.map
generated
vendored
2
dist/index.js.map
generated
vendored
File diff suppressed because one or more lines are too long
127
dist/licenses.txt
generated
vendored
127
dist/licenses.txt
generated
vendored
@@ -71,6 +71,28 @@ The above copyright notice and this permission notice shall be included in all c
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
@fastify/busboy
|
||||
MIT
|
||||
Copyright Brian White. All rights reserved.
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to
|
||||
deal in the Software without restriction, including without limitation the
|
||||
rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
sell copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
IN THE SOFTWARE.
|
||||
|
||||
@octokit/auth-token
|
||||
MIT
|
||||
The MIT License
|
||||
@@ -243,16 +265,6 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
|
||||
|
||||
@vercel/ncc
|
||||
MIT
|
||||
Copyright 2018 ZEIT, Inc.
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
before-after-hook
|
||||
Apache-2.0
|
||||
Apache License
|
||||
@@ -653,32 +665,6 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
|
||||
|
||||
node-fetch
|
||||
MIT
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2016 David Frank
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
|
||||
|
||||
|
||||
once
|
||||
ISC
|
||||
The ISC License
|
||||
@@ -748,9 +734,6 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
|
||||
|
||||
tr46
|
||||
MIT
|
||||
|
||||
tunnel
|
||||
MIT
|
||||
The MIT License (MIT)
|
||||
@@ -776,6 +759,31 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
|
||||
|
||||
undici
|
||||
MIT
|
||||
MIT License
|
||||
|
||||
Copyright (c) Matteo Collina and Undici contributors
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
|
||||
|
||||
universal-user-agent
|
||||
ISC
|
||||
# [ISC License](https://spdx.org/licenses/ISC)
|
||||
@@ -800,47 +808,6 @@ The above copyright notice and this permission notice shall be included in all c
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
|
||||
webidl-conversions
|
||||
BSD-2-Clause
|
||||
# The BSD 2-Clause License
|
||||
|
||||
Copyright (c) 2014, Domenic Denicola
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
|
||||
|
||||
1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
|
||||
|
||||
2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
|
||||
whatwg-url
|
||||
MIT
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2015–2016 Sebastian Mayr
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
|
||||
|
||||
wrappy
|
||||
ISC
|
||||
The ISC License
|
||||
|
||||
55
package.json
55
package.json
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "@tj-actions/glob",
|
||||
"version": "17.2.5",
|
||||
"description": "Glob pattern matching github action",
|
||||
"name": "@tj-actions/changed-files",
|
||||
"version": "39.2.4",
|
||||
"description": "Github action to retrieve all (added, copied, modified, deleted, renamed, type changed, unmerged, unknown) files and directories.",
|
||||
"main": "lib/main.js",
|
||||
"publishConfig": {
|
||||
"registry": "https://npm.pkg.github.com"
|
||||
@@ -10,7 +10,7 @@
|
||||
"build": "tsc",
|
||||
"format": "prettier --write **/*.ts",
|
||||
"format-check": "prettier --check **/*.ts",
|
||||
"lint": "eslint src/**/*.ts",
|
||||
"lint": "eslint **/*.ts --max-warnings 0",
|
||||
"lint:fix": "eslint --fix src/**/*.ts",
|
||||
"package": "ncc build lib/main.js --source-map --license licenses.txt",
|
||||
"test": "jest --coverage",
|
||||
@@ -18,7 +18,7 @@
|
||||
},
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "git+https://github.com/tj-actions/glob.git"
|
||||
"url": "git+https://github.com/tj-actions/changed-files.git"
|
||||
},
|
||||
"keywords": [
|
||||
"actions",
|
||||
@@ -28,34 +28,35 @@
|
||||
"author": "Tonye Jack",
|
||||
"license": "MIT",
|
||||
"bugs": {
|
||||
"url": "https://github.com/tj-actions/glob/issues"
|
||||
"url": "https://github.com/tj-actions/changed-files/issues"
|
||||
},
|
||||
"homepage": "https://github.com/tj-actions/glob#readme",
|
||||
"homepage": "https://github.com/tj-actions/changed-files#readme",
|
||||
"dependencies": {
|
||||
"@actions/core": "1.10.0",
|
||||
"@actions/exec": "1.1.1",
|
||||
"@actions/github": "5.1.1",
|
||||
"lodash": "^4.17.15",
|
||||
"@actions/core": "^1.10.0",
|
||||
"@actions/exec": "^1.1.1",
|
||||
"@actions/github": "^6.0.0",
|
||||
"@octokit/rest": "^20.0.1",
|
||||
"lodash": "^4.17.21",
|
||||
"micromatch": "^4.0.5",
|
||||
"yaml": "^2.3.1",
|
||||
"@octokit/rest": "^19.0.7"
|
||||
"yaml": "^2.3.1"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/jest": "29.5.2",
|
||||
"@types/jest": "^29.5.2",
|
||||
"@types/lodash": "^4.14.195",
|
||||
"@types/micromatch": "^4.0.2",
|
||||
"@types/node": "20.3.1",
|
||||
"@types/uuid": "9.0.2",
|
||||
"@typescript-eslint/eslint-plugin": "5.60.0",
|
||||
"@typescript-eslint/parser": "5.60.0",
|
||||
"@vercel/ncc": "0.36.1",
|
||||
"eslint": "8.43.0",
|
||||
"eslint-plugin-github": "4.8.0",
|
||||
"eslint-plugin-jest": "27.2.2",
|
||||
"eslint-plugin-prettier": "^4.2.1",
|
||||
"jest": "29.5.0",
|
||||
"prettier": "2.8.8",
|
||||
"ts-jest": "29.1.0",
|
||||
"typescript": "5.1.3"
|
||||
"@types/node": "^20.3.2",
|
||||
"@types/uuid": "^9.0.2",
|
||||
"@typescript-eslint/eslint-plugin": "^6.0.0",
|
||||
"@typescript-eslint/parser": "^6.0.0",
|
||||
"@vercel/ncc": "^0.38.0",
|
||||
"eslint": "^8.43.0",
|
||||
"eslint-plugin-github": "^4.8.0",
|
||||
"eslint-plugin-jest": "^27.2.2",
|
||||
"eslint-plugin-prettier": "^5.0.0-alpha.2",
|
||||
"eslint-config-prettier": "^9.0.0",
|
||||
"jest": "^29.5.0",
|
||||
"prettier": "^3.0.0",
|
||||
"ts-jest": "^29.1.0",
|
||||
"typescript": "^5.1.3"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,8 +3,8 @@
|
||||
"config:base"
|
||||
],
|
||||
"enabled": true,
|
||||
"prHourlyLimit": 30,
|
||||
"prConcurrentLimit": 10,
|
||||
"prHourlyLimit": 10,
|
||||
"prConcurrentLimit": 5,
|
||||
"rebaseWhen": "behind-base-branch",
|
||||
"addLabels": [
|
||||
"dependencies",
|
||||
@@ -20,13 +20,21 @@
|
||||
"enabled": true,
|
||||
"automerge": true
|
||||
},
|
||||
"nvm": {
|
||||
"enabled": false
|
||||
},
|
||||
"packageRules": [
|
||||
{
|
||||
"matchUpdateTypes": ["minor", "patch", "pin", "digest"],
|
||||
"matchUpdateTypes": [
|
||||
"minor",
|
||||
"patch",
|
||||
"pin",
|
||||
"digest"
|
||||
],
|
||||
"automerge": true,
|
||||
"rebaseWhen": "behind-base-branch",
|
||||
"addLabels": [
|
||||
"automerge"
|
||||
"merge when passing"
|
||||
]
|
||||
},
|
||||
{
|
||||
@@ -34,10 +42,15 @@
|
||||
"matchLanguages": [
|
||||
"docker"
|
||||
],
|
||||
"matchUpdateTypes": ["minor", "patch", "pin", "digest"],
|
||||
"matchUpdateTypes": [
|
||||
"minor",
|
||||
"patch",
|
||||
"pin",
|
||||
"digest"
|
||||
],
|
||||
"rebaseWhen": "behind-base-branch",
|
||||
"addLabels": [
|
||||
"automerge"
|
||||
"merge when passing"
|
||||
],
|
||||
"automerge": true
|
||||
}
|
||||
|
||||
578
src/__tests__/utils.test.ts
Normal file
578
src/__tests__/utils.test.ts
Normal file
@@ -0,0 +1,578 @@
|
||||
import {ChangeTypeEnum} from '../changedFiles'
|
||||
import {
|
||||
getDirname,
|
||||
getDirnameMaxDepth,
|
||||
getFilteredChangedFiles,
|
||||
normalizeSeparators
|
||||
} from '../utils'
|
||||
|
||||
const originalPlatform = process.platform
|
||||
|
||||
function mockedPlatform(platform: string): void {
|
||||
Object.defineProperty(process, 'platform', {
|
||||
value: platform
|
||||
})
|
||||
}
|
||||
|
||||
describe('utils test', () => {
|
||||
afterEach(() => {
|
||||
Object.defineProperty(process, 'platform', {
|
||||
value: originalPlatform
|
||||
})
|
||||
})
|
||||
|
||||
describe('getDirnameMaxDepth_function', () => {
|
||||
// Tests that the function returns the correct dirname when the relative path has multiple directories
|
||||
it('test_multiple_directories', () => {
|
||||
const result = getDirnameMaxDepth({
|
||||
relativePath: 'path/to/some/file',
|
||||
dirNamesMaxDepth: 2,
|
||||
excludeCurrentDir: false
|
||||
})
|
||||
expect(result).toEqual('path/to')
|
||||
})
|
||||
|
||||
// Tests that the function returns the correct dirname when the relative path has only one directory
|
||||
it('test_single_directory', () => {
|
||||
const result = getDirnameMaxDepth({
|
||||
relativePath: 'path/to',
|
||||
dirNamesMaxDepth: 1,
|
||||
excludeCurrentDir: false
|
||||
})
|
||||
expect(result).toEqual('path')
|
||||
})
|
||||
|
||||
// Tests that the function returns the correct dirname when the relative path has no directories
|
||||
it('test_no_directories', () => {
|
||||
const result = getDirnameMaxDepth({
|
||||
relativePath: 'file.txt',
|
||||
dirNamesMaxDepth: 1,
|
||||
excludeCurrentDir: false
|
||||
})
|
||||
expect(result).toEqual('.')
|
||||
})
|
||||
|
||||
// Tests that the function returns the correct dirname when dirNamesMaxDepth is set to a value less than the number of directories in the relative path
|
||||
it('test_dirnames_max_depth_less_than_num_directories', () => {
|
||||
const result = getDirnameMaxDepth({
|
||||
relativePath: 'path/to/some/file',
|
||||
dirNamesMaxDepth: 1,
|
||||
excludeCurrentDir: false
|
||||
})
|
||||
expect(result).toEqual('path')
|
||||
})
|
||||
|
||||
// Tests that the function returns an empty string when excludeCurrentDir is true and the output is '.'
|
||||
it('test_exclude_current_dir_is_true_and_output_is_dot', () => {
|
||||
const result = getDirnameMaxDepth({
|
||||
relativePath: '.',
|
||||
dirNamesMaxDepth: 1,
|
||||
excludeCurrentDir: true
|
||||
})
|
||||
expect(result).toEqual('')
|
||||
})
|
||||
|
||||
// Tests that the function returns the correct dirname when the relative path is a Windows drive root and excludeCurrentDir is true
|
||||
it('test_windows_drive_root_and_exclude_current_dir_is_true', () => {
|
||||
mockedPlatform('win32')
|
||||
const result = getDirnameMaxDepth({
|
||||
relativePath: 'C:\\',
|
||||
dirNamesMaxDepth: 1,
|
||||
excludeCurrentDir: true
|
||||
})
|
||||
expect(result).toEqual('')
|
||||
})
|
||||
|
||||
// Tests that getDirnameMaxDepth handles a relative path with a trailing separator correctly
|
||||
it('test_trailing_separator', () => {
|
||||
const input = {
|
||||
relativePath: 'path/to/dir/',
|
||||
dirNamesMaxDepth: 2,
|
||||
excludeCurrentDir: true
|
||||
}
|
||||
const expectedOutput = 'path/to'
|
||||
const actualOutput = getDirnameMaxDepth(input)
|
||||
expect(actualOutput).toEqual(expectedOutput)
|
||||
})
|
||||
|
||||
// Tests that getDirnameMaxDepth returns an empty string when excludeCurrentDir is true and the output is '.'
|
||||
it('test_trailing_separator_exclude_current_dir', () => {
|
||||
const input = {
|
||||
relativePath: 'file',
|
||||
excludeCurrentDir: true
|
||||
}
|
||||
const expectedOutput = ''
|
||||
const actualOutput = getDirnameMaxDepth(input)
|
||||
expect(actualOutput).toEqual(expectedOutput)
|
||||
})
|
||||
|
||||
// Tests that getDirnameMaxDepth returns the correct output for a Windows UNC root path
|
||||
it('test_windows_unc_root', () => {
|
||||
mockedPlatform('win32')
|
||||
const input = {
|
||||
relativePath: '\\hello',
|
||||
dirNamesMaxDepth: 2,
|
||||
excludeCurrentDir: true
|
||||
}
|
||||
const expectedOutput = ''
|
||||
expect(getDirnameMaxDepth(input)).toEqual(expectedOutput)
|
||||
})
|
||||
|
||||
// Tests that getDirnameMaxDepth returns an empty string when given a Windows UNC root and excludeCurrentDir is true
|
||||
it('test_windows_unc_root_exclude_current_dir', () => {
|
||||
mockedPlatform('win32')
|
||||
const relativePath = '\\hello'
|
||||
const result = getDirnameMaxDepth({
|
||||
relativePath,
|
||||
excludeCurrentDir: true
|
||||
})
|
||||
expect(result).toEqual('')
|
||||
})
|
||||
|
||||
// Tests that getDirnameMaxDepth returns the correct dirname with a relative path that contains both forward and backward slashes
|
||||
it('test_relative_path_with_slashes', () => {
|
||||
const relativePath = 'path/to\file'
|
||||
const expectedOutput = 'path'
|
||||
const actualOutput = getDirnameMaxDepth({relativePath})
|
||||
expect(actualOutput).toEqual(expectedOutput)
|
||||
})
|
||||
|
||||
// Tests that getDirnameMaxDepth returns the correct dirname for a relative path that contains special characters
|
||||
it('test_special_characters', () => {
|
||||
const relativePath =
|
||||
'path/with/special/characters/!@#$%^&*()_+{}|:<>?[];,./'
|
||||
const expectedDirname = 'path/with/special/characters'
|
||||
const actualDirname = getDirnameMaxDepth({relativePath})
|
||||
expect(actualDirname).toEqual(expectedDirname)
|
||||
})
|
||||
})
|
||||
|
||||
describe('getDirname_function', () => {
|
||||
// Tests that the function returns the correct dirname for a valid path
|
||||
it('test valid path', () => {
|
||||
expect(getDirname('/path/to/file')).toEqual('/path/to')
|
||||
})
|
||||
|
||||
// Tests that the function returns the correct dirname for a valid Windows UNC root path
|
||||
it('test windows unc root path', () => {
|
||||
mockedPlatform('win32')
|
||||
expect(getDirname('\\helloworld')).toEqual('.')
|
||||
})
|
||||
|
||||
// Tests that the function returns the correct dirname for a path with a trailing slash
|
||||
it('test path with trailing slash', () => {
|
||||
expect(getDirname('/path/to/file/')).toEqual('/path/to')
|
||||
})
|
||||
|
||||
// Tests that the function returns the correct dirname for a Windows UNC root path with a trailing slash
|
||||
it('test windows unc root path with trailing slash', () => {
|
||||
mockedPlatform('win32')
|
||||
expect(getDirname('\\hello\\world\\')).toEqual('.')
|
||||
})
|
||||
|
||||
// Tests that the function returns the correct dirname for a path with multiple slashes
|
||||
it('test path with multiple slashes', () => {
|
||||
expect(getDirname('/path//to/file')).toEqual('/path/to')
|
||||
})
|
||||
|
||||
// Tests that the function returns the correct dirname for a Windows UNC root path with multiple slashes
|
||||
it('test windows unc root path with multiple slashes', () => {
|
||||
mockedPlatform('win32')
|
||||
expect(getDirname('\\hello\\world')).toEqual('.')
|
||||
})
|
||||
})
|
||||
|
||||
describe('normalizeSeparators_function', () => {
|
||||
// Tests that forward slashes are normalized on Linux
|
||||
it('test forward slashes linux', () => {
|
||||
const input = 'path/to/file'
|
||||
const expectedOutput = 'path/to/file'
|
||||
const actualOutput = normalizeSeparators(input)
|
||||
expect(actualOutput).toEqual(expectedOutput)
|
||||
})
|
||||
|
||||
// Tests that backslashes are normalized on Windows
|
||||
it('test backslashes windows', () => {
|
||||
mockedPlatform('win32')
|
||||
const input = 'path\\to\\file'
|
||||
const expectedOutput = 'path\\to\\file'
|
||||
const actualOutput = normalizeSeparators(input)
|
||||
expect(actualOutput).toEqual(expectedOutput)
|
||||
})
|
||||
|
||||
// Tests that forward slashes are normalized on Windows
|
||||
it('test mixed slashes windows', () => {
|
||||
mockedPlatform('win32')
|
||||
const input = 'path/to/file'
|
||||
const expectedOutput = 'path\\to\\file'
|
||||
const actualOutput = normalizeSeparators(input)
|
||||
expect(actualOutput).toEqual(expectedOutput)
|
||||
})
|
||||
|
||||
// Tests that mixed slashes are normalized on Windows
|
||||
it('test mixed slashes windows', () => {
|
||||
mockedPlatform('win32')
|
||||
const input = 'path\\to/file'
|
||||
const expectedOutput = 'path\\to\\file'
|
||||
const actualOutput = normalizeSeparators(input)
|
||||
expect(actualOutput).toEqual(expectedOutput)
|
||||
})
|
||||
|
||||
// Tests that an empty string returns an empty string
|
||||
it('test empty string', () => {
|
||||
const input = ''
|
||||
const expectedOutput = ''
|
||||
const actualOutput = normalizeSeparators(input)
|
||||
expect(actualOutput).toEqual(expectedOutput)
|
||||
})
|
||||
|
||||
// Tests that multiple consecutive slashes are removed
|
||||
it('test multiple consecutive slashes', () => {
|
||||
const input = 'path//to//file'
|
||||
const expectedOutput = 'path/to/file'
|
||||
const actualOutput = normalizeSeparators(input)
|
||||
expect(actualOutput).toEqual(expectedOutput)
|
||||
})
|
||||
|
||||
// Tests that UNC format is preserved on Windows
|
||||
it('test unc format windows', () => {
|
||||
mockedPlatform('win32')
|
||||
const input = '\\\\hello\\world'
|
||||
const expectedOutput = '\\\\hello\\world'
|
||||
const actualOutput = normalizeSeparators(input)
|
||||
expect(actualOutput).toEqual(expectedOutput)
|
||||
})
|
||||
|
||||
// Tests that a drive root is preserved on Windows
|
||||
it('test drive root windows', () => {
|
||||
mockedPlatform('win32')
|
||||
const input = 'C:\\'
|
||||
const expectedOutput = 'C:\\'
|
||||
const actualOutput = normalizeSeparators(input)
|
||||
expect(actualOutput).toEqual(expectedOutput)
|
||||
})
|
||||
})
|
||||
|
||||
describe('getFilteredChangedFiles', () => {
|
||||
// Tests that the function returns an empty object when allDiffFiles and filePatterns are empty
|
||||
it('should return an empty object when allDiffFiles and filePatterns are empty', async () => {
|
||||
const result = await getFilteredChangedFiles({
|
||||
allDiffFiles: {
|
||||
[ChangeTypeEnum.Added]: [],
|
||||
[ChangeTypeEnum.Copied]: [],
|
||||
[ChangeTypeEnum.Deleted]: [],
|
||||
[ChangeTypeEnum.Modified]: [],
|
||||
[ChangeTypeEnum.Renamed]: [],
|
||||
[ChangeTypeEnum.TypeChanged]: [],
|
||||
[ChangeTypeEnum.Unmerged]: [],
|
||||
[ChangeTypeEnum.Unknown]: []
|
||||
},
|
||||
filePatterns: []
|
||||
})
|
||||
expect(result).toEqual({
|
||||
[ChangeTypeEnum.Added]: [],
|
||||
[ChangeTypeEnum.Copied]: [],
|
||||
[ChangeTypeEnum.Deleted]: [],
|
||||
[ChangeTypeEnum.Modified]: [],
|
||||
[ChangeTypeEnum.Renamed]: [],
|
||||
[ChangeTypeEnum.TypeChanged]: [],
|
||||
[ChangeTypeEnum.Unmerged]: [],
|
||||
[ChangeTypeEnum.Unknown]: []
|
||||
})
|
||||
})
|
||||
|
||||
// Tests that the function returns allDiffFiles when filePatterns is empty
|
||||
it('should return allDiffFiles when filePatterns is empty', async () => {
|
||||
const allDiffFiles = {
|
||||
[ChangeTypeEnum.Added]: ['file1.txt'],
|
||||
[ChangeTypeEnum.Copied]: [],
|
||||
[ChangeTypeEnum.Deleted]: [],
|
||||
[ChangeTypeEnum.Modified]: [],
|
||||
[ChangeTypeEnum.Renamed]: [],
|
||||
[ChangeTypeEnum.TypeChanged]: [],
|
||||
[ChangeTypeEnum.Unmerged]: [],
|
||||
[ChangeTypeEnum.Unknown]: []
|
||||
}
|
||||
const result = await getFilteredChangedFiles({
|
||||
allDiffFiles,
|
||||
filePatterns: []
|
||||
})
|
||||
expect(result).toEqual(allDiffFiles)
|
||||
})
|
||||
|
||||
// Tests that the function returns an empty object when allDiffFiles is empty
|
||||
it('should return an empty object when allDiffFiles is empty', async () => {
|
||||
const result = await getFilteredChangedFiles({
|
||||
allDiffFiles: {
|
||||
[ChangeTypeEnum.Added]: [],
|
||||
[ChangeTypeEnum.Copied]: [],
|
||||
[ChangeTypeEnum.Deleted]: [],
|
||||
[ChangeTypeEnum.Modified]: [],
|
||||
[ChangeTypeEnum.Renamed]: [],
|
||||
[ChangeTypeEnum.TypeChanged]: [],
|
||||
[ChangeTypeEnum.Unmerged]: [],
|
||||
[ChangeTypeEnum.Unknown]: []
|
||||
},
|
||||
filePatterns: ['*.txt']
|
||||
})
|
||||
expect(result).toEqual({
|
||||
[ChangeTypeEnum.Added]: [],
|
||||
[ChangeTypeEnum.Copied]: [],
|
||||
[ChangeTypeEnum.Deleted]: [],
|
||||
[ChangeTypeEnum.Modified]: [],
|
||||
[ChangeTypeEnum.Renamed]: [],
|
||||
[ChangeTypeEnum.TypeChanged]: [],
|
||||
[ChangeTypeEnum.Unmerged]: [],
|
||||
[ChangeTypeEnum.Unknown]: []
|
||||
})
|
||||
})
|
||||
|
||||
// Tests that the function returns only the files that match the file patterns on non windows platforms
|
||||
it('should return only the files that match the file patterns', async () => {
|
||||
const allDiffFiles = {
|
||||
[ChangeTypeEnum.Added]: [
|
||||
'file1.txt',
|
||||
'file2.md',
|
||||
'file3.txt',
|
||||
'test/dir/file4.txt',
|
||||
'test/dir/file5.txt',
|
||||
'dir/file6.md'
|
||||
],
|
||||
[ChangeTypeEnum.Copied]: [],
|
||||
[ChangeTypeEnum.Deleted]: [],
|
||||
[ChangeTypeEnum.Modified]: [],
|
||||
[ChangeTypeEnum.Renamed]: [],
|
||||
[ChangeTypeEnum.TypeChanged]: [],
|
||||
[ChangeTypeEnum.Unmerged]: [],
|
||||
[ChangeTypeEnum.Unknown]: []
|
||||
}
|
||||
const result = await getFilteredChangedFiles({
|
||||
allDiffFiles,
|
||||
filePatterns: ['*.txt']
|
||||
})
|
||||
expect(result).toEqual({
|
||||
[ChangeTypeEnum.Added]: ['file1.txt', 'file3.txt'],
|
||||
[ChangeTypeEnum.Copied]: [],
|
||||
[ChangeTypeEnum.Deleted]: [],
|
||||
[ChangeTypeEnum.Modified]: [],
|
||||
[ChangeTypeEnum.Renamed]: [],
|
||||
[ChangeTypeEnum.TypeChanged]: [],
|
||||
[ChangeTypeEnum.Unmerged]: [],
|
||||
[ChangeTypeEnum.Unknown]: []
|
||||
})
|
||||
})
|
||||
|
||||
// Tests that the function returns only the files that match the file patterns on windows
|
||||
it('should return only the files that match the file patterns on windows', async () => {
|
||||
mockedPlatform('win32')
|
||||
const allDiffFiles = {
|
||||
[ChangeTypeEnum.Added]: [
|
||||
'file1.txt',
|
||||
'file2.md',
|
||||
'file3.txt',
|
||||
'test\\dir\\file4.txt',
|
||||
'test\\dir\\file5.txt',
|
||||
'dir\\file6.md'
|
||||
],
|
||||
[ChangeTypeEnum.Copied]: [],
|
||||
[ChangeTypeEnum.Deleted]: [],
|
||||
[ChangeTypeEnum.Modified]: [],
|
||||
[ChangeTypeEnum.Renamed]: [],
|
||||
[ChangeTypeEnum.TypeChanged]: [],
|
||||
[ChangeTypeEnum.Unmerged]: [],
|
||||
[ChangeTypeEnum.Unknown]: []
|
||||
}
|
||||
const result = await getFilteredChangedFiles({
|
||||
allDiffFiles,
|
||||
filePatterns: ['*.txt']
|
||||
})
|
||||
|
||||
expect(result).toEqual({
|
||||
[ChangeTypeEnum.Added]: ['file1.txt', 'file3.txt'],
|
||||
[ChangeTypeEnum.Copied]: [],
|
||||
[ChangeTypeEnum.Deleted]: [],
|
||||
[ChangeTypeEnum.Modified]: [],
|
||||
[ChangeTypeEnum.Renamed]: [],
|
||||
[ChangeTypeEnum.TypeChanged]: [],
|
||||
[ChangeTypeEnum.Unmerged]: [],
|
||||
[ChangeTypeEnum.Unknown]: []
|
||||
})
|
||||
})
|
||||
|
||||
// Tests that the function returns only the files that match the file patterns with globstar on non windows platforms
|
||||
it('should return only the files that match the file patterns with globstar', async () => {
|
||||
const allDiffFiles = {
|
||||
[ChangeTypeEnum.Added]: [
|
||||
'file1.txt',
|
||||
'file2.md',
|
||||
'file3.txt',
|
||||
'test/dir/file4.txt',
|
||||
'test/dir/file5.txt',
|
||||
'dir/file6.md'
|
||||
],
|
||||
[ChangeTypeEnum.Copied]: [],
|
||||
[ChangeTypeEnum.Deleted]: [],
|
||||
[ChangeTypeEnum.Modified]: [],
|
||||
[ChangeTypeEnum.Renamed]: [],
|
||||
[ChangeTypeEnum.TypeChanged]: [],
|
||||
[ChangeTypeEnum.Unmerged]: [],
|
||||
[ChangeTypeEnum.Unknown]: []
|
||||
}
|
||||
const result = await getFilteredChangedFiles({
|
||||
allDiffFiles,
|
||||
filePatterns: ['**.txt']
|
||||
})
|
||||
expect(result).toEqual({
|
||||
[ChangeTypeEnum.Added]: [
|
||||
'file1.txt',
|
||||
'file3.txt',
|
||||
'test/dir/file4.txt',
|
||||
'test/dir/file5.txt'
|
||||
],
|
||||
[ChangeTypeEnum.Copied]: [],
|
||||
[ChangeTypeEnum.Deleted]: [],
|
||||
[ChangeTypeEnum.Modified]: [],
|
||||
[ChangeTypeEnum.Renamed]: [],
|
||||
[ChangeTypeEnum.TypeChanged]: [],
|
||||
[ChangeTypeEnum.Unmerged]: [],
|
||||
[ChangeTypeEnum.Unknown]: []
|
||||
})
|
||||
})
|
||||
|
||||
// Tests that the function returns only the files that match the file patterns with globstar on windows
|
||||
it('should return only the files that match the file patterns with globstar on windows', async () => {
|
||||
mockedPlatform('win32')
|
||||
const allDiffFiles = {
|
||||
[ChangeTypeEnum.Added]: ['test\\test rename-1.txt'],
|
||||
[ChangeTypeEnum.Copied]: [],
|
||||
[ChangeTypeEnum.Deleted]: [],
|
||||
[ChangeTypeEnum.Modified]: [],
|
||||
[ChangeTypeEnum.Renamed]: [],
|
||||
[ChangeTypeEnum.TypeChanged]: [],
|
||||
[ChangeTypeEnum.Unmerged]: [],
|
||||
[ChangeTypeEnum.Unknown]: []
|
||||
}
|
||||
const result = await getFilteredChangedFiles({
|
||||
allDiffFiles,
|
||||
filePatterns: ['test/**']
|
||||
})
|
||||
expect(result).toEqual({
|
||||
[ChangeTypeEnum.Added]: ['test\\test rename-1.txt'],
|
||||
[ChangeTypeEnum.Copied]: [],
|
||||
[ChangeTypeEnum.Deleted]: [],
|
||||
[ChangeTypeEnum.Modified]: [],
|
||||
[ChangeTypeEnum.Renamed]: [],
|
||||
[ChangeTypeEnum.TypeChanged]: [],
|
||||
[ChangeTypeEnum.Unmerged]: [],
|
||||
[ChangeTypeEnum.Unknown]: []
|
||||
})
|
||||
})
|
||||
|
||||
// Tests that the function returns an empty object when there are no files that match the file patterns
|
||||
it('should return an empty object when there are no files that match the file patterns', async () => {
|
||||
const allDiffFiles = {
|
||||
[ChangeTypeEnum.Added]: ['file1.md', 'file2.md', 'file3.md'],
|
||||
[ChangeTypeEnum.Copied]: [],
|
||||
[ChangeTypeEnum.Deleted]: [],
|
||||
[ChangeTypeEnum.Modified]: [],
|
||||
[ChangeTypeEnum.Renamed]: [],
|
||||
[ChangeTypeEnum.TypeChanged]: [],
|
||||
[ChangeTypeEnum.Unmerged]: [],
|
||||
[ChangeTypeEnum.Unknown]: []
|
||||
}
|
||||
const result = await getFilteredChangedFiles({
|
||||
allDiffFiles,
|
||||
filePatterns: ['*.txt']
|
||||
})
|
||||
expect(result).toEqual({
|
||||
[ChangeTypeEnum.Added]: [],
|
||||
[ChangeTypeEnum.Copied]: [],
|
||||
[ChangeTypeEnum.Deleted]: [],
|
||||
[ChangeTypeEnum.Modified]: [],
|
||||
[ChangeTypeEnum.Renamed]: [],
|
||||
[ChangeTypeEnum.TypeChanged]: [],
|
||||
[ChangeTypeEnum.Unmerged]: [],
|
||||
[ChangeTypeEnum.Unknown]: []
|
||||
})
|
||||
})
|
||||
|
||||
// Tests that the function can handle file names with special characters
|
||||
it('should handle file names with special characters', async () => {
|
||||
const allDiffFiles = {
|
||||
[ChangeTypeEnum.Added]: [
|
||||
'file1.txt',
|
||||
'file2 with spaces.txt',
|
||||
'file3$$.txt'
|
||||
],
|
||||
[ChangeTypeEnum.Copied]: [],
|
||||
[ChangeTypeEnum.Deleted]: [],
|
||||
[ChangeTypeEnum.Modified]: [],
|
||||
[ChangeTypeEnum.Renamed]: [],
|
||||
[ChangeTypeEnum.TypeChanged]: [],
|
||||
[ChangeTypeEnum.Unmerged]: [],
|
||||
[ChangeTypeEnum.Unknown]: []
|
||||
}
|
||||
const result = await getFilteredChangedFiles({
|
||||
allDiffFiles,
|
||||
filePatterns: ['file2*.txt']
|
||||
})
|
||||
expect(result).toEqual({
|
||||
[ChangeTypeEnum.Added]: ['file2 with spaces.txt'],
|
||||
[ChangeTypeEnum.Copied]: [],
|
||||
[ChangeTypeEnum.Deleted]: [],
|
||||
[ChangeTypeEnum.Modified]: [],
|
||||
[ChangeTypeEnum.Renamed]: [],
|
||||
[ChangeTypeEnum.TypeChanged]: [],
|
||||
[ChangeTypeEnum.Unmerged]: [],
|
||||
[ChangeTypeEnum.Unknown]: []
|
||||
})
|
||||
})
|
||||
|
||||
// Tests that getFilteredChangedFiles correctly filters files using glob patterns
|
||||
it('should filter files using glob patterns', async () => {
|
||||
const allDiffFiles = {
|
||||
[ChangeTypeEnum.Added]: ['test/migrations/test.sql'],
|
||||
[ChangeTypeEnum.Copied]: [],
|
||||
[ChangeTypeEnum.Deleted]: [],
|
||||
[ChangeTypeEnum.Modified]: [],
|
||||
[ChangeTypeEnum.Renamed]: [],
|
||||
[ChangeTypeEnum.TypeChanged]: [],
|
||||
[ChangeTypeEnum.Unmerged]: [],
|
||||
[ChangeTypeEnum.Unknown]: []
|
||||
}
|
||||
const filePatterns = ['test/migrations/**']
|
||||
const filteredFiles = await getFilteredChangedFiles({
|
||||
allDiffFiles,
|
||||
filePatterns
|
||||
})
|
||||
expect(filteredFiles[ChangeTypeEnum.Added]).toEqual([
|
||||
'test/migrations/test.sql'
|
||||
])
|
||||
})
|
||||
|
||||
// Tests that getFilteredChangedFiles correctly filters files using ignore glob patterns
|
||||
it('should filter files using ignore glob patterns', async () => {
|
||||
const allDiffFiles = {
|
||||
[ChangeTypeEnum.Added]: [],
|
||||
[ChangeTypeEnum.Copied]: [],
|
||||
[ChangeTypeEnum.Deleted]: [],
|
||||
[ChangeTypeEnum.Modified]: [
|
||||
'assets/scripts/configure-minikube-linux.sh'
|
||||
],
|
||||
[ChangeTypeEnum.Renamed]: [],
|
||||
[ChangeTypeEnum.TypeChanged]: [],
|
||||
[ChangeTypeEnum.Unmerged]: [],
|
||||
[ChangeTypeEnum.Unknown]: []
|
||||
}
|
||||
const filePatterns = [
|
||||
'assets/scripts/**.sh',
|
||||
'!assets/scripts/configure-minikube-linux.sh'
|
||||
]
|
||||
const filteredFiles = await getFilteredChangedFiles({
|
||||
allDiffFiles,
|
||||
filePatterns
|
||||
})
|
||||
expect(filteredFiles[ChangeTypeEnum.Modified]).toEqual([])
|
||||
})
|
||||
})
|
||||
})
|
||||
@@ -1,19 +1,122 @@
|
||||
import * as core from '@actions/core'
|
||||
import * as github from '@actions/github'
|
||||
import type {RestEndpointMethodTypes} from '@octokit/rest'
|
||||
import flatten from 'lodash/flatten'
|
||||
import mm from 'micromatch'
|
||||
import * as path from 'path'
|
||||
|
||||
import {setOutputsAndGetModifiedAndChangedFilesStatus} from './changedFilesOutput'
|
||||
import {DiffResult} from './commitSha'
|
||||
import {Env} from './env'
|
||||
import {Inputs} from './inputs'
|
||||
import {
|
||||
canDiffCommits,
|
||||
getAllChangedFiles,
|
||||
getDirnameMaxDepth,
|
||||
getDirNamesIncludeFilesPattern,
|
||||
getFilteredChangedFiles,
|
||||
gitRenamedFiles,
|
||||
gitSubmoduleDiffSHA,
|
||||
isWindows,
|
||||
jsonOutput,
|
||||
getAllChangedFiles
|
||||
setArrayOutput
|
||||
} from './utils'
|
||||
import flatten from 'lodash/flatten'
|
||||
|
||||
export const processChangedFiles = async ({
|
||||
filePatterns,
|
||||
allDiffFiles,
|
||||
inputs,
|
||||
yamlFilePatterns,
|
||||
workingDirectory
|
||||
}: {
|
||||
filePatterns: string[]
|
||||
allDiffFiles: ChangedFiles
|
||||
inputs: Inputs
|
||||
yamlFilePatterns: Record<string, string[]>
|
||||
workingDirectory?: string
|
||||
}): Promise<void> => {
|
||||
if (filePatterns.length > 0) {
|
||||
core.startGroup('changed-files-patterns')
|
||||
const allFilteredDiffFiles = await getFilteredChangedFiles({
|
||||
allDiffFiles,
|
||||
filePatterns
|
||||
})
|
||||
core.debug(
|
||||
`All filtered diff files: ${JSON.stringify(allFilteredDiffFiles)}`
|
||||
)
|
||||
await setOutputsAndGetModifiedAndChangedFilesStatus({
|
||||
allDiffFiles,
|
||||
allFilteredDiffFiles,
|
||||
inputs,
|
||||
filePatterns,
|
||||
workingDirectory
|
||||
})
|
||||
core.info('All Done!')
|
||||
core.endGroup()
|
||||
}
|
||||
|
||||
if (Object.keys(yamlFilePatterns).length > 0) {
|
||||
const modifiedKeys: string[] = []
|
||||
const changedKeys: string[] = []
|
||||
|
||||
for (const key of Object.keys(yamlFilePatterns)) {
|
||||
core.startGroup(`changed-files-yaml-${key}`)
|
||||
const allFilteredDiffFiles = await getFilteredChangedFiles({
|
||||
allDiffFiles,
|
||||
filePatterns: yamlFilePatterns[key]
|
||||
})
|
||||
core.debug(
|
||||
`All filtered diff files for ${key}: ${JSON.stringify(
|
||||
allFilteredDiffFiles
|
||||
)}`
|
||||
)
|
||||
const {anyChanged, anyModified} =
|
||||
await setOutputsAndGetModifiedAndChangedFilesStatus({
|
||||
allDiffFiles,
|
||||
allFilteredDiffFiles,
|
||||
inputs,
|
||||
filePatterns: yamlFilePatterns[key],
|
||||
outputPrefix: key,
|
||||
workingDirectory
|
||||
})
|
||||
if (anyModified) {
|
||||
modifiedKeys.push(key)
|
||||
}
|
||||
if (anyChanged) {
|
||||
changedKeys.push(key)
|
||||
}
|
||||
|
||||
core.info('All Done!')
|
||||
core.endGroup()
|
||||
}
|
||||
|
||||
if (modifiedKeys.length > 0) {
|
||||
await setArrayOutput({
|
||||
key: 'modified_keys',
|
||||
inputs,
|
||||
value: modifiedKeys
|
||||
})
|
||||
}
|
||||
|
||||
if (changedKeys.length > 0) {
|
||||
await setArrayOutput({
|
||||
key: 'changed_keys',
|
||||
inputs,
|
||||
value: changedKeys
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
if (filePatterns.length === 0 && Object.keys(yamlFilePatterns).length === 0) {
|
||||
core.startGroup('changed-files-all')
|
||||
await setOutputsAndGetModifiedAndChangedFilesStatus({
|
||||
allDiffFiles,
|
||||
allFilteredDiffFiles: allDiffFiles,
|
||||
inputs,
|
||||
workingDirectory
|
||||
})
|
||||
core.info('All Done!')
|
||||
core.endGroup()
|
||||
}
|
||||
}
|
||||
|
||||
export const getRenamedFiles = async ({
|
||||
inputs,
|
||||
@@ -52,11 +155,29 @@ export const getRenamedFiles = async ({
|
||||
)
|
||||
|
||||
if (submoduleShaResult.currentSha && submoduleShaResult.previousSha) {
|
||||
let diff = '...'
|
||||
|
||||
if (
|
||||
!(await canDiffCommits({
|
||||
cwd: submoduleWorkingDirectory,
|
||||
sha1: submoduleShaResult.previousSha,
|
||||
sha2: submoduleShaResult.currentSha,
|
||||
diff
|
||||
}))
|
||||
) {
|
||||
let message = `Unable to use three dot diff for: ${submodulePath} submodule. Falling back to two dot diff. You can set 'fetch_additional_submodule_history: true' to fetch additional submodule history in order to use three dot diff`
|
||||
if (inputs.fetchSubmoduleHistory) {
|
||||
message = `To fetch additional submodule history for: ${submodulePath} you can increase history depth using 'fetch_depth' input`
|
||||
}
|
||||
core.info(message)
|
||||
diff = '..'
|
||||
}
|
||||
|
||||
const submoduleRenamedFiles = await gitRenamedFiles({
|
||||
cwd: submoduleWorkingDirectory,
|
||||
sha1: submoduleShaResult.previousSha,
|
||||
sha2: submoduleShaResult.currentSha,
|
||||
diff: diffResult.diff,
|
||||
diff,
|
||||
oldNewSeparator: inputs.oldNewSeparator,
|
||||
isSubmodule: true,
|
||||
parentDir: submodulePath
|
||||
@@ -99,20 +220,27 @@ export const getAllDiffFiles = async ({
|
||||
hasSubmodule,
|
||||
diffResult,
|
||||
submodulePaths,
|
||||
outputRenamedFilesAsDeletedAndAdded
|
||||
outputRenamedFilesAsDeletedAndAdded,
|
||||
fetchSubmoduleHistory,
|
||||
failOnInitialDiffError,
|
||||
failOnSubmoduleDiffError
|
||||
}: {
|
||||
workingDirectory: string
|
||||
hasSubmodule: boolean
|
||||
diffResult: DiffResult
|
||||
submodulePaths: string[]
|
||||
outputRenamedFilesAsDeletedAndAdded: boolean
|
||||
fetchSubmoduleHistory: boolean
|
||||
failOnInitialDiffError: boolean
|
||||
failOnSubmoduleDiffError: boolean
|
||||
}): Promise<ChangedFiles> => {
|
||||
const files = await getAllChangedFiles({
|
||||
cwd: workingDirectory,
|
||||
sha1: diffResult.previousSha,
|
||||
sha2: diffResult.currentSha,
|
||||
diff: diffResult.diff,
|
||||
outputRenamedFilesAsDeletedAndAdded
|
||||
outputRenamedFilesAsDeletedAndAdded,
|
||||
failOnInitialDiffError
|
||||
})
|
||||
|
||||
if (hasSubmodule) {
|
||||
@@ -131,14 +259,33 @@ export const getAllDiffFiles = async ({
|
||||
)
|
||||
|
||||
if (submoduleShaResult.currentSha && submoduleShaResult.previousSha) {
|
||||
let diff = '...'
|
||||
|
||||
if (
|
||||
!(await canDiffCommits({
|
||||
cwd: submoduleWorkingDirectory,
|
||||
sha1: submoduleShaResult.previousSha,
|
||||
sha2: submoduleShaResult.currentSha,
|
||||
diff
|
||||
}))
|
||||
) {
|
||||
let message = `Set 'fetch_additional_submodule_history: true' to fetch additional submodule history for: ${submodulePath}`
|
||||
if (fetchSubmoduleHistory) {
|
||||
message = `To fetch additional submodule history for: ${submodulePath} you can increase history depth using 'fetch_depth' input`
|
||||
}
|
||||
core.warning(message)
|
||||
diff = '..'
|
||||
}
|
||||
|
||||
const submoduleFiles = await getAllChangedFiles({
|
||||
cwd: submoduleWorkingDirectory,
|
||||
sha1: submoduleShaResult.previousSha,
|
||||
sha2: submoduleShaResult.currentSha,
|
||||
diff: diffResult.diff,
|
||||
diff,
|
||||
isSubmodule: true,
|
||||
parentDir: submodulePath,
|
||||
outputRenamedFilesAsDeletedAndAdded
|
||||
outputRenamedFilesAsDeletedAndAdded,
|
||||
failOnSubmoduleDiffError
|
||||
})
|
||||
|
||||
for (const changeType of Object.keys(
|
||||
@@ -156,6 +303,35 @@ export const getAllDiffFiles = async ({
|
||||
return files
|
||||
}
|
||||
|
||||
function* getFilePaths({
|
||||
inputs,
|
||||
filePaths,
|
||||
dirNamesIncludeFilePatterns
|
||||
}: {
|
||||
inputs: Inputs
|
||||
filePaths: string[]
|
||||
dirNamesIncludeFilePatterns: string[]
|
||||
}): Generator<string> {
|
||||
for (const filePath of filePaths) {
|
||||
if (inputs.dirNames) {
|
||||
if (dirNamesIncludeFilePatterns.length > 0) {
|
||||
const isWin = isWindows()
|
||||
const matchOptions = {dot: true, windows: isWin, noext: true}
|
||||
if (mm.isMatch(filePath, dirNamesIncludeFilePatterns, matchOptions)) {
|
||||
yield filePath
|
||||
}
|
||||
}
|
||||
yield getDirnameMaxDepth({
|
||||
relativePath: filePath,
|
||||
dirNamesMaxDepth: inputs.dirNamesMaxDepth,
|
||||
excludeCurrentDir: inputs.dirNamesExcludeCurrentDir
|
||||
})
|
||||
} else {
|
||||
yield filePath
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function* getChangeTypeFilesGenerator({
|
||||
inputs,
|
||||
changedFiles,
|
||||
@@ -165,18 +341,21 @@ function* getChangeTypeFilesGenerator({
|
||||
changedFiles: ChangedFiles
|
||||
changeTypes: ChangeTypeEnum[]
|
||||
}): Generator<string> {
|
||||
const dirNamesIncludeFilePatterns = getDirNamesIncludeFilesPattern({inputs})
|
||||
core.debug(
|
||||
`Dir names include file patterns: ${JSON.stringify(
|
||||
dirNamesIncludeFilePatterns
|
||||
)}`
|
||||
)
|
||||
|
||||
for (const changeType of changeTypes) {
|
||||
const files = changedFiles[changeType] || []
|
||||
for (const file of files) {
|
||||
if (inputs.dirNames) {
|
||||
yield getDirnameMaxDepth({
|
||||
pathStr: file,
|
||||
dirNamesMaxDepth: inputs.dirNamesMaxDepth,
|
||||
excludeCurrentDir: inputs.dirNamesExcludeCurrentDir
|
||||
})
|
||||
} else {
|
||||
yield file
|
||||
}
|
||||
const filePaths = changedFiles[changeType] || []
|
||||
for (const filePath of getFilePaths({
|
||||
inputs,
|
||||
filePaths,
|
||||
dirNamesIncludeFilePatterns
|
||||
})) {
|
||||
yield filePath
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -189,20 +368,15 @@ export const getChangeTypeFiles = async ({
|
||||
inputs: Inputs
|
||||
changedFiles: ChangedFiles
|
||||
changeTypes: ChangeTypeEnum[]
|
||||
}): Promise<{paths: string; count: string}> => {
|
||||
}): Promise<{paths: string[] | string; count: string}> => {
|
||||
const files = [
|
||||
...new Set(getChangeTypeFilesGenerator({inputs, changedFiles, changeTypes}))
|
||||
]
|
||||
].filter(Boolean)
|
||||
|
||||
if (inputs.json) {
|
||||
return {
|
||||
paths: jsonOutput({value: files, shouldEscape: inputs.escapeJson}),
|
||||
count: files.length.toString()
|
||||
}
|
||||
}
|
||||
const paths = inputs.json ? files : files.join(inputs.separator)
|
||||
|
||||
return {
|
||||
paths: files.join(inputs.separator),
|
||||
paths,
|
||||
count: files.length.toString()
|
||||
}
|
||||
}
|
||||
@@ -214,16 +388,21 @@ function* getAllChangeTypeFilesGenerator({
|
||||
inputs: Inputs
|
||||
changedFiles: ChangedFiles
|
||||
}): Generator<string> {
|
||||
for (const file of flatten(Object.values(changedFiles))) {
|
||||
if (inputs.dirNames) {
|
||||
yield getDirnameMaxDepth({
|
||||
pathStr: file,
|
||||
dirNamesMaxDepth: inputs.dirNamesMaxDepth,
|
||||
excludeCurrentDir: inputs.dirNamesExcludeCurrentDir
|
||||
})
|
||||
} else {
|
||||
yield file
|
||||
}
|
||||
const dirNamesIncludeFilePatterns = getDirNamesIncludeFilesPattern({inputs})
|
||||
core.debug(
|
||||
`Dir names include file patterns: ${JSON.stringify(
|
||||
dirNamesIncludeFilePatterns
|
||||
)}`
|
||||
)
|
||||
|
||||
const filePaths = flatten(Object.values(changedFiles))
|
||||
|
||||
for (const filePath of getFilePaths({
|
||||
inputs,
|
||||
filePaths,
|
||||
dirNamesIncludeFilePatterns
|
||||
})) {
|
||||
yield filePath
|
||||
}
|
||||
}
|
||||
|
||||
@@ -233,30 +412,23 @@ export const getAllChangeTypeFiles = async ({
|
||||
}: {
|
||||
inputs: Inputs
|
||||
changedFiles: ChangedFiles
|
||||
}): Promise<{paths: string; count: string}> => {
|
||||
}): Promise<{paths: string[] | string; count: string}> => {
|
||||
const files = [
|
||||
...new Set(getAllChangeTypeFilesGenerator({inputs, changedFiles}))
|
||||
]
|
||||
].filter(Boolean)
|
||||
|
||||
if (inputs.json) {
|
||||
return {
|
||||
paths: jsonOutput({value: files, shouldEscape: inputs.escapeJson}),
|
||||
count: files.length.toString()
|
||||
}
|
||||
}
|
||||
const paths = inputs.json ? files : files.join(inputs.separator)
|
||||
|
||||
return {
|
||||
paths: files.join(inputs.separator),
|
||||
paths,
|
||||
count: files.length.toString()
|
||||
}
|
||||
}
|
||||
|
||||
export const getChangedFilesFromGithubAPI = async ({
|
||||
inputs,
|
||||
env
|
||||
inputs
|
||||
}: {
|
||||
inputs: Inputs
|
||||
env: Env
|
||||
}): Promise<ChangedFiles> => {
|
||||
const octokit = github.getOctokit(inputs.token, {
|
||||
baseUrl: inputs.apiUrl
|
||||
@@ -277,13 +449,14 @@ export const getChangedFilesFromGithubAPI = async ({
|
||||
const options = octokit.rest.pulls.listFiles.endpoint.merge({
|
||||
owner: github.context.repo.owner,
|
||||
repo: github.context.repo.repo,
|
||||
pull_number: env.GITHUB_EVENT_PULL_REQUEST_NUMBER,
|
||||
pull_number: github.context.payload.pull_request?.number,
|
||||
per_page: 100
|
||||
})
|
||||
|
||||
const paginatedResponse = await octokit.paginate<
|
||||
RestEndpointMethodTypes['pulls']['listFiles']['response']['data'][0]
|
||||
>(options)
|
||||
const paginatedResponse =
|
||||
await octokit.paginate<
|
||||
RestEndpointMethodTypes['pulls']['listFiles']['response']['data'][0]
|
||||
>(options)
|
||||
|
||||
core.info(`Found ${paginatedResponse.length} changed files from GitHub API`)
|
||||
const statusMap: Record<string, ChangeTypeEnum> = {
|
||||
|
||||
@@ -1,63 +1,55 @@
|
||||
import * as core from '@actions/core'
|
||||
import path from 'path'
|
||||
import {
|
||||
ChangedFiles,
|
||||
ChangeTypeEnum,
|
||||
getAllChangeTypeFiles,
|
||||
getChangeTypeFiles
|
||||
} from './changedFiles'
|
||||
import {DiffResult} from './commitSha'
|
||||
import {Inputs} from './inputs'
|
||||
import {getFilteredChangedFiles, recoverDeletedFiles, setOutput} from './utils'
|
||||
import {getOutputKey, setArrayOutput, setOutput, exists} from './utils'
|
||||
|
||||
const getOutputKey = (key: string, outputPrefix: string): string => {
|
||||
return outputPrefix ? `${outputPrefix}_${key}` : key
|
||||
const getArrayFromPaths = (
|
||||
paths: string | string[],
|
||||
inputs: Inputs
|
||||
): string[] => {
|
||||
return Array.isArray(paths) ? paths : paths.split(inputs.separator)
|
||||
}
|
||||
|
||||
export const setChangedFilesOutput = async ({
|
||||
export const setOutputsAndGetModifiedAndChangedFilesStatus = async ({
|
||||
allDiffFiles,
|
||||
allFilteredDiffFiles,
|
||||
inputs,
|
||||
workingDirectory,
|
||||
diffResult,
|
||||
filePatterns = [],
|
||||
outputPrefix = ''
|
||||
outputPrefix = '',
|
||||
workingDirectory
|
||||
}: {
|
||||
allDiffFiles: ChangedFiles
|
||||
allFilteredDiffFiles: ChangedFiles
|
||||
inputs: Inputs
|
||||
workingDirectory: string
|
||||
diffResult?: DiffResult
|
||||
filePatterns?: string[]
|
||||
outputPrefix?: string
|
||||
}): Promise<void> => {
|
||||
const allFilteredDiffFiles = await getFilteredChangedFiles({
|
||||
allDiffFiles,
|
||||
filePatterns
|
||||
})
|
||||
core.debug(`All filtered diff files: ${JSON.stringify(allFilteredDiffFiles)}`)
|
||||
|
||||
if (diffResult) {
|
||||
await recoverDeletedFiles({
|
||||
inputs,
|
||||
workingDirectory,
|
||||
deletedFiles: allFilteredDiffFiles[ChangeTypeEnum.Deleted],
|
||||
sha: diffResult.previousSha
|
||||
})
|
||||
}
|
||||
|
||||
workingDirectory?: string
|
||||
}): Promise<{anyModified: boolean; anyChanged: boolean}> => {
|
||||
const addedFiles = await getChangeTypeFiles({
|
||||
inputs,
|
||||
changedFiles: allFilteredDiffFiles,
|
||||
changeTypes: [ChangeTypeEnum.Added]
|
||||
})
|
||||
core.debug(`Added files: ${addedFiles}`)
|
||||
core.debug(`Added files: ${JSON.stringify(addedFiles)}`)
|
||||
await setOutput({
|
||||
key: getOutputKey('added_files', outputPrefix),
|
||||
value: addedFiles.paths,
|
||||
inputs
|
||||
writeOutputFiles: inputs.writeOutputFiles,
|
||||
outputDir: inputs.outputDir,
|
||||
json: inputs.json,
|
||||
shouldEscape: inputs.escapeJson
|
||||
})
|
||||
await setOutput({
|
||||
key: getOutputKey('added_files_count', outputPrefix),
|
||||
value: addedFiles.count,
|
||||
inputs
|
||||
writeOutputFiles: inputs.writeOutputFiles,
|
||||
outputDir: inputs.outputDir
|
||||
})
|
||||
|
||||
const copiedFiles = await getChangeTypeFiles({
|
||||
@@ -65,17 +57,21 @@ export const setChangedFilesOutput = async ({
|
||||
changedFiles: allFilteredDiffFiles,
|
||||
changeTypes: [ChangeTypeEnum.Copied]
|
||||
})
|
||||
core.debug(`Copied files: ${copiedFiles}`)
|
||||
core.debug(`Copied files: ${JSON.stringify(copiedFiles)}`)
|
||||
await setOutput({
|
||||
key: getOutputKey('copied_files', outputPrefix),
|
||||
value: copiedFiles.paths,
|
||||
inputs
|
||||
writeOutputFiles: inputs.writeOutputFiles,
|
||||
outputDir: inputs.outputDir,
|
||||
json: inputs.json,
|
||||
shouldEscape: inputs.escapeJson
|
||||
})
|
||||
|
||||
await setOutput({
|
||||
key: getOutputKey('copied_files_count', outputPrefix),
|
||||
value: copiedFiles.count,
|
||||
inputs
|
||||
writeOutputFiles: inputs.writeOutputFiles,
|
||||
outputDir: inputs.outputDir
|
||||
})
|
||||
|
||||
const modifiedFiles = await getChangeTypeFiles({
|
||||
@@ -83,17 +79,21 @@ export const setChangedFilesOutput = async ({
|
||||
changedFiles: allFilteredDiffFiles,
|
||||
changeTypes: [ChangeTypeEnum.Modified]
|
||||
})
|
||||
core.debug(`Modified files: ${modifiedFiles}`)
|
||||
core.debug(`Modified files: ${JSON.stringify(modifiedFiles)}`)
|
||||
await setOutput({
|
||||
key: getOutputKey('modified_files', outputPrefix),
|
||||
value: modifiedFiles.paths,
|
||||
inputs
|
||||
writeOutputFiles: inputs.writeOutputFiles,
|
||||
outputDir: inputs.outputDir,
|
||||
json: inputs.json,
|
||||
shouldEscape: inputs.escapeJson
|
||||
})
|
||||
|
||||
await setOutput({
|
||||
key: getOutputKey('modified_files_count', outputPrefix),
|
||||
value: modifiedFiles.count,
|
||||
inputs
|
||||
writeOutputFiles: inputs.writeOutputFiles,
|
||||
outputDir: inputs.outputDir
|
||||
})
|
||||
|
||||
const renamedFiles = await getChangeTypeFiles({
|
||||
@@ -101,17 +101,21 @@ export const setChangedFilesOutput = async ({
|
||||
changedFiles: allFilteredDiffFiles,
|
||||
changeTypes: [ChangeTypeEnum.Renamed]
|
||||
})
|
||||
core.debug(`Renamed files: ${renamedFiles}`)
|
||||
core.debug(`Renamed files: ${JSON.stringify(renamedFiles)}`)
|
||||
await setOutput({
|
||||
key: getOutputKey('renamed_files', outputPrefix),
|
||||
value: renamedFiles.paths,
|
||||
inputs
|
||||
writeOutputFiles: inputs.writeOutputFiles,
|
||||
outputDir: inputs.outputDir,
|
||||
json: inputs.json,
|
||||
shouldEscape: inputs.escapeJson
|
||||
})
|
||||
|
||||
await setOutput({
|
||||
key: getOutputKey('renamed_files_count', outputPrefix),
|
||||
value: renamedFiles.count,
|
||||
inputs
|
||||
writeOutputFiles: inputs.writeOutputFiles,
|
||||
outputDir: inputs.outputDir
|
||||
})
|
||||
|
||||
const typeChangedFiles = await getChangeTypeFiles({
|
||||
@@ -119,17 +123,21 @@ export const setChangedFilesOutput = async ({
|
||||
changedFiles: allFilteredDiffFiles,
|
||||
changeTypes: [ChangeTypeEnum.TypeChanged]
|
||||
})
|
||||
core.debug(`Type changed files: ${typeChangedFiles}`)
|
||||
core.debug(`Type changed files: ${JSON.stringify(typeChangedFiles)}`)
|
||||
await setOutput({
|
||||
key: getOutputKey('type_changed_files', outputPrefix),
|
||||
value: typeChangedFiles.paths,
|
||||
inputs
|
||||
writeOutputFiles: inputs.writeOutputFiles,
|
||||
outputDir: inputs.outputDir,
|
||||
json: inputs.json,
|
||||
shouldEscape: inputs.escapeJson
|
||||
})
|
||||
|
||||
await setOutput({
|
||||
key: getOutputKey('type_changed_files_count', outputPrefix),
|
||||
value: typeChangedFiles.count,
|
||||
inputs
|
||||
writeOutputFiles: inputs.writeOutputFiles,
|
||||
outputDir: inputs.outputDir
|
||||
})
|
||||
|
||||
const unmergedFiles = await getChangeTypeFiles({
|
||||
@@ -137,17 +145,21 @@ export const setChangedFilesOutput = async ({
|
||||
changedFiles: allFilteredDiffFiles,
|
||||
changeTypes: [ChangeTypeEnum.Unmerged]
|
||||
})
|
||||
core.debug(`Unmerged files: ${unmergedFiles}`)
|
||||
core.debug(`Unmerged files: ${JSON.stringify(unmergedFiles)}`)
|
||||
await setOutput({
|
||||
key: getOutputKey('unmerged_files', outputPrefix),
|
||||
value: unmergedFiles.paths,
|
||||
inputs
|
||||
writeOutputFiles: inputs.writeOutputFiles,
|
||||
outputDir: inputs.outputDir,
|
||||
json: inputs.json,
|
||||
shouldEscape: inputs.escapeJson
|
||||
})
|
||||
|
||||
await setOutput({
|
||||
key: getOutputKey('unmerged_files_count', outputPrefix),
|
||||
value: unmergedFiles.count,
|
||||
inputs
|
||||
writeOutputFiles: inputs.writeOutputFiles,
|
||||
outputDir: inputs.outputDir
|
||||
})
|
||||
|
||||
const unknownFiles = await getChangeTypeFiles({
|
||||
@@ -155,34 +167,46 @@ export const setChangedFilesOutput = async ({
|
||||
changedFiles: allFilteredDiffFiles,
|
||||
changeTypes: [ChangeTypeEnum.Unknown]
|
||||
})
|
||||
core.debug(`Unknown files: ${unknownFiles}`)
|
||||
core.debug(`Unknown files: ${JSON.stringify(unknownFiles)}`)
|
||||
await setOutput({
|
||||
key: getOutputKey('unknown_files', outputPrefix),
|
||||
value: unknownFiles.paths,
|
||||
inputs
|
||||
writeOutputFiles: inputs.writeOutputFiles,
|
||||
outputDir: inputs.outputDir,
|
||||
json: inputs.json,
|
||||
shouldEscape: inputs.escapeJson
|
||||
})
|
||||
|
||||
await setOutput({
|
||||
key: getOutputKey('unknown_files_count', outputPrefix),
|
||||
value: unknownFiles.count,
|
||||
inputs
|
||||
writeOutputFiles: inputs.writeOutputFiles,
|
||||
outputDir: inputs.outputDir
|
||||
})
|
||||
|
||||
const allChangedAndModifiedFiles = await getAllChangeTypeFiles({
|
||||
inputs,
|
||||
changedFiles: allFilteredDiffFiles
|
||||
})
|
||||
core.debug(`All changed and modified files: ${allChangedAndModifiedFiles}`)
|
||||
core.debug(
|
||||
`All changed and modified files: ${JSON.stringify(
|
||||
allChangedAndModifiedFiles
|
||||
)}`
|
||||
)
|
||||
await setOutput({
|
||||
key: getOutputKey('all_changed_and_modified_files', outputPrefix),
|
||||
value: allChangedAndModifiedFiles.paths,
|
||||
inputs
|
||||
writeOutputFiles: inputs.writeOutputFiles,
|
||||
outputDir: inputs.outputDir,
|
||||
json: inputs.json,
|
||||
shouldEscape: inputs.escapeJson
|
||||
})
|
||||
|
||||
await setOutput({
|
||||
key: getOutputKey('all_changed_and_modified_files_count', outputPrefix),
|
||||
value: allChangedAndModifiedFiles.count,
|
||||
inputs
|
||||
writeOutputFiles: inputs.writeOutputFiles,
|
||||
outputDir: inputs.outputDir
|
||||
})
|
||||
|
||||
const allChangedFiles = await getChangeTypeFiles({
|
||||
@@ -195,23 +219,29 @@ export const setChangedFilesOutput = async ({
|
||||
ChangeTypeEnum.Renamed
|
||||
]
|
||||
})
|
||||
core.debug(`All changed files: ${allChangedFiles}`)
|
||||
core.debug(`All changed files: ${JSON.stringify(allChangedFiles)}`)
|
||||
await setOutput({
|
||||
key: getOutputKey('all_changed_files', outputPrefix),
|
||||
value: allChangedFiles.paths,
|
||||
inputs
|
||||
writeOutputFiles: inputs.writeOutputFiles,
|
||||
outputDir: inputs.outputDir,
|
||||
json: inputs.json,
|
||||
shouldEscape: inputs.escapeJson
|
||||
})
|
||||
|
||||
await setOutput({
|
||||
key: getOutputKey('all_changed_files_count', outputPrefix),
|
||||
value: allChangedFiles.count,
|
||||
inputs
|
||||
writeOutputFiles: inputs.writeOutputFiles,
|
||||
outputDir: inputs.outputDir
|
||||
})
|
||||
|
||||
await setOutput({
|
||||
key: getOutputKey('any_changed', outputPrefix),
|
||||
value: allChangedFiles.paths.length > 0 && filePatterns.length > 0,
|
||||
inputs
|
||||
writeOutputFiles: inputs.writeOutputFiles,
|
||||
outputDir: inputs.outputDir,
|
||||
json: inputs.json
|
||||
})
|
||||
|
||||
const allOtherChangedFiles = await getChangeTypeFiles({
|
||||
@@ -224,14 +254,20 @@ export const setChangedFilesOutput = async ({
|
||||
ChangeTypeEnum.Renamed
|
||||
]
|
||||
})
|
||||
core.debug(`All other changed files: ${allOtherChangedFiles}`)
|
||||
core.debug(`All other changed files: ${JSON.stringify(allOtherChangedFiles)}`)
|
||||
|
||||
const otherChangedFiles = allOtherChangedFiles.paths
|
||||
.split(inputs.separator)
|
||||
.filter(
|
||||
(filePath: string) =>
|
||||
!allChangedFiles.paths.split(inputs.separator).includes(filePath)
|
||||
)
|
||||
const allOtherChangedFilesPaths: string[] = getArrayFromPaths(
|
||||
allOtherChangedFiles.paths,
|
||||
inputs
|
||||
)
|
||||
const allChangedFilesPaths: string[] = getArrayFromPaths(
|
||||
allChangedFiles.paths,
|
||||
inputs
|
||||
)
|
||||
|
||||
const otherChangedFiles = allOtherChangedFilesPaths.filter(
|
||||
(filePath: string) => !allChangedFilesPaths.includes(filePath)
|
||||
)
|
||||
|
||||
const onlyChanged =
|
||||
otherChangedFiles.length === 0 &&
|
||||
@@ -241,19 +277,23 @@ export const setChangedFilesOutput = async ({
|
||||
await setOutput({
|
||||
key: getOutputKey('only_changed', outputPrefix),
|
||||
value: onlyChanged,
|
||||
inputs
|
||||
writeOutputFiles: inputs.writeOutputFiles,
|
||||
outputDir: inputs.outputDir,
|
||||
json: inputs.json
|
||||
})
|
||||
|
||||
await setOutput({
|
||||
key: getOutputKey('other_changed_files', outputPrefix),
|
||||
value: otherChangedFiles.join(inputs.separator),
|
||||
inputs
|
||||
await setArrayOutput({
|
||||
key: 'other_changed_files',
|
||||
inputs,
|
||||
value: otherChangedFiles,
|
||||
outputPrefix
|
||||
})
|
||||
|
||||
await setOutput({
|
||||
key: getOutputKey('other_changed_files_count', outputPrefix),
|
||||
value: otherChangedFiles.length.toString(),
|
||||
inputs
|
||||
writeOutputFiles: inputs.writeOutputFiles,
|
||||
outputDir: inputs.outputDir
|
||||
})
|
||||
|
||||
const allModifiedFiles = await getChangeTypeFiles({
|
||||
@@ -267,23 +307,29 @@ export const setChangedFilesOutput = async ({
|
||||
ChangeTypeEnum.Deleted
|
||||
]
|
||||
})
|
||||
core.debug(`All modified files: ${allModifiedFiles}`)
|
||||
core.debug(`All modified files: ${JSON.stringify(allModifiedFiles)}`)
|
||||
await setOutput({
|
||||
key: getOutputKey('all_modified_files', outputPrefix),
|
||||
value: allModifiedFiles.paths,
|
||||
inputs
|
||||
writeOutputFiles: inputs.writeOutputFiles,
|
||||
outputDir: inputs.outputDir,
|
||||
json: inputs.json,
|
||||
shouldEscape: inputs.escapeJson
|
||||
})
|
||||
|
||||
await setOutput({
|
||||
key: getOutputKey('all_modified_files_count', outputPrefix),
|
||||
value: allModifiedFiles.count,
|
||||
inputs
|
||||
writeOutputFiles: inputs.writeOutputFiles,
|
||||
outputDir: inputs.outputDir
|
||||
})
|
||||
|
||||
await setOutput({
|
||||
key: getOutputKey('any_modified', outputPrefix),
|
||||
value: allModifiedFiles.paths.length > 0 && filePatterns.length > 0,
|
||||
inputs
|
||||
writeOutputFiles: inputs.writeOutputFiles,
|
||||
outputDir: inputs.outputDir,
|
||||
json: inputs.json
|
||||
})
|
||||
|
||||
const allOtherModifiedFiles = await getChangeTypeFiles({
|
||||
@@ -298,12 +344,19 @@ export const setChangedFilesOutput = async ({
|
||||
]
|
||||
})
|
||||
|
||||
const otherModifiedFiles = allOtherModifiedFiles.paths
|
||||
.split(inputs.separator)
|
||||
.filter(
|
||||
(filePath: string) =>
|
||||
!allModifiedFiles.paths.split(inputs.separator).includes(filePath)
|
||||
)
|
||||
const allOtherModifiedFilesPaths: string[] = getArrayFromPaths(
|
||||
allOtherModifiedFiles.paths,
|
||||
inputs
|
||||
)
|
||||
|
||||
const allModifiedFilesPaths: string[] = getArrayFromPaths(
|
||||
allModifiedFiles.paths,
|
||||
inputs
|
||||
)
|
||||
|
||||
const otherModifiedFiles = allOtherModifiedFilesPaths.filter(
|
||||
(filePath: string) => !allModifiedFilesPaths.includes(filePath)
|
||||
)
|
||||
|
||||
const onlyModified =
|
||||
otherModifiedFiles.length === 0 &&
|
||||
@@ -313,19 +366,23 @@ export const setChangedFilesOutput = async ({
|
||||
await setOutput({
|
||||
key: getOutputKey('only_modified', outputPrefix),
|
||||
value: onlyModified,
|
||||
inputs
|
||||
writeOutputFiles: inputs.writeOutputFiles,
|
||||
outputDir: inputs.outputDir,
|
||||
json: inputs.json
|
||||
})
|
||||
|
||||
await setOutput({
|
||||
key: getOutputKey('other_modified_files', outputPrefix),
|
||||
value: otherModifiedFiles.join(inputs.separator),
|
||||
inputs
|
||||
await setArrayOutput({
|
||||
key: 'other_modified_files',
|
||||
inputs,
|
||||
value: otherModifiedFiles,
|
||||
outputPrefix
|
||||
})
|
||||
|
||||
await setOutput({
|
||||
key: getOutputKey('other_modified_files_count', outputPrefix),
|
||||
value: otherModifiedFiles.length.toString(),
|
||||
inputs
|
||||
writeOutputFiles: inputs.writeOutputFiles,
|
||||
outputDir: inputs.outputDir
|
||||
})
|
||||
|
||||
const deletedFiles = await getChangeTypeFiles({
|
||||
@@ -333,23 +390,51 @@ export const setChangedFilesOutput = async ({
|
||||
changedFiles: allFilteredDiffFiles,
|
||||
changeTypes: [ChangeTypeEnum.Deleted]
|
||||
})
|
||||
core.debug(`Deleted files: ${deletedFiles}`)
|
||||
core.debug(`Deleted files: ${JSON.stringify(deletedFiles)}`)
|
||||
|
||||
if (
|
||||
inputs.dirNamesDeletedFilesIncludeOnlyDeletedDirs &&
|
||||
inputs.dirNames &&
|
||||
workingDirectory
|
||||
) {
|
||||
const newDeletedFilesPaths: string[] = []
|
||||
for (const deletedPath of getArrayFromPaths(deletedFiles.paths, inputs)) {
|
||||
const dirPath = path.join(workingDirectory, deletedPath)
|
||||
core.debug(`Checking if directory exists: ${dirPath}`)
|
||||
if (!(await exists(dirPath))) {
|
||||
core.debug(`Directory not found: ${dirPath}`)
|
||||
newDeletedFilesPaths.push(deletedPath)
|
||||
}
|
||||
}
|
||||
deletedFiles.paths = inputs.json
|
||||
? newDeletedFilesPaths
|
||||
: newDeletedFilesPaths.join(inputs.separator)
|
||||
deletedFiles.count = newDeletedFilesPaths.length.toString()
|
||||
core.debug(`New deleted files: ${JSON.stringify(deletedFiles)}`)
|
||||
}
|
||||
|
||||
await setOutput({
|
||||
key: getOutputKey('deleted_files', outputPrefix),
|
||||
value: deletedFiles.paths,
|
||||
inputs
|
||||
writeOutputFiles: inputs.writeOutputFiles,
|
||||
outputDir: inputs.outputDir,
|
||||
json: inputs.json,
|
||||
shouldEscape: inputs.escapeJson
|
||||
})
|
||||
|
||||
await setOutput({
|
||||
key: getOutputKey('deleted_files_count', outputPrefix),
|
||||
value: deletedFiles.count,
|
||||
inputs
|
||||
writeOutputFiles: inputs.writeOutputFiles,
|
||||
outputDir: inputs.outputDir
|
||||
})
|
||||
|
||||
await setOutput({
|
||||
key: getOutputKey('any_deleted', outputPrefix),
|
||||
value: deletedFiles.paths.length > 0 && filePatterns.length > 0,
|
||||
inputs
|
||||
writeOutputFiles: inputs.writeOutputFiles,
|
||||
outputDir: inputs.outputDir,
|
||||
json: inputs.json
|
||||
})
|
||||
|
||||
const allOtherDeletedFiles = await getChangeTypeFiles({
|
||||
@@ -358,11 +443,19 @@ export const setChangedFilesOutput = async ({
|
||||
changeTypes: [ChangeTypeEnum.Deleted]
|
||||
})
|
||||
|
||||
const otherDeletedFiles = allOtherDeletedFiles.paths
|
||||
.split(inputs.separator)
|
||||
.filter(
|
||||
filePath => !deletedFiles.paths.split(inputs.separator).includes(filePath)
|
||||
)
|
||||
const allOtherDeletedFilesPaths: string[] = getArrayFromPaths(
|
||||
allOtherDeletedFiles.paths,
|
||||
inputs
|
||||
)
|
||||
|
||||
const deletedFilesPaths: string[] = getArrayFromPaths(
|
||||
deletedFiles.paths,
|
||||
inputs
|
||||
)
|
||||
|
||||
const otherDeletedFiles = allOtherDeletedFilesPaths.filter(
|
||||
filePath => !deletedFilesPaths.includes(filePath)
|
||||
)
|
||||
|
||||
const onlyDeleted =
|
||||
otherDeletedFiles.length === 0 &&
|
||||
@@ -372,18 +465,27 @@ export const setChangedFilesOutput = async ({
|
||||
await setOutput({
|
||||
key: getOutputKey('only_deleted', outputPrefix),
|
||||
value: onlyDeleted,
|
||||
inputs
|
||||
writeOutputFiles: inputs.writeOutputFiles,
|
||||
outputDir: inputs.outputDir,
|
||||
json: inputs.json
|
||||
})
|
||||
|
||||
await setOutput({
|
||||
key: getOutputKey('other_deleted_files', outputPrefix),
|
||||
value: otherDeletedFiles.join(inputs.separator),
|
||||
inputs
|
||||
await setArrayOutput({
|
||||
key: 'other_deleted_files',
|
||||
inputs,
|
||||
value: otherDeletedFiles,
|
||||
outputPrefix
|
||||
})
|
||||
|
||||
await setOutput({
|
||||
key: getOutputKey('other_deleted_files_count', outputPrefix),
|
||||
value: otherDeletedFiles.length.toString(),
|
||||
inputs
|
||||
writeOutputFiles: inputs.writeOutputFiles,
|
||||
outputDir: inputs.outputDir
|
||||
})
|
||||
|
||||
return {
|
||||
anyModified: allModifiedFiles.paths.length > 0 && filePatterns.length > 0,
|
||||
anyChanged: allChangedFiles.paths.length > 0 && filePatterns.length > 0
|
||||
}
|
||||
}
|
||||
|
||||
323
src/commitSha.ts
323
src/commitSha.ts
@@ -1,9 +1,11 @@
|
||||
import * as core from '@actions/core'
|
||||
import * as github from '@actions/github'
|
||||
|
||||
import {Env} from './env'
|
||||
import {Inputs} from './inputs'
|
||||
import {
|
||||
canDiffCommits,
|
||||
getCurrentBranchName,
|
||||
getHeadSha,
|
||||
getParentSha,
|
||||
getPreviousGitTag,
|
||||
@@ -15,11 +17,9 @@ import {
|
||||
} from './utils'
|
||||
|
||||
const getCurrentSHA = async ({
|
||||
env,
|
||||
inputs,
|
||||
workingDirectory
|
||||
}: {
|
||||
env: Env
|
||||
inputs: Inputs
|
||||
workingDirectory: string
|
||||
}): Promise<string> => {
|
||||
@@ -50,14 +50,16 @@ const getCurrentSHA = async ({
|
||||
} else {
|
||||
if (!currentSha) {
|
||||
if (
|
||||
env.GITHUB_EVENT_PULL_REQUEST_HEAD_SHA &&
|
||||
github.context.payload.pull_request?.head?.sha &&
|
||||
(await verifyCommitSha({
|
||||
sha: env.GITHUB_EVENT_PULL_REQUEST_HEAD_SHA,
|
||||
sha: github.context.payload.pull_request?.head?.sha,
|
||||
cwd: workingDirectory,
|
||||
showAsErrorMessage: false
|
||||
})) === 0
|
||||
) {
|
||||
currentSha = env.GITHUB_EVENT_PULL_REQUEST_HEAD_SHA
|
||||
currentSha = github.context.payload.pull_request?.head?.sha
|
||||
} else if (github.context.eventName === 'merge_group') {
|
||||
currentSha = github.context.payload.merge_group?.head_sha
|
||||
} else {
|
||||
currentSha = await getHeadSha({cwd: workingDirectory})
|
||||
}
|
||||
@@ -79,7 +81,7 @@ export interface DiffResult {
|
||||
initialCommit?: boolean
|
||||
}
|
||||
|
||||
export const getSHAForPushEvent = async (
|
||||
export const getSHAForNonPullRequestEvent = async (
|
||||
inputs: Inputs,
|
||||
env: Env,
|
||||
workingDirectory: string,
|
||||
@@ -89,57 +91,89 @@ export const getSHAForPushEvent = async (
|
||||
isTag: boolean
|
||||
): Promise<DiffResult> => {
|
||||
let targetBranch = env.GITHUB_REF_NAME
|
||||
const currentBranch = targetBranch
|
||||
let currentBranch = targetBranch
|
||||
let initialCommit = false
|
||||
|
||||
if (isShallow) {
|
||||
core.info('Repository is shallow, fetching more history...')
|
||||
if (!inputs.skipInitialFetch) {
|
||||
if (isShallow) {
|
||||
core.info('Repository is shallow, fetching more history...')
|
||||
|
||||
if (isTag) {
|
||||
const sourceBranch =
|
||||
env.GITHUB_EVENT_BASE_REF.replace('refs/heads/', '') ||
|
||||
env.GITHUB_EVENT_RELEASE_TARGET_COMMITISH
|
||||
await gitFetch({
|
||||
cwd: workingDirectory,
|
||||
args: [
|
||||
...gitFetchExtraArgs,
|
||||
'-u',
|
||||
'--progress',
|
||||
`--deepen=${inputs.fetchDepth}`,
|
||||
'origin',
|
||||
`+refs/heads/${sourceBranch}:refs/remotes/origin/${sourceBranch}`
|
||||
]
|
||||
})
|
||||
if (isTag) {
|
||||
let sourceBranch = ''
|
||||
|
||||
if (github.context.payload.base_ref) {
|
||||
sourceBranch = github.context.payload.base_ref.replace(
|
||||
'refs/heads/',
|
||||
''
|
||||
)
|
||||
} else if (github.context.payload.release?.target_commitish) {
|
||||
sourceBranch = github.context.payload.release?.target_commitish
|
||||
}
|
||||
|
||||
await gitFetch({
|
||||
cwd: workingDirectory,
|
||||
args: [
|
||||
...gitFetchExtraArgs,
|
||||
'-u',
|
||||
'--progress',
|
||||
`--deepen=${inputs.fetchDepth}`,
|
||||
'origin',
|
||||
`+refs/heads/${sourceBranch}:refs/remotes/origin/${sourceBranch}`
|
||||
]
|
||||
})
|
||||
} else {
|
||||
await gitFetch({
|
||||
cwd: workingDirectory,
|
||||
args: [
|
||||
...gitFetchExtraArgs,
|
||||
'-u',
|
||||
'--progress',
|
||||
`--deepen=${inputs.fetchDepth}`,
|
||||
'origin',
|
||||
`+refs/heads/${targetBranch}:refs/remotes/origin/${targetBranch}`
|
||||
]
|
||||
})
|
||||
}
|
||||
|
||||
if (hasSubmodule) {
|
||||
await gitFetchSubmodules({
|
||||
cwd: workingDirectory,
|
||||
args: [
|
||||
...gitFetchExtraArgs,
|
||||
'-u',
|
||||
'--progress',
|
||||
`--deepen=${inputs.fetchDepth}`
|
||||
]
|
||||
})
|
||||
}
|
||||
} else {
|
||||
await gitFetch({
|
||||
cwd: workingDirectory,
|
||||
args: [
|
||||
...gitFetchExtraArgs,
|
||||
'-u',
|
||||
'--progress',
|
||||
`--deepen=${inputs.fetchDepth}`,
|
||||
'origin',
|
||||
`+refs/heads/${targetBranch}:refs/remotes/origin/${targetBranch}`
|
||||
]
|
||||
})
|
||||
}
|
||||
|
||||
if (hasSubmodule) {
|
||||
await gitFetchSubmodules({
|
||||
cwd: workingDirectory,
|
||||
args: [
|
||||
...gitFetchExtraArgs,
|
||||
'-u',
|
||||
'--progress',
|
||||
`--deepen=${inputs.fetchDepth}`
|
||||
]
|
||||
})
|
||||
if (hasSubmodule && inputs.fetchSubmoduleHistory) {
|
||||
await gitFetchSubmodules({
|
||||
cwd: workingDirectory,
|
||||
args: [
|
||||
...gitFetchExtraArgs,
|
||||
'-u',
|
||||
'--progress',
|
||||
`--deepen=${inputs.fetchDepth}`
|
||||
]
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const currentSha = await getCurrentSHA({env, inputs, workingDirectory})
|
||||
const currentSha = await getCurrentSHA({inputs, workingDirectory})
|
||||
let previousSha = inputs.baseSha
|
||||
const diff = '..'
|
||||
const currentBranchName = await getCurrentBranchName({cwd: workingDirectory})
|
||||
|
||||
if (
|
||||
currentBranchName &&
|
||||
currentBranchName !== 'HEAD' &&
|
||||
(currentBranchName !== targetBranch || currentBranchName !== currentBranch)
|
||||
) {
|
||||
targetBranch = currentBranchName
|
||||
currentBranch = currentBranchName
|
||||
}
|
||||
|
||||
if (previousSha && currentSha && currentBranch && targetBranch) {
|
||||
if (previousSha === currentSha) {
|
||||
@@ -190,9 +224,17 @@ export const getSHAForPushEvent = async (
|
||||
previousSha = sha
|
||||
targetBranch = tag
|
||||
} else {
|
||||
core.debug('Getting previous SHA for last remote commit...')
|
||||
if (env.GITHUB_EVENT_FORCED === 'false' || !env.GITHUB_EVENT_FORCED) {
|
||||
previousSha = env.GITHUB_EVENT_BEFORE
|
||||
if (github.context.eventName === 'merge_group') {
|
||||
core.debug('Getting previous SHA for merge group...')
|
||||
previousSha = github.context.payload.merge_group?.base_sha
|
||||
} else {
|
||||
core.debug('Getting previous SHA for last remote commit...')
|
||||
if (
|
||||
github.context.payload.forced === 'false' ||
|
||||
!github.context.payload.forced
|
||||
) {
|
||||
previousSha = github.context.payload.before
|
||||
}
|
||||
}
|
||||
|
||||
if (
|
||||
@@ -265,61 +307,74 @@ export const getSHAForPullRequestEvent = async (
|
||||
hasSubmodule: boolean,
|
||||
gitFetchExtraArgs: string[]
|
||||
): Promise<DiffResult> => {
|
||||
let targetBranch = env.GITHUB_EVENT_PULL_REQUEST_BASE_REF
|
||||
const currentBranch = env.GITHUB_EVENT_PULL_REQUEST_HEAD_REF
|
||||
let targetBranch = github.context.payload.pull_request?.base?.ref
|
||||
const currentBranch = github.context.payload.pull_request?.head?.ref
|
||||
if (inputs.sinceLastRemoteCommit) {
|
||||
targetBranch = currentBranch
|
||||
}
|
||||
|
||||
if (isShallow) {
|
||||
if (!inputs.skipInitialFetch) {
|
||||
core.info('Repository is shallow, fetching more history...')
|
||||
|
||||
let prFetchExitCode = await gitFetch({
|
||||
cwd: workingDirectory,
|
||||
args: [
|
||||
...gitFetchExtraArgs,
|
||||
'-u',
|
||||
'--progress',
|
||||
'origin',
|
||||
`pull/${env.GITHUB_EVENT_PULL_REQUEST_NUMBER}/head:${currentBranch}`
|
||||
]
|
||||
})
|
||||
|
||||
if (prFetchExitCode !== 0) {
|
||||
prFetchExitCode = await gitFetch({
|
||||
if (isShallow) {
|
||||
let prFetchExitCode = await gitFetch({
|
||||
cwd: workingDirectory,
|
||||
args: [
|
||||
...gitFetchExtraArgs,
|
||||
'-u',
|
||||
'--progress',
|
||||
`--deepen=${inputs.fetchDepth}`,
|
||||
'origin',
|
||||
`+refs/heads/${currentBranch}*:refs/remotes/origin/${currentBranch}*`
|
||||
]
|
||||
})
|
||||
}
|
||||
|
||||
if (prFetchExitCode !== 0) {
|
||||
throw new Error(
|
||||
'Failed to fetch pull request branch. Please ensure "persist-credentials" is set to "true" when checking out the repository. See: https://github.com/actions/checkout#usage'
|
||||
)
|
||||
}
|
||||
|
||||
if (!inputs.sinceLastRemoteCommit) {
|
||||
core.debug('Fetching target branch...')
|
||||
await gitFetch({
|
||||
cwd: workingDirectory,
|
||||
args: [
|
||||
...gitFetchExtraArgs,
|
||||
'-u',
|
||||
'--progress',
|
||||
`--deepen=${inputs.fetchDepth}`,
|
||||
'origin',
|
||||
`+refs/heads/${targetBranch}:refs/remotes/origin/${targetBranch}`
|
||||
`pull/${github.context.payload.pull_request?.number}/head:${currentBranch}`
|
||||
]
|
||||
})
|
||||
|
||||
if (hasSubmodule) {
|
||||
if (prFetchExitCode !== 0) {
|
||||
prFetchExitCode = await gitFetch({
|
||||
cwd: workingDirectory,
|
||||
args: [
|
||||
...gitFetchExtraArgs,
|
||||
'-u',
|
||||
'--progress',
|
||||
`--deepen=${inputs.fetchDepth}`,
|
||||
'origin',
|
||||
`+refs/heads/${currentBranch}*:refs/remotes/origin/${currentBranch}*`
|
||||
]
|
||||
})
|
||||
}
|
||||
|
||||
if (prFetchExitCode !== 0) {
|
||||
throw new Error(
|
||||
'Failed to fetch pull request branch. Please ensure "persist-credentials" is set to "true" when checking out the repository. See: https://github.com/actions/checkout#usage'
|
||||
)
|
||||
}
|
||||
|
||||
if (!inputs.sinceLastRemoteCommit) {
|
||||
core.debug('Fetching target branch...')
|
||||
await gitFetch({
|
||||
cwd: workingDirectory,
|
||||
args: [
|
||||
...gitFetchExtraArgs,
|
||||
'-u',
|
||||
'--progress',
|
||||
`--deepen=${inputs.fetchDepth}`,
|
||||
'origin',
|
||||
`+refs/heads/${targetBranch}:refs/remotes/origin/${targetBranch}`
|
||||
]
|
||||
})
|
||||
|
||||
if (hasSubmodule) {
|
||||
await gitFetchSubmodules({
|
||||
cwd: workingDirectory,
|
||||
args: [
|
||||
...gitFetchExtraArgs,
|
||||
'-u',
|
||||
'--progress',
|
||||
`--deepen=${inputs.fetchDepth}`
|
||||
]
|
||||
})
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (hasSubmodule && inputs.fetchSubmoduleHistory) {
|
||||
await gitFetchSubmodules({
|
||||
cwd: workingDirectory,
|
||||
args: [
|
||||
@@ -334,7 +389,7 @@ export const getSHAForPullRequestEvent = async (
|
||||
core.info('Completed fetching more history.')
|
||||
}
|
||||
|
||||
const currentSha = await getCurrentSHA({env, inputs, workingDirectory})
|
||||
const currentSha = await getCurrentSHA({inputs, workingDirectory})
|
||||
let previousSha = inputs.baseSha
|
||||
let diff = '...'
|
||||
|
||||
@@ -362,44 +417,76 @@ export const getSHAForPullRequestEvent = async (
|
||||
}
|
||||
|
||||
if (
|
||||
!env.GITHUB_EVENT_PULL_REQUEST_BASE_REF ||
|
||||
env.GITHUB_EVENT_HEAD_REPO_FORK === 'true'
|
||||
!github.context.payload.pull_request?.base?.ref ||
|
||||
github.context.payload.head?.repo?.fork === 'true'
|
||||
) {
|
||||
diff = '..'
|
||||
}
|
||||
|
||||
if (!previousSha) {
|
||||
if (inputs.sinceLastRemoteCommit) {
|
||||
previousSha = env.GITHUB_EVENT_BEFORE
|
||||
previousSha = github.context.payload.before
|
||||
|
||||
if (
|
||||
!previousSha ||
|
||||
(previousSha &&
|
||||
(await verifyCommitSha({sha: previousSha, cwd: workingDirectory})) !==
|
||||
0)
|
||||
(await verifyCommitSha({
|
||||
sha: previousSha,
|
||||
cwd: workingDirectory,
|
||||
showAsErrorMessage: false
|
||||
})) !== 0)
|
||||
) {
|
||||
core.warning(
|
||||
'Unable to locate the remote branch head sha. Falling back to the previous commit in the local history.'
|
||||
core.info(
|
||||
`Unable to locate the previous commit in the local history for ${github.context.eventName} (${github.context.payload.action}) event. Falling back to the previous commit in the local history.`
|
||||
)
|
||||
|
||||
previousSha = await getParentSha({
|
||||
cwd: workingDirectory
|
||||
})
|
||||
|
||||
if (!previousSha) {
|
||||
core.warning(
|
||||
'Unable to locate the previous commit in the local history. Falling back to the pull request base sha.'
|
||||
if (
|
||||
github.context.payload.action &&
|
||||
github.context.payload.action === 'synchronize' &&
|
||||
previousSha &&
|
||||
(!previousSha ||
|
||||
(previousSha &&
|
||||
(await verifyCommitSha({
|
||||
sha: previousSha,
|
||||
cwd: workingDirectory,
|
||||
showAsErrorMessage: false
|
||||
})) !== 0))
|
||||
) {
|
||||
throw new Error(
|
||||
'Unable to locate the previous commit in the local history. Please ensure to checkout pull request HEAD commit instead of the merge commit. See: https://github.com/actions/checkout/blob/main/README.md#checkout-pull-request-head-commit-instead-of-merge-commit'
|
||||
)
|
||||
}
|
||||
|
||||
if (
|
||||
!previousSha ||
|
||||
(previousSha &&
|
||||
(await verifyCommitSha({
|
||||
sha: previousSha,
|
||||
cwd: workingDirectory,
|
||||
showAsErrorMessage: false
|
||||
})) !== 0)
|
||||
) {
|
||||
throw new Error(
|
||||
'Unable to locate the previous commit in the local history. Please ensure to checkout pull request HEAD commit instead of the merge commit. See: https://github.com/actions/checkout/blob/main/README.md#checkout-pull-request-head-commit-instead-of-merge-commit'
|
||||
)
|
||||
previousSha = env.GITHUB_EVENT_PULL_REQUEST_BASE_SHA
|
||||
}
|
||||
}
|
||||
} else {
|
||||
previousSha = await getRemoteBranchHeadSha({
|
||||
cwd: workingDirectory,
|
||||
branch: targetBranch
|
||||
})
|
||||
if (github.context.payload.action === 'closed') {
|
||||
previousSha = github.context.payload.pull_request?.base?.sha
|
||||
} else {
|
||||
previousSha = await getRemoteBranchHeadSha({
|
||||
cwd: workingDirectory,
|
||||
branch: targetBranch
|
||||
})
|
||||
|
||||
if (!previousSha) {
|
||||
previousSha = env.GITHUB_EVENT_PULL_REQUEST_BASE_SHA
|
||||
if (!previousSha) {
|
||||
previousSha = github.context.payload.pull_request?.base?.sha
|
||||
}
|
||||
}
|
||||
|
||||
if (isShallow) {
|
||||
@@ -411,7 +498,7 @@ export const getSHAForPullRequestEvent = async (
|
||||
diff
|
||||
}))
|
||||
) {
|
||||
core.debug(
|
||||
core.info(
|
||||
'Merge base is not in the local history, fetching remote target branch...'
|
||||
)
|
||||
|
||||
@@ -439,17 +526,17 @@ export const getSHAForPullRequestEvent = async (
|
||||
break
|
||||
}
|
||||
|
||||
core.debug(
|
||||
core.info(
|
||||
'Merge base is not in the local history, fetching remote target branch again...'
|
||||
)
|
||||
core.debug(`Attempt ${i}/10`)
|
||||
core.info(`Attempt ${i}/10`)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!previousSha || previousSha === currentSha) {
|
||||
previousSha = env.GITHUB_EVENT_PULL_REQUEST_BASE_SHA
|
||||
previousSha = github.context.payload.pull_request?.base?.sha
|
||||
}
|
||||
}
|
||||
|
||||
@@ -475,6 +562,12 @@ export const getSHAForPullRequestEvent = async (
|
||||
diff
|
||||
}))
|
||||
) {
|
||||
core.warning(
|
||||
'If this pull request is from a forked repository, please set the checkout action `repository` input to the same repository as the pull request.'
|
||||
)
|
||||
core.warning(
|
||||
'This can be done by setting actions/checkout `repository` to ${{ github.event.pull_request.head.repo.full_name }}'
|
||||
)
|
||||
throw new Error(
|
||||
`Unable to determine a difference between ${previousSha}${diff}${currentSha}`
|
||||
)
|
||||
@@ -494,7 +587,7 @@ export const getSHAForPullRequestEvent = async (
|
||||
// uses: actions/checkout@v3
|
||||
// with:
|
||||
// repository: ${{ github.event.pull_request.head.repo.full_name }}
|
||||
if (env.GITHUB_EVENT_NAME === 'pull_request_target') {
|
||||
if (github.context.eventName === 'pull_request_target') {
|
||||
core.warning(
|
||||
'If this pull request is from a forked repository, please set the checkout action `repository` input to the same repository as the pull request.'
|
||||
)
|
||||
|
||||
68
src/env.ts
68
src/env.ts
@@ -1,80 +1,16 @@
|
||||
import {promises as fs} from 'fs'
|
||||
import * as core from '@actions/core'
|
||||
|
||||
export type Env = {
|
||||
GITHUB_REF_NAME: string
|
||||
GITHUB_REF: string
|
||||
GITHUB_WORKSPACE: string
|
||||
GITHUB_EVENT_ACTION: string
|
||||
GITHUB_EVENT_NAME: string
|
||||
GITHUB_EVENT_FORCED: string
|
||||
GITHUB_EVENT_BEFORE: string
|
||||
GITHUB_EVENT_BASE_REF: string
|
||||
GITHUB_EVENT_RELEASE_TARGET_COMMITISH: string
|
||||
GITHUB_EVENT_HEAD_REPO_FORK: string
|
||||
GITHUB_EVENT_PULL_REQUEST_NUMBER: string
|
||||
GITHUB_EVENT_PULL_REQUEST_BASE_SHA: string
|
||||
GITHUB_EVENT_PULL_REQUEST_HEAD_SHA: string
|
||||
GITHUB_EVENT_PULL_REQUEST_HEAD_REF: string
|
||||
GITHUB_EVENT_PULL_REQUEST_BASE_REF: string
|
||||
GITHUB_REPOSITORY_OWNER: string
|
||||
GITHUB_REPOSITORY: string
|
||||
}
|
||||
|
||||
type GithubEvent = {
|
||||
action?: string
|
||||
forced?: string
|
||||
pull_request?: {
|
||||
head: {
|
||||
ref: string
|
||||
sha: string
|
||||
}
|
||||
base: {
|
||||
ref: string
|
||||
sha: string
|
||||
}
|
||||
number: string
|
||||
}
|
||||
release?: {
|
||||
target_commitish: string
|
||||
}
|
||||
before?: string
|
||||
base_ref?: string
|
||||
head?: {
|
||||
repo?: {
|
||||
fork: string
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export const getEnv = async (): Promise<Env> => {
|
||||
const eventPath = process.env.GITHUB_EVENT_PATH
|
||||
let eventJson: GithubEvent = {}
|
||||
|
||||
if (eventPath) {
|
||||
eventJson = JSON.parse(await fs.readFile(eventPath, {encoding: 'utf8'}))
|
||||
}
|
||||
core.debug(`Env: ${JSON.stringify(process.env, null, 2)}`)
|
||||
core.debug(`Event: ${JSON.stringify(eventJson, null, 2)}`)
|
||||
core.debug(`Process Env: ${JSON.stringify(process.env, null, 2)}`)
|
||||
|
||||
return {
|
||||
GITHUB_EVENT_PULL_REQUEST_HEAD_REF: eventJson.pull_request?.head?.ref || '',
|
||||
GITHUB_EVENT_PULL_REQUEST_BASE_REF: eventJson.pull_request?.base?.ref || '',
|
||||
GITHUB_EVENT_BEFORE: eventJson.before || '',
|
||||
GITHUB_EVENT_BASE_REF: eventJson.base_ref || '',
|
||||
GITHUB_EVENT_RELEASE_TARGET_COMMITISH:
|
||||
eventJson.release?.target_commitish || '',
|
||||
GITHUB_EVENT_HEAD_REPO_FORK: eventJson.head?.repo?.fork || '',
|
||||
GITHUB_EVENT_PULL_REQUEST_NUMBER: eventJson.pull_request?.number || '',
|
||||
GITHUB_EVENT_PULL_REQUEST_BASE_SHA: eventJson.pull_request?.base?.sha || '',
|
||||
GITHUB_EVENT_PULL_REQUEST_HEAD_SHA: eventJson.pull_request?.head?.sha || '',
|
||||
GITHUB_EVENT_FORCED: eventJson.forced || '',
|
||||
GITHUB_EVENT_ACTION: eventJson.action || '',
|
||||
GITHUB_REF_NAME: process.env.GITHUB_REF_NAME || '',
|
||||
GITHUB_REF: process.env.GITHUB_REF || '',
|
||||
GITHUB_WORKSPACE: process.env.GITHUB_WORKSPACE || '',
|
||||
GITHUB_EVENT_NAME: process.env.GITHUB_EVENT_NAME || '',
|
||||
GITHUB_REPOSITORY_OWNER: process.env.GITHUB_REPOSITORY_OWNER || '',
|
||||
GITHUB_REPOSITORY: process.env.GITHUB_REPOSITORY || ''
|
||||
GITHUB_WORKSPACE: process.env.GITHUB_WORKSPACE || ''
|
||||
}
|
||||
}
|
||||
|
||||
@@ -29,17 +29,28 @@ export type Inputs = {
|
||||
dirNames: boolean
|
||||
dirNamesMaxDepth?: number
|
||||
dirNamesExcludeCurrentDir: boolean
|
||||
dirNamesIncludeFiles: string
|
||||
dirNamesIncludeFilesSeparator: string
|
||||
dirNamesDeletedFilesIncludeOnlyDeletedDirs: boolean
|
||||
json: boolean
|
||||
escapeJson: boolean
|
||||
fetchDepth?: number
|
||||
fetchSubmoduleHistory: boolean
|
||||
sinceLastRemoteCommit: boolean
|
||||
writeOutputFiles: boolean
|
||||
outputDir: string
|
||||
outputRenamedFilesAsDeletedAndAdded: boolean
|
||||
recoverDeletedFiles: boolean
|
||||
recoverDeletedFilesToDestination: string
|
||||
recoverFiles: string
|
||||
recoverFilesSeparator: string
|
||||
recoverFilesIgnore: string
|
||||
recoverFilesIgnoreSeparator: string
|
||||
token: string
|
||||
apiUrl: string
|
||||
skipInitialFetch: boolean
|
||||
failOnInitialDiffError: boolean
|
||||
failOnSubmoduleDiffError: boolean
|
||||
}
|
||||
|
||||
export const getInputs = (): Inputs => {
|
||||
@@ -130,6 +141,16 @@ export const getInputs = (): Inputs => {
|
||||
required: false
|
||||
}
|
||||
)
|
||||
const dirNamesIncludeFiles = core.getInput('dir_names_include_files', {
|
||||
required: false
|
||||
})
|
||||
const dirNamesIncludeFilesSeparator = core.getInput(
|
||||
'dir_names_include_files_separator',
|
||||
{
|
||||
required: false,
|
||||
trimWhitespace: false
|
||||
}
|
||||
)
|
||||
const json = core.getBooleanInput('json', {required: false})
|
||||
const escapeJson = core.getBooleanInput('escape_json', {required: false})
|
||||
const fetchDepth = core.getInput('fetch_depth', {required: false})
|
||||
@@ -152,8 +173,50 @@ export const getInputs = (): Inputs => {
|
||||
'recover_deleted_files_to_destination',
|
||||
{required: false}
|
||||
)
|
||||
const recoverFiles = core.getInput('recover_files', {required: false})
|
||||
const recoverFilesSeparator = core.getInput('recover_files_separator', {
|
||||
required: false,
|
||||
trimWhitespace: false
|
||||
})
|
||||
const recoverFilesIgnore = core.getInput('recover_files_ignore', {
|
||||
required: false
|
||||
})
|
||||
const recoverFilesIgnoreSeparator = core.getInput(
|
||||
'recover_files_ignore_separator',
|
||||
{
|
||||
required: false,
|
||||
trimWhitespace: false
|
||||
}
|
||||
)
|
||||
const token = core.getInput('token', {required: false})
|
||||
const apiUrl = core.getInput('api_url', {required: false})
|
||||
const skipInitialFetch = core.getBooleanInput('skip_initial_fetch', {
|
||||
required: false
|
||||
})
|
||||
const fetchSubmoduleHistory = core.getBooleanInput(
|
||||
'fetch_additional_submodule_history',
|
||||
{
|
||||
required: false
|
||||
}
|
||||
)
|
||||
const failOnInitialDiffError = core.getBooleanInput(
|
||||
'fail_on_initial_diff_error',
|
||||
{
|
||||
required: false
|
||||
}
|
||||
)
|
||||
const failOnSubmoduleDiffError = core.getBooleanInput(
|
||||
'fail_on_submodule_diff_error',
|
||||
{
|
||||
required: false
|
||||
}
|
||||
)
|
||||
const dirNamesDeletedFilesIncludeOnlyDeletedDirs = core.getBooleanInput(
|
||||
'dir_names_deleted_files_include_only_deleted_dirs',
|
||||
{
|
||||
required: false
|
||||
}
|
||||
)
|
||||
|
||||
const inputs: Inputs = {
|
||||
files,
|
||||
@@ -170,6 +233,8 @@ export const getInputs = (): Inputs => {
|
||||
filesIgnoreYaml,
|
||||
filesIgnoreYamlFromSourceFile,
|
||||
filesIgnoreYamlFromSourceFileSeparator,
|
||||
failOnInitialDiffError,
|
||||
failOnSubmoduleDiffError,
|
||||
separator,
|
||||
// Not Supported via REST API
|
||||
sha,
|
||||
@@ -182,12 +247,21 @@ export const getInputs = (): Inputs => {
|
||||
sinceLastRemoteCommit,
|
||||
recoverDeletedFiles,
|
||||
recoverDeletedFilesToDestination,
|
||||
recoverFiles,
|
||||
recoverFilesSeparator,
|
||||
recoverFilesIgnore,
|
||||
recoverFilesIgnoreSeparator,
|
||||
includeAllOldNewRenamedFiles,
|
||||
oldNewSeparator,
|
||||
oldNewFilesSeparator,
|
||||
skipInitialFetch,
|
||||
fetchSubmoduleHistory,
|
||||
dirNamesDeletedFilesIncludeOnlyDeletedDirs,
|
||||
// End Not Supported via REST API
|
||||
dirNames,
|
||||
dirNamesExcludeCurrentDir,
|
||||
dirNamesIncludeFiles,
|
||||
dirNamesIncludeFilesSeparator,
|
||||
json,
|
||||
escapeJson,
|
||||
writeOutputFiles,
|
||||
|
||||
207
src/main.ts
207
src/main.ts
@@ -1,38 +1,46 @@
|
||||
import * as core from '@actions/core'
|
||||
import * as github from '@actions/github'
|
||||
import path from 'path'
|
||||
import {
|
||||
processChangedFiles,
|
||||
ChangeTypeEnum,
|
||||
getAllDiffFiles,
|
||||
getChangedFilesFromGithubAPI,
|
||||
getRenamedFiles
|
||||
} from './changedFiles'
|
||||
import {setChangedFilesOutput} from './changedFilesOutput'
|
||||
import {
|
||||
DiffResult,
|
||||
getSHAForPullRequestEvent,
|
||||
getSHAForPushEvent
|
||||
getSHAForNonPullRequestEvent,
|
||||
getSHAForPullRequestEvent
|
||||
} from './commitSha'
|
||||
import {Env, getEnv} from './env'
|
||||
import {getInputs, Inputs} from './inputs'
|
||||
import {
|
||||
getFilePatterns,
|
||||
getRecoverFilePatterns,
|
||||
getSubmodulePath,
|
||||
getYamlFilePatterns,
|
||||
hasLocalGitDirectory,
|
||||
isRepoShallow,
|
||||
recoverDeletedFiles,
|
||||
setOutput,
|
||||
submoduleExists,
|
||||
updateGitGlobalConfig,
|
||||
verifyMinimumGitVersion
|
||||
} from './utils'
|
||||
|
||||
const getChangedFilesFromLocalGit = async ({
|
||||
const getChangedFilesFromLocalGitHistory = async ({
|
||||
inputs,
|
||||
env,
|
||||
workingDirectory
|
||||
workingDirectory,
|
||||
filePatterns,
|
||||
yamlFilePatterns
|
||||
}: {
|
||||
inputs: Inputs
|
||||
env: Env
|
||||
workingDirectory: string
|
||||
filePatterns: string[]
|
||||
yamlFilePatterns: Record<string, string[]>
|
||||
}): Promise<void> => {
|
||||
await verifyMinimumGitVersion()
|
||||
|
||||
@@ -72,9 +80,9 @@ const getChangedFilesFromLocalGit = async ({
|
||||
|
||||
let diffResult: DiffResult
|
||||
|
||||
if (!env.GITHUB_EVENT_PULL_REQUEST_BASE_REF) {
|
||||
core.info(`Running on a ${env.GITHUB_EVENT_NAME || 'push'} event...`)
|
||||
diffResult = await getSHAForPushEvent(
|
||||
if (!github.context.payload.pull_request?.base?.ref) {
|
||||
core.info(`Running on a ${github.context.eventName || 'push'} event...`)
|
||||
diffResult = await getSHAForNonPullRequestEvent(
|
||||
inputs,
|
||||
env,
|
||||
workingDirectory,
|
||||
@@ -85,8 +93,8 @@ const getChangedFilesFromLocalGit = async ({
|
||||
)
|
||||
} else {
|
||||
core.info(
|
||||
`Running on a ${env.GITHUB_EVENT_NAME || 'pull_request'} (${
|
||||
env.GITHUB_EVENT_ACTION
|
||||
`Running on a ${github.context.eventName || 'pull_request'} (${
|
||||
github.context.payload.action
|
||||
}) event...`
|
||||
)
|
||||
diffResult = await getSHAForPullRequestEvent(
|
||||
@@ -114,65 +122,40 @@ const getChangedFilesFromLocalGit = async ({
|
||||
hasSubmodule,
|
||||
diffResult,
|
||||
submodulePaths,
|
||||
outputRenamedFilesAsDeletedAndAdded
|
||||
outputRenamedFilesAsDeletedAndAdded,
|
||||
fetchSubmoduleHistory: inputs.fetchSubmoduleHistory,
|
||||
failOnInitialDiffError: inputs.failOnInitialDiffError,
|
||||
failOnSubmoduleDiffError: inputs.failOnSubmoduleDiffError
|
||||
})
|
||||
core.debug(`All diff files: ${JSON.stringify(allDiffFiles)}`)
|
||||
core.info('All Done!')
|
||||
core.endGroup()
|
||||
|
||||
const filePatterns = await getFilePatterns({
|
||||
inputs,
|
||||
workingDirectory
|
||||
})
|
||||
core.debug(`File patterns: ${filePatterns}`)
|
||||
if (inputs.recoverDeletedFiles) {
|
||||
let recoverPatterns = getRecoverFilePatterns({inputs})
|
||||
|
||||
if (filePatterns.length > 0) {
|
||||
core.startGroup('changed-files-patterns')
|
||||
await setChangedFilesOutput({
|
||||
allDiffFiles,
|
||||
filePatterns,
|
||||
inputs,
|
||||
workingDirectory,
|
||||
diffResult
|
||||
})
|
||||
core.info('All Done!')
|
||||
core.endGroup()
|
||||
}
|
||||
|
||||
const yamlFilePatterns = await getYamlFilePatterns({
|
||||
inputs,
|
||||
workingDirectory
|
||||
})
|
||||
core.debug(`Yaml file patterns: ${JSON.stringify(yamlFilePatterns)}`)
|
||||
|
||||
if (Object.keys(yamlFilePatterns).length > 0) {
|
||||
for (const key of Object.keys(yamlFilePatterns)) {
|
||||
core.startGroup(`changed-files-yaml-${key}`)
|
||||
await setChangedFilesOutput({
|
||||
allDiffFiles,
|
||||
filePatterns: yamlFilePatterns[key],
|
||||
outputPrefix: key,
|
||||
inputs,
|
||||
workingDirectory,
|
||||
diffResult
|
||||
})
|
||||
core.info('All Done!')
|
||||
core.endGroup()
|
||||
if (recoverPatterns.length > 0 && filePatterns.length > 0) {
|
||||
core.info('No recover patterns found; defaulting to file patterns')
|
||||
recoverPatterns = filePatterns
|
||||
}
|
||||
}
|
||||
|
||||
if (filePatterns.length === 0 && Object.keys(yamlFilePatterns).length === 0) {
|
||||
core.startGroup('changed-files-all')
|
||||
await setChangedFilesOutput({
|
||||
allDiffFiles,
|
||||
await recoverDeletedFiles({
|
||||
inputs,
|
||||
workingDirectory,
|
||||
diffResult
|
||||
deletedFiles: allDiffFiles[ChangeTypeEnum.Deleted],
|
||||
recoverPatterns,
|
||||
sha: diffResult.previousSha
|
||||
})
|
||||
core.info('All Done!')
|
||||
core.endGroup()
|
||||
}
|
||||
|
||||
await processChangedFiles({
|
||||
filePatterns,
|
||||
allDiffFiles,
|
||||
inputs,
|
||||
yamlFilePatterns,
|
||||
workingDirectory
|
||||
})
|
||||
|
||||
if (inputs.includeAllOldNewRenamedFiles) {
|
||||
core.startGroup('changed-files-all-old-new-renamed-files')
|
||||
const allOldNewRenamedFiles = await getRenamedFiles({
|
||||
@@ -186,12 +169,16 @@ const getChangedFilesFromLocalGit = async ({
|
||||
await setOutput({
|
||||
key: 'all_old_new_renamed_files',
|
||||
value: allOldNewRenamedFiles.paths,
|
||||
inputs
|
||||
writeOutputFiles: inputs.writeOutputFiles,
|
||||
outputDir: inputs.outputDir,
|
||||
json: inputs.json
|
||||
})
|
||||
await setOutput({
|
||||
key: 'all_old_new_renamed_files_count',
|
||||
value: allOldNewRenamedFiles.count,
|
||||
inputs
|
||||
writeOutputFiles: inputs.writeOutputFiles,
|
||||
outputDir: inputs.outputDir,
|
||||
json: inputs.json
|
||||
})
|
||||
core.info('All Done!')
|
||||
core.endGroup()
|
||||
@@ -200,69 +187,25 @@ const getChangedFilesFromLocalGit = async ({
|
||||
|
||||
const getChangedFilesFromRESTAPI = async ({
|
||||
inputs,
|
||||
env,
|
||||
workingDirectory
|
||||
filePatterns,
|
||||
yamlFilePatterns
|
||||
}: {
|
||||
inputs: Inputs
|
||||
env: Env
|
||||
workingDirectory: string
|
||||
filePatterns: string[]
|
||||
yamlFilePatterns: Record<string, string[]>
|
||||
}): Promise<void> => {
|
||||
const allDiffFiles = await getChangedFilesFromGithubAPI({
|
||||
inputs,
|
||||
env
|
||||
inputs
|
||||
})
|
||||
core.debug(`All diff files: ${JSON.stringify(allDiffFiles)}`)
|
||||
core.info('All Done!')
|
||||
|
||||
const filePatterns = await getFilePatterns({
|
||||
await processChangedFiles({
|
||||
filePatterns,
|
||||
allDiffFiles,
|
||||
inputs,
|
||||
workingDirectory
|
||||
yamlFilePatterns
|
||||
})
|
||||
core.debug(`File patterns: ${filePatterns}`)
|
||||
|
||||
if (filePatterns.length > 0) {
|
||||
core.startGroup('changed-files-patterns')
|
||||
await setChangedFilesOutput({
|
||||
allDiffFiles,
|
||||
filePatterns,
|
||||
inputs,
|
||||
workingDirectory
|
||||
})
|
||||
core.info('All Done!')
|
||||
core.endGroup()
|
||||
}
|
||||
|
||||
const yamlFilePatterns = await getYamlFilePatterns({
|
||||
inputs,
|
||||
workingDirectory
|
||||
})
|
||||
core.debug(`Yaml file patterns: ${JSON.stringify(yamlFilePatterns)}`)
|
||||
|
||||
if (Object.keys(yamlFilePatterns).length > 0) {
|
||||
for (const key of Object.keys(yamlFilePatterns)) {
|
||||
core.startGroup(`changed-files-yaml-${key}`)
|
||||
await setChangedFilesOutput({
|
||||
allDiffFiles,
|
||||
filePatterns: yamlFilePatterns[key],
|
||||
outputPrefix: key,
|
||||
inputs,
|
||||
workingDirectory
|
||||
})
|
||||
core.info('All Done!')
|
||||
core.endGroup()
|
||||
}
|
||||
}
|
||||
|
||||
if (filePatterns.length === 0 && Object.keys(yamlFilePatterns).length === 0) {
|
||||
core.startGroup('changed-files-all')
|
||||
await setChangedFilesOutput({
|
||||
allDiffFiles,
|
||||
inputs,
|
||||
workingDirectory
|
||||
})
|
||||
core.info('All Done!')
|
||||
core.endGroup()
|
||||
}
|
||||
}
|
||||
|
||||
export async function run(): Promise<void> {
|
||||
@@ -270,17 +213,36 @@ export async function run(): Promise<void> {
|
||||
|
||||
const env = await getEnv()
|
||||
core.debug(`Env: ${JSON.stringify(env, null, 2)}`)
|
||||
|
||||
const inputs = getInputs()
|
||||
core.debug(`Inputs: ${JSON.stringify(inputs, null, 2)}`)
|
||||
|
||||
core.debug(`Github Context: ${JSON.stringify(github.context, null, 2)}`)
|
||||
|
||||
const workingDirectory = path.resolve(
|
||||
env.GITHUB_WORKSPACE || process.cwd(),
|
||||
inputs.path
|
||||
)
|
||||
core.debug(`Working directory: ${workingDirectory}`)
|
||||
|
||||
const hasGitDirectory = await hasLocalGitDirectory({workingDirectory})
|
||||
core.debug(`Has git directory: ${hasGitDirectory}`)
|
||||
|
||||
const filePatterns = await getFilePatterns({
|
||||
inputs,
|
||||
workingDirectory
|
||||
})
|
||||
core.debug(`File patterns: ${filePatterns}`)
|
||||
|
||||
const yamlFilePatterns = await getYamlFilePatterns({
|
||||
inputs,
|
||||
workingDirectory
|
||||
})
|
||||
core.debug(`Yaml file patterns: ${JSON.stringify(yamlFilePatterns)}`)
|
||||
|
||||
if (
|
||||
inputs.token &&
|
||||
env.GITHUB_EVENT_PULL_REQUEST_NUMBER &&
|
||||
github.context.payload.pull_request?.number &&
|
||||
!hasGitDirectory
|
||||
) {
|
||||
core.info("Using GitHub's REST API to get changed files")
|
||||
@@ -292,7 +254,12 @@ export async function run(): Promise<void> {
|
||||
'sinceLastRemoteCommit',
|
||||
'recoverDeletedFiles',
|
||||
'recoverDeletedFilesToDestination',
|
||||
'includeAllOldNewRenamedFiles'
|
||||
'recoverFiles',
|
||||
'recoverFilesIgnore',
|
||||
'includeAllOldNewRenamedFiles',
|
||||
'skipInitialFetch',
|
||||
'fetchSubmoduleHistory',
|
||||
'dirNamesDeletedFilesIncludeOnlyDeletedDirs'
|
||||
]
|
||||
|
||||
for (const input of unsupportedInputs) {
|
||||
@@ -302,7 +269,11 @@ export async function run(): Promise<void> {
|
||||
)
|
||||
}
|
||||
}
|
||||
await getChangedFilesFromRESTAPI({inputs, env, workingDirectory})
|
||||
await getChangedFilesFromRESTAPI({
|
||||
inputs,
|
||||
filePatterns,
|
||||
yamlFilePatterns
|
||||
})
|
||||
} else {
|
||||
if (!hasGitDirectory) {
|
||||
core.setFailed(
|
||||
@@ -312,7 +283,13 @@ export async function run(): Promise<void> {
|
||||
}
|
||||
|
||||
core.info('Using local .git directory')
|
||||
await getChangedFilesFromLocalGit({inputs, env, workingDirectory})
|
||||
await getChangedFilesFromLocalGitHistory({
|
||||
inputs,
|
||||
env,
|
||||
workingDirectory,
|
||||
filePatterns,
|
||||
yamlFilePatterns
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
435
src/utils.ts
435
src/utils.ts
@@ -9,20 +9,22 @@ import * as path from 'path'
|
||||
import {createInterface} from 'readline'
|
||||
import {parseDocument} from 'yaml'
|
||||
import {ChangedFiles, ChangeTypeEnum} from './changedFiles'
|
||||
|
||||
import {Inputs} from './inputs'
|
||||
|
||||
const IS_WINDOWS = process.platform === 'win32'
|
||||
const MINIMUM_GIT_VERSION = '2.18.0'
|
||||
|
||||
export const isWindows = (): boolean => {
|
||||
return process.platform === 'win32'
|
||||
}
|
||||
|
||||
/**
|
||||
* Normalize file path separators to '/' on Windows and Linux/macOS
|
||||
* @param p file path
|
||||
* Normalize file path separators to '/' on Linux/macOS and '\\' on Windows
|
||||
* @param p - file path
|
||||
* @returns file path with normalized separators
|
||||
*/
|
||||
const normalizeSeparators = (p: string): string => {
|
||||
export const normalizeSeparators = (p: string): string => {
|
||||
// Windows
|
||||
if (IS_WINDOWS) {
|
||||
if (isWindows()) {
|
||||
// Convert slashes on Windows
|
||||
p = p.replace(/\//g, '\\')
|
||||
|
||||
@@ -37,7 +39,7 @@ const normalizeSeparators = (p: string): string => {
|
||||
|
||||
/**
|
||||
* Trims unnecessary trailing slash from file path
|
||||
* @param p file path
|
||||
* @param p - file path
|
||||
* @returns file path without unnecessary trailing slash
|
||||
*/
|
||||
const safeTrimTrailingSeparator = (p: string): string => {
|
||||
@@ -60,7 +62,7 @@ const safeTrimTrailingSeparator = (p: string): string => {
|
||||
}
|
||||
|
||||
// On Windows, avoid trimming the drive root, e.g. C:\ or \\hello
|
||||
if (IS_WINDOWS && /^[A-Z]:\\$/i.test(p)) {
|
||||
if (isWindows() && /^[A-Z]:\\$/i.test(p)) {
|
||||
return p
|
||||
}
|
||||
|
||||
@@ -68,12 +70,18 @@ const safeTrimTrailingSeparator = (p: string): string => {
|
||||
return p.substring(0, p.length - 1)
|
||||
}
|
||||
|
||||
const dirname = (p: string): string => {
|
||||
/**
|
||||
* Gets the dirname of a path, similar to the Node.js path.dirname() function except that this function
|
||||
* also works for Windows UNC root paths, e.g. \\hello\world
|
||||
* @param p - file path
|
||||
* @returns dirname of path
|
||||
*/
|
||||
export const getDirname = (p: string): string => {
|
||||
// Normalize slashes and trim unnecessary trailing slash
|
||||
p = safeTrimTrailingSeparator(p)
|
||||
|
||||
// Windows UNC root, e.g. \\hello or \\hello\world
|
||||
if (IS_WINDOWS && /^\\\\[^\\]+(\\[^\\]+)?$/.test(p)) {
|
||||
if (isWindows() && /^\\\\[^\\]+(\\[^\\]+)?$/.test(p)) {
|
||||
return p
|
||||
}
|
||||
|
||||
@@ -81,18 +89,31 @@ const dirname = (p: string): string => {
|
||||
let result = path.dirname(p)
|
||||
|
||||
// Trim trailing slash for Windows UNC root, e.g. \\hello\world\
|
||||
if (IS_WINDOWS && /^\\\\[^\\]+\\[^\\]+\\$/.test(result)) {
|
||||
if (isWindows() && /^\\\\[^\\]+\\[^\\]+\\$/.test(result)) {
|
||||
result = safeTrimTrailingSeparator(result)
|
||||
}
|
||||
|
||||
return result
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts the version string to a number
|
||||
* @param version - version string
|
||||
* @returns version number
|
||||
*/
|
||||
const versionToNumber = (version: string): number => {
|
||||
const [major, minor, patch] = version.split('.').map(Number)
|
||||
return major * 1000000 + minor * 1000 + patch
|
||||
}
|
||||
|
||||
/**
|
||||
* Verifies the minimum required git version
|
||||
* @returns minimum required git version
|
||||
* @throws Minimum git version requirement is not met
|
||||
* @throws Git is not installed
|
||||
* @throws Git is not found in PATH
|
||||
* @throws An unexpected error occurred
|
||||
*/
|
||||
export const verifyMinimumGitVersion = async (): Promise<void> => {
|
||||
const {exitCode, stdout, stderr} = await exec.getExecOutput(
|
||||
'git',
|
||||
@@ -113,7 +134,12 @@ export const verifyMinimumGitVersion = async (): Promise<void> => {
|
||||
}
|
||||
}
|
||||
|
||||
const exists = async (filePath: string): Promise<boolean> => {
|
||||
/**
|
||||
* Checks if a path exists
|
||||
* @param filePath - path to check
|
||||
* @returns path exists
|
||||
*/
|
||||
export const exists = async (filePath: string): Promise<boolean> => {
|
||||
try {
|
||||
await fs.access(filePath)
|
||||
return true
|
||||
@@ -122,6 +148,11 @@ const exists = async (filePath: string): Promise<boolean> => {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Generates lines of a file as an async iterable iterator
|
||||
* @param filePath - path of file to read
|
||||
* @param excludedFiles - whether to exclude files
|
||||
*/
|
||||
async function* lineOfFileGenerator({
|
||||
filePath,
|
||||
excludedFiles
|
||||
@@ -153,6 +184,11 @@ async function* lineOfFileGenerator({
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the file patterns from a source file
|
||||
* @param filePaths - paths of files to read
|
||||
* @param excludedFiles - whether to exclude the file patterns
|
||||
*/
|
||||
const getFilesFromSourceFile = async ({
|
||||
filePaths,
|
||||
excludedFiles = false
|
||||
@@ -169,6 +205,12 @@ const getFilesFromSourceFile = async ({
|
||||
return lines
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the global git configs
|
||||
* @param name - name of config
|
||||
* @param value - value of config
|
||||
* @throws Couldn't update git global config
|
||||
*/
|
||||
export const updateGitGlobalConfig = async ({
|
||||
name,
|
||||
value
|
||||
@@ -191,6 +233,11 @@ export const updateGitGlobalConfig = async ({
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if a git repository is shallow
|
||||
* @param cwd - working directory
|
||||
* @returns repository is shallow
|
||||
*/
|
||||
export const isRepoShallow = async ({cwd}: {cwd: string}): Promise<boolean> => {
|
||||
const {stdout} = await exec.getExecOutput(
|
||||
'git',
|
||||
@@ -204,6 +251,11 @@ export const isRepoShallow = async ({cwd}: {cwd: string}): Promise<boolean> => {
|
||||
return stdout.trim() === 'true'
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if a submodule exists
|
||||
* @param cwd - working directory
|
||||
* @returns submodule exists
|
||||
*/
|
||||
export const submoduleExists = async ({
|
||||
cwd
|
||||
}: {
|
||||
@@ -227,6 +279,11 @@ export const submoduleExists = async ({
|
||||
return stdout.trim() !== ''
|
||||
}
|
||||
|
||||
/**
|
||||
* Fetches the git repository
|
||||
* @param args - arguments for fetch command
|
||||
* @param cwd - working directory
|
||||
*/
|
||||
export const gitFetch = async ({
|
||||
args,
|
||||
cwd
|
||||
@@ -243,6 +300,11 @@ export const gitFetch = async ({
|
||||
return exitCode
|
||||
}
|
||||
|
||||
/**
|
||||
* Fetches the git repository submodules
|
||||
* @param args - arguments for fetch command
|
||||
* @param cwd - working directory
|
||||
*/
|
||||
export const gitFetchSubmodules = async ({
|
||||
args,
|
||||
cwd
|
||||
@@ -266,10 +328,10 @@ export const gitFetchSubmodules = async ({
|
||||
}
|
||||
}
|
||||
|
||||
const normalizePath = (p: string): string => {
|
||||
return p.replace(/\\/g, '/')
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves all the submodule paths
|
||||
* @param cwd - working directory
|
||||
*/
|
||||
export const getSubmodulePath = async ({
|
||||
cwd
|
||||
}: {
|
||||
@@ -293,9 +355,17 @@ export const getSubmodulePath = async ({
|
||||
return stdout
|
||||
.trim()
|
||||
.split('\n')
|
||||
.map((line: string) => normalizePath(line.trim().split(' ')[1]))
|
||||
.map((line: string) => normalizeSeparators(line.trim().split(' ')[1]))
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves commit sha of a submodule from a parent commit
|
||||
* @param cwd - working directory
|
||||
* @param parentSha1 - parent commit sha
|
||||
* @param parentSha2 - parent commit sha
|
||||
* @param submodulePath - path of submodule
|
||||
* @param diff - diff type between parent commits (`..` or `...`)
|
||||
*/
|
||||
export const gitSubmoduleDiffSHA = async ({
|
||||
cwd,
|
||||
parentSha1,
|
||||
@@ -311,7 +381,7 @@ export const gitSubmoduleDiffSHA = async ({
|
||||
}): Promise<{previousSha?: string; currentSha?: string}> => {
|
||||
const {stdout} = await exec.getExecOutput(
|
||||
'git',
|
||||
['diff', parentSha1, parentSha2, '--', submodulePath],
|
||||
['diff', `${parentSha1}${diff}${parentSha2}`, '--', submodulePath],
|
||||
{
|
||||
cwd,
|
||||
silent: !core.isDebug()
|
||||
@@ -398,16 +468,30 @@ export const gitRenamedFiles = async ({
|
||||
core.debug(`Renamed file: ${line}`)
|
||||
const [, oldPath, newPath] = line.split('\t')
|
||||
if (isSubmodule) {
|
||||
return `${normalizePath(
|
||||
return `${normalizeSeparators(
|
||||
path.join(parentDir, oldPath)
|
||||
)}${oldNewSeparator}${normalizePath(path.join(parentDir, newPath))}`
|
||||
)}${oldNewSeparator}${normalizeSeparators(
|
||||
path.join(parentDir, newPath)
|
||||
)}`
|
||||
}
|
||||
return `${normalizePath(oldPath)}${oldNewSeparator}${normalizePath(
|
||||
newPath
|
||||
)}`
|
||||
return `${normalizeSeparators(
|
||||
oldPath
|
||||
)}${oldNewSeparator}${normalizeSeparators(newPath)}`
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves all the changed files between two commits
|
||||
* @param cwd - working directory
|
||||
* @param sha1 - commit sha
|
||||
* @param sha2 - commit sha
|
||||
* @param diff - diff type between parent commits (`..` or `...`)
|
||||
* @param isSubmodule - is the repo a submodule
|
||||
* @param parentDir - parent directory of the submodule
|
||||
* @param outputRenamedFilesAsDeletedAndAdded - output renamed files as deleted and added
|
||||
* @param failOnInitialDiffError - fail if the initial diff fails
|
||||
* @param failOnSubmoduleDiffError - fail if the submodule diff fails
|
||||
*/
|
||||
export const getAllChangedFiles = async ({
|
||||
cwd,
|
||||
sha1,
|
||||
@@ -415,7 +499,9 @@ export const getAllChangedFiles = async ({
|
||||
diff,
|
||||
isSubmodule = false,
|
||||
parentDir = '',
|
||||
outputRenamedFilesAsDeletedAndAdded = false
|
||||
outputRenamedFilesAsDeletedAndAdded = false,
|
||||
failOnInitialDiffError = false,
|
||||
failOnSubmoduleDiffError = false
|
||||
}: {
|
||||
cwd: string
|
||||
sha1: string
|
||||
@@ -424,6 +510,8 @@ export const getAllChangedFiles = async ({
|
||||
isSubmodule?: boolean
|
||||
parentDir?: string
|
||||
outputRenamedFilesAsDeletedAndAdded?: boolean
|
||||
failOnInitialDiffError?: boolean
|
||||
failOnSubmoduleDiffError?: boolean
|
||||
}): Promise<ChangedFiles> => {
|
||||
const {exitCode, stdout, stderr} = await exec.getExecOutput(
|
||||
'git',
|
||||
@@ -451,6 +539,18 @@ export const getAllChangedFiles = async ({
|
||||
[ChangeTypeEnum.Unknown]: []
|
||||
}
|
||||
|
||||
if (exitCode !== 0) {
|
||||
if (failOnInitialDiffError && !isSubmodule) {
|
||||
throw new Error(
|
||||
`Failed to get changed files between: ${sha1}${diff}${sha2}: ${stderr}`
|
||||
)
|
||||
} else if (failOnSubmoduleDiffError && isSubmodule) {
|
||||
throw new Error(
|
||||
`Failed to get changed files for submodule between: ${sha1}${diff}${sha2}: ${stderr}`
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
if (exitCode !== 0) {
|
||||
if (isSubmodule) {
|
||||
core.warning(
|
||||
@@ -474,11 +574,11 @@ export const getAllChangedFiles = async ({
|
||||
for (const line of lines) {
|
||||
const [changeType, filePath, newPath = ''] = line.split('\t')
|
||||
const normalizedFilePath = isSubmodule
|
||||
? normalizePath(path.join(parentDir, filePath))
|
||||
: normalizePath(filePath)
|
||||
? normalizeSeparators(path.join(parentDir, filePath))
|
||||
: normalizeSeparators(filePath)
|
||||
const normalizedNewPath = isSubmodule
|
||||
? normalizePath(path.join(parentDir, newPath))
|
||||
: normalizePath(newPath)
|
||||
? normalizeSeparators(path.join(parentDir, newPath))
|
||||
: normalizeSeparators(newPath)
|
||||
|
||||
if (changeType.startsWith('R')) {
|
||||
if (outputRenamedFilesAsDeletedAndAdded) {
|
||||
@@ -494,6 +594,11 @@ export const getAllChangedFiles = async ({
|
||||
return changedFiles
|
||||
}
|
||||
|
||||
/**
|
||||
* Filters the changed files by the file patterns
|
||||
* @param allDiffFiles - all the changed files
|
||||
* @param filePatterns - file patterns to filter by
|
||||
*/
|
||||
export const getFilteredChangedFiles = async ({
|
||||
allDiffFiles,
|
||||
filePatterns
|
||||
@@ -512,15 +617,16 @@ export const getFilteredChangedFiles = async ({
|
||||
[ChangeTypeEnum.Unknown]: []
|
||||
}
|
||||
const hasFilePatterns = filePatterns.length > 0
|
||||
const isWin = isWindows()
|
||||
|
||||
for (const changeType of Object.keys(allDiffFiles)) {
|
||||
const files = allDiffFiles[changeType as ChangeTypeEnum]
|
||||
if (hasFilePatterns) {
|
||||
changedFiles[changeType as ChangeTypeEnum] = mm(files, filePatterns, {
|
||||
dot: true,
|
||||
windows: IS_WINDOWS,
|
||||
windows: isWin,
|
||||
noext: true
|
||||
})
|
||||
}).map(normalizeSeparators)
|
||||
} else {
|
||||
changedFiles[changeType as ChangeTypeEnum] = files
|
||||
}
|
||||
@@ -590,6 +696,28 @@ export const getRemoteBranchHeadSha = async ({
|
||||
return stdout.trim()
|
||||
}
|
||||
|
||||
export const getCurrentBranchName = async ({
|
||||
cwd
|
||||
}: {
|
||||
cwd: string
|
||||
}): Promise<string> => {
|
||||
const {stdout, exitCode} = await exec.getExecOutput(
|
||||
'git',
|
||||
['rev-parse', '--abbrev-ref', 'HEAD'],
|
||||
{
|
||||
cwd,
|
||||
ignoreReturnCode: true,
|
||||
silent: !core.isDebug()
|
||||
}
|
||||
)
|
||||
|
||||
if (exitCode !== 0) {
|
||||
return ''
|
||||
}
|
||||
|
||||
return stdout.trim()
|
||||
}
|
||||
|
||||
export const getParentSha = async ({cwd}: {cwd: string}): Promise<string> => {
|
||||
const {stdout, exitCode} = await exec.getExecOutput(
|
||||
'git',
|
||||
@@ -650,7 +778,7 @@ export const getPreviousGitTag = async ({
|
||||
}): Promise<{tag: string; sha: string}> => {
|
||||
const {stdout} = await exec.getExecOutput(
|
||||
'git',
|
||||
['tag', '--sort=-version:refname'],
|
||||
['tag', '--sort=-creatordate'],
|
||||
{
|
||||
cwd,
|
||||
silent: !core.isDebug()
|
||||
@@ -691,9 +819,58 @@ export const canDiffCommits = async ({
|
||||
sha2: string
|
||||
diff: string
|
||||
}): Promise<boolean> => {
|
||||
const {exitCode, stderr} = await exec.getExecOutput(
|
||||
if (diff === '...') {
|
||||
const mergeBase = await getMergeBase(cwd, sha1, sha2)
|
||||
|
||||
if (!mergeBase) {
|
||||
core.warning(`Unable to find merge base between ${sha1} and ${sha2}`)
|
||||
return false
|
||||
}
|
||||
|
||||
const {exitCode, stderr} = await exec.getExecOutput(
|
||||
'git',
|
||||
['log', '--format=%H', `${mergeBase}..${sha2}`],
|
||||
{
|
||||
cwd,
|
||||
ignoreReturnCode: true,
|
||||
silent: !core.isDebug()
|
||||
}
|
||||
)
|
||||
|
||||
if (exitCode !== 0) {
|
||||
core.warning(stderr || `Error checking commit history`)
|
||||
return false
|
||||
}
|
||||
|
||||
return true
|
||||
} else {
|
||||
const {exitCode, stderr} = await exec.getExecOutput(
|
||||
'git',
|
||||
['diff', '--quiet', sha1, sha2],
|
||||
{
|
||||
cwd,
|
||||
ignoreReturnCode: true,
|
||||
silent: !core.isDebug()
|
||||
}
|
||||
)
|
||||
|
||||
if (exitCode !== 0) {
|
||||
core.warning(stderr || `Error checking commit history`)
|
||||
return false
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
const getMergeBase = async (
|
||||
cwd: string,
|
||||
sha1: string,
|
||||
sha2: string
|
||||
): Promise<string | null> => {
|
||||
const {exitCode, stdout} = await exec.getExecOutput(
|
||||
'git',
|
||||
['diff', '--name-only', '--ignore-submodules=all', `${sha1}${diff}${sha2}`],
|
||||
['merge-base', sha1, sha2],
|
||||
{
|
||||
cwd,
|
||||
ignoreReturnCode: true,
|
||||
@@ -702,23 +879,22 @@ export const canDiffCommits = async ({
|
||||
)
|
||||
|
||||
if (exitCode !== 0) {
|
||||
core.warning(stderr || `Unable find merge base between ${sha1} and ${sha2}`)
|
||||
return false
|
||||
return null
|
||||
}
|
||||
|
||||
return true
|
||||
return stdout.trim()
|
||||
}
|
||||
|
||||
export const getDirnameMaxDepth = ({
|
||||
pathStr,
|
||||
relativePath,
|
||||
dirNamesMaxDepth,
|
||||
excludeCurrentDir
|
||||
}: {
|
||||
pathStr: string
|
||||
relativePath: string
|
||||
dirNamesMaxDepth?: number
|
||||
excludeCurrentDir?: boolean
|
||||
}): string => {
|
||||
const pathArr = dirname(pathStr).split(path.sep)
|
||||
const pathArr = getDirname(relativePath).split(path.sep)
|
||||
const maxDepth = Math.min(dirNamesMaxDepth || pathArr.length, pathArr.length)
|
||||
let output = pathArr[0]
|
||||
|
||||
@@ -730,14 +906,14 @@ export const getDirnameMaxDepth = ({
|
||||
return ''
|
||||
}
|
||||
|
||||
return normalizePath(output)
|
||||
return normalizeSeparators(output)
|
||||
}
|
||||
|
||||
export const jsonOutput = ({
|
||||
value,
|
||||
shouldEscape
|
||||
}: {
|
||||
value: string | string[]
|
||||
value: string | string[] | boolean
|
||||
shouldEscape: boolean
|
||||
}): string => {
|
||||
const result = JSON.stringify(value)
|
||||
@@ -745,6 +921,16 @@ export const jsonOutput = ({
|
||||
return shouldEscape ? result.replace(/"/g, '\\"') : result
|
||||
}
|
||||
|
||||
export const getDirNamesIncludeFilesPattern = ({
|
||||
inputs
|
||||
}: {
|
||||
inputs: Inputs
|
||||
}): string[] => {
|
||||
return inputs.dirNamesIncludeFiles
|
||||
.split(inputs.dirNamesIncludeFilesSeparator)
|
||||
.filter(Boolean)
|
||||
}
|
||||
|
||||
export const getFilePatterns = async ({
|
||||
inputs,
|
||||
workingDirectory
|
||||
@@ -754,7 +940,7 @@ export const getFilePatterns = async ({
|
||||
}): Promise<string[]> => {
|
||||
let filePatterns = inputs.files
|
||||
.split(inputs.filesSeparator)
|
||||
.filter(p => p !== '')
|
||||
.filter(Boolean)
|
||||
.join('\n')
|
||||
|
||||
if (inputs.filesFromSourceFile !== '') {
|
||||
@@ -815,30 +1001,14 @@ export const getFilePatterns = async ({
|
||||
filePatterns = filePatterns.concat('\n', filesIgnoreFromSourceFiles)
|
||||
}
|
||||
|
||||
if (IS_WINDOWS) {
|
||||
if (isWindows()) {
|
||||
filePatterns = filePatterns.replace(/\r\n/g, '\n')
|
||||
filePatterns = filePatterns.replace(/\r/g, '\n')
|
||||
}
|
||||
|
||||
core.debug(`file patterns: ${filePatterns}`)
|
||||
core.debug(`Input file patterns: ${filePatterns}`)
|
||||
|
||||
return filePatterns
|
||||
.trim()
|
||||
.split('\n')
|
||||
.filter(Boolean)
|
||||
.map(pattern => {
|
||||
if (pattern.endsWith('/')) {
|
||||
return `${pattern}**`
|
||||
} else {
|
||||
const pathParts = pattern.split(path.sep)
|
||||
const lastPart = pathParts[pathParts.length - 1]
|
||||
if (!lastPart.includes('.')) {
|
||||
return `${pattern}${path.sep}**`
|
||||
} else {
|
||||
return pattern
|
||||
}
|
||||
}
|
||||
})
|
||||
return filePatterns.trim().split('\n').filter(Boolean)
|
||||
}
|
||||
|
||||
// Example YAML input:
|
||||
@@ -893,17 +1063,17 @@ const getYamlFilePatternsFromContents = async ({
|
||||
|
||||
if (doc.errors.length > 0) {
|
||||
if (filePath) {
|
||||
core.warning(`YAML errors in ${filePath}: ${doc.errors}`)
|
||||
throw new Error(`YAML errors in ${filePath}: ${doc.errors}`)
|
||||
} else {
|
||||
core.warning(`YAML errors: ${doc.errors}`)
|
||||
throw new Error(`YAML errors: ${doc.errors}`)
|
||||
}
|
||||
}
|
||||
|
||||
if (doc.warnings.length > 0) {
|
||||
if (filePath) {
|
||||
core.warning(`YAML warnings in ${filePath}: ${doc.warnings}`)
|
||||
throw new Error(`YAML warnings in ${filePath}: ${doc.warnings}`)
|
||||
} else {
|
||||
core.warning(`YAML warnings: ${doc.warnings}`)
|
||||
throw new Error(`YAML warnings: ${doc.warnings}`)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1028,21 +1198,88 @@ export const getYamlFilePatterns = async ({
|
||||
return filePatterns
|
||||
}
|
||||
|
||||
export const getRecoverFilePatterns = ({
|
||||
inputs
|
||||
}: {
|
||||
inputs: Inputs
|
||||
}): string[] => {
|
||||
let filePatterns: string[] = inputs.recoverFiles.split(
|
||||
inputs.recoverFilesSeparator
|
||||
)
|
||||
|
||||
if (inputs.recoverFilesIgnore) {
|
||||
const ignoreFilePatterns = inputs.recoverFilesIgnore.split(
|
||||
inputs.recoverFilesSeparator
|
||||
)
|
||||
|
||||
filePatterns = filePatterns.concat(
|
||||
ignoreFilePatterns.map(p => {
|
||||
if (p.startsWith('!')) {
|
||||
return p
|
||||
} else {
|
||||
return `!${p}`
|
||||
}
|
||||
})
|
||||
)
|
||||
}
|
||||
|
||||
core.debug(`recover file patterns: ${filePatterns}`)
|
||||
|
||||
return filePatterns.filter(Boolean)
|
||||
}
|
||||
|
||||
export const getOutputKey = (key: string, outputPrefix: string): string => {
|
||||
return outputPrefix ? `${outputPrefix}_${key}` : key
|
||||
}
|
||||
|
||||
export const setArrayOutput = async ({
|
||||
key,
|
||||
inputs,
|
||||
value,
|
||||
outputPrefix
|
||||
}: {
|
||||
key: string
|
||||
inputs: Inputs
|
||||
value: string[]
|
||||
outputPrefix?: string
|
||||
}): Promise<void> => {
|
||||
core.debug(`${key}: ${JSON.stringify(value)}`)
|
||||
await setOutput({
|
||||
key: outputPrefix ? getOutputKey(key, outputPrefix) : key,
|
||||
value: inputs.json ? value : value.join(inputs.separator),
|
||||
writeOutputFiles: inputs.writeOutputFiles,
|
||||
outputDir: inputs.outputDir,
|
||||
json: inputs.json,
|
||||
shouldEscape: inputs.escapeJson
|
||||
})
|
||||
}
|
||||
|
||||
export const setOutput = async ({
|
||||
key,
|
||||
value,
|
||||
inputs
|
||||
writeOutputFiles,
|
||||
outputDir,
|
||||
json = false,
|
||||
shouldEscape = false
|
||||
}: {
|
||||
key: string
|
||||
value: string | boolean
|
||||
inputs: Inputs
|
||||
value: string | string[] | boolean
|
||||
writeOutputFiles: boolean
|
||||
outputDir: string
|
||||
json?: boolean
|
||||
shouldEscape?: boolean
|
||||
}): Promise<void> => {
|
||||
const cleanedValue = value.toString().trim()
|
||||
let cleanedValue
|
||||
if (json) {
|
||||
cleanedValue = jsonOutput({value, shouldEscape})
|
||||
} else {
|
||||
cleanedValue = value.toString().trim()
|
||||
}
|
||||
|
||||
core.setOutput(key, cleanedValue)
|
||||
|
||||
if (inputs.writeOutputFiles) {
|
||||
const outputDir = inputs.outputDir
|
||||
const extension = inputs.json ? 'json' : 'txt'
|
||||
if (writeOutputFiles) {
|
||||
const extension = json ? 'json' : 'txt'
|
||||
const outputFilePath = path.join(outputDir, `${key}.${extension}`)
|
||||
|
||||
if (!(await exists(outputDir))) {
|
||||
@@ -1084,36 +1321,48 @@ export const recoverDeletedFiles = async ({
|
||||
inputs,
|
||||
workingDirectory,
|
||||
deletedFiles,
|
||||
recoverPatterns,
|
||||
sha
|
||||
}: {
|
||||
inputs: Inputs
|
||||
workingDirectory: string
|
||||
deletedFiles: string[]
|
||||
recoverPatterns: string[]
|
||||
sha: string
|
||||
}): Promise<void> => {
|
||||
if (inputs.recoverDeletedFiles) {
|
||||
for (const deletedFile of deletedFiles) {
|
||||
let target = path.join(workingDirectory, deletedFile)
|
||||
let recoverableDeletedFiles = deletedFiles
|
||||
core.debug(`recoverable deleted files: ${recoverableDeletedFiles}`)
|
||||
|
||||
if (inputs.recoverDeletedFilesToDestination) {
|
||||
target = path.join(
|
||||
workingDirectory,
|
||||
inputs.recoverDeletedFilesToDestination,
|
||||
deletedFile
|
||||
)
|
||||
}
|
||||
if (recoverPatterns.length > 0) {
|
||||
recoverableDeletedFiles = mm(deletedFiles, recoverPatterns, {
|
||||
dot: true,
|
||||
windows: isWindows(),
|
||||
noext: true
|
||||
})
|
||||
core.debug(`filtered recoverable deleted files: ${recoverableDeletedFiles}`)
|
||||
}
|
||||
|
||||
const deletedFileContents = await getDeletedFileContents({
|
||||
cwd: workingDirectory,
|
||||
filePath: deletedFile,
|
||||
sha
|
||||
})
|
||||
for (const deletedFile of recoverableDeletedFiles) {
|
||||
let target = path.join(workingDirectory, deletedFile)
|
||||
|
||||
if (!(await exists(path.dirname(target)))) {
|
||||
await fs.mkdir(path.dirname(target), {recursive: true})
|
||||
}
|
||||
await fs.writeFile(target, deletedFileContents)
|
||||
if (inputs.recoverDeletedFilesToDestination) {
|
||||
target = path.join(
|
||||
workingDirectory,
|
||||
inputs.recoverDeletedFilesToDestination,
|
||||
deletedFile
|
||||
)
|
||||
}
|
||||
|
||||
const deletedFileContents = await getDeletedFileContents({
|
||||
cwd: workingDirectory,
|
||||
filePath: deletedFile,
|
||||
sha
|
||||
})
|
||||
|
||||
if (!(await exists(path.dirname(target)))) {
|
||||
await fs.mkdir(path.dirname(target), {recursive: true})
|
||||
}
|
||||
await fs.writeFile(target, deletedFileContents)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1122,9 +1371,7 @@ export const hasLocalGitDirectory = async ({
|
||||
}: {
|
||||
workingDirectory: string
|
||||
}): Promise<boolean> => {
|
||||
const insideWorkTree = await isInsideWorkTree({
|
||||
return await isInsideWorkTree({
|
||||
cwd: workingDirectory
|
||||
})
|
||||
|
||||
return insideWorkTree
|
||||
}
|
||||
|
||||
Submodule test/demo updated: 83ccca9b63...5dfac2e9a7
Reference in New Issue
Block a user