-
Notifications
You must be signed in to change notification settings - Fork 62
264 lines (258 loc) · 11.9 KB
/
goreleaser.yml
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
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
name: Build and Release
on:
workflow_dispatch:
push:
tags:
- '*'
env:
GOPRIVATE: "github.com/sourcegraph/*"
PRIVATE_TOKEN: "${{ secrets.PRIVATE_SG_ACCESS_TOKEN }}"
# There are two cases where this GitHub action will run:
#
# 1. We are releasing a new latest version for src-cli, as a major, minor, or patch
# update, for instance 4.0.2 -> 4.1.0, OR
# 2. We are releasing a new minor/patch version for an older major/minor version of
# src-cli, for instance if the latest version is 4.0.2 and we're releasing 3.43.3
#
# In both cases, we want to run both goreleaser and npm to publish new versions in all the
# places we care about. For goreleaser publishing to Homebrew, we need to publish to
# different formulas depending on if we're case 1. or case 2, and neither goreleaser nor
# Homebrew has a good way of handling this automatically. In the case of the former (a new
# latest release), we must:
#
# 1. Copy the main formula in our Homebrew tap for the previous latest release to a
# versioned formula
# 2. Build and publish the new release to the main formula
# 3. Update the Homebrew symlink alias for the latest version
#
# In the case of the latter (a patch release for an older version), we only need to:
#
# 1. Build and publish the new release to a versioned Homebrew formula
#
# This action contains 5 jobs to accommodate both cases:
#
# release_type [always] - checks tags, determines if we're case 1. or case 2.
# goreleaser_pre [if case 1.] - copies the main formula to a versioned formula
# goreleaser [always] - runs tests, builds + publishes with goreleaser
# goreleaser_post [if case 1.] - updates symlink to latest version
# npm [always] - publishes to npm
jobs:
# release_type compares the current tag to the highest versioned tag available on the
# repo to determine if this release is for a new latest version or a patch of an older
# version.
release_type:
name: Determine release type
runs-on: ubuntu-latest
outputs:
is_latest_version: ${{ env.is_latest_version }}
latest_tag: ${{ env.latest_tag }}
second_latest_tag: ${{ env.second_latest_tag }}
steps:
- name: Checkout
uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Set current tag, latest (highest version) tag, and second latest tag
# For latest and second latest tags, we can't use git tag --sort=version:refname
# because git doesn't have a concept of pre-release versions and thus mis-sorts
# versions like 4.0.0-rc.0 *after* 4.0.0.
run: |
echo "current_tag=${GITHUB_REF_NAME}" >> $GITHUB_ENV
echo "latest_tag=$(git tag | tr - \~ | sort --version-sort | tr \~ - | tail -1)" >> $GITHUB_ENV
echo "second_latest_tag=$(git tag | tr - \~ | sort --version-sort | tr \~ - | tail -2 | sed -n 1p)" >> $GITHUB_ENV
- name: Install semver
run: |
wget -O /usr/local/bin/semver https://raw.githubusercontent.com/fsaintjacques/semver-tool/master/src/semver
chmod +x /usr/local/bin/semver
- name: Compare tags
# If the current tag is also the latest (highest-versioned) tag, semver compare
# returns 0. If the current tag is older (i.e. it's a patch for an older version),
# semver compare will return -1. By definition, it should be impossible for the
# current tag to be newer than the latest tag unless somehow the current tag is
# not a real tag, but if for some reason this happens, it will be treated the same
# as if it were the latest.
run: |
if [ "$(semver compare ${{ env.current_tag }} ${{ env.latest_tag }})" -ge 0 ]
then
echo "is_latest_version=1" >> $GITHUB_ENV
else
echo "is_latest_version=0" >> $GITHUB_ENV
fi
- name: Log variables
run: |
echo "Version for this release: ${{ env.current_tag }}"
echo "Latest version: ${{ env.latest_tag }}"
if [[ ${{ env.is_latest_version }} == 1 ]]
then
echo "Releasing new latest version."
else
echo "Releasing patch of older version."
fi
# goreleaser_pre copies the main formula in our Homebrew tap for the previous latest
# release (second latest tag) to a versioned formula, so that it is preserved when
# goreleaser runs and overwrites the main formula for the latest build.
goreleaser_pre:
name: Copy previous release
runs-on: ubuntu-latest
needs: release_type
# Only run this step if we're releasing a new latest version. Creating a patch release
# does not touch the main formula.
if: needs.release_type.outputs.is_latest_version == 1
steps:
- name: Set variables
run: |
echo "latest_tag=${{ needs.release_type.outputs.latest_tag }}" >> $GITHUB_ENV
echo "second_latest_tag=${{ needs.release_type.outputs.second_latest_tag }}" >> $GITHUB_ENV
- name: Checkout
uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Set versioning variables
run: |
echo "versioned_formula_file=Formula/src-cli@${{ env.second_latest_tag }}.rb" >> $GITHUB_ENV
echo "versioned_classname=SrcCliAT$(echo ${{ env.second_latest_tag }} | sed 's/\.//g')" >> $GITHUB_ENV
- name: Log variables
run: |
echo "Second latest tag (previous latest release): ${{ env.second_latest_tag }}"
echo "Versioned formula file: ${{ env.versioned_formula_file }}"
echo "Versioned classname: ${{ env.versioned_classname }}"
- name: Checkout Homebrew tap
uses: actions/checkout@v4
with:
repository: sourcegraph/homebrew-src-cli
fetch-depth: 0
token: ${{ secrets.BOT_CROSS_REPO_PAT }}
- name: Copy main release formula file to versioned formula file
run: cp Formula/src-cli.rb ${{ env.versioned_formula_file }}
# Homebrew expects the name of the class in a versioned formula file to be of the
# format {Formula}AT{Major}{Minor}{Patch}, but the main formula classname is just
# {Formula}, so we manually update the name: SrcCli -> SrcCliAT###
- name: Rename formula classname
run: sed -i 's/class SrcCli/class ${{ env.versioned_classname }}/' ${{ env.versioned_formula_file }}
- name: Commit result
run: |
git config user.name sourcegraph-bot
git config user.email sourcegraph-bot-github@sourcegraph.com
git add .
git commit --allow-empty -m "Copy previous release"
git push
# goreleaser runs tests before building, then uses goreleaser to publish to Homebrew and
# Docker Hub.
goreleaser:
name: Run goreleaser
runs-on: ubuntu-latest
needs: [release_type, goreleaser_pre]
# By default, this job will be skipped if either "needs" job is skipped. This tells
# GitHub actions to always run it, so long as the previous jobs that ran didn't fail.
if: |
always() &&
(needs.release_type.result == 'success') &&
(needs.goreleaser_pre.result == 'success' || needs.goreleaser_pre.result == 'skipped')
outputs:
# Passthrough from previous jobs so that they're also available in goreleaser_post
second_latest_tag: ${{ needs.release_type.outputs.second_latest_tag }}
latest_tag: ${{ needs.release_type.outputs.latest_tag }}
is_latest_version: ${{ env.is_latest_version }}
steps:
- name: Set variables
run: echo "is_latest_version=${{ needs.release_type.outputs.is_latest_version }}" >> $GITHUB_ENV
- name: Set config file
# These goreleaser config files are identical except for the brews.name template.
# Homebrew expects the main formula to be named one way, and versioned formulas to
# be named another, but goreleaser only allows us to specify a single template.
run: |
if [[ ${{ env.is_latest_version }} == 1 ]]
then
echo "config_file=.goreleaser.yml" >> $GITHUB_ENV
else
echo "config_file=.goreleaser-patch.yml" >> $GITHUB_ENV
fi
- name: Log config file
run: |
echo "Goreleaser config file: ${{ env.config_file }}"
- name: Checkout
uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Set up Go
uses: actions/setup-go@v5
with:
go-version: 1.22.8
- name: Enable pulling Go modules from private sourcegraph/sourcegraph
run: git config --global url."https://${PRIVATE_TOKEN}@github.com/sourcegraph/".insteadOf "https://github.com/sourcegraph/"
- run: go test ./...
- run: go test -race -v ./...
- run: echo "${DOCKER_PASSWORD}" | docker login -u=$DOCKER_USERNAME --password-stdin
env:
DOCKER_PASSWORD: ${{ secrets.DOCKER_PASSWORD }}
DOCKER_USERNAME: ${{ secrets.DOCKER_USERNAME }}
- name: Run GoReleaser
uses: goreleaser/goreleaser-action@v5
with:
version: latest
# We use a different goreleaser config for releasing a new latest version vs.
# releasing a patch on an older version. For releasing the new latest version,
# we want to update the main (unversioned) Homebrew formula. For releasing a
# patch on an older version, we want to publish a new versioned formula and
# leave the main formula untouched.
args: release --clean --config=${{ env.config_file }}
env:
# Use separate access token, because we need a scope:repo token to publish the brew formula.
GITHUB_TOKEN: ${{ secrets.GH_PAT }}
# goreleaser_post updates the symlink name to refer to the new release version. The
# symlink enables users to install the latest src-cli with the versioned command:
# $ brew install sourcegraph/src-cli/src-cli@X.Y.Z
# alongside the command to install it via the main formula:
# $ brew install sourcegraph/src-cli/src-cli
goreleaser_post:
name: Create new release version symlink
runs-on: ubuntu-latest
needs: goreleaser
# Only run this step if we're releasing a new latest version. Creating a patch release
# does not require updating the symlink.
if: needs.goreleaser.outputs.is_latest_version == 1
steps:
- name: Set variables
run: |
echo "old_symlink_name=Aliases/src-cli@${{ needs.goreleaser.outputs.second_latest_tag }}" >> $GITHUB_ENV
echo "new_symlink_name=Aliases/src-cli@${{ needs.goreleaser.outputs.latest_tag }}" >> $GITHUB_ENV
- name: Log variables
run: |
echo "Old symlink: ${{ env.old_symlink_name }}"
echo "New symlink: ${{ env.new_symlink_name }}"
- name: Checkout Homebrew tap
uses: actions/checkout@v4
with:
repository: sourcegraph/homebrew-src-cli
fetch-depth: 0
token: ${{ secrets.BOT_CROSS_REPO_PAT }}
- name: Replace symlink
run: mv ${{ env.old_symlink_name }} ${{ env.new_symlink_name }}
- name: Commit result
run: |
git config user.name sourcegraph-bot
git config user.email sourcegraph-bot-github@sourcegraph.com
git add .
git commit -m "Update latest release symlink"
git push
# npm publishes the new version to the npm package registry
npm:
runs-on: ubuntu-latest
needs: goreleaser
steps:
- name: Checkout
uses: actions/checkout@v4
with:
fetch-depth: 0
- uses: actions/setup-node@v4
with:
node-version: 16
registry-url: 'https://registry.npmjs.org'
- run: echo "VERSION=${GITHUB_REF/refs\/tags\//}" >> $GITHUB_ENV
- run: echo "Releasing version ${{ env.version }}"
- run: yarn version --no-git-tag-version --new-version "${{ env.VERSION }}"
working-directory: npm-distribution
- run: npm publish --access public
working-directory: npm-distribution
env:
NODE_AUTH_TOKEN: ${{secrets.NPM_TOKEN}}