Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
98 changes: 85 additions & 13 deletions .devcell.toml
Original file line number Diff line number Diff line change
@@ -1,21 +1,93 @@
# .devcell.toml — project-level DevCell overrides (merged on top of ~/.config/devcell/devcell.toml)
# .devcell.toml
# DevCell project configuration. Optional global defaults at ~/.config/devcell/devcell.toml

# [cell]
# image_tag = "latest-go"
# gui = true
[cell]
# Base stack (one of: base, go, node, python, fullstack, electronics, ultimate)
stack = "ultimate"
#
# Addon modules (from nixhome/modules/): desktop, electronics, financial,
# graphics, infra, news, nixos, qa-tools, scraping, travel, go, node, python
# modules = ["electronics", "desktop"]
#
# Disable GUI (Xvfb + VNC + browser). GUI is enabled by default.
# gui = false
# Timezone (IANA format). If omitted, inherits host $TZ.
# timezone = "Europe/Prague"

[op]
# 1Password items to resolve and inject as env vars.
# Requires `op` CLI on the host.
items = [
"prod-nmd-trips",
"prod-nmd-finances"
]
# AI agent configuration — all LLM settings in one place.
# [llm]
# Route Claude Code through a local ollama instance (Anthropic API compat).
# Equivalent to: cell claude --ollama
# use_ollama = false
#
# Project context injected into all AI agents (Claude, Codex, OpenCode).
# Sits on top of CLAUDE.md and agent-native config files.
# system_prompt = """
# This project uses PostgreSQL 16 with pgx/v5.
# API endpoints follow REST conventions at /api/v2/.
# """

# Git identity forwarded into the container.
# If omitted and no GIT_AUTHOR_* env vars are set, ~/.config/git/config is mounted read-only instead.
# [git]
# author_name = "Your Name"
# author_email = "you@example.com"
# committer_name = "Your Name" # defaults to author_name if omitted
# committer_email = "you@example.com" # defaults to author_email if omitted

# 1Password documents whose fields are passed into the container as env vars.
# Requires `op` CLI on the host. Each field in the document becomes an env var:
# e.g. a field labeled "API_KEY" with value "sk-123" → env var API_KEY=sk-123.
# [op]
# documents = ["prod-api-keys", "dev-secrets"]

# AWS credential scoping. When true, credentials are scoped to read-only
# via IAM session policy. All AWS tools (cli, terraform, SDKs, MCP servers)
# get read-only creds. Default: false (full access).
# [aws]
# read_only = true

# Port forwarding from container to host. Bare port = same on both sides.
# [ports]
# forward = ["3000", "8080:3000"]

# [env]
# Extra environment variables forwarded into the container.
# MY_VAR = "value"
[env]
# GITHUB_TOKEN = "ghp_xxx"
# ANTHROPIC_API_KEY = "sk-ant-xxx"

# mise runtime settings forwarded as MISE_<UPPER_KEY> env vars.
# See: https://mise.jdx.dev/configuration.html
[mise]
# trusted_config_paths = "/"
# idiomatic_version_file = "true"

# Extra volume mounts appended to docker run.
# [[volumes]]
# mount = "~/work/secrets:/run/secrets:ro"
#
# [[volumes]]
# mount = "~/.ssh:/home/user/.ssh:ro"

# [llm.models]
# Default LLM model (format: provider/model). Used by opencode and other agents.
# default = "ollama/deepseek-r1:32b"

# [llm.models.providers.ollama]
# models = ["deepseek-r1:32b", "qwen3:8b"]

# [llm.models.providers.lmstudio]
# base_url = "http://host.docker.internal:1234/v1"
# models = ["deepseek-r1:32b"]

# npm packages installed in the container. Edit and run 'cell build'.
# All core tools (claude-code, codex, slidev, patchright, opentofu-mcp) are
# managed via nix modules. Only add packages here that are NOT in nixhome.
# [packages.npm]
# "some-tool" = "^1.0.0"

# Python packages installed in the container. Edit and run 'cell build'.
[packages.python]
"pre-commit" = "*"
# "httpie" = "*"
# "pipx" = "*"
146 changes: 91 additions & 55 deletions .github/workflows/build.dev.yml
Original file line number Diff line number Diff line change
Expand Up @@ -12,16 +12,22 @@ on:
- feature/add-web
- feature/web
workflow_dispatch:
inputs:
skip_nix_cache:
description: 'Skip nix cache (genesis mode — full rebuild, no pre-seeding)'
type: boolean
default: false

permissions:
contents: write
packages: write
pages: write
id-token: write

env:
REGISTRY: ghcr.io
IMAGE_NAME: ${{ github.repository }}
NIX_CACHE_IMAGE: ${{ inputs.skip_nix_cache == true && 'public.ecr.aws/docker/library/debian:trixie-slim' || 'ghcr.io/dimmkirr/devcell:v0.0.0-ultimate' }}
ECR_REGISTRY: public.ecr.aws/w1l3v2k8/devcell

jobs:
secrets:
Expand Down Expand Up @@ -64,6 +70,10 @@ jobs:

- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
with:
buildkitd-config-inline: |
[worker.oci]
max-parallelism = 4

- name: Log in to GitHub Container Registry
uses: docker/login-action@v3
Expand All @@ -72,12 +82,47 @@ jobs:
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}

- name: Build and push ci group
run: docker buildx bake --push ci
- name: Configure AWS credentials
uses: aws-actions/configure-aws-credentials@v4
with:
role-to-assume: ${{ secrets.AWS_ECR_ROLE_ARN }}
aws-region: us-east-1

- name: Log in to ECR Public
uses: aws-actions/amazon-ecr-login@v2
with:
registry-type: public

- name: Pre-pull nix-cache as OCI layout
if: inputs.skip_nix_cache != true
run: |
skopeo copy --src-tls-verify=true \
docker://${{ env.REGISTRY }}/${{ env.IMAGE_NAME_LC }}:v0.0.0-ultimate \
oci:/tmp/nix-cache-oci:latest
echo "NIX_CACHE_OCI=/tmp/nix-cache-oci" >> "$GITHUB_ENV"

- name: Build and push ci group (GHCR)
run: >-
docker buildx bake
--set '*.output=type=image,push=true,compression=zstd,compression-level=3,force-compression=true'
${{ env.NIX_CACHE_OCI && format('--set ultimate.contexts.nix-cache=oci-layout://{0}', env.NIX_CACHE_OCI) || '' }}
ci
env:
VERSION: v0.0.0-${{ matrix.arch }}
PLATFORMS: ${{ matrix.platform }}
REGISTRY: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME_LC }}
CACHE_ARCH: -${{ matrix.arch }}

- name: Push to ECR Public
run: |
GHCR=${{ env.REGISTRY }}/${{ env.IMAGE_NAME_LC }}
ECR=${{ env.ECR_REGISTRY }}
V=v0.0.0-${{ matrix.arch }}
for suffix in "" "-core" "-ultimate"; do
SRC="${GHCR}:${V}${suffix}"
DST="${ECR}:${V}${suffix}"
docker buildx imagetools create -t "${DST}" "${SRC}"
done

docker-test:
name: Docker Test (${{ matrix.arch }}, ${{ matrix.variant }})
Expand Down Expand Up @@ -126,12 +171,18 @@ jobs:
go-version-file: go.mod
cache-dependency-path: go.sum

- name: Pull test images
run: |
docker pull ${{ env.REGISTRY }}/${{ env.IMAGE_NAME_LC }}:v0.0.0-${{ matrix.arch }}-${{ matrix.variant }}
docker pull ${{ env.REGISTRY }}/${{ env.IMAGE_NAME_LC }}:v0.0.0-${{ matrix.arch }}-core

- name: Run container tests
env:
DEVCELL_TEST_IMAGE: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME_LC }}:v0.0.0-${{ matrix.arch }}-${{ matrix.variant }}
DEVCELL_BASE_IMAGE: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME_LC }}:v0.0.0-${{ matrix.arch }}-base
DEVCELL_TEST_BASE_IMAGE: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME_LC }}:v0.0.0-${{ matrix.arch }}-base
DEVCELL_BASE_IMAGE: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME_LC }}:v0.0.0-${{ matrix.arch }}-core
DEVCELL_TEST_BASE_IMAGE: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME_LC }}:v0.0.0-${{ matrix.arch }}-core
DEVCELL_USER_IMAGE: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME_LC }}:v0.0.0-${{ matrix.arch }}-${{ matrix.variant }}
DEVCELL_TEST_PROJECT_DIR: ${{ runner.temp }}/devcell-test
MCP_SECRET_TEST_PASSWORD: fake-secret-ci-value
MCP_SECRET_GITHUB_TOKEN: fake-token-ci-value
run: |
Expand Down Expand Up @@ -159,10 +210,21 @@ jobs:
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}

- name: Create manifests
- name: Configure AWS credentials
uses: aws-actions/configure-aws-credentials@v4
with:
role-to-assume: ${{ secrets.AWS_ECR_ROLE_ARN }}
aws-region: us-east-1

- name: Log in to ECR Public
uses: aws-actions/amazon-ecr-login@v2
with:
registry-type: public

- name: Create GHCR manifests
run: |
R=${{ env.REGISTRY }}/${{ env.IMAGE_NAME_LC }}
for suffix in "" "-base" "-ultimate"; do
for suffix in "" "-core" "-ultimate"; do
docker buildx imagetools create \
-t "${R}:dev${suffix}" \
-t "${R}:latest${suffix}" \
Expand All @@ -171,6 +233,18 @@ jobs:
"${R}:v0.0.0-arm64${suffix}"
done

- name: Create ECR Public manifests
run: |
ECR=${{ env.ECR_REGISTRY }}
for suffix in "" "-core" "-ultimate"; do
docker buildx imagetools create \
-t "${ECR}:dev${suffix}" \
-t "${ECR}:latest${suffix}" \
-t "${ECR}:v0.0.0${suffix}" \
"${ECR}:v0.0.0-amd64${suffix}" \
"${ECR}:v0.0.0-arm64${suffix}"
done

cell-build:
name: Cell CLI Dev Build
needs: secrets
Expand Down Expand Up @@ -217,7 +291,7 @@ jobs:
- name: Publish release
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: gh release edit "${{ env.RELEASE_VERSION }}" --draft=false --latest=false
run: gh release edit "${{ env.RELEASE_VERSION }}" --draft=false --latest=false --prerelease

e2e-install:
name: E2E Install (${{ matrix.arch }})
Expand Down Expand Up @@ -256,6 +330,8 @@ jobs:
password: ${{ secrets.GITHUB_TOKEN }}

- name: Run cell claude --version (full pipeline)
env:
DEVCELL_NIXHOME_PATH: ${{ github.workspace }}/nixhome
run: |
# Simulate a new user in a fresh project dir
mkdir -p /tmp/e2e-project && cd /tmp/e2e-project
Expand Down Expand Up @@ -299,10 +375,15 @@ jobs:
/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)" < /dev/null
echo "/home/linuxbrew/.linuxbrew/bin" >> $GITHUB_PATH

- name: Brew install devcell
- name: Brew install devcell-dev
run: |
brew tap DimmKirr/tap
brew install devcell
brew install devcell-dev || true
# Verify binary was actually linked despite potential broken pipe
if ! command -v cell &>/dev/null; then
echo "Binary not found, retrying..."
brew install devcell-dev
fi

- name: Verify version
run: |
Expand All @@ -315,48 +396,3 @@ jobs:
exit 1
fi

deploy-site:
name: Deploy Site
needs: secrets
if: github.ref == 'refs/heads/main'
runs-on: ubuntu-latest
environment:
name: github-pages
url: ${{ steps.deployment.outputs.page_url }}
steps:
- uses: actions/checkout@v4

- name: Setup Go
uses: actions/setup-go@v5
with:
go-version-file: go.mod

- name: Generate CLI docs
run: go run $(ls cmd/*.go | grep -Ev '(_test|gendoc|main)\.go' | tr '\n' ' ') cmd/gendoc.go web/src/content/cell

- name: Setup Node
uses: actions/setup-node@v4
with:
node-version: 20
cache: npm
cache-dependency-path: web/package-lock.json

- name: Setup Pages
uses: actions/configure-pages@v5

- name: Install dependencies
run: npm ci
working-directory: web

- name: Build with Astro
run: npm run build
working-directory: web

- name: Upload artifact
uses: actions/upload-pages-artifact@v3
with:
path: ./web/dist

- name: Deploy to GitHub Pages
id: deployment
uses: actions/deploy-pages@v4
Loading
Loading