-
Notifications
You must be signed in to change notification settings - Fork 11
202 lines (174 loc) · 8.98 KB
/
create-release-pr.yaml
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
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
name: Create or update release PR
on:
pull_request:
types: [edited]
branches:
- main
push:
branches:
- develop
jobs:
create-release-pr:
name: Create or update release PR
runs-on: ubuntu-latest
steps:
- name: Save branch name output
shell: bash
run: echo "branchName=${GITHUB_HEAD_REF:-${GITHUB_REF#refs/heads/}}" >> $GITHUB_OUTPUT
id: current-branch-name
- name: Create release PR or get existing PR ID
id: get-pr
uses: actions/github-script@v5
with:
github-token: ${{secrets.GITHUB_TOKEN}}
script: |
/* We already have the id if this is a PR edit event: */
const editedIdMatch = context.ref.match(/^refs\/pull\/(\d+)\//);
const editedId = editedIdMatch ? editedIdMatch[1] : null;
if (editedId) {
return editedId;
}
const owner = context.repo.owner;
const repo = context.repo.repo;
const triggeringRefHead = context.ref.split('/').pop();
const base = "main";
const { data: prs } = await github.rest.pulls.list({
owner,
repo,
});
let pr = prs.find((pr) => {
return pr.head.ref === triggeringRefHead && pr.base.ref === base;
});
if (!pr) {
const { data: latestCommit } = await github.rest.repos.getCommit({
owner,
repo,
ref: triggeringRefHead,
});
const result = await github.rest.pulls.create({
owner,
repo,
head: triggeringRefHead,
base,
title: latestCommit.commit.message.replace(/\sGitOrigin-RevId.*/, ""),
body: "If this change should result in new package versions please add a changeset before merging. You can do so by clicking the link provided by changeset bot below."
});
pr = result.data;
}
return pr.number;
- name: "Checkout"
uses: "actions/checkout@v3"
with:
fetch-depth: 0
- name: Create main branch
run: "git branch --track main origin/main"
- name: Setup node
uses: "actions/setup-node@v3"
with:
node-version-file: ".nvmrc"
- name: yarn install with cache
uses: ./.github/actions/yarn-nm-install
with:
cwd: "."
# Lock file differences shouldn't matter for these jobs and it's difficult to
# sync up with the test-release-sync workflow (which actually needs the lock
# to be updated and runs at the same time)
install-mode: "install-allow-lock-update"
- name: Run changeset
id: changeset
run: |
echo "$(node ./.github/workflows/runChangeset.mjs | grep changeset)" >> $GITHUB_OUTPUT
- name: List changed packages
run: |
echo "${{ steps.changeset.outputs.changeset }}"
- name: Get PR comment vars
id: pr-comment-vars
run: |
echo "lastCommit=$(git rev-parse --short HEAD)" >> $GITHUB_OUTPUT
- name: Update or post comment on PR with link to create changeset
id: pr-comment
uses: actions/github-script@v5
with:
github-token: ${{secrets.GITHUB_TOKEN}}
script: |
const owner = context.repo.owner;
const repo = context.repo.repo;
const base = "main";
let pr;
/* We already have the id if this is a PR edit event: */
const editedIdMatch = context.ref.match(/^refs\/pull\/(\d+)\//);
const editedId = editedIdMatch ? editedIdMatch[1] : null;
if (editedId) {
const prRequest = await github.rest.pulls.get({
owner,
repo,
pull_number: editedId,
});
pr = prRequest.data;
} else {
const triggeringRefHead = context.ref.split('/').pop();
const { data: prs } = await github.rest.pulls.list({
owner,
repo,
});
pr = prs.find((pr) => {
return pr.head.ref === triggeringRefHead && pr.base.ref === base;
});
if (!pr) {
const { data: latestCommit } = await github.rest.repos.getCommit({
owner,
repo,
ref: triggeringRefHead,
});
const result = await github.rest.pulls.create({
owner,
repo,
head: triggeringRefHead,
base,
title: latestCommit.commit.message.replace(/\sGitOrigin-RevId.*/, "").substring(0, 30),
body: "If this change should result in new package versions please add a changeset before merging. You can do so by clicking the maintainers link provided by changeset-bot below.\n\nPlease note that changeset-bot appears to produce inconsistent / incorrect results with the latest version of changesets when run locally. Be sure to check that it is correctly mentioning the changed packages in the referenced link, or produce the changeset locally `yarn changeset` and push it to the branch."
});
pr = result.data;
}
}
const { data: comments } = await github.rest.issues.listComments({
owner,
repo,
issue_number: pr.number,
});
/* 41898282 is github-actions[bot] */
let comment = comments.find(comment => comment.user.id === 41898282);
const changesetRawStr = ${{ steps.changeset.outputs.changeset }}.replace(/\n/g, "\\n");
const changeset = JSON.parse(changesetRawStr);
const changedPackagesLines = changeset.changedPackages.map(x => `| ${x.name} | ${x.version} |`).join("\n");
const lastCommit = "${{ steps.pr-comment-vars.outputs.lastCommit }}";
const changesetCount = changeset.changesets.length;
const changedPackagesStr = changeset.changedPackages.length
? `The following public packages have changed files:\n| Changed | Current version |\n| - | - |\n${changedPackagesLines}`
: "No public packages have changed files.";
const changesetSingle = changesetCount === 1;
const commitChangesetLinkBase = `https://github.com/lightsparkdev/js-sdk/new/${pr.head.ref}?filename=.changeset/${changeset.suggestedChangesetId}.md`;
const suggestedChangesets = changeset.changedPackages.map(x => `"${x.name}": patch`).join("\n");
const commitChangesetLink = `${commitChangesetLinkBase}&value=${encodeURIComponent(`---\n${suggestedChangesets}\n---\n\n${pr.title}`)}`;
const noChangesetStr = `If the changes in this PR should result in new published versions for the packages above please [add a changeset](${commitChangesetLink})`;
const hasChangesetStr = `If additional changes have been made that require different versions for any package simply [add another changeset](${commitChangesetLink})`;
const changesetStr = `There ${changesetSingle ? "is" : "are"} ${changesetCount || "no"} existing changeset${changesetSingle ? '' : 's'} for this branch. ${changesetCount > 0 ? hasChangesetStr : noChangesetStr}. Any packages that depend on the planned releases will be updated and released automatically in a separate PR.`;
const packageReleasesStr = changeset.releases.map(x => `| ${x.name} | ${x.type} |`).join("\n");
const changelogGuidanceStr = `Each changeset corresponds to an update in the CHANGELOG for the packages listed in the changeset. Therefore, you should add a changeset for each noteable package change that this PR contains. For example, if a PR adds two features - one feature for packages A and B and one feature for package C - you should add two changesets. One changeset for packages A and B and one changeset for package C, with a description of each feature. The feature description will end up being the CHANGELOG entry for the packages in the changeset.`;
const releasesStr = `${changeset.releases.length ? `The following releases are planned based on the existing changesets:\n\n| Planned releases | Update |\n\| - | - |\n${packageReleasesStr}` : "No releases planned."}`;
const commentBody = `${changedPackagesStr}\n\n${changesetStr}\n\n${changelogGuidanceStr}\n\n${releasesStr}\n\nLast updated by commit ${lastCommit}`;
if (!comment) {
github.rest.issues.createComment({
owner,
repo,
issue_number: pr.number,
body: commentBody,
});
} else {
github.rest.issues.updateComment({
owner,
repo,
comment_id: comment.id,
body: commentBody,
});
}