Files
homelab/project-usage/cicd-workflow.md
T

223 lines
5.1 KiB
Markdown
Raw Normal View History

# CI/CD Pipeline (Forgejo + Argo CD)
**Git Forge:** `https://forgejo.riotpiao.com`
**Deployments:** `https://argocd.riotpiao.com` (or `kubectl port-forward`)
**Namespaces:** `cicd`, `forge`
## When to Use
- **Build & test** — Forgejo Actions CI (GitHub Actions syntax)
- **Image push** — Build OCI images, push to Forgejo registry
- **GitOps deployment** — Argo CD syncs deploy repo to cluster
- **Secrets in CI** — ci-bot JWT tokens, never kubeconfig
## Quick Start
**1. Clone a repo from Forgejo:**
```bash
git clone https://forgejo.riotpiao.com/rock/source.git
cd source
```
**2. Create workflow:**
```bash
mkdir -p .forgejo/workflows
cat > .forgejo/workflows/ci.yml <<EOF
name: CI
on: [push]
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- run: npm test
- run: docker build -t myapp:latest .
- run: |
docker login forgejo.riotpiao.com \
-u ci-bot \
-p ${{ secrets.CI_BOT_TOKEN }}
docker push forgejo.riotpiao.com/rock/myapp:latest
EOF
git add .forgejo/workflows/ci.yml
git commit -m "ci: add build workflow"
git push
```
**3. Trigger deployment:**
```bash
# Update deployment repo (rock/deploy)
git clone https://forgejo.riotpiao.com/rock/deploy.git
cd deploy
# Update image tag
sed -i 's|forgejo.riotpiao.com/rock/myapp:.*|forgejo.riotpiao.com/rock/myapp:abc123|' k8s/deployment.yaml
git add k8s/deployment.yaml
git commit -m "deploy: bump myapp to abc123"
git push
```
**4. Argo CD auto-syncs:**
```bash
# Watch deployment
k rollout status -n <app-namespace> deployment/<app-name>
# Or check Argo CD UI
kubectl port-forward -n argocd svc/argocd-server 8443:443
# https://localhost:8443 (login via Authentik)
```
## Workflow Syntax (GitHub Actions)
**Basic structure:**
```yaml
name: CI
on:
push:
branches: [main, develop]
pull_request:
jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- run: npm ci
- run: npm test
build:
needs: test # wait for test job
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- run: docker build -t myapp:${{ github.sha }} .
- run: docker push forgejo.riotpiao.com/rock/myapp:${{ github.sha }}
```
**Available variables:**
```bash
${{ github.sha }} # commit hash
${{ github.ref_name }} # branch name
${{ github.run_number }} # build #
${{ secrets.CI_BOT_TOKEN }} # injected from Forgejo
```
## Secrets & Authentication
**ci-bot JWT token (auto-injected):**
```yaml
- run: |
echo "${{ secrets.CI_BOT_TOKEN }}" | docker login \
forgejo.riotpiao.com \
-u ci-bot \
--password-stdin
docker push forgejo.riotpiao.com/rock/myapp:latest
```
**API token (for pushing commits):**
```yaml
- run: |
git config user.name "ci-bot"
git config user.email "ci-bot@homelab"
git commit --allow-empty -m "bump: version"
git push https://ci-bot:${{ secrets.CI_BOT_TOKEN }}@forgejo.riotpiao.com/rock/deploy.git main
```
**Vault secrets (via talos CLI):**
```bash
# Not available in CI runner — use Argo CD post-sync hooks instead
# Or inject via init container before workflow runs
```
## Argo CD GitOps
**Create app (one-time):**
```bash
argocd app create story-crater \
--repo https://forgejo.riotpiao.com/rock/deploy.git \
--path k8s/ \
--dest-server https://kubernetes.default.svc \
--dest-namespace story-crater-backend \
--sync-policy automated
```
**Monitor sync:**
```bash
# CLI
argocd app get story-crater
argocd app logs story-crater
# UI: https://argocd.riotpiao.com
# Login: Authentik SSO (homelab-admins group only)
```
**Manual sync:**
```bash
argocd app sync story-crater
argocd app wait story-crater
```
## Security Rules
**DO:**
- Store credentials in Forgejo Secrets (auto-injected)
- Use ci-bot JWT for image push only
- Commit to deploy repo (triggers Argo CD)
- Enable branch protection (require CI pass)
**DON'T:**
- Put kubeconfig in CI (Argo CD bridges gap)
- Commit secrets to source repo
- Use admin-bot in CI workflows (over-privileged)
- Push images directly to cluster (use Argo CD)
## Monitoring
**Grafana dashboard:** `svc-forgejo`, `svc-argocd`
**Key metrics:**
- `forgejo_workflows_running` — active workflows
- `argocd_app_sync_duration_seconds` — deployment time
- `argocd_app_info{sync_status="OutOfSync"}` — drift detection
## Troubleshooting
**Workflow fails silently:**
```bash
# Check runner logs
k logs -n cicd -f deploy/forgejo-runner
# Check if runner pod is healthy
k get pods -n cicd -l app=forgejo-runner
```
**Image push fails (401 Unauthorized):**
```bash
# Verify ci-bot token in Forgejo
# Settings → Applications → ci-bot → check scopes (package:write)
# Or re-create token
core put cluster/iam/agents/ci-bot-token TOKEN="$(openssl rand -hex 32)"
```
**Argo CD out-of-sync:**
```bash
# Check deploy repo changes
argocd app diff story-crater
# Manual sync
argocd app sync story-crater --prune
```
**Webhook not triggering:**
```bash
# Verify Forgejo webhook config
# Repo Settings → Webhooks → Check delivery logs
# Or manually trigger
argocd app sync story-crater
```
See `/TROUBLESHOOTING.md` for full incident guide.