.github/workflows/release.yml
1
name: release
3
on:
4
push:
5
branches: [main]
6
workflow_dispatch:
8
permissions:
9
contents: read
11
concurrency:
12
group: ${{ github.workflow }}-${{ github.ref }}
13
cancel-in-progress: false
15
jobs:
16
please:
17
name: release please
18
runs-on: ubuntu-24.04
19
permissions:
20
contents: write
21
id-token: write
22
pull-requests: write
23
outputs:
24
released: ${{ steps.release.outputs.release_created }}
25
tag: ${{ steps.release.outputs.tag_name }}
26
version: ${{ steps.release.outputs.version }}
27
steps:
28
- uses: googleapis/release-please-action@45996ed1f6d02564a971a2fa1b5860e934307cf7 # v5.0.0
29
id: release
30
with:
31
config-file: release-please-config.json
32
manifest-file: .release-please-manifest.json
34
binaries:
35
name: publish binaries
36
needs: please
37
if: needs.please.outputs.released == 'true'
38
runs-on: ubuntu-24.04
39
permissions:
40
contents: write
41
id-token: write
42
steps:
43
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
44
with:
45
persist-credentials: false
46
- uses: actions/setup-go@b7ad1dad31e06c5925ef5d2fc7ad053ef454303e # v7.0.0
47
with:
48
go-version-file: go.mod
49
cache: true
51
- name: build
52
env:
53
VERSION: ${{ needs.please.outputs.version }}
54
run: |
55
set -euo pipefail
56
mkdir -p dist
57
cp LICENSE README.md dist/
58
for target in linux/amd64 linux/arm64 darwin/amd64 darwin/arm64 windows/amd64 windows/arm64; do
59
os=${target%/*}
60
arch=${target#*/}
61
binary=koment
62
[ "$os" = windows ] && binary=koment.exe
64
CGO_ENABLED=0 GOOS=$os GOARCH=$arch go build -trimpath \
65
-ldflags="-s -w -X main.releaseVersion=${VERSION} -X main.sourceRevision=${GITHUB_SHA}" \
66
-o "dist/${binary}" ./cmd/koment
68
name="koment_${VERSION}_${os}_${arch}"
69
if [ "$os" = windows ]; then
70
(cd dist && zip -q "${name}.zip" "$binary" LICENSE README.md && rm "$binary")
71
else
72
(cd dist && tar -czf "${name}.tar.gz" "$binary" LICENSE README.md && rm "$binary")
73
fi
74
done
75
rm dist/LICENSE dist/README.md
77
linux_amd64_sha=$(sha256sum "dist/koment_${VERSION}_linux_amd64.tar.gz" | awk '{print $1}')
78
linux_arm64_sha=$(sha256sum "dist/koment_${VERSION}_linux_arm64.tar.gz" | awk '{print $1}')
79
darwin_amd64_sha=$(sha256sum "dist/koment_${VERSION}_darwin_amd64.tar.gz" | awk '{print $1}')
80
darwin_arm64_sha=$(sha256sum "dist/koment_${VERSION}_darwin_arm64.tar.gz" | awk '{print $1}')
81
windows_amd64_sha=$(sha256sum "dist/koment_${VERSION}_windows_amd64.zip" | awk '{print $1}')
82
windows_arm64_sha=$(sha256sum "dist/koment_${VERSION}_windows_arm64.zip" | awk '{print $1}')
84
render() {
85
sed \
86
-e "s/{{VERSION}}/${VERSION}/g" \
87
-e "s/{{LINUX_AMD64_SHA}}/${linux_amd64_sha}/g" \
88
-e "s/{{LINUX_ARM64_SHA}}/${linux_arm64_sha}/g" \
89
-e "s/{{DARWIN_AMD64_SHA}}/${darwin_amd64_sha}/g" \
90
-e "s/{{DARWIN_ARM64_SHA}}/${darwin_arm64_sha}/g" \
91
-e "s/{{WINDOWS_AMD64_SHA}}/${windows_amd64_sha}/g" \
92
-e "s/{{WINDOWS_ARM64_SHA}}/${windows_arm64_sha}/g" \
93
-e "s/{{WINDOWS_AMD64_SHA_UPPER}}/$(printf '%s' "$windows_amd64_sha" | tr '[:lower:]' '[:upper:]')/g" \
94
-e "s/{{WINDOWS_ARM64_SHA_UPPER}}/$(printf '%s' "$windows_arm64_sha" | tr '[:lower:]' '[:upper:]')/g" \
95
"$1" > "$2"
96
}
98
render packaging/homebrew/koment.rb.tmpl dist/koment.rb
99
render packaging/scoop/koment.json.tmpl dist/koment-scoop.json
100
mkdir -p dist/winget
101
render packaging/winget/JanPuc.Koment.installer.yaml.tmpl dist/winget/JanPuc.Koment.installer.yaml
102
render packaging/winget/JanPuc.Koment.locale.en-US.yaml.tmpl dist/winget/JanPuc.Koment.locale.en-US.yaml
103
render packaging/winget/JanPuc.Koment.yaml.tmpl dist/winget/JanPuc.Koment.yaml
104
(cd dist/winget && zip -q "../koment_${VERSION}_winget.zip" ./*.yaml)
106
(cd dist && sha256sum ./*.tar.gz ./*.zip ./koment.rb ./koment-scoop.json | sed 's| \./| |' > "koment_${VERSION}_checksums.txt")
107
ls -l dist
109
- name: install cosign
110
uses: sigstore/cosign-installer@6f9f17788090df1f26f669e9d70d6ae9567deba6 # v4.1.2
112
- name: sign checksum manifest
113
env:
114
VERSION: ${{ needs.please.outputs.version }}
115
run: |
116
cosign sign-blob --yes \
117
--bundle "dist/koment_${VERSION}_checksums.sigstore.json" \
118
"dist/koment_${VERSION}_checksums.txt"
120
- name: attach to the release
121
env:
122
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
123
RELEASE_TAG: ${{ needs.please.outputs.tag }}
124
run: |
125
gh release upload "$RELEASE_TAG" \
126
dist/koment_*.tar.gz dist/koment_*.zip dist/koment_*_checksums.txt \
127
dist/koment_*_checksums.sigstore.json dist/koment.rb dist/koment-scoop.json \
128
--clobber
130
verify:
131
name: verify the published release
132
needs: [please, binaries]
133
if: needs.please.outputs.released == 'true'
134
runs-on: ${{ matrix.os }}
135
permissions:
136
contents: read
137
strategy:
138
fail-fast: false
139
matrix:
140
os:
141
- ubuntu-24.04
142
- macos-15
143
steps:
144
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
145
with:
146
persist-credentials: false
148
- name: Install the release that was just published
149
id: setup
150
uses: ./
152
- name: Verify it is the release this run produced
153
env:
154
INSTALLED_VERSION: ${{ steps.setup.outputs.version }}
155
RELEASED_VERSION: ${{ needs.please.outputs.version }}
156
run: |
157
set -euo pipefail
158
command -v koment
159
koment version
160
test "$INSTALLED_VERSION" = "$RELEASED_VERSION"
161
koment version | grep -q "$RELEASED_VERSION"
163
image:
164
name: publish image
165
needs: please
166
if: needs.please.outputs.released == 'true'
167
runs-on: ubuntu-24.04
168
permissions:
169
contents: read
170
packages: write
171
id-token: write
172
steps:
173
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
174
with:
175
persist-credentials: false
177
- uses: docker/setup-qemu-action@96fe6ef7f33517b61c61be40b68a1882f3264fb8 # v4.2.0
178
- uses: docker/setup-buildx-action@bb05f3f5519dd87d3ba754cc423b652a5edd6d2c # v4.2.0
180
- uses: docker/login-action@dbcb813823bdd20940b903addbd779551569679f # v4.6.0
181
with:
182
registry: ghcr.io
183
username: ${{ github.actor }}
184
password: ${{ secrets.GITHUB_TOKEN }}
186
- id: meta
187
uses: docker/metadata-action@dc802804100637a589fabce1cb79ff13a1411302 # v6.2.0
188
with:
189
images: ghcr.io/${{ github.repository }}
190
tags: |
191
type=semver,pattern={{version}},value=${{ needs.please.outputs.tag }}
192
type=semver,pattern={{major}}.{{minor}},value=${{ needs.please.outputs.tag }}
193
type=raw,value=latest
195
- id: build
196
uses: docker/build-push-action@53b7df96c91f9c12dcc8a07bcb9ccacbed38856a # v7.3.0
197
with:
198
context: .
199
platforms: linux/amd64,linux/arm64
200
push: true
201
provenance: true
202
sbom: true
203
tags: ${{ steps.meta.outputs.tags }}
204
labels: ${{ steps.meta.outputs.labels }}
205
build-args: |
206
VERSION=${{ needs.please.outputs.version }}
207
REVISION=${{ github.sha }}
208
cache-from: type=gha
209
cache-to: type=gha,mode=max
211
- name: install cosign
212
uses: sigstore/cosign-installer@6f9f17788090df1f26f669e9d70d6ae9567deba6 # v4.1.2
214
- name: sign image manifest
215
env:
216
DIGEST: ${{ steps.build.outputs.digest }}
217
IMAGE: ghcr.io/${{ github.repository }}
218
run: cosign sign --yes "${IMAGE}@${DIGEST}"
220
mcp-registry:
221
name: publish MCP registry metadata
222
needs: [please, image]
223
if: needs.please.outputs.released == 'true'
224
runs-on: ubuntu-24.04
225
permissions:
226
contents: read
227
id-token: write
228
env:
229
MCP_PUBLISHER_SHA256: 1370446bbe74d562608e8005a6ccce02d146a661fbd78674e11cc70b9618d6cf
230
MCP_PUBLISHER_VERSION: 1.8.0
231
steps:
232
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
233
with:
234
persist-credentials: false
236
- name: Prepare release metadata
237
env:
238
IMAGE: ghcr.io/${{ github.repository }}:${{ needs.please.outputs.version }}
239
VERSION: ${{ needs.please.outputs.version }}
240
run: |
241
mkdir -p /tmp/koment-mcp
242
jq --arg version "$VERSION" --arg image "$IMAGE" \
243
'.version = $version | .packages[0].identifier = $image | del(.packages[0].version)' \
244
server.json > /tmp/koment-mcp/server.json
246
- name: Install MCP publisher
247
run: |
248
archive=/tmp/mcp-publisher.tar.gz
249
curl --fail --location --silent --show-error \
250
--output "$archive" \
251
"https://github.com/modelcontextprotocol/registry/releases/download/v${MCP_PUBLISHER_VERSION}/mcp-publisher_linux_amd64.tar.gz"
252
printf '%s %s\n' "$MCP_PUBLISHER_SHA256" "$archive" | sha256sum --check
253
tar -xzf "$archive" -C /tmp mcp-publisher
255
- name: Publish MCP server
256
working-directory: /tmp/koment-mcp
257
run: |
258
/tmp/mcp-publisher login github-oidc
259
/tmp/mcp-publisher publish
261
chart:
262
name: publish chart
263
needs: [please, image]
264
if: needs.please.outputs.released == 'true'
265
runs-on: ubuntu-24.04
266
permissions:
267
contents: write
268
packages: write
269
id-token: write
270
env:
271
CHART_VERSION: ${{ needs.please.outputs.version }}
272
REGISTRY_OWNER: ${{ github.repository_owner }}
273
REGISTRY_PASSWORD: ${{ secrets.GITHUB_TOKEN }}
274
REGISTRY_USER: ${{ github.actor }}
275
steps:
276
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
277
with:
278
persist-credentials: false
279
- uses: azure/setup-helm@9bc31f4ebc9c6b171d7bfbaa5d006ae7abdb4310 # v5.0.1
280
- uses: sigstore/cosign-installer@6f9f17788090df1f26f669e9d70d6ae9567deba6 # v4.1.2
282
- uses: docker/login-action@dbcb813823bdd20940b903addbd779551569679f # v4.6.0
283
with:
284
registry: ghcr.io
285
username: ${{ github.actor }}
286
password: ${{ secrets.GITHUB_TOKEN }}
288
- name: package and push
289
env:
290
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
291
RELEASE_TAG: ${{ needs.please.outputs.tag }}
292
run: |
293
helm registry login ghcr.io \
294
--username "$REGISTRY_USER" \
295
--password "$REGISTRY_PASSWORD"
296
helm package charts/koment --destination /tmp
297
push_output=$(helm push "/tmp/koment-${CHART_VERSION}.tgz" \
298
"oci://ghcr.io/${REGISTRY_OWNER}/charts")
299
printf '%s\n' "$push_output"
300
digest=$(printf '%s\n' "$push_output" | awk '/^Digest:/ {print $2}')
301
test -n "$digest"
302
cosign sign --yes "ghcr.io/${REGISTRY_OWNER}/charts/koment@${digest}"
303
cosign sign-blob --yes \
304
--bundle "/tmp/koment-${CHART_VERSION}.tgz.sigstore.json" \
305
"/tmp/koment-${CHART_VERSION}.tgz"
306
gh release upload "$RELEASE_TAG" \
307
"/tmp/koment-${CHART_VERSION}.tgz" \
308
"/tmp/koment-${CHART_VERSION}.tgz.sigstore.json" \
309
--clobber
311
editor:
312
name: publish editor extension
313
needs: [please, binaries]
314
if: needs.please.outputs.released == 'true'
315
runs-on: ubuntu-24.04
316
permissions:
317
contents: write
318
id-token: write
319
env:
320
OVSX_PAT: ${{ secrets.OVSX_PAT }}
321
PUBLISH_EDITOR_MARKETPLACES: ${{ vars.PUBLISH_EDITOR_MARKETPLACES }}
322
VSCE_PAT: ${{ secrets.VSCE_PAT }}
323
steps:
324
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
325
with:
326
persist-credentials: false
328
- uses: jdx/mise-action@7e36c90d9ab29c415a2384db3006f3ec8a8cc654 # v4.2.4
329
with:
330
experimental: true
331
install: false
333
- name: install locked editor tools
334
run: mise --cd editors/vscode install --locked
336
- name: install editor packaging tools
337
run: mise --cd editors/vscode exec -- npm ci
339
- name: collect the canonical archives
340
env:
341
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
342
RELEASE_TAG: ${{ needs.please.outputs.tag }}
343
run: |
344
set -euo pipefail
345
mkdir -p archives
346
gh release download "$RELEASE_TAG" --dir archives \
347
--pattern 'koment_*.tar.gz' --pattern 'koment_*.zip' --pattern 'koment_*_checksums.txt'
348
ls -l archives
350
- name: package extension for every platform
351
env:
352
VERSION: ${{ needs.please.outputs.version }}
353
run: |
354
set -euo pipefail
355
test "$(node -p "require('./editors/vscode/package.json').version")" = "$VERSION"
356
./editors/vscode/package-vsix.sh "$VERSION" archives dist
358
- name: install cosign
359
uses: sigstore/cosign-installer@6f9f17788090df1f26f669e9d70d6ae9567deba6 # v4.1.2
361
- name: sign and attach every extension package
362
env:
363
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
364
RELEASE_TAG: ${{ needs.please.outputs.tag }}
365
run: |
366
set -euo pipefail
367
for package in dist/koment-vscode_*.vsix; do
368
cosign sign-blob --yes --bundle "${package}.sigstore.json" "$package"
369
done
370
gh release upload "$RELEASE_TAG" \
371
dist/koment-vscode_*.vsix dist/koment-vscode_*.vsix.sigstore.json \
372
--clobber
374
- name: report that marketplace publication is off
375
if: env.PUBLISH_EDITOR_MARKETPLACES != 'true'
376
run: |
377
echo "::notice::PUBLISH_EDITOR_MARKETPLACES is not 'true'." \
378
"The signed VSIX is attached to the release; no marketplace was updated."
380
- name: publish to VS Code Marketplace
381
if: env.PUBLISH_EDITOR_MARKETPLACES == 'true'
382
run: |
383
set -euo pipefail
384
if [ -z "$VSCE_PAT" ]; then
385
echo "::error::marketplace publication is enabled but VSCE_PAT is unset"
386
exit 1
387
fi
388
for package in dist/koment-vscode_*.vsix; do
389
editors/vscode/node_modules/.bin/vsce publish --packagePath "$package"
390
done
392
- name: publish to Open VSX
393
if: env.PUBLISH_EDITOR_MARKETPLACES == 'true'
394
run: |
395
set -euo pipefail
396
if [ -z "$OVSX_PAT" ]; then
397
echo "::error::marketplace publication is enabled but OVSX_PAT is unset"
398
exit 1
399
fi
400
publisher=$(node -p "require('./editors/vscode/package.json').publisher")
401
if curl --fail --silent --output /dev/null "https://open-vsx.org/api/${publisher}"; then
402
echo "Open VSX namespace ${publisher} already exists"
403
else
404
echo "creating Open VSX namespace ${publisher}"
405
editors/vscode/node_modules/.bin/ovsx create-namespace "$publisher"
406
fi
407
for package in dist/koment-vscode_*.vsix; do
408
editors/vscode/node_modules/.bin/ovsx publish "$package"
409
done