-
Notifications
You must be signed in to change notification settings - Fork 621
143 lines (129 loc) · 5.97 KB
/
Copy pathdocs-pr-sync.yml
File metadata and controls
143 lines (129 loc) · 5.97 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
# .github/workflows/docs-pr-sync.yml
#
# Place this file in:
# mattermost/docs -> .github/workflows/docs-pr-sync.yml
#
# Authentication — dedicated "Changelog Automation PRs r+w" GitHub App:
#
# vars.CHANGELOG_PR_CLIENT_ID - Client ID of the PR sync GitHub App
# secrets.CHANGELOG_PR_PRIVATE_KEY - Private key of the PR sync GitHub App
#
# The app has pull-requests: write and is installed on:
# mattermost/mattermost, mattermost/mattermost-mobile,
# mattermost/desktop, mattermost/docs
# This allows the bot to remove Docs/Needed and add Docs/Done on the
# original dev PR when a docs PR is closed.
# Short-lived installation tokens are generated automatically per run.
#
# Behaviour:
# When a docs/mattermost-pr-* or docs/desktop-pr-* PR is closed
# (merged OR abandoned), parses the dev PR reference from the branch name
# and updates labels on the original dev PR:
# Removes Docs/Needed
# Adds Docs/Done
name: "Docs PR Sync - Update Dev PR Labels on Close"
on:
pull_request:
types: [closed]
workflow_dispatch:
inputs:
branch_name:
description: 'Docs branch name to simulate closing (e.g. docs/mattermost-pr-1234)'
required: true
type: string
jobs:
sync-labels:
name: "Remove Docs/Needed, Add Docs/Done on dev PR"
runs-on: ubuntu-latest
permissions:
pull-requests: read
# Branch name encodes the source repo - only run for branches created by
# docs-needed.yml. Fork guard prevents runs on PRs from external forks.
# workflow_dispatch bypasses both guards for manual testing.
if: |
github.event_name == 'workflow_dispatch' ||
(startsWith(github.event.pull_request.head.ref, 'docs/') &&
github.event.pull_request.head.repo.full_name == github.repository)
steps:
# 0. Generate a short-lived write token scoped to the three engineering
# repos. Uses the shared changelog write app so the token is not tied
# to any individual user account and expires automatically after 1 hour.
- name: Generate write token
id: token
uses: actions/create-github-app-token@bcd2ba49218906704ab6c1aa796996da409d3eb1 # v3.2.0
with:
client-id: ${{ vars.CHANGELOG_PR_CLIENT_ID }}
private-key: ${{ secrets.CHANGELOG_PR_PRIVATE_KEY }}
repositories: >-
mattermost,
mattermost-mobile,
desktop
# 1. Parse dev PR reference from branch name
# Branch format: docs/<repo-name>-pr-<number>
# e.g. docs/mattermost-pr-1234 -> mattermost/mattermost#1234
# docs/mattermost-mobile-pr-99 -> mattermost/mattermost-mobile#99
# docs/desktop-pr-7 -> mattermost/desktop#7
- name: Parse dev PR reference
id: parse
env:
HEAD_REF: ${{ github.event_name == 'workflow_dispatch' && inputs.branch_name || github.event.pull_request.head.ref }}
run: |
# Accept only: docs/(mattermost|mattermost-mobile|desktop)-pr-<number>
if ! [[ "$HEAD_REF" =~ ^docs/(mattermost|mattermost-mobile|desktop)-pr-([0-9]+)$ ]]; then
echo "::error::Could not parse repo name and PR number from branch '$HEAD_REF'."
exit 1
fi
REPO_NAME="${BASH_REMATCH[1]}"
PR_NUMBER="${BASH_REMATCH[2]}"
FULL_REPO="mattermost/${REPO_NAME}"
echo "repo_name=$REPO_NAME" >> "$GITHUB_OUTPUT"
echo "full_repo=$FULL_REPO" >> "$GITHUB_OUTPUT"
echo "pr_number=$PR_NUMBER" >> "$GITHUB_OUTPUT"
echo "Dev PR resolved to: ${FULL_REPO}#${PR_NUMBER}"
# 2. Update labels on the dev PR
# Docs/Done is applied whether the docs PR was merged OR closed without
# merging. An abandoned docs PR means the developer is handling docs
# another way, or the feature was reverted; leaving Docs/Needed on the
# dev PR indefinitely is worse. Docs/Needed can be re-applied if new
# documentation is still required.
- name: Update labels
env:
GH_TOKEN: ${{ steps.token.outputs.token }}
DEV_REPO: ${{ steps.parse.outputs.full_repo }}
DEV_PR: ${{ steps.parse.outputs.pr_number }}
DOCS_PR_MERGED: ${{ github.event.pull_request.merged }}
run: |
echo "Updating labels on ${DEV_REPO}#${DEV_PR}..."
# Remove Docs/Needed (soft-fail - label may already be absent)
if gh pr edit "$DEV_PR" --repo "$DEV_REPO" \
--remove-label "Docs/Needed" 2>/dev/null; then
echo " Removed Docs/Needed"
else
echo " Docs/Needed not present or could not be removed - continuing"
fi
# Add Docs/Done (hard-fail - this must succeed)
# Applied for both merged and closed-without-merging; see comment above.
gh pr edit "$DEV_PR" --repo "$DEV_REPO" --add-label "Docs/Done"
echo " Added Docs/Done"
# 3. Comment on the dev PR
# Skipped for workflow_dispatch: there is no real docs PR being closed,
# so github.event.pull_request.number is empty and the link would be broken.
- name: Comment on dev PR
if: github.event_name != 'workflow_dispatch'
env:
GH_TOKEN: ${{ steps.token.outputs.token }}
DEV_REPO: ${{ steps.parse.outputs.full_repo }}
DEV_PR: ${{ steps.parse.outputs.pr_number }}
DOCS_PR_NUMBER: ${{ github.event.pull_request.number }}
DOCS_PR_MERGED: ${{ github.event.pull_request.merged || 'false' }}
run: |
if [ "$DOCS_PR_MERGED" == "true" ]; then
STATUS="merged"
else
STATUS="closed without merging"
fi
DOCS_LINK="[mattermost/docs#${DOCS_PR_NUMBER}]"
DOCS_LINK="${DOCS_LINK}(https://github.com/mattermost/docs/pull/${DOCS_PR_NUMBER})"
gh pr comment "$DEV_PR" \
--repo "$DEV_REPO" \
--body "The associated docs PR ${DOCS_LINK} has been **${STATUS}**. Label updated: Docs/Needed -> Docs/Done."