Repository navigation
Expand file tree
/
Copy pathaction.yml
More file actions
78 lines (71 loc) · 3.59 KB
/
Copy pathaction.yml
File metadata and controls
78 lines (71 loc) · 3.59 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
name: 'Create Milestone'
description: >
Creates a milestone with the given title in the specified repository if one
does not already exist.
inputs:
repo:
description: 'Full repository path (e.g. spring-cloud/spring-cloud-config-commercial)'
required: true
version:
description: 'Milestone title / version string (e.g. 5.0.2.1)'
required: true
token:
description: 'GitHub token with repository write access'
required: true
runs:
using: composite
steps:
- name: Create milestone if missing
shell: bash
env:
GH_TOKEN: ${{ inputs.token }}
run: |
set -uo pipefail
repo="${{ inputs.repo }}"
version="${{ inputs.version }}"
echo "Checking for milestone '${version}' in ${repo}..."
# state=all and --paginate, both load-bearing. Milestone titles are not unique, so
# missing an existing one here creates a duplicate - and the default state=open on
# a single unpaginated page misses two different ways: a closed milestone with this
# title, and, in the repositories past a hundred milestones, anything after page
# one. The list comes back sorted by due date ascending, so the newest go last.
#
# The listing is captured and its exit status checked before anything is created.
# Piping it straight into jq made a failed lookup - a rate limit, a 5xx, a token
# that cannot read the repository - indistinguishable from "no such milestone",
# and the only way this action can produce a duplicate is by creating one while
# blind. A lookup that did not succeed fails the step instead.
if ! listing=$(gh api --paginate "repos/${repo}/milestones?state=all&per_page=100"); then
echo "::error::create-milestone: could not list the milestones of ${repo}, so it is not"
echo "::error::possible to tell whether '${version}' already exists. Nothing was created."
exit 1
fi
# Titles are compared trimmed: a title that differs from the requested version only
# by surrounding whitespace is the same milestone to a human, and creating a second
# one is not what anybody wants.
if ! matches=$(printf '%s' "$listing" \
| jq -r -s --arg title "$version" \
'add // [] | .[] | select((.title | gsub("^\\s+|\\s+$"; "")) == ($title | gsub("^\\s+|\\s+$"; ""))) | .number'); then
echo "::error::create-milestone: could not parse the milestone listing for ${repo}."
echo "::error::Nothing was created."
exit 1
fi
milestone_number=$(printf '%s' "$matches" | head -n 1)
if [[ -n "$milestone_number" ]]; then
count=$(printf '%s' "$matches" | grep -c . || true)
if [[ "$count" -gt 1 ]]; then
# Nothing here can safely merge them, but silently picking one hides a problem
# that only ever gets worse as issues are filed against both.
echo "::warning::create-milestone: ${repo} already has ${count} milestones titled '${version}' (#$(printf '%s' "$matches" | tr '\n' ' ')). Nothing was created; merge them by hand."
fi
echo "Milestone '${version}' already exists (#${milestone_number})."
else
echo "Milestone '${version}' not found — creating..."
if ! gh api "repos/${repo}/milestones" \
--method POST \
--field title="$version"; then
echo "::error::create-milestone: could not create milestone '${version}' in ${repo}."
exit 1
fi
echo "Milestone '${version}' created in ${repo}."
fi