From 80f20474b684848d5085b92b3ab18d1ccd550f6a Mon Sep 17 00:00:00 2001 From: Story Crater Bot <19826264+Riotpiaole@users.noreply.github.com> Date: Sun, 23 Aug 2026 16:05:18 -0700 Subject: [PATCH] Standardize CI/CD: use homelab-frontend pattern (REGISTRY_PAT, docker:27-cli, all repos) --- .forgejo/workflows/TEMPLATE.md | 156 +++++++++++++++++++++++ .forgejo/workflows/build.yaml | 66 +++++----- CI-FOR-ALL-POIMEN-REPOS.md | 224 +++++++++++++++++++++++++++++++++ CI-SETUP.md | 186 +++++++++++++++------------ QUICK-START.md | 80 ++++++++++++ 5 files changed, 603 insertions(+), 109 deletions(-) create mode 100644 .forgejo/workflows/TEMPLATE.md create mode 100644 CI-FOR-ALL-POIMEN-REPOS.md create mode 100644 QUICK-START.md diff --git a/.forgejo/workflows/TEMPLATE.md b/.forgejo/workflows/TEMPLATE.md new file mode 100644 index 0000000..d9304fb --- /dev/null +++ b/.forgejo/workflows/TEMPLATE.md @@ -0,0 +1,156 @@ +# CI/CD Workflow Template for Poimen Repos + +## Pattern Used by Homelab-Frontend + +**File**: `.gitea/workflows/build-prod.yaml` (equivalent: `.forgejo/workflows/build.yaml`) + +### Key Components + +```yaml +jobs: + build: + runs-on: golang # or rust, or docker + container: + image: docker:27-cli + volumes: + - /docker-certs/client:/docker-certs/client:ro + env: + DOCKER_HOST: tcp://localhost:2376 + DOCKER_TLS_VERIFY: "1" + DOCKER_CERT_PATH: /docker-certs/client + steps: + - name: Registry login + run: | + echo "${REGISTRY_PAT}" | docker login "${REGISTRY}" \ + --username rock --password-stdin + env: + REGISTRY_PAT: ${{ secrets.REGISTRY_PAT }} + + - name: Build + run: docker build -t "${IMAGE}:latest" . + + - name: Push + run: docker push "${IMAGE}:latest" +``` + +--- + +## How to Apply to Any Poimen Repo + +### Step 1: Create Personal Access Token + +```bash +# In browser: https://git.riotpiao.com/user/settings/tokens +# Or use the existing 'rock' PAT for the organization +``` + +### Step 2: Set Repository Secret + +Go to **`https://git.riotpiao.com/rock//settings/secrets`** + +Add secret: +- **Name**: `REGISTRY_PAT` +- **Value**: `` + +### Step 3: Create Workflow File + +Copy this to `.forgejo/workflows/build.yaml`: + +```yaml +name: Build and Push + +on: + push: + branches: [main] + +env: + REGISTRY: forgejo.riotpiao.com + IMAGE_NAME: rock/ + +jobs: + test: + runs-on: rust # or golang, or docker + steps: + - uses: actions/checkout@v4 + - name: Run tests + run: cargo test --all # adjust for your language + + build: + runs-on: golang + needs: test + if: github.event_name == 'push' && github.ref == 'refs/heads/main' + container: + image: docker:27-cli + volumes: + - /docker-certs/client:/docker-certs/client:ro + env: + DOCKER_HOST: tcp://localhost:2376 + DOCKER_TLS_VERIFY: "1" + DOCKER_CERT_PATH: /docker-certs/client + steps: + - name: install node (required by JS-based actions) + run: apk add --no-cache nodejs git + + - uses: actions/checkout@v4 + + - name: Registry login + run: | + echo "${REGISTRY_PAT}" | docker login "${REGISTRY}" \ + --username rock --password-stdin + env: + REGISTRY_PAT: ${{ secrets.REGISTRY_PAT }} + + - name: Build + run: | + docker build \ + -t "${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:latest" \ + -t "${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:${{ github.sha }}" \ + . + + - name: Push + run: | + docker push "${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:latest" + docker push "${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:${{ github.sha }}" +``` + +--- + +## Apply to Poimen Repos + +### poimen-memory ✅ (current) +- Status: Uses `FORGEJO_TOKEN` (built-in) +- Can upgrade to `REGISTRY_PAT` pattern + +### poimen (orchestrator) +- If has Dockerfile: add workflow +- If K8s-only: validate with `yamllint` + `kustomize` + +### poimen-workflows +- If has Docker: add workflow +- Otherwise: validate YAML only + +### Pattern for All Repos + +``` +.forgejo/workflows/ +├── build.yaml # For repos with Dockerfile +├── validate.yaml # For K8s-only repos (like homelab) +``` + +--- + +## Summary + +**Established Pattern**: +1. `REGISTRY_PAT` secret in repo +2. `docker login` → `docker build` → `docker push` +3. Image tagged: `latest` + commit SHA +4. ArgoCD watches and auto-deploys + +**Once set up once**: +- Every push triggers build +- Image auto-pushes to registry +- ArgoCD syncs automatically +- Zero manual intervention + +**Effort**: ~5 minutes per repo (token + secret + workflow file) diff --git a/.forgejo/workflows/build.yaml b/.forgejo/workflows/build.yaml index 0e78144..17d378c 100644 --- a/.forgejo/workflows/build.yaml +++ b/.forgejo/workflows/build.yaml @@ -8,7 +8,7 @@ on: env: REGISTRY: forgejo.riotpiao.com - IMAGE_NAME: rock/poimen-memory + IMAGE: forgejo.riotpiao.com/rock/poimen-memory jobs: test: @@ -17,39 +17,49 @@ jobs: steps: - uses: actions/checkout@v4 - - name: Run cargo build - run: cargo build --workspace - - - name: Run cargo test + - name: Run tests run: cargo test --all - build-image: - name: Build and Push Image - runs-on: rust + build: + name: Build and push image + runs-on: golang needs: test if: github.event_name == 'push' && github.ref == 'refs/heads/main' + container: + image: docker:27-cli + volumes: + - /docker-certs/client:/docker-certs/client:ro + env: + DOCKER_HOST: tcp://localhost:2376 + DOCKER_TLS_VERIFY: "1" + DOCKER_CERT_PATH: /docker-certs/client steps: + - name: install node (required by JS-based actions) + run: apk add --no-cache nodejs git + - uses: actions/checkout@v4 - - - name: Build Docker image + + - name: Get short SHA + id: sha + run: | + SHORT_SHA=$(git rev-parse --short HEAD) + echo "short_sha=${SHORT_SHA}" >> $GITHUB_OUTPUT + + - name: Registry login + run: | + echo "${REGISTRY_PAT}" | docker login "${REGISTRY}" \ + --username rock --password-stdin + env: + REGISTRY_PAT: ${{ secrets.REGISTRY_PAT }} + + - name: Build run: | docker build \ - -t ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:latest \ - -t ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:${{ github.sha }} \ - -f Dockerfile . - - echo "Built images:" - docker images | grep "${{ env.IMAGE_NAME }}" - - - name: Login to registry and push + -t "${IMAGE}:${{ steps.sha.outputs.short_sha }}" \ + -t "${IMAGE}:latest" \ + . + + - name: Push run: | - # Use Forgejo's actor token which has registry access - echo "${{ secrets.FORGEJO_TOKEN }}" | docker login ${{ env.REGISTRY }} \ - -u ${{ github.actor }} --password-stdin - - docker push ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:latest - docker push ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:${{ github.sha }} - - echo "Image pushed: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:latest" - env: - FORGEJO_TOKEN: ${{ secrets.FORGEJO_TOKEN }} + docker push "${IMAGE}:${{ steps.sha.outputs.short_sha }}" + docker push "${IMAGE}:latest" diff --git a/CI-FOR-ALL-POIMEN-REPOS.md b/CI-FOR-ALL-POIMEN-REPOS.md new file mode 100644 index 0000000..88336d7 --- /dev/null +++ b/CI-FOR-ALL-POIMEN-REPOS.md @@ -0,0 +1,224 @@ +# CI/CD for All Poimen Repos — Standardized Pattern + +## Overview + +All Poimen repos should follow the same CI/CD pattern for consistency and maintainability. + +**Pattern**: Test locally → Build image → Push to registry → ArgoCD deploys + +**Based on**: homelab-frontend (proven production pattern) + +--- + +## Repos & Status + +### Repos That Need Docker Deployment + +| Repo | Status | Dockerfile | Notes | +|------|--------|-----------|-------| +| **poimen-memory** | ✅ Ready | Yes | This repo - see `.forgejo/workflows/build.yaml` | +| **poimen** | ⏳ TBD | Yes (assumed) | Orchestrator - needs deployment | +| **poimen-workflows** | ⏳ TBD | Maybe | Check if containerized | + +### Repos That Don't Need Docker + +| Repo | Status | Type | Notes | +|------|--------|------|-------| +| **homelab** | ✅ Done | K8s manifests | Validates with yamllint + kubeval | + +--- + +## Implementation Checklist for Each Repo + +### Step 0: Prerequisites +- [ ] Repo has a `Dockerfile` +- [ ] Repo has a `.forgejo/` or `.gitea/` directory +- [ ] Docker builds successfully: `docker build -t test:latest .` +- [ ] Tests pass: `cargo test` / `npm test` / etc + +### Step 1: Create Workflow File +```bash +# Copy from poimen-memory: +cp ~/workplace/Poimen/memory/.forgejo/workflows/build.yaml \ + ~/workplace/Poimen//.forgejo/workflows/build.yaml + +# Edit if needed: +# - Change IMAGE_NAME from "rock/poimen-memory" to "rock/" +# - Adjust test command if not Rust (cargo test) +``` + +### Step 2: Set Repository Secret +``` +https://git.riotpiao.com/rock//settings/secrets + +Add: +- Name: REGISTRY_PAT +- Value: +``` + +### Step 3: Commit & Push +```bash +git add .forgejo/workflows/build.yaml +git commit -m "Add CI/CD: auto-build and push to registry" +git push origin main +``` + +### Step 4: Create ArgoCD Application +```bash +# Create k8s/argocd/-app.yaml + +apiVersion: argoproj.io/v1alpha1 +kind: Application +metadata: + name: poimen--app + namespace: argocd +spec: + project: homelab + source: + repoURL: https://forgejo.riotpiao.com/rock/poimen-.git + targetRevision: main + path: k8s/app # adjust if different + destination: + server: https://kubernetes.default.svc + namespace: poimen + syncPolicy: + automated: + prune: true + selfHeal: true +``` + +### Step 5: Apply Application +```bash +kubectl apply -f k8s/argocd/-app.yaml +``` + +### Done! ✅ +- Every push to main triggers: + 1. Test suite + 2. Docker build + 3. Push to `forgejo.riotpiao.com/rock/:latest` + 4. ArgoCD auto-deploys + +--- + +## File Reference + +### Workflow Comparison + +**poimen-memory** (current): +```yaml +runs-on: golang +container: + image: docker:27-cli + volumes: + - /docker-certs/client:/docker-certs/client:ro +env: + DOCKER_HOST: tcp://localhost:2376 + DOCKER_TLS_VERIFY: "1" + DOCKER_CERT_PATH: /docker-certs/client +``` + +**Why this setup:** +- Runs on `golang` runner (has Docker daemon) +- Uses Docker CLI in container with DinD (Docker-in-Docker) +- TLS certs mounted for secure daemon access +- Allows building AND pushing in same job + +### Test Job + +Adjust for your language: + +**Rust** (poimen-memory): +```yaml +runs-on: rust +steps: + - uses: actions/checkout@v4 + - run: cargo test --all +``` + +**Go**: +```yaml +runs-on: golang +steps: + - uses: actions/checkout@v4 + - run: go test ./... +``` + +**Node.js**: +```yaml +runs-on: docker +steps: + - uses: actions/checkout@v4 + - run: npm install && npm test +``` + +--- + +## Organization-Wide Setup + +### One-Time: Set Organization Secret +Instead of per-repo secrets, Forgejo supports organization secrets. + +**If available**, set `REGISTRY_PAT` at org level: +``` +https://git.riotpiao.com/rock/settings/secrets +``` + +Then all repos automatically inherit it (no per-repo setup needed). + +**Check**: Try accessing org secrets settings +- If available: set once, use everywhere +- If not: set per-repo (5 minutes per repo) + +--- + +## Monitoring & Troubleshooting + +### Build Failures + +**Check logs:** +``` +https://git.riotpiao.com/rock//actions +``` + +**Common issues:** +- Test failures → Fix tests locally +- Docker build error → Check Dockerfile syntax +- Push fails → Verify REGISTRY_PAT token + +### Deployment Issues + +**Watch ArgoCD:** +```bash +kubectl get application -n argocd poimen--app -w +kubectl logs -n argocd argocd-application-controller | grep poimen +``` + +**Check pods:** +```bash +kubectl get pods -n poimen -l app.kubernetes.io/name=poimen- -w +kubectl describe pod -n poimen +``` + +--- + +## Summary + +**Effort**: ~10 minutes per repo (once) + +**Benefit**: +- Zero-touch deployments +- Every commit automatically tested & deployed +- Consistent across organization +- No manual image pushes ever + +**Best practice**: Use org-level secret if available (1 setup, unlimited repos) + +--- + +## Next Steps + +1. **poimen-memory**: ✅ Done (this repo) +2. **poimen**: Set up workflow + secret +3. **poimen-workflows**: Set up workflow + secret +4. **Document in**: homelab-poimen-standard.md (org wiki) diff --git a/CI-SETUP.md b/CI-SETUP.md index 34fa2c3..e8fff1a 100644 --- a/CI-SETUP.md +++ b/CI-SETUP.md @@ -1,40 +1,45 @@ -# CI/CD Setup — Forgejo Actions Registry Credentials +# CI/CD Setup — Registry Push Configuration -## Required Configuration +## One-Time Setup -The CI pipeline (`.forgejo/workflows/build.yaml`) automatically builds and pushes Docker images on each push to `main`. However, it requires registry credentials to be configured as repository secrets. +The CI/CD pipeline automatically builds and pushes Docker images when you push to `main`. -### Setup Steps +### 1. Create or Get Registry Token -#### 1. **Get Registry Credentials** - -From the homelab setup: +**Option A: Use Organization Token** (Recommended) ```bash -# Get ci-bot token (or use your personal access token) -kubectl get secret -n poimen $(kubectl get secret -n poimen -l app.kubernetes.io/name=ci-bot -o name | head -1) -o jsonpath='{.data.token}' | base64 -d +# Ask Rock for the existing 'rock' organization PAT +# It should already have write:package permissions ``` -Or use a personal Forgejo access token: -- URL: https://forgejo.riotpiao.com/user/settings/tokens -- Create token with `write:package` scope +**Option B: Create Personal Token** +```bash +# In browser: https://git.riotpiao.com/user/settings/tokens +# 1. Click "Generate New Token" +# 2. Name: "Docker Registry" +# 3. Scope: Check `write:package` +# 4. Generate and copy the token +``` -#### 2. **Set Repository Secrets** +### 2. Add Repository Secret Go to: **https://git.riotpiao.com/rock/poimen-memory/settings/secrets** -Add two secrets: -- **`REGISTRY_USER`**: `ci-bot` (or your username) -- **`REGISTRY_TOKEN`**: `` +Add secret: +- **Name**: `REGISTRY_PAT` +- **Value**: `` +- **Save** -#### 3. **Verify Setup** +### 3. Verify Setup -Push a commit and check: ```bash -# Via web UI -https://git.riotpiao.com/rock/poimen-memory/actions +# Push a commit (any change will do) +cd ~/workplace/Poimen/memory +git commit --allow-empty -m "Trigger CI build" +git push origin main -# Or check if image exists -docker pull forgejo.riotpiao.com/rock/poimen-memory:latest +# Check Actions tab +# https://git.riotpiao.com/rock/poimen-memory/actions ``` --- @@ -42,82 +47,101 @@ docker pull forgejo.riotpiao.com/rock/poimen-memory:latest ## How It Works ``` -┌─────────────────┐ -│ Push to main │ -└────────┬────────┘ - │ - ↓ -┌─────────────────────────────────────────┐ -│ Forgejo Actions (rust runner) │ -│ 1. cargo build --workspace │ -│ 2. cargo test --all │ -└────────┬────────────────────────────────┘ - │ - ↓ (only if tests pass) -┌─────────────────────────────────────────┐ -│ Build Docker Image │ -│ docker build -t forgejo.../latest . │ -└────────┬────────────────────────────────┘ - │ - ↓ -┌─────────────────────────────────────────┐ -│ Push to Registry │ -│ docker login + push │ -│ Uses: REGISTRY_USER + REGISTRY_TOKEN │ -└────────┬────────────────────────────────┘ - │ - ↓ -┌─────────────────────────────────────────┐ -│ ArgoCD Detects Image │ -│ Syncs k8s/app/ with new image │ -└────────┬────────────────────────────────┘ - │ - ↓ -┌─────────────────────────────────────────┐ -│ K8s Deployment │ -│ Pulls new image, restarts pods │ -└─────────────────────────────────────────┘ +Push to main + ↓ +Forgejo Actions triggered + ↓ +Test: cargo test --all + ↓ (only if tests pass) +Build: docker build -t forgejo.riotpiao.com/rock/poimen-memory:latest . + ↓ +Push: docker push (using REGISTRY_PAT secret) + ↓ +ArgoCD detects new image + ↓ +Auto-deploy to poimen namespace +``` + +--- + +## Check Status + +**Web UI** — See build progress: +``` +https://git.riotpiao.com/rock/poimen-memory/actions +``` + +**CLI** — Watch deployment: +```bash +kubectl get application -n argocd poimen-memory-app -w +kubectl get pods -n poimen -l app.kubernetes.io/name=poimen-memory -w +``` + +**Verify Image** — Check registry: +```bash +docker pull forgejo.riotpiao.com/rock/poimen-memory:latest +``` + +--- + +## Once Image is Ready + +```bash +# Port forward to local +kubectl port-forward -n poimen svc/poimen-memory 8080:80 & + +# Test +curl http://localhost:8080/health ``` --- ## Troubleshooting -### Build Fails During Tests -- Check workflow logs: https://git.riotpiao.com/rock/poimen-memory/actions -- Run locally: `cargo test --all` +### Secret Not Found Error +- Go to: https://git.riotpiao.com/rock/poimen-memory/settings/secrets +- Verify `REGISTRY_PAT` is set -### Image Not Pushing -- Verify `REGISTRY_TOKEN` secret is set correctly -- Check docker login error in workflow logs -- Ensure token has `write:package` scope +### Login Failed +- Token might be expired or revoked +- Create a new token and update the secret -### ArgoCD Not Syncing -```bash -kubectl get application -n argocd poimen-memory-app -o yaml | grep -A 5 status -``` +### Build Failed +- Check Actions logs for the error +- Usually: tests failed +- Fix locally: `cargo test --all` + +### Image Exists But Pods Not Running +- Check pod events: `kubectl describe pod -n poimen ` +- Usually: image pull policy issue or pod crashed +- Check logs: `kubectl logs -n poimen deployment/poimen-memory` --- -## Manual Alternative +## Apply to Other Repos -If CI is not working, you can push manually: +The same setup works for all Poimen repos: ```bash -# From homelab machine (has registry access) -cd ~/workplace/Poimen/memory -cargo build --release -docker build -t forgejo.riotpiao.com/rock/poimen-memory:latest . -docker push forgejo.riotpiao.com/rock/poimen-memory:latest +# For poimen, poimen-workflows, etc: +# 1. Create .forgejo/workflows/build.yaml (copy from template below) +# 2. Add REGISTRY_PAT secret +# 3. Push and watch it deploy ``` -But the goal is **zero-touch CI/CD**, so set up the secrets once and forget about it. +**Template**: See `.forgejo/workflows/TEMPLATE.md` in this repo --- -## Status +## Pattern Overview -- ✅ Workflow file: `.forgejo/workflows/build.yaml` -- ✅ ArgoCD App: `k8s/argocd/memory-app.yaml` -- ⏳ **Required**: Set `REGISTRY_USER` and `REGISTRY_TOKEN` secrets -- ⏳ Then: Push to main, watch image build and deploy automatically +**Based on**: homelab-frontend (proven production pattern) +- Uses `REGISTRY_PAT` secret ✓ +- Docker login + push ✓ +- Tags: commit SHA + latest ✓ +- ArgoCD watches tags ✓ + +**Consistency**: All Poimen repos use same pattern +- Same secret name: `REGISTRY_PAT` +- Same workflow structure +- Same deployment process diff --git a/QUICK-START.md b/QUICK-START.md new file mode 100644 index 0000000..6c9fbb8 --- /dev/null +++ b/QUICK-START.md @@ -0,0 +1,80 @@ +# Quick Start — One-Time CI/CD Setup (3 minutes) + +## 🚀 Setup + +### 1. Get Registry Token +```bash +# Ask for the 'rock' org token (already has write:package) +# OR create one: https://git.riotpiao.com/user/settings/tokens +# - Scope: write:package +# - Copy the token value +``` + +### 2. Add Secret to Repository +```bash +# Go to: https://git.riotpiao.com/rock/poimen-memory/settings/secrets +# Add: Name=REGISTRY_PAT, Value= +# Save +``` + +### 3. Push to Trigger Build +```bash +cd ~/workplace/Poimen/memory +git commit --allow-empty -m "Trigger CI" +git push +``` + +--- + +## ✨ That's It! + +After these 3 steps, every push automatically: +- ✅ Runs all tests +- ✅ Builds Docker image +- ✅ Pushes to `forgejo.riotpiao.com/rock/poimen-memory:latest` +- ✅ ArgoCD deploys to K8s + +--- + +## 📊 Monitor + +```bash +# Watch build +https://git.riotpiao.com/rock/poimen-memory/actions + +# Watch deployment +kubectl get pods -n poimen -l app.kubernetes.io/name=poimen-memory -w +``` + +--- + +## 🧪 Test When Ready + +```bash +# Port forward +kubectl port-forward -n poimen svc/poimen-memory 8080:80 & + +# Health check +curl http://localhost:8080/health +``` + +--- + +## 🔄 Apply to Other Repos + +Same pattern for `poimen`, `poimen-workflows`, etc: + +1. Add `REGISTRY_PAT` secret +2. Copy `.forgejo/workflows/build.yaml` from this repo +3. Push + +See `CI-SETUP.md` for details. + +--- + +## Pattern Details + +- **Based on**: homelab-frontend (proven pattern) +- **Runner**: docker:27-cli (supports buildx) +- **Tags**: commit SHA + "latest" +- **No manual steps**: Fully automated