-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathaction.yml
157 lines (128 loc) · 6.46 KB
/
action.yml
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
name: Cascading Merge
description: Creates or updates a pull request to merge the current branch into the next one in alphabetic order.
inputs:
branch_prefix:
description: >
Prefix of branches to consider when triggering the workflow or looking for the next branch to cascade to.
default: 'maintenance/mps'
required: false
exclude_branch_prefix:
description: Prefix of branches to exclude from consideration.
required: false
merge_prefix:
description: >
Prefix to use for merge branches created by the workflow. `branch_prefix` will be stripped before prepending
the given prefix.
default: 'merge/mps'
required: false
default_merge_prefix:
description: Prefix to use for merge branch for merging to the default branch.
default: 'merge/'
required: false
update_from_base:
description: >
Whether to update the merge branch from the base branch, as may be required by branch protection rules.
default: 'false'
required: false
token:
description: >
GitHub token to use for repository operations. If not specified, the repository token will be used and operations
performed by the action will not trigger any workflows. In particular, pull request checks will not run for PRs
created or updated by the action.
required: false
outputs:
pr_number:
description: "Number of the pull request for the merge created or updated by the action"
value: ${{ steps.create-pr.outputs.pr_number }}
pr_url:
description: "URL of the pull request for the merge created or updated by the action"
value: ${{ steps.create-pr.outputs.pr_url }}
runs:
using: composite
steps:
- id: create-pr
name: Create PR for new changes in ${{ github.ref_name }}
shell: bash
env:
GH_TOKEN: ${{ inputs.token || github.token }}
owner_and_repo: ${{ github.repository }}
branch_prefix: ${{ inputs.branch_prefix }}
default_merge_prefix: ${{ inputs.default_merge_prefix }}
merge_prefix: ${{ inputs.merge_prefix }}
update_from_base: ${{ inputs.update_from_base }}
default_branch: ${{ github.event.repository.default_branch }}
run: |
jq_expr='.[] | .ref | ltrimstr("refs/heads/") | select(. > "'$GITHUB_REF_NAME'")'
if [[ -n '${{ inputs.exclude_branch_prefix }}' ]]
then
jq_expr+=' | select(startswith("${{ inputs.exclude_branch_prefix }}") | not)'
fi
jq_expr='['$jq_expr'] | min'
echo "Calculating PR branches:"
# Next branch matching refs/heads/${{ inputs.branch_prefix}}, or empty if we're on the last one
next_maintenance_branch=$(gh api "/repos/$owner_and_repo/git/matching-refs/heads/${{ inputs.branch_prefix }}" \
--jq "$jq_expr")
echo " Next maintenance branch: ${next_maintenance_branch:-(none)}"
# Substitute the default branch if empty
base_branch=${next_maintenance_branch:-$default_branch}
echo " PR base branch: $base_branch"
# Calculate PR head branch name (the branch to merge) by substituting 'maintenance' with 'merge'
head_branch="$GITHUB_REF_NAME"
if [[ "$base_branch" == "$default_branch" ]]
then
merge_branch="$default_merge_prefix$default_branch"
else
merge_branch=${base_branch/#$branch_prefix/$merge_prefix}
fi
echo " Merge branch (will be used as PR head): $merge_branch"
echo ""
echo "Pushing $GITHUB_REF_NAME to $merge_branch"
# Create or update $merge_branch
if gh api repos/$owner_and_repo/git/ref/heads/$merge_branch --silent
then
# Branch exists, merge $head_branch into it:
# First, try fast-forwarding
echo "Updating $merge_branch to SHA $GITHUB_SHA"
gh api repos/$owner_and_repo/git/refs/heads/$merge_branch --silent --method=PATCH -f sha="$GITHUB_SHA" \
-F force=false ||
# If that failed, try merging
(echo "Update failed, trying to merge $head_branch into $merge_branch" ;
gh api repos/$owner_and_repo/merges --silent --method=POST -f base=$merge_branch -f head=$head_branch) ||
# If that failed, report an error
(echo "Merging $head_branch to existing $merge_branch failed, aborting." ; exit 1)
else
# Branch does not exist, create it from $head_branch
gh api repos/$owner_and_repo/git/refs --silent --method=POST -f ref="refs/heads/$merge_branch" -f sha="$GITHUB_SHA" ||
(echo "Could not create merge branch $merge_branch" ; exit 1)
fi
# Update $base_branch from $base_branch, if requested
if [[ "$update_from_base" == true ]]
then
# The head and base arguments are intentionally reversed because this is a reverse merge.
gh api repos/$owner_and_repo/merges --silent --method=POST -f base=$merge_branch -f head=$base_branch ||
echo "Updating $merge_branch from $base_branch failed, please do it manually."
fi
# Create PR if it does not exist yet
read -r pr_number pr_url < <(gh pr list --repo $owner_and_repo --head $merge_branch --base $base_branch \
--json number,url --jq 'map(.number, .url) | join(" ")')
if [[ $pr_number ]]
then
echo "Found existing PR #$pr_number for $merge_branch -> $base_branch ($pr_url)"
echo "Requesting review on PR #$pr_number from $GITHUB_ACTOR"
gh api repos/$owner_and_repo/pulls/$pr_number/requested_reviewers \
--silent --method=POST -f "reviewers[]=$GITHUB_ACTOR" || true
echo "Assigning PR #$pr_number to $GITHUB_ACTOR"
gh api repos/$owner_and_repo/issues/$pr_number/assignees \
--silent --method=POST -f "assignees[]=$GITHUB_ACTOR" || true
else
echo "Creating a new pull request $merge_branch -> $base_branch"
gh pr create --repo $owner_and_repo --head $merge_branch --base $base_branch \
--title "Merge $GITHUB_REF_NAME into $base_branch" \
--body "Merge changes from \`$GITHUB_REF_NAME\` to \`$base_branch\`." \
--assignee "$GITHUB_ACTOR" \
--reviewer "$GITHUB_ACTOR"
read -r pr_number pr_url < <(gh pr list --repo $owner_and_repo --head $merge_branch --base $base_branch \
--json number,url --jq 'map(.number, .url) | join(" ")')
fi
echo "pr_number=$pr_number" >> $GITHUB_OUTPUT
echo "pr_url=$pr_url" >> $GITHUB_OUTPUT