snapshot of 8b9e9fcfc8b13c2d29024f6f756b28bc6851512b Annotations about the code that implements koment.

.github/workflows/ci.yml

1 ---
2 # yaml-language-server: $schema=https://json.schemastore.org/github-workflow.json
3 name: CI
4
5 on:
6 push:
7 branches:
8 - main
9 pull_request:
10 branches:
11 - main
12 merge_group:
13 workflow_dispatch:
14
15 concurrency:
16 group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}
17 cancel-in-progress: ${{ github.event_name == 'pull_request' }}
18
19 permissions:
20 contents: read
21
22 jobs:
23 quality:
24 name: quality
25 runs-on: ubuntu-24.04
26 permissions:
27 contents: read
28 steps:
29 - name: Checkout
30 uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
31 with:
32 persist-credentials: false
33
34 - name: Setup Mise
35 uses: jdx/mise-action@7e36c90d9ab29c415a2384db3006f3ec8a8cc654 # v4.2.4
36 with:
37 experimental: true
38 install_args: --locked
39
40 - name: Cache Go
41 uses: actions/cache@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6.1.0
42 with:
43 path: |
44 ~/.cache/go-build
45 ~/go/pkg/mod
46 key: ${{ runner.os }}-go-${{ hashFiles('go.sum') }}
47 restore-keys: ${{ runner.os }}-go-
48
49 - name: Check formatting
50 run: mise run fmt-check
51
52 - name: Check module metadata
53 run: mise run tidy-check
54
55 - name: Run go vet
56 run: mise run vet
57
58 - name: Check generated files
59 run: mise run generate-check
60
61 - name: Check annotations
62 run: mise run annotations
63
64 - name: Check comment policy
65 run: mise run comments
66
67 - name: Check agent adapters
68 run: mise run agent-policy
69
70 - name: Lint and audit workflows
71 run: mise run workflow-lint
72
73 - name: Run govulncheck
74 run: mise run vulncheck
75
76 lint:
77 name: lint
78 runs-on: ubuntu-24.04
79 permissions:
80 contents: read
81 steps:
82 - name: Checkout
83 uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
84 with:
85 persist-credentials: false
86
87 - name: Setup Mise
88 uses: jdx/mise-action@7e36c90d9ab29c415a2384db3006f3ec8a8cc654 # v4.2.4
89 with:
90 experimental: true
91 install_args: --locked
92
93 - name: Cache Go
94 uses: actions/cache@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6.1.0
95 with:
96 path: |
97 ~/.cache/go-build
98 ~/go/pkg/mod
99 key: ${{ runner.os }}-go-${{ hashFiles('go.sum') }}
100 restore-keys: ${{ runner.os }}-go-
101
102 - name: Cache golangci-lint
103 uses: actions/cache@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6.1.0
104 with:
105 path: ~/.cache/golangci-lint
106 key: ${{ runner.os }}-golangci-lint-${{ hashFiles('go.sum', '.golangci.yml', '.mise/mise.lock') }}
107
108 - name: Run linter
109 run: mise run lint
110
111 test:
112 name: test
113 runs-on: ubuntu-24.04
114 permissions:
115 contents: read
116 steps:
117 - name: Checkout
118 uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
119 with:
120 persist-credentials: false
121
122 - name: Setup Mise
123 uses: jdx/mise-action@7e36c90d9ab29c415a2384db3006f3ec8a8cc654 # v4.2.4
124 with:
125 experimental: true
126 install_args: --locked
127
128 - name: Cache Go
129 uses: actions/cache@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6.1.0
130 with:
131 path: |
132 ~/.cache/go-build
133 ~/go/pkg/mod
134 key: ${{ runner.os }}-go-${{ hashFiles('go.sum') }}
135 restore-keys: ${{ runner.os }}-go-
136
137 - name: Run tests
138 run: mise run test
139
140 - name: Report coverage
141 run: go tool cover -func=coverage.out | tail -1
142
143 container:
144 name: container
145 runs-on: ubuntu-24.04
146 permissions:
147 contents: read
148 steps:
149 - name: Checkout
150 uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
151 with:
152 persist-credentials: false
153
154 - name: Setup Mise
155 uses: jdx/mise-action@7e36c90d9ab29c415a2384db3006f3ec8a8cc654 # v4.2.4
156 with:
157 experimental: true
158 install: false
159
160 - name: Resolve Go version
161 id: tools
162 run: echo "go=$(mise config get tools.go)" >> "$GITHUB_OUTPUT"
163
164 - name: Setup Buildx
165 uses: docker/setup-buildx-action@bb05f3f5519dd87d3ba754cc423b652a5edd6d2c # v4.2.0
166
167 - name: Build image
168 uses: docker/build-push-action@53b7df96c91f9c12dcc8a07bcb9ccacbed38856a # v7.3.0
169 with:
170 context: .
171 push: false
172 load: true
173 tags: koment:ci
174 build-args: GO_VERSION=${{ steps.tools.outputs.go }}
175 cache-from: type=gha
176 cache-to: type=gha,mode=max
177
178 - name: Run binary
179 run: docker run --rm koment:ci help
180
181 - name: Exercise unified service
182 env:
183 SYNCHRONIZATION_TOKEN: ${{ secrets.GITHUB_TOKEN }}
184 run: |
185 set -euo pipefail
186 token="$RUNNER_TEMP/koment-synchronization-token"
187 printf '%s' "$SYNCHRONIZATION_TOKEN" > "$token"
188 chmod 0444 "$token"
189 docker run --detach --name koment-ci-service \
190 --publish 127.0.0.1:18080:8080 \
191 --mount type=bind,src="$PWD/testdata/server/repositories.yaml",dst=/config/repositories.yaml,readonly \
192 --mount type=bind,src="$token",dst=/config/synchronization-token,readonly \
193 koment:ci serve --config /config/repositories.yaml \
194 --github-token-file /config/synchronization-token \
195 --listen 0.0.0.0:8080 --trusted-proxies 127.0.0.1/32
196 cleanup() {
197 docker logs koment-ci-service
198 docker rm --force koment-ci-service
199 rm -f "$token"
200 }
201 trap cleanup EXIT
202 for attempt in $(seq 1 30); do
203 if curl --fail --silent http://127.0.0.1:18080/readyz; then
204 break
205 fi
206 if [ "$attempt" -eq 30 ]; then
207 exit 1
208 fi
209 sleep 2
210 done
211 curl --fail --silent http://127.0.0.1:18080/livez
212 test "$(curl --silent --output /dev/null --write-out '%{http_code}' http://127.0.0.1:18080/r/koment/)" = 401
213
214 - name: Setup Helm
215 uses: azure/setup-helm@9bc31f4ebc9c6b171d7bfbaa5d006ae7abdb4310 # v5.0.1
216
217 - name: Create Kind cluster
218 uses: helm/kind-action@ef37e7f390d99f746eb8b610417061a60e82a6cc # v1.14.0
219
220 - name: Exercise Helm release
221 env:
222 SYNCHRONIZATION_TOKEN: ${{ secrets.GITHUB_TOKEN }}
223 run: |
224 set -euo pipefail
225 diagnostics() {
226 kubectl get deployments,pods,services --all-namespaces
227 kubectl describe pods --namespace default
228 kubectl logs deployment/koment-koment --namespace default || true
229 }
230 trap diagnostics ERR
231 kind load docker-image koment:ci --name chart-testing
232 kubectl create secret generic koment-synchronization \
233 --from-literal=github-token="$SYNCHRONIZATION_TOKEN"
234 helm upgrade --install koment charts/koment \
235 --set image.repository=koment \
236 --set-string image.tag=ci \
237 --set image.pullPolicy=Never \
238 --set github.existingSecret=koment-synchronization \
239 --wait --timeout 5m
240 helm test koment --logs --timeout 2m
241
242 setup-action:
243 name: setup-action (${{ matrix.os }})
244 runs-on: ${{ matrix.os }}
245 permissions:
246 contents: read
247 strategy:
248 fail-fast: false
249 matrix:
250 os:
251 - ubuntu-24.04
252 - macos-15
253 steps:
254 - name: Checkout
255 uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
256 with:
257 persist-credentials: false
258
259 - name: Explain why the published release is not installed here
260 if: github.event_name == 'push'
261 run: |
262 echo "::notice::A push to main can be a release commit, whose tag becomes 'latest'" \
263 "minutes before its archives are uploaded. The release workflow verifies its own" \
264 "output once publication finishes."
265
266 - name: Install koment
267 id: setup
268 if: github.event_name != 'push'
269 uses: ./
270
271 - name: Verify installation
272 if: github.event_name != 'push'
273 env:
274 INSTALLED_VERSION: ${{ steps.setup.outputs.version }}
275 run: |
276 command -v koment
277 koment version
278 test -n "$INSTALLED_VERSION"
279 koment version | grep -q "$INSTALLED_VERSION"
280
281 windows-archive:
282 name: windows-archive (advisory)
283 runs-on: windows-2025
284 permissions:
285 contents: read
286 steps:
287 - name: Install the published Windows archive the way Scoop and WinGet do
288 if: github.event_name != 'push'
289 shell: pwsh
290 env:
291 KOMENT_SOURCE: koment-dev/koment
292 run: |
293 $ErrorActionPreference = 'Stop'
294
295 $resolved = (Invoke-WebRequest -Uri "https://github.com/$env:KOMENT_SOURCE/releases/latest" -UseBasicParsing).BaseResponse.RequestMessage.RequestUri.AbsoluteUri
296 $tag = ($resolved -split '/')[-1]
297 $version = $tag.TrimStart('v')
298 if ($version -notmatch '^\d+\.\d+\.\d+') {
299 throw "could not resolve a koment release from $resolved"
300 }
301
302 $archive = "koment_${version}_windows_amd64.zip"
303 $base = "https://github.com/$env:KOMENT_SOURCE/releases/download/$tag"
304 $work = New-Item -ItemType Directory -Force -Path (Join-Path $env:RUNNER_TEMP 'koment-windows')
305
306 Write-Host "installing koment $version (windows/amd64)"
307 Invoke-WebRequest -Uri "$base/$archive" -OutFile (Join-Path $work $archive) -UseBasicParsing
308 Invoke-WebRequest -Uri "$base/koment_${version}_checksums.txt" -OutFile (Join-Path $work 'checksums.txt') -UseBasicParsing
309
310 $listed = Select-String -Path (Join-Path $work 'checksums.txt') -Pattern " $([regex]::Escape($archive))$"
311 if (-not $listed) {
312 throw "$archive is not listed in the release checksum manifest"
313 }
314 $expected = ($listed.Line -split '\s+')[0]
315 $actual = (Get-FileHash -Path (Join-Path $work $archive) -Algorithm SHA256).Hash.ToLower()
316 if ($expected -ne $actual) {
317 throw "${archive}: expected $expected, got $actual"
318 }
319 Write-Host "${archive}: OK"
320
321 $extracted = Join-Path $work 'extracted'
322 Expand-Archive -Path (Join-Path $work $archive) -DestinationPath $extracted -Force
323 foreach ($member in @('koment.exe', 'LICENSE', 'README.md')) {
324 if (-not (Test-Path (Join-Path $extracted $member))) {
325 throw "$member is not at the root of $archive"
326 }
327 }
328 Write-Host 'archive root carries koment.exe, LICENSE and README.md'
329
330 $reported = (& (Join-Path $extracted 'koment.exe') version) -join ' '
331 Write-Host $reported
332 if ($reported -notmatch [regex]::Escape($version)) {
333 throw "koment.exe reported '$reported', which does not name $version"
334 }
335
336 helm:
337 name: helm
338 runs-on: ubuntu-24.04
339 permissions:
340 contents: read
341 steps:
342 - name: Checkout
343 uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
344 with:
345 persist-credentials: false
346
347 - name: Setup Mise
348 uses: jdx/mise-action@7e36c90d9ab29c415a2384db3006f3ec8a8cc654 # v4.2.4
349 with:
350 experimental: true
351 install_args: --locked
352
353 - name: Lint chart
354 run: mise run helm-lint
355
356 - name: Render supported modes
357 run: mise run helm-template
358
359 editor:
360 name: editor
361 runs-on: ubuntu-24.04
362 permissions:
363 contents: read
364 steps:
365 - name: Checkout
366 uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
367 with:
368 persist-credentials: false
369
370 - name: Setup Mise
371 uses: jdx/mise-action@7e36c90d9ab29c415a2384db3006f3ec8a8cc654 # v4.2.4
372 with:
373 experimental: true
374 install: false
375
376 - name: Install the pinned Go toolchain
377 run: |
378 set -euo pipefail
379 mise install go --locked
380 echo "$(mise where go)/bin" >> "$GITHUB_PATH"
381
382 - name: Cache cross-compilation
383 uses: actions/cache@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6.1.0
384 with:
385 path: |
386 ~/.cache/go-build
387 ~/go/pkg/mod
388 key: ${{ runner.os }}-go-cross-${{ hashFiles('go.sum') }}
389 restore-keys: ${{ runner.os }}-go-cross-
390
391 - name: Install locked editor tools
392 run: mise --cd editors/vscode install --locked
393
394 - name: Install editor packaging tools
395 run: mise --cd editors/vscode exec -- npm ci
396
397 - name: Test extension protocol
398 run: mise run extension-test
399
400 - name: Build the archives the extension bundles
401 run: |
402 set -euo pipefail
403 test "$(go env GOVERSION)" = "go$(mise config get tools.go)"
404 version=0.0.0-ci
405 mkdir -p archives
406 cp LICENSE README.md archives/
407 for target in linux/amd64 linux/arm64 darwin/amd64 darwin/arm64 windows/amd64 windows/arm64; do
408 os=${target%/*}
409 arch=${target#*/}
410 binary=koment
411 [ "$os" = windows ] && binary=koment.exe
412 CGO_ENABLED=0 GOOS=$os GOARCH=$arch go build -trimpath -o "archives/${binary}" ./cmd/koment
413 name="koment_${version}_${os}_${arch}"
414 if [ "$os" = windows ]; then
415 (cd archives && zip -q "${name}.zip" "$binary" LICENSE README.md && rm "$binary")
416 else
417 (cd archives && tar -czf "${name}.tar.gz" "$binary" LICENSE README.md && rm "$binary")
418 fi
419 done
420 rm archives/LICENSE archives/README.md
421 (cd archives && sha256sum ./*.tar.gz ./*.zip | sed 's| \./| |' > "koment_${version}_checksums.txt")
422
423 - name: Validate every VSIX
424 run: |
425 set -euo pipefail
426 version=0.0.0-ci
427 manifest=editors/vscode/package.json
428 cp "$manifest" "$RUNNER_TEMP/package.json"
429 trap 'cp "$RUNNER_TEMP/package.json" "$manifest"' EXIT
430 node -e "
431 const p = require('./editors/vscode/package.json');
432 p.version = '$version';
433 require('fs').writeFileSync('editors/vscode/package.json', JSON.stringify(p, null, 2) + '\n');
434 "
435 ./editors/vscode/package-vsix.sh "$version" archives dist >/dev/null
436
437 for pair in linux-x64:koment linux-arm64:koment darwin-x64:koment darwin-arm64:koment \
438 win32-x64:koment.exe win32-arm64:koment.exe; do
439 target=${pair%%:*}
440 expected=${pair##*:}
441 package="dist/koment-vscode_${version}_${target}.vsix"
442 carried=$(unzip -l "$package" | awk '/extension\/bin\//{print $NF}' | sed 's|extension/bin/||')
443 test "$carried" = "$expected" || {
444 echo "::error::$package carries '$carried', expected '$expected'"
445 exit 1
446 }
447 unzip -p "$package" extension.vsixmanifest | grep -q "TargetPlatform=\"${target}\"" || {
448 echo "::error::$package is not declared for $target"
449 exit 1
450 }
451 echo "$package: $expected for $target"
452 done
453
454 universal="dist/koment-vscode_${version}.vsix"
455 if unzip -l "$universal" | grep -q 'extension/bin/'; then
456 echo "::error::the universal package must carry no binary"
457 exit 1
458 fi
459 echo "$universal: no binary, falls back to PATH"
460
461 ci:
462 if: ${{ always() }}
463 name: ci
464 needs:
465 - container
466 - editor
467 - helm
468 - lint
469 - quality
470 - setup-action
471 - test
472 runs-on: ubuntu-24.04
473 permissions: {}
474 steps:
475 - name: Reject failed, cancelled, or skipped jobs
476 if: ${{ contains(needs.*.result, 'failure') || contains(needs.*.result, 'cancelled') || contains(needs.*.result, 'skipped') }}
477 run: exit 1
478
479 - name: Accept successful jobs
480 if: ${{ !(contains(needs.*.result, 'failure') || contains(needs.*.result, 'cancelled') || contains(needs.*.result, 'skipped')) }}
481 run: echo "All CI jobs passed"

Find an annotation

Search file paths, rationale, kinds, and authors.

moveEnter openEsc close