-
Notifications
You must be signed in to change notification settings - Fork 334
183 lines (165 loc) · 8.85 KB
/
port-pr.yaml
File metadata and controls
183 lines (165 loc) · 8.85 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
name: Port PR
on:
issue_comment:
types:
- created
jobs:
port-pr:
permissions:
pull-requests: write
contents: write
actions: write
id-token: write
runs-on: ubuntu-latest
if: (startsWith(github.event.comment.body, '/backport') || startsWith(github.event.comment.body, '/forwardport')) && github.event.issue.pull_request
steps:
- name: Read secrets
uses: rancher-eio/read-vault-secrets@0da85151ad1f19ed7986c41587e45aac1ace74b6 # v3
with:
secrets: |
secret/data/github/repo/${{ github.repository }}/github/app-credentials appId | APPID;
secret/data/github/repo/${{ github.repository }}/github/app-credentials privateKey | PRIVATEKEY
- name: Generate Token
id: generate-token
uses: actions/create-github-app-token@1b10c78c7865c340bc4f6099eb2f838309f1e8c3 # v3.1.1
with:
app-id: ${{ env.APPID }}
private-key: ${{ env.PRIVATEKEY }}
- name: Check org membership
env:
APP_TOKEN: ${{ steps.generate-token.outputs.token }}
GH_TOKEN: ${{ steps.generate-token.outputs.token }}
run: |
if gh api orgs/${GITHUB_REPOSITORY_OWNER}/members --paginate | jq -e --arg GITHUB_ACTOR "$GITHUB_ACTOR" '.[] | select(.login == $GITHUB_ACTOR)' > /dev/null; then
echo "${GITHUB_ACTOR} is a member"
echo "is_member=true" >> $GITHUB_ENV
else
echo "${GITHUB_ACTOR} is not a member" >> $GITHUB_STEP_SUMMARY
echo "is_member=false" >> $GITHUB_ENV
fi
- name: Check milestone
if: ${{ env.is_member == 'true' }}
env:
APP_TOKEN: ${{ steps.generate-token.outputs.token }}
GH_TOKEN: ${{ steps.generate-token.outputs.token }}
ORIGINAL_ISSUE_NUMBER: ${{ github.event.issue.number }}
COMMENT_BODY: ${{ github.event.comment.body }}
run: |
BODY_MILESTONE=$(echo "${COMMENT_BODY}" | awk '{ print $2 }')
# Sanitize input
MILESTONE=${BODY_MILESTONE//[^a-zA-Z0-9\-\.]/}
if gh api repos/${GITHUB_REPOSITORY}/milestones --paginate | jq -e --arg MILESTONE "$MILESTONE" '.[] | select(.title == $MILESTONE)' > /dev/null; then
echo "Milestone exists"
echo "milestone_exists=true" >> $GITHUB_ENV
echo "milestone=${MILESTONE}" >> $GITHUB_ENV
else
echo "Milestone ${MILESTONE} does not exist" >> $GITHUB_STEP_SUMMARY
gh issue comment -R ${GITHUB_REPOSITORY} ${ORIGINAL_ISSUE_NUMBER} --body "Not creating port issue, milestone ${MILESTONE} does not exist or is not an open milestone"
echo "milestone_exists=false" >> $GITHUB_ENV
fi
- name: Get target branch
if: ${{ env.is_member == 'true' }} && ${{ env.milestone_exists == 'true' }}
env:
APP_TOKEN: ${{ steps.generate-token.outputs.token }}
GH_TOKEN: ${{ steps.generate-token.outputs.token }}
COMMENT_BODY: ${{ github.event.comment.body }}
run: |
TYPE=$(echo "${COMMENT_BODY}" | awk '{ print $1 }' | sed -e 's_/__')
echo "Type: ${TYPE}" >> $GITHUB_STEP_SUMMARY
echo "type=${TYPE}" >> $GITHUB_ENV
TARGET_BRANCH=$(echo "${COMMENT_BODY}" | awk '{ print $3 }')
echo "Target branch: ${TARGET_BRANCH}" >> $GITHUB_STEP_SUMMARY
echo "target_branch=${TARGET_BRANCH}" >> $GITHUB_ENV
ISSUE_NUMBER=$(echo "${COMMENT_BODY}" | awk '{ print $4 }' | sed -e 's/#//')
echo "Issue number: ${ISSUE_NUMBER}" >> $GITHUB_STEP_SUMMARY
echo "issue_number=${ISSUE_NUMBER}" >> $GITHUB_ENV
if gh api repos/${GITHUB_REPOSITORY}/branches --paginate | jq -e --arg TARGET_BRANCH "$TARGET_BRANCH" '.[] | select(.name == $TARGET_BRANCH)' > /dev/null; then
echo "target_branch_exists=true" >> $GITHUB_ENV
else
echo "target_branch_exists=false" >> $GITHUB_ENV
fi
- name: Checkout
if: ${{ env.is_member == 'true' }} && ${{ env.milestone_exists == 'true' }} && ${{ env.target_branch_exists == 'true' }}
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
with:
ref: ${{ env.target_branch }}
fetch-depth: '0'
token: ${{ steps.generate-token.outputs.token }}
- name: Port PR
if: ${{ env.is_member == 'true' }} && ${{ env.milestone_exists == 'true' }} && ${{ env.target_branch_exists == 'true' }}
env:
APP_TOKEN: ${{ steps.generate-token.outputs.token }}
GH_TOKEN: ${{ steps.generate-token.outputs.token }}
ORIGINAL_ISSUE_NUMBER: ${{ github.event.issue.number }}
TYPE: ${{ env.type }}
TARGET_BRANCH: ${{ env.target_branch }}
MILESTONE: ${{ env.milestone }}
ISSUE_NUMBER: ${{ env.issue_number }}
run: |
echo "Starting Port PR step..."
echo "Original Issue Number: ${ORIGINAL_ISSUE_NUMBER}"
echo "Type: ${TYPE}"
echo "Target Branch: ${TARGET_BRANCH}"
echo "Target Issue Number: ${ISSUE_NUMBER}"
echo "Milestone: ${MILESTONE}"
PATCH_FILE=$(mktemp)
echo "Created temporary patch file: ${PATCH_FILE}"
gh pr diff $ORIGINAL_ISSUE_NUMBER --patch > $PATCH_FILE
echo "Downloaded patch for PR ${ORIGINAL_ISSUE_NUMBER}"
BRANCH="gha-portpr-${GITHUB_RUN_ID}-${GITHUB_RUN_ATTEMPT}"
echo "Creating new branch: ${BRANCH}"
echo "branch=${BRANCH}" >> $GITHUB_ENV
git config --global user.email "41898282+github-actions[bot]@users.noreply.github.com"
git config --global user.name "github-actions[bot]"
echo "Configured git user"
git checkout -b $BRANCH
echo "Checked out new branch: ${BRANCH}"
if ! git am -3 "$PATCH_FILE" > error.log 2>&1; then
echo "Failed to apply patch"
ERROR_MESSAGE=$(cat error.log)
FORMATTED_ERROR_MESSAGE=$(printf "\n\`\`\`\n%s\n\`\`\`" "$ERROR_MESSAGE")
echo "Error message: ${FORMATTED_ERROR_MESSAGE}"
gh issue comment ${ORIGINAL_ISSUE_NUMBER} --body "Not creating port PR, there was an error running git am -3: $FORMATTED_ERROR_MESSAGE"
else
echo "Patch applied successfully"
git push origin $BRANCH
echo "Pushed new branch to origin"
ORIGINAL_PR=$(gh pr view ${ORIGINAL_ISSUE_NUMBER} --json title,body,assignees)
ORIGINAL_TITLE=$(echo "${ORIGINAL_PR}" | jq -r .title)
ORIGINAL_ASSIGNEE=$(echo "${ORIGINAL_PR}" | jq -r '.assignee.login // empty')
echo "Original PR Title: ${ORIGINAL_TITLE}"
echo "Original PR Assignee: ${ORIGINAL_ASSIGNEE}"
BODY=$(mktemp)
echo "Created temporary body file: ${BODY}"
echo -e "This is an automated request to port PR #${ORIGINAL_ISSUE_NUMBER} by @${GITHUB_ACTOR}\n\n" > $BODY
echo -e "Original PR body:\n\n" >> $BODY
CLEANED_BODY=$(echo "${ORIGINAL_PR}" | jq -r .body | sed -E 's@(close|closes|closed|fix|fixes|fixed|resolve|resolves|resolved):?\s+([a-zA-Z0-9.-]+/[a-zA-Z0-9.-]*)?#[0-9]+\s*,?\s*@Original text redacted by port-pr.yaml @gI')
echo "${CLEANED_BODY}" >> $BODY
if [ -n "$ISSUE_NUMBER" ]; then
echo -e "\n\nFixes #${ISSUE_NUMBER}" >> $BODY
fi
ASSIGNEES=$(echo "${ORIGINAL_PR}" | jq -r .assignees[].login)
echo "Original PR Assignees: ${ASSIGNEES}"
if [ -n "$ASSIGNEES" ]; then
echo "Checking if assignee is member before assigning"
DELIMITER=""
NEW_ASSIGNEES=""
for ASSIGNEE in $ASSIGNEES; do
if gh api orgs/${GITHUB_REPOSITORY_OWNER}/members --paginate | jq -e --arg GITHUB_ACTOR "$GITHUB_ACTOR" '.[] | select(.login == $GITHUB_ACTOR)' > /dev/null; then
echo "${ASSIGNEE} is a member, adding to assignees"
NEW_ASSIGNEES="${NEW_ASSIGNEES}${DELIMITER}${ASSIGNEE}"
DELIMITER=","
else
echo "${ASSIGNEE} is not a member, skipping"
fi
done
if [ -n "$NEW_ASSIGNEES" ]; then
echo "Assignees for new issue: ${NEW_ASSIGNEES}"
additional_cmd+=("--assignee")
additional_cmd+=("${NEW_ASSIGNEES}")
fi
fi
NEW_PR=$(gh pr create --title="[${TYPE} ${MILESTONE}] ${ORIGINAL_TITLE}" --body-file="${BODY}" --head "${BRANCH}" --base "${TARGET_BRANCH}" --milestone "${MILESTONE}" "${additional_cmd[@]}")
echo "Port PR created: ${NEW_PR}"
echo "Port PR created: ${NEW_PR}" >> $GITHUB_STEP_SUMMARY
fi