The deploy-openclaw job required a CONFIG_REPO_TOKEN secret that was never configured, causing it to fail on every CI run. Tag updates for the openclaw HelmRelease are now handled by Renovate, which detects new images in registry.johnogle.info and opens PRs against k3s-cluster-config to update manifests. The build-and-push-openclaw job remains: it builds the thin Docker image and pushes it to the registry. Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent) Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
175 lines
6.3 KiB
YAML
175 lines
6.3 KiB
YAML
name: CI
|
|
|
|
on:
|
|
push:
|
|
branches: [main]
|
|
pull_request:
|
|
branches: [main]
|
|
|
|
jobs:
|
|
check:
|
|
runs-on: ubuntu-latest
|
|
steps:
|
|
- uses: actions/checkout@v6
|
|
|
|
- uses: https://git.johnogle.info/johno/gitea-actions/nix-setup@v1
|
|
|
|
- name: Check flake
|
|
run: nix flake check
|
|
env:
|
|
NIX_CONFIG: "access-tokens = git.johnogle.info=${{ secrets.GITEA_ACCESS_TOKEN }}"
|
|
|
|
build-and-cache:
|
|
runs-on: ubuntu-latest
|
|
needs: check
|
|
if: github.event_name == 'push' && github.ref == 'refs/heads/main'
|
|
steps:
|
|
- uses: actions/checkout@v6
|
|
|
|
- uses: https://git.johnogle.info/johno/gitea-actions/nix-setup@v1
|
|
|
|
- name: Setup SSH for cache
|
|
run: |
|
|
mkdir -p ~/.ssh
|
|
echo "${{ secrets.CACHE_SSH_KEY }}" > ~/.ssh/cache_key
|
|
chmod 600 ~/.ssh/cache_key
|
|
ssh-keyscan -H ${{ secrets.CACHE_HOST }} >> ~/.ssh/known_hosts 2>/dev/null || true
|
|
|
|
- name: Setup signing key
|
|
run: |
|
|
echo "${{ secrets.NIX_SIGNING_KEY }}" > /tmp/signing-key
|
|
chmod 600 /tmp/signing-key
|
|
|
|
- name: Build, sign, and cache all packages
|
|
run: |
|
|
PACKAGES=(
|
|
custom-claude-code
|
|
custom-app-launcher-server
|
|
custom-mcrcon-rbw
|
|
custom-tea-rbw
|
|
custom-rclone-torbox-setup
|
|
custom-opencode
|
|
custom-qmd
|
|
openclaw-runtime-closure
|
|
custom-nextcloud-talk-desktop
|
|
qt-pinned-jellyfin-media-player
|
|
qt-pinned-stremio
|
|
nix-deck-kernel
|
|
)
|
|
|
|
FAILED=()
|
|
SKIPPED=()
|
|
for pkg in "${PACKAGES[@]}"; do
|
|
echo "::group::Building $pkg"
|
|
|
|
# Check if package is already cached by evaluating its store path and checking the remote
|
|
OUT_PATH=$(nix eval ".#$pkg.outPath" --raw 2>/dev/null)
|
|
if [ -n "$OUT_PATH" ] && ssh -i ~/.ssh/cache_key ${{ secrets.CACHE_USER }}@${{ secrets.CACHE_HOST }} \
|
|
"nix path-info '$OUT_PATH' >/dev/null 2>&1"; then
|
|
echo "⏭ $pkg already cached ($OUT_PATH), skipping"
|
|
SKIPPED+=("$pkg")
|
|
echo "::endgroup::"
|
|
continue
|
|
fi
|
|
|
|
# --cores 2 limits parallel jobs to reduce RAM pressure on john-endesktop
|
|
if BUILD_OUTPUT=$(nix build ".#$pkg" --no-link --print-out-paths --cores 2 2>&1); then
|
|
OUT_PATH=$(echo "$BUILD_OUTPUT" | grep '^/nix/store/' | tail -1)
|
|
echo "$BUILD_OUTPUT"
|
|
echo "Store path: $OUT_PATH"
|
|
|
|
# Sign the closure
|
|
nix store sign --key-file /tmp/signing-key -r "$OUT_PATH"
|
|
|
|
# Push to cache
|
|
nix copy --to "ssh-ng://${{ secrets.CACHE_USER }}@${{ secrets.CACHE_HOST }}?ssh-key=$HOME/.ssh/cache_key" "$OUT_PATH"
|
|
|
|
# Create GC root to prevent garbage collection
|
|
OUT_HASH=$(basename "$OUT_PATH" | cut -d'-' -f1)
|
|
ssh -i ~/.ssh/cache_key ${{ secrets.CACHE_USER }}@${{ secrets.CACHE_HOST }} \
|
|
"mkdir -p /nix/var/nix/gcroots/ci-cache && ln -sfn $OUT_PATH /nix/var/nix/gcroots/ci-cache/${OUT_HASH}"
|
|
|
|
echo "✓ $pkg cached successfully"
|
|
else
|
|
echo "✗ $pkg failed to build"
|
|
FAILED+=("$pkg")
|
|
fi
|
|
echo "::endgroup::"
|
|
done
|
|
|
|
if [ ${#SKIPPED[@]} -gt 0 ]; then
|
|
echo "Skipped (already cached): ${SKIPPED[*]}"
|
|
fi
|
|
|
|
if [ ${#FAILED[@]} -gt 0 ]; then
|
|
echo "::error::Failed packages: ${FAILED[*]}"
|
|
exit 1
|
|
fi
|
|
env:
|
|
NIX_CONFIG: "access-tokens = git.johnogle.info=${{ secrets.GITEA_ACCESS_TOKEN }}"
|
|
|
|
build-and-push-openclaw:
|
|
name: Build & Push OpenClaw Image
|
|
runs-on: ubuntu-latest
|
|
needs: check
|
|
if: github.event_name == 'push' && github.ref == 'refs/heads/main'
|
|
outputs:
|
|
image_tag: ${{ steps.meta.outputs.tag }}
|
|
steps:
|
|
- uses: actions/checkout@v6
|
|
|
|
- uses: https://git.johnogle.info/johno/gitea-actions/nix-setup@v1
|
|
|
|
- name: Setup SSH for cache
|
|
run: |
|
|
mkdir -p ~/.ssh
|
|
echo "${{ secrets.CACHE_SSH_KEY }}" > ~/.ssh/cache_key
|
|
chmod 600 ~/.ssh/cache_key
|
|
ssh-keyscan -H ${{ secrets.CACHE_HOST }} >> ~/.ssh/known_hosts 2>/dev/null || true
|
|
|
|
- name: Generate image tag
|
|
id: meta
|
|
run: |
|
|
# Read the image tag from the nix definition's tag attribute
|
|
# buildLayeredImage sets tag from openclawImageTag in default.nix
|
|
IMAGE_TAG=$(nix eval .#packages.x86_64-linux.openclaw-image.imageTag --raw 2>/dev/null || \
|
|
nix eval .#openclaw-image.imageTag --raw 2>/dev/null || \
|
|
nix eval .#openclaw-image.outPath --raw 2>/dev/null | xargs basename | sed 's/.*-//')
|
|
# Fallback to short SHA if tag extraction fails
|
|
if [ -z "$IMAGE_TAG" ] || [ "$IMAGE_TAG" = "tar.gz" ]; then
|
|
IMAGE_TAG=$(echo "${{ github.sha }}" | cut -c1-7)
|
|
fi
|
|
echo "tag=${IMAGE_TAG}" >> $GITHUB_OUTPUT
|
|
echo "Image will be tagged: ${IMAGE_TAG}"
|
|
|
|
- name: Build Docker image with Nix
|
|
run: nix build .#openclaw-image --cores 2
|
|
env:
|
|
NIX_CONFIG: "access-tokens = git.johnogle.info=${{ secrets.GITEA_ACCESS_TOKEN }}"
|
|
|
|
- name: Load and tag image
|
|
run: |
|
|
docker load < result
|
|
docker tag openclaw:${{ steps.meta.outputs.tag }} registry.johnogle.info/openclaw:${{ steps.meta.outputs.tag }}
|
|
docker tag openclaw:${{ steps.meta.outputs.tag }} registry.johnogle.info/openclaw:latest
|
|
|
|
- name: Login to registry
|
|
run: |
|
|
echo "${{ secrets.REGISTRY_PASSWORD }}" | docker login registry.johnogle.info -u ${{ secrets.REGISTRY_USERNAME }} --password-stdin
|
|
|
|
- name: Push image
|
|
run: |
|
|
# Push versioned tag with retry (large images can timeout on slow connections)
|
|
for i in 1 2 3; do
|
|
if docker push registry.johnogle.info/openclaw:${{ steps.meta.outputs.tag }}; then
|
|
break
|
|
fi
|
|
echo "Push attempt $i failed, retrying in 10s..."
|
|
sleep 10
|
|
done
|
|
# Push latest tag — mostly a manifest push since layers already exist
|
|
docker push registry.johnogle.info/openclaw:latest || \
|
|
echo "::warning::Failed to push :latest tag (versioned tag already pushed)"
|
|
|
|
|