Skip to content
/ bits Public

Commit db89685

Browse files
committed
Improve CI
1 parent 45e7f6f commit db89685

File tree

22 files changed

+1020
-143
lines changed

22 files changed

+1020
-143
lines changed

.claude/skills/commit-all/SKILL.md

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,17 @@
11
---
22
name: commit-all
33
description: Create atomic commits from all unstaged changes
4-
allowed-tools: Bash(git status, git diff*, git add, git commit, git log)
4+
allowed-tools: Bash(just fmt, git status, git diff*, git add, git commit, git log)
55
---
66

77
# Commit All Unstaged Changes
88

99
Create atomic commits from all unstaged changes.
1010

11+
## Step 1: Format Code
12+
13+
!`just fmt`
14+
1115
## Current State
1216

1317
!`git status --short`

.claude/skills/commit/SKILL.md

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,23 @@
11
---
22
name: commit
33
description: Create atomic commits from session changes only
4-
allowed-tools: Bash(git status, git diff*, git add, git commit, git log)
4+
allowed-tools: Bash(just fmt, git status, git diff*, git add, git commit, git log)
55
---
66

77
# Commit Session Changes
88

99
Create atomic commits for **only the changes we made together** in this session.
1010

11-
## Step 1: Identify Session Changes
11+
## Step 1: Format Code
12+
13+
!`just fmt`
14+
15+
## Step 2: Identify Session Changes
1216

1317
Review your tool use history from this conversation. List the files you edited
1418
using Edit or Write tools. These are "our changes."
1519

16-
## Step 2: Cross-Reference with Git
20+
## Step 3: Cross-Reference with Git
1721

1822
!`git status --short`
1923

@@ -26,7 +30,7 @@ Only consider files that:
2630

2731
Ignore any pre-existing uncommitted changes that weren't part of our work.
2832

29-
## Step 3: Propose Atomic Commits
33+
## Step 4: Propose Atomic Commits
3034

3135
Group related changes into logical commits. For each proposed commit, show:
3236

