-
Notifications
You must be signed in to change notification settings - Fork 1
169 lines (160 loc) · 7.24 KB
/
Copy pathupdate-readme.yml
File metadata and controls
169 lines (160 loc) · 7.24 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
# Update README.md + composer.lock (v4)
#
# Previous (v3): ran on every push to main regardless of whether composer.lock
# changed, and wget'd update-readme.sh from the v3 branch at run time.
#
# Next (v4): the script is bundled in the update-readme composite action.
# Callers should gate this workflow on composer.lock actually changing, e.g.:
# if: contains(toJSON(github.event.commits.*.modified), 'composer.lock')
#
# v4.4: also re-syncs composer.lock before regenerating the README. release-please
# bumps the `version` field in composer.json on every release PR without touching
# the lock, so `composer validate` fails on the release branch (and every branch
# cut from it) until someone re-locks by hand. Running `composer update --lock`
# here keeps the release PR's lock valid; the README table is then generated from
# the fresh lock. The sync is best-effort: if resolution fails (e.g. private
# repositories needing auth this workflow doesn't have), the lock is left
# untouched and only the README updates, exactly as before.
#
# v4.5: merges the PR it opens. Until now this workflow created the README PR and
# stopped, and nothing downstream merged it — so the refresh sat open indefinitely
# while release-please merged its release PR into main without it. The visible
# symptom is a README whose version is current but whose "Latest Release" date and
# plugin table are stale by however long the PR has been sitting: release-please
# writes the version straight into README.md via its `extra-files` config, so that
# one field lands on main regardless, while the date and plugin list — both
# produced here — never do. On linchpin.com the README PR had been open for ~3
# weeks and the date was a full release behind.
#
# Merging here rather than in a separate `pull_request_target` workflow avoids a
# race (the PR number is known directly from create-pull-request's output, so
# there is nothing to poll for or re-discover) and means consumers do not each
# need to carry their own auto-merge workflow. Set `automerge: false` to restore
# the old open-and-stop behavior.
name: Update README.md
on:
workflow_call:
inputs:
base:
description: "Where the branch is based from. Typically release please"
required: false
default: "release-please--branches--main"
type: string
branch:
description: "What branch do we create when updating the readme"
required: false
default: "release-please--branches--main--readme"
type: string
automerge:
description: >-
Squash-merge the README PR into `base` once it is mergeable. Defaults to
true — an unmerged README refresh is never the desired end state, since
the whole point is for it to ride along with the release PR. Set false
to open the PR and leave it for a human.
required: false
default: true
type: boolean
secrets:
GH_BOT_TOKEN:
description: "Token used to open the README update PR"
required: true
permissions:
contents: write
pull-requests: write
jobs:
update-readme:
name: Update Readme
runs-on: ubuntu-latest
timeout-minutes: 5
steps:
# Checkout just the files the steps read/write
- name: Checkout code
uses: actions/checkout@v6
with:
ref: ${{ inputs.base }}
sparse-checkout: |
README.md
composer.json
composer.lock
sparse-checkout-cone-mode: false
# Best-effort: a failed resolution (network, private repos needing auth)
# must not break the README update, so restore the lock and continue.
- name: Sync composer.lock with composer.json
run: |
if [ ! -f composer.json ] || [ ! -f composer.lock ]; then
echo "No composer.json/composer.lock — skipping lock sync"
exit 0
fi
if composer update --lock --no-install --no-scripts --no-plugins --no-audit --no-interaction; then
echo "composer.lock is in sync with composer.json"
else
echo "::warning::composer update --lock failed; leaving composer.lock unchanged"
git checkout -- composer.lock
fi
- name: Update README.md from composer.lock
uses: linchpin/actions/actions/update-readme@v4
- name: Commit changes to README.md and composer.lock
id: commit_changes
run: |
git config --local user.email "linchpin-bot@github.com"
git config --local user.name "Linchpin Bot"
git add README.md composer.lock
if git diff --cached --quiet; then
echo "No changes to commit"
echo "skip_pr=true" >> "$GITHUB_OUTPUT"
else
git commit -m "Update README.md plugin list and sync composer.lock"
echo "skip_pr=false" >> "$GITHUB_OUTPUT"
fi
- name: Create or Update Pull Request
id: cpr
if: ${{ steps.commit_changes.outputs.skip_pr == 'false' }}
uses: peter-evans/create-pull-request@v8
with:
commit-message: "[automated] Update Plugin List / composer.lock"
title: "[Maintenance] Update README.md plugin list & sync composer.lock"
body: "Automated update of the README plugin/theme table and composer.lock re-sync (release-please bumps composer.json's version field without regenerating the lock, which breaks `composer validate` until re-locked)."
base: ${{ inputs.base }}
branch: ${{ inputs.branch }}
labels: |
wordpress
automated pr
maintenance
token: ${{ secrets.GH_BOT_TOKEN }}
# Without this the PR just accumulates. See the v4.5 note at the top.
#
# GitHub computes mergeability asynchronously, so a freshly-opened PR reports
# UNKNOWN for a moment — poll until it settles rather than failing on the
# first read. A DIRTY (conflicted) PR is left open on purpose: that means the
# base moved in a way this workflow should not silently resolve.
- name: Squash-merge the README PR
if: ${{ inputs.automerge && steps.commit_changes.outputs.skip_pr == 'false' && steps.cpr.outputs.pull-request-number != '' }}
env:
GH_TOKEN: ${{ secrets.GH_BOT_TOKEN }}
PR_NUMBER: ${{ steps.cpr.outputs.pull-request-number }}
GH_REPO: ${{ github.repository }}
run: |
set -uo pipefail
for i in $(seq 1 10); do
state="$(gh pr view "$PR_NUMBER" --json mergeable,state \
--jq '.mergeable + "/" + .state')"
echo "Attempt $i: $state"
case "$state" in
MERGEABLE/OPEN)
gh pr merge "$PR_NUMBER" --squash
echo "Merged README PR #$PR_NUMBER into ${{ inputs.base }}."
exit 0
;;
*/MERGED|*/CLOSED)
echo "PR #$PR_NUMBER is already ${state#*/}; nothing to do."
exit 0
;;
CONFLICTING/*)
echo "::warning::README PR #$PR_NUMBER is conflicted; leaving it open for a human."
exit 0
;;
esac
sleep 6
done
echo "::error::README PR #$PR_NUMBER never became MERGEABLE after 10 attempts."
exit 1