forked from empydoodle/action-artifacts
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathaction.yml
More file actions
231 lines (202 loc) · 7.66 KB
/
action.yml
File metadata and controls
231 lines (202 loc) · 7.66 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
name: Doodle Artifacts
description: 'List, search for and delete GitHub artifacts by repository'
branding:
icon: package
color: green
inputs:
github_token:
description: 'GitHub token (e.g. secrets.GITHUB_TOKEN)'
required: true
repo:
description: 'Target repository (i.e. owner/repo)'
required: true
method:
description: 'Method to use (list, search, delete)'
required: true
search_name:
description: 'Name (not ID) of the artifact to search / delete'
default: ''
required: false
action_fail_on_list_mismatch:
description: "Fail the action if the populated artifact list size does not equal the size reported by GitHub API"
default: 'false'
required: false
action_fail_on_empty_search:
description: 'Fail the action if no artifacts are found in search'
default: 'false'
required: false
action_fail_on_delete_error:
description: 'Fail the action if a delete operation fails'
default: 'false'
required: false
outputs:
no_artifacts:
description: 'Number of artifacts in repository (as reported by GitHub API)'
value: ${{ steps.check.outputs.no_artifacts }}
artifacts:
description: 'Full list of repo artifacts JSON objects (JSON array)'
value: ${{ steps.list.outputs.artifacts }}
search_results:
description: 'List of artifacts matching the search criteria (JSON array)'
value: ${{ steps.search.outputs.results }}
delete_results:
description: 'List of artifacts deleted by the action (JSON array)'
value: ${{ steps.delete.outputs.results }}
runs:
using: composite
steps:
- name: Check connection and artifact count
id: check
shell: bash
env:
GH_TOKEN: ${{ inputs.github_token }}
repo: ${{ inputs.repo }}
run: |
# Check total number of artifacts in repo + validate GitHub API connection
# Get response + HTTP code
gh api -i -X GET \
-H "Accept: application/vnd.github+json" \
"/repos/${repo}/actions/artifacts?per_page=1" \
> response.txt
readarray -t check <<< $(cat response.txt)
# Validate HTTP code, exit if not 200
if [[ ! "${check[0]}" =~ ("200 OK"$) ]]; then
echo "Error calling GitHub API!"
echo "Response:"
cat response.txt
exit 1
fi
# Extract artifact count
no_artifacts=$(echo "${check[-1]}" | jq -r '.total_count')
echo "Found $no_artifacts artifact(s)!"
# Set output
echo "no_artifacts=$no_artifacts" >> $GITHUB_OUTPUT
# Cleanup
rm response.txt
unset check
- name: Fetch all artifacts
id: list
shell: bash
env:
GH_TOKEN: ${{ inputs.github_token }}
repo: ${{ inputs.repo }}
no_artifacts: ${{ steps.check.outputs.no_artifacts }}
page_size: 100
mismatch_fail: ${{ inputs.action_fail_on_list_mismatch }}
run: |
# Fetch all artifacts in repo
# Set placeholder file
echo '[]' > artifacts_list.json
# Calculate how many pages we need to iterate through
pages=$(expr 1 + $(expr $no_artifacts / $page_size))
echo "Iterating through $pages page(s)..."
# Iterate through each page, save array of artifacts to file
for page in $(seq 1 $pages); do
# Fetch page via API and save response
readarray -t response <<< $(gh api -i -X GET \
-H "Accept: application/vnd.github+json" \
"/repos/${repo}/actions/artifacts?per_page=${page_size}&page=${page}")
# Extract artifacts array from response
page_list=$(echo "${response[-1]}" | jq -rc '.artifacts')
# Add to full list file
echo "$(cat artifacts_list.json | jq -rc --argjson list "$page_list" '. += $list | flatten')" > artifacts_list.json
unset response
done
echo "... done!"
# Verify the number of fetched artifacts matches what GitHub says
list_size=$(cat artifacts_list.json | jq 'length')
if [[ "$list_size" -eq "$no_artifacts" ]]; then
echo "Fetched all artifacts!"
else
echo "Artifact list mismatch!" >&2
echo "- Found $list_size artifacts but GitHub reports $no_artifacts artifacts." >&2
if [[ "$mismatch_fail" == "true" ]]; then
exit 1
fi
fi
# Set output
echo "artifacts=$(cat artifacts_list.json | jq -rc)" >> $GITHUB_OUTPUT
- name: Search artifacts
id: search
if: contains(fromJson('["search", "delete"]'), inputs.method) && inputs.search_name != ''
shell: bash
env:
search_query: ${{ inputs.search_name }}
no_results_fail: ${{ inputs.action_fail_on_empty_search }}
run: |
# Extract target artifact(s) to results file
echo "$(cat artifacts_list.json | jq -rc --arg q "$search_query" 'map(select(.name | test($q)))')" > artifacts_search.json
# Validate and report result
search_count=$(cat artifacts_search.json | jq -r 'length')
if [[ "$search_count" -gt 0 ]]; then
echo "Found $search_count artifacts(s) matching the search criteria! (Search regex: $search_query)"
else
echo "No artifacts found! (Search regex: $search_query)"
if [[ "$no_results_fail" == "true" ]]; then
exit 1
fi
fi
# Set output
echo "results=$(cat artifacts_search.json | jq -rc)" >> $GITHUB_OUTPUT
- name: Delete artifacts
id: delete
if: contains(fromJson('["delete"]'), inputs.method) && steps.search.outputs.results != '[]'
shell: bash
env:
GH_TOKEN: ${{ inputs.github_token }}
repo: ${{ inputs.repo }}
no_delete_fail: ${{ inputs.action_fail_on_delete_error }}
run: |
# Delete artifacts
results="[]"
for artifact in $(cat artifacts_search.json | jq -rc '.[]'); do
id=$(echo "$artifact" | jq -r '.id')
name=$(echo "$artifact" | jq -r '.name')
echo "Deleting artifact: $name (ID: $id)..."
# Call GitHub API to delete artifact
gh api -i -X DELETE \
-H "Accept: application/vnd.github+json" \
/repos/$repo/actions/artifacts/$id \
> $id.txt
readarray -t response <<< $(cat $id.txt)
# Validate HTTP code
if [[ "${response[0]}" =~ ("200 OK"|"204 No Content"$) ]]; then
# Artifact deleted successfully
result=true
else
echo " Error calling GitHub API!"
echo " Response:"
cat $id.txt
result=false
if [[ "$no_delete_fail" == "true" ]]; then
exit 1
fi
fi
# Add result to output array
results=$(echo "$results" | jq -c \
--arg id "$id" \
--arg name "$name" \
--argjson result "$result" \
'. + [{
"name": $name,
"id": $id,
"deleted": $result
}]'
)
# Cleanup
rm $id.txt
unset id name response result
echo "... done."
done
# Set output
echo "results=$(echo $results | jq -c)" >> $GITHUB_OUTPUT
echo "$results" > artifacts_delete.json
# Report results
total=$(echo "$results" | jq -r 'length')
success=$(echo "$results" | jq -r 'map(select(.deleted == true)) | length')
echo "Successfully deleted $success/$total artifacts!"
- name: Cleanup files
if: always() && inputs.cleanup_files == 'true'
shell: bash
run: |
rm -f artifacts_list.json artifacts_search.json artifacts_delete.json