@@ -39,7 +43,7 @@ Commit 2: <message>
3943
- path/to/other.clj
4044
```
4145

42-
## Step 4: Wait for Approval
46+
## Step 5: Wait for Approval
4347

4448
Present the plan and ask: "Ready to create these commits?"
4549

.claude/skills/sync-deps/SKILL.md

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
---
2+
name: sync-deps
3+
description: Synchronise Nix deps hash after changing deps.edn
4+
---
5+
6+
# Sync Dependencies Hash
7+
8+
Update the fixed-output derivation hash in `pkgs/bits-uberjar/default.nix` after
9+
changing `deps.edn`.
10+
11+
## Background
12+
13+
The uberjar build uses a fixed-output derivation (FOD) to cache Maven/Clojure
14+
dependencies. When `deps.edn` changes, the hash becomes stale and builds fail
15+
with a hash mismatch error containing the correct hash.
16+
17+
## Process
18+
19+
1. Read `pkgs/bits-uberjar/default.nix`
20+
21+
2. Edit `depsHash` to an invalid value to force recomputation:
22+
23+
```nix
24+
depsHash = "sha256-AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=";
25+
```
26+
27+
3. Clear devenv cache: `rm -f .devenv/nix-eval-cache.db`
28+
29+
4. Run: `devenv build outputs.bits-uberjar`
30+
31+
The build fails with a hash mismatch. Find the `got:` line containing the
32+
correct hash (format: `sha256-...=`).
33+
34+
5. Edit `depsHash` with the correct hash from the error output.
35+
36+
6. Verify: `devenv build outputs.bits-uberjar`
37+
38+
7. If verification fails, restore: `git checkout pkgs/bits-uberjar/default.nix`
39+
40+
$ARGUMENTS

.forgejo/scripts/attic-push.sh

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
#!/usr/bin/env bash
2+
set -eu
3+
4+
# Push gcroots and their closures to Attic
5+
# This ensures future CI runs can fetch from Attic instead of cache.nixos.org
6+
for path in .devenv/gc/*; do
7+
if [[ -L $path ]]; then
8+
# Resolve symlink and push the actual store path with its closure
9+
store_path=$(readlink -f "$path")
10+
attic push invetica:invetica "$store_path" || true
11+
fi
12+
done

.forgejo/scripts/attic-setup.sh

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
#!/usr/bin/env bash
2+
set -eu
3+
4+
usage() {
5+
echo >&2 "Usage: ATTIC_TOKEN=<token> attic-setup.sh"
6+
}
7+
8+
if [[ -z ${ATTIC_TOKEN:-} ]]; then
9+
usage
10+
exit 22 # EINVAL
11+
fi
12+
13+
attic login invetica https://attic.lan.invetica.co.uk "$ATTIC_TOKEN"
14+
attic use invetica:invetica

.forgejo/scripts/build.sh

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
#!/usr/bin/env bash
2+
set -eu
3+
4+
usage() {
5+
echo >&2 "Usage: build.sh <output-name>"
6+
}
7+
8+
if [[ $# -ne 1 ]]; then
9+
usage
10+
exit 22 # EINVAL
11+
fi
12+
13+
output=$1
14+
15+
devenv build "outputs.$output"

.forgejo/scripts/filter-devenv.sh

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
#!/usr/bin/env bash
2+
3+
# Filter devenv spinner noise from output, preserving error lines
4+
grep -v '^[⠋⠙⠹⠸⠼⠴⠦⠧⠇]' || true

.forgejo/scripts/tag-image.sh

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
#!/usr/bin/env zsh
2+
set -eu
3+
4+
usage() {
5+
echo >&2 "Usage: tag-image.sh <image-path> <arch>"
6+
}
7+
8+
if [[ $# -ne 2 ]]; then
9+
usage
10+
exit 22 # EINVAL
11+
fi
12+
13+
image_path=$1
14+
arch=$2
15+
16+
podman load <"$image_path"
17+
18+
version=$(podman images bits --format '{{.Tag}}' | head -1)
19+
echo "version=$version" >>"$GITHUB_OUTPUT"
20+
echo "Version: $version"
21+
22+
image="ghcr.io/jcf/bits"
23+
podman tag "bits:$version" "$image:$version-$arch"
24+
echo "image=$image" >>"$GITHUB_OUTPUT"

.forgejo/workflows/bootstrap.yml

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
name: Bootstrap
2+
3+
on:
4+
workflow_dispatch:
5+
push:
6+
branches: [main, morph]
7+
paths:
8+
- "pkgs/bits-ci/**"
9+
- ".forgejo/workflows/bootstrap.yml"
10+
11+
concurrency:
12+
group: ${{ github.workflow }}-${{ github.ref }}
13+
cancel-in-progress: true
14+
15+
jobs:
16+
build:
17+
name: Build
18+
runs-on: nixos
19+
20+
steps:
21+
- uses: actions/checkout@v4
22+
23+
- name: Configure Attic cache
24+
env:
25+
ATTIC_TOKEN: ${{ secrets.ATTIC_TOKEN }}
26+
run: .forgejo/scripts/attic-setup.sh
27+
28+
- name: Build CI container
29+
id: build
30+
run: |
31+
set -euo pipefail
32+
output=$(.forgejo/scripts/build.sh bits-ci-amd64 2>&1) || {
33+
echo "$output"
34+
exit 1
35+
}
36+
image_path=$(echo "$output" | .forgejo/scripts/filter-devenv.sh | tail -1)
37+
echo "image_path=$image_path" >> "$GITHUB_OUTPUT"
38+
39+
- name: Push closure to Attic cache
40+
run: nix-store -qR "${{ steps.build.outputs.image_path }}" | xargs attic push invetica:invetica
41+
42+
- name: Push to Forgejo
43+
env:
44+
REGISTRY_AUTH_FILE: ${{ runner.temp }}/auth.json
45+
run: |
46+
echo "${{ secrets.FORGEJO_PKG_TOKEN }}" | skopeo login git.lan.invetica.co.uk -u jcf --password-stdin
47+
version="$(date +%Y%m%d)-$(git rev-parse --short HEAD)"
48+
image="git.lan.invetica.co.uk/jcf/bits/bits-ci"
49+
skopeo copy \
50+
"docker-archive:${{ steps.build.outputs.image_path }}" \
51+
"docker://$image:$version"
52+
skopeo copy \
53+
"docker-archive:${{ steps.build.outputs.image_path }}" \
54+
"docker://$image:latest"
55+
echo ""
56+
echo "✨ Images pushed!"
57+
echo ""
58+
echo "$image:$version"
59+
echo "$image:latest"

0 commit comments

Comments
 (0)