Repository navigation
227 lines (209 loc) · 8.86 KB
/
Copy pathpublish.yml
File metadata and controls
227 lines (209 loc) · 8.86 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
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
name: Publish
on:
workflow_call:
inputs:
tag_name:
description: The draft release tag to attach artifacts to and publish (e.g. v7.1.0)
required: true
type: string
secrets:
OAUTH_CLIENT_ID:
required: true
# Signing certificates
CSC_LINK:
required: true
WIN_CSC_LINK:
required: true
CSC_KEY_PASSWORD:
required: true
WIN_CSC_KEY_PASSWORD:
required: true
# macOS specific
APPLE_ID_USERNAME:
required: true
APPLE_ID_PASSWORD:
required: true
APPLE_ID_TEAM_ID:
required: true
workflow_dispatch: # For manually running release process to verify code-signing of artifacts
inputs:
tag_name:
description: The draft release tag to publish (leave blank for a signing-only dry run)
required: false
type: string
permissions: {}
jobs:
release:
name: Publish ${{ matrix.platform }} [electron-builder]
permissions:
contents: write
strategy:
matrix:
include:
- os: macos-latest
platform: macOS
package-cmd: vp run package:macos --publish onTagOrDraft
artifact-name: Gitify-release-mac
use-apple-notarization: true
- os: windows-latest
platform: Windows
package-cmd: vp run package:win --publish onTagOrDraft
artifact-name: Gitify-release-win
use-apple-notarization: false
- os: ubuntu-latest
platform: Linux
package-cmd: vp run package:linux --publish onTagOrDraft
artifact-name: Gitify-release-linux
use-apple-notarization: false
runs-on: ${{ matrix.os }}
steps:
- name: Checkout
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
persist-credentials: false
- name: Setup Vite+
uses: voidzero-dev/setup-vp@68f39c78aaf39be468cabd2afb09c162574c84af # v1.21.2
with:
cache: true
node-version-file: '.nvmrc'
- name: Build application
run: vp run build
env:
OAUTH_CLIENT_ID: ${{ secrets.OAUTH_CLIENT_ID }}
- name: Package and publish for ${{ matrix.platform }}
run: ${{ matrix.package-cmd }}
env:
# Signing certificates - important to use the correct cert per platform
CSC_LINK: ${{ matrix.platform == 'macOS' && secrets.CSC_LINK || (matrix.platform == 'windows' && secrets.WIN_CSC_LINK || '') }}
CSC_KEY_PASSWORD: ${{ matrix.platform == 'macOS' && secrets.CSC_KEY_PASSWORD || (matrix.platform == 'windows' && secrets.WIN_CSC_KEY_PASSWORD || '') }}
# macOS specific
APPLE_ID_USERNAME: ${{ secrets.APPLE_ID_USERNAME }}
APPLE_ID_PASSWORD: ${{ secrets.APPLE_ID_PASSWORD }}
APPLE_ID_TEAM_ID: ${{ secrets.APPLE_ID_TEAM_ID }}
NOTARIZE: ${{ matrix.use-apple-notarization }}
# General
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- name: Upload artifacts
uses: actions/upload-artifact@cf430e030ddbb5b0abf93d22962f4752f3646cd9 # v7.0.2
with:
name: ${{ matrix.artifact-name }}
path: |
dist/*
!dist/*/
overwrite: true
publish-release:
name: Publish release
needs: release
if: ${{ inputs.tag_name != '' }}
runs-on: ubuntu-latest
permissions:
contents: write
steps:
# release-please creates the release as a draft so electron-builder can attach
# signed artifacts to it. Now that every platform has uploaded, flip it to
# published: this materialises the git tag and fires the `release: published`
# event that redeploys the website.
#
# We resolve the release by id rather than `gh release edit <tag>`: a draft
# has no git tag yet, so the tag lookup fails with HTTP 422. Patching the
# draft flag by id is also idempotent, so re-running an already-published
# release is a no-op.
- name: Publish draft release
run: |
# The draft is the newest release, so a single page comfortably covers it.
release=$(gh api "repos/${REPO}/releases?per_page=100" \
--jq 'map(select(.tag_name == env.TAG_NAME)) | .[0] // empty')
release_id=$(printf '%s' "${release}" | jq -r '.id // empty')
if [ -z "${release_id}" ]; then
echo "::error::No release found for tag ${TAG_NAME}"
exit 1
fi
# Credit contributors in the release body. GitHub's generated notes
# attribute every PR to its author; the @mentions also drive the
# contributor avatar strip on the release page. The tag does not
# exist yet, so generate against the draft's target commitish.
target=$(printf '%s' "${release}" | jq -r '.target_commitish')
notes=$(gh api --method POST "repos/${REPO}/releases/generate-notes" \
-f tag_name="${TAG_NAME}" -f target_commitish="${target}" --jq '.body' || true)
contributors=$(printf '%s\n' "${notes}" | grep -oE 'by @[A-Za-z0-9-]+' | sed 's/^by //' \
| sort -u | grep -viE '^@(github-actions|renovate|dependabot)$' | sed 's/^/* /' || true)
new_contributors=$(printf '%s\n' "${notes}" | sed -n '/^## New Contributors/,/^$/p')
# Idempotency: a re-run of an already-published release must not
# append the contributor sections a second time.
body=$(printf '%s' "${release}" | jq -r '.body')
case "${body}" in
*'### 🫶 Contributors'*) contributors='' new_contributors='' ;;
esac
{
printf '%s\n' "${body}"
if [ -n "${contributors}" ]; then
printf '\n### 🫶 Contributors\n\n%s\n' "${contributors}"
fi
if [ -n "${new_contributors}" ]; then
printf '\n%s\n' "${new_contributors}"
fi
} > /tmp/release-body.md
gh api --method PATCH "repos/${REPO}/releases/${release_id}" \
-F draft=false -F 'body=@/tmp/release-body.md' > /dev/null
echo "Published ${TAG_NAME} (release id ${release_id})"
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
TAG_NAME: ${{ inputs.tag_name }}
REPO: ${{ github.repository }}
notify-pull-requests:
name: Notify included pull requests
needs: publish-release
runs-on: ubuntu-latest
permissions:
contents: read
issues: write
pull-requests: write
steps:
- name: Close milestone for released version
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
REPO: ${{ github.repository }}
TAG_NAME: ${{ inputs.tag_name }}
run: |
# The release is published, so the tag URL is definitively live. Finalize
# the milestone before notifying: description becomes the release URL, the
# due date becomes today, and the milestone is closed. The notification
# step queries milestones across all states, so a closed milestone still
# finds the pull requests it contains on re-runs.
version="${TAG_NAME#v}"
title="Release ${version}"
url="https://github.com/${REPO}/releases/tag/${TAG_NAME}"
number=$(gh api --method GET "repos/${REPO}/milestones?state=open&per_page=100" \
--jq ".[] | select(.title == \"${title}\") | .number" | head -1)
if [ -z "${number}" ]; then
echo "::warning::No open milestone titled '${title}' found; skipping finalize"
exit 0
fi
now=$(date -u +%Y-%m-%dT%H:%M:%SZ)
gh api --method PATCH "repos/${REPO}/milestones/${number}" \
-f "description=${url}" -f "due_on=${now}" -f state=closed
echo "Finalized milestone '${title}': ${url}"
- name: Checkout trusted release automation
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
persist-credentials: false
ref: ${{ github.sha }}
- name: Notify pull requests included in the release
uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0
with:
github-token: ${{ secrets.GITHUB_TOKEN }}
script: |
const { pathToFileURL } = await import('node:url');
const scriptUrl = pathToFileURL(
`${process.env.GITHUB_WORKSPACE}/.github/scripts/notify-release-pull-requests.mjs`,
);
const { notifyReleasedPullRequests } = await import(scriptUrl);
const result = await notifyReleasedPullRequests(github, {
...context.repo,
tag: process.env.TAG_NAME,
});
core.info(
`Release ${process.env.TAG_NAME}: notified ${result.notified} pull request(s), skipped ${result.skipped}`,
);
env:
TAG_NAME: ${{ inputs.tag_name }}