Skip to content

Commit 00a892d

Browse files
committed
Gemini inside a container
1 parent a36a0ec commit 00a892d

8 files changed

Lines changed: 534 additions & 8 deletions

File tree

.github/workflows/build-ai-dev.yml

Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,88 @@
1+
# Build and publish ai-dev container image
2+
# Triggered on changes to dot_files/ai-dev/ or manual dispatch
3+
# Image published to: ghcr.io/binarypie-dev/ai-dev:latest
4+
5+
name: Build ai-dev Image
6+
7+
concurrency:
8+
group: ${{ github.workflow }}-${{ github.ref }}
9+
cancel-in-progress: true
10+
11+
on:
12+
push:
13+
branches:
14+
- main
15+
paths:
16+
- 'dot_files/ai-dev/**'
17+
- '.github/workflows/build-ai-dev.yml'
18+
pull_request:
19+
paths:
20+
- 'dot_files/ai-dev/**'
21+
- '.github/workflows/build-ai-dev.yml'
22+
workflow_dispatch:
23+
schedule:
24+
# Rebuild daily to get updated packages
25+
- cron: '0 6 * * *'
26+
27+
env:
28+
IMAGE_NAME: ai-dev
29+
IMAGE_REGISTRY: ghcr.io/${{ github.repository_owner }}
30+
31+
jobs:
32+
build:
33+
runs-on: ubuntu-latest-m
34+
permissions:
35+
contents: read
36+
packages: write
37+
38+
steps:
39+
- name: Checkout repository
40+
uses: actions/checkout@v6
41+
42+
- name: Set up Docker Buildx
43+
uses: docker/setup-buildx-action@v3
44+
45+
- name: Log in to GitHub Container Registry
46+
if: github.event_name != 'pull_request'
47+
uses: docker/login-action@v3
48+
with:
49+
registry: ghcr.io
50+
username: ${{ github.actor }}
51+
password: ${{ secrets.GITHUB_TOKEN }}
52+
53+
- name: Extract metadata
54+
id: meta
55+
uses: docker/metadata-action@v5
56+
with:
57+
images: ${{ env.IMAGE_REGISTRY }}/${{ env.IMAGE_NAME }}
58+
tags: |
59+
type=raw,value=latest,enable=${{ github.ref == 'refs/heads/main' }}
60+
type=sha,prefix=
61+
type=ref,event=pr
62+
63+
- name: Build and push
64+
uses: docker/build-push-action@v6
65+
with:
66+
context: dot_files/ai-dev
67+
file: dot_files/ai-dev/Containerfile
68+
push: ${{ github.event_name != 'pull_request' }}
69+
tags: ${{ steps.meta.outputs.tags }}
70+
labels: ${{ steps.meta.outputs.labels }}
71+
cache-from: type=gha
72+
cache-to: type=gha,mode=max
73+
74+
- name: Generate build summary
75+
if: github.event_name != 'pull_request'
76+
run: |
77+
echo "## ai-dev Image Built" >> $GITHUB_STEP_SUMMARY
78+
echo "" >> $GITHUB_STEP_SUMMARY
79+
echo "**Image:** \`${{ env.IMAGE_REGISTRY }}/${{ env.IMAGE_NAME }}:latest\`" >> $GITHUB_STEP_SUMMARY
80+
echo "" >> $GITHUB_STEP_SUMMARY
81+
echo "### Usage" >> $GITHUB_STEP_SUMMARY
82+
echo "\`\`\`bash" >> $GITHUB_STEP_SUMMARY
83+
echo "# Run Claude Code" >> $GITHUB_STEP_SUMMARY
84+
echo "podman run --rm -it --user root --security-opt label=disable \\" >> $GITHUB_STEP_SUMMARY
85+
echo " -e HOST_UID=\$(id -u) -e HOST_GID=\$(id -g) -e HOME=\$HOME \\" >> $GITHUB_STEP_SUMMARY
86+
echo " -v \"\$(pwd):\$(pwd):rw\" -w \"\$(pwd)\" \\" >> $GITHUB_STEP_SUMMARY
87+
echo " ${{ env.IMAGE_REGISTRY }}/${{ env.IMAGE_NAME }}:latest claude" >> $GITHUB_STEP_SUMMARY
88+
echo "\`\`\`" >> $GITHUB_STEP_SUMMARY

.github/workflows/build-nvim-dev.yml

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
# Build and publish nvim-dev container image
22
# Triggered on changes to dot_files/nvim/ or manual dispatch
3-
# Image published to: ghcr.io/binarypie/nvim-dev:latest
3+
# Image published to: ghcr.io/binarypie-dev/nvim-dev:latest
44

55
name: Build nvim-dev Image
66

@@ -21,8 +21,8 @@ on:
2121
- '.github/workflows/build-nvim-dev.yml'
2222
workflow_dispatch:
2323
schedule:
24-
# Rebuild weekly to get updated packages
25-
- cron: '0 6 * * 0'
24+
# Rebuild daily to get updated packages
25+
- cron: '0 6 * * *'
2626

2727
env:
2828
IMAGE_NAME: nvim-dev

.github/workflows/check-package-versions.yml

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -253,13 +253,14 @@ jobs:
253253
env:
254254
GH_TOKEN: ${{ github.token }}
255255
run: |
256-
BRANCH="${{ steps.info.outputs.branch }}"
256+
TITLE="${{ steps.info.outputs.title }}"
257257
258-
# Check for PR with this branch
259-
EXISTING=$(gh pr list --head "$BRANCH" --json number --jq '.[0].number' 2>/dev/null) || EXISTING=""
258+
# Check for open PR with the same title
259+
EXISTING=$(gh pr list --state open --search "in:title $TITLE" --json number,title \
260+
--jq ".[] | select(.title == \"$TITLE\") | .number" 2>/dev/null | head -1) || EXISTING=""
260261
261262
if [[ -n "$EXISTING" ]]; then
262-
echo "PR #$EXISTING already exists for this update group"
263+
echo "PR #$EXISTING already exists with title: $TITLE"
263264
echo "exists=true" >> $GITHUB_OUTPUT
264265
else
265266
echo "exists=false" >> $GITHUB_OUTPUT

dot_files/ai-dev/Containerfile

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
# AI Development Environment (Sandboxed Podman Container)
2+
# Pre-built image with Claude Code and Gemini CLI
3+
#
4+
# Build: podman build -t ai-dev .
5+
# Run: podman run --rm -it --user 0:0 --security-opt label=disable \
6+
# -e HOME=$HOME -v "$(pwd):$(pwd):rw" -w "$(pwd)" localhost/ai-dev
7+
8+
FROM ghcr.io/binarypie-dev/nvim-dev:latest
9+
10+
# =============================================================================
11+
# LAYER 1: Claude Code (native install)
12+
# =============================================================================
13+
USER linuxbrew
14+
WORKDIR /home/linuxbrew
15+
16+
RUN curl -fsSL https://claude.ai/install.sh | bash
17+
18+
# =============================================================================
19+
# LAYER 2: Gemini CLI via npm
20+
# =============================================================================
21+
RUN npm install -g @google/gemini-cli
22+
23+
# =============================================================================
24+
# LAYER 3: Entrypoint script (sets PATH, execs command)
25+
# =============================================================================
26+
USER root
27+
COPY ai-entrypoint.sh /usr/local/bin/ai-entrypoint.sh
28+
RUN chmod +x /usr/local/bin/ai-entrypoint.sh
29+
30+
# In rootless podman, --user 0:0 maps to host UID (no privilege escalation)
31+
ENTRYPOINT ["/usr/local/bin/ai-entrypoint.sh"]
32+
CMD ["bash"]
33+
34+
# Labels for GitHub Container Registry
35+
LABEL org.opencontainers.image.source="https://github.com/binarypie/hypercube"
36+
LABEL org.opencontainers.image.description="AI development environment with Claude Code and Gemini CLI"
37+
LABEL org.opencontainers.image.licenses="MIT"

0 commit comments

Comments
 (0)