<< All versions

Skill v1.0.0

currentAutomated scan100/100
rqd6f4g6zn-bit/onecommand/automation-installer
──Details
PublishedOctober 3, 2026 at 06:17 PM
Content Hashsha256:c2844c3b42e87a66...
Git SHAbcaaeb04b6d7
──Files
Files (1 file, 12.4 KB)
SKILL.md12.4 KBactive
SKILL.md · 444 lines · 12.4 KB

version: "1.0.0" name: automation-installer description: Installs production-grade automations into the generated project. Dev tooling (husky pre-commit, GitHub Actions CI, Makefile, .gitignore) PLUS USC Profi-Standard production hardening (deploy.sh with frontend/backend/db targets, watchdog every 60s, daily DB backup with 14-day retention, restart:always policy, resource limits, healthchecks, gold-master recovery). Hardening section is conditional on backend presence.


You are the Automation Installer for OneCommand. You make the generated project self-maintaining through automated quality gates.

Steps

1. Git Hooks via Husky

Install husky and add a pre-commit hook that runs lint + typecheck before every commit:

bash
npm install --save-dev husky

Add prepare script to package.json:

json
{
"scripts": {
"prepare": "husky install"
}
}

Initialize husky and create the pre-commit hook:

bash
npx husky install
npx husky add .husky/pre-commit "npm run lint --if-present && npx tsc --noEmit 2>/dev/null || true"
chmod +x .husky/pre-commit

2. GitHub Actions CI/CD

Create .github/workflows/ci.yml:

yaml
name: CI
on:
push:
branches: [main, develop]
pull_request:
branches: [main]
jobs:
build-and-test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: '20'
cache: 'npm'
- name: Install dependencies
run: npm ci
- name: Type check
run: npx tsc --noEmit 2>/dev/null || true
- name: Build
run: npm run build
- name: Test
run: npm test -- --passWithNoTests
env:
DATABASE_URL: postgresql://postgres:postgres@localhost:5432/testdb
NEXTAUTH_SECRET: test-secret-for-ci
NEXTAUTH_URL: http://localhost:3000

3. Makefile

Create Makefile in the project root:

makefile
.PHONY: dev build test deploy clean install setup
# Read deploy target from spec if available
DEPLOY_TARGET := $(shell python3 -c "import json,sys; d=json.load(open('.onecommand-spec.json')); print(d.get('deploy_target','vercel'))" 2>/dev/null || echo "vercel")
dev:
npm run dev
build:
npm run build
test:
npm test -- --passWithNoTests
install:
npm install
setup:
npm install
npx prisma generate 2>/dev/null || true
cp -n .env.example .env.local 2>/dev/null || true
@echo "Setup complete. Edit .env.local with your values, then run: make dev"
deploy:
ifeq ($(DEPLOY_TARGET),vercel)
@echo "Deploying to Vercel..."
npx vercel --prod
else ifeq ($(DEPLOY_TARGET),railway)
@echo "Deploying to Railway..."
railway up
else ifeq ($(DEPLOY_TARGET),fly)
@echo "Deploying to Fly.io..."
fly deploy
else
@echo "Deploying with Docker..."
docker-compose up --build -d
endif
clean:
rm -rf .next node_modules dist build
db-push:
npx prisma db push
db-seed:
npx prisma db seed
db-studio:
npx prisma studio

4. Ensure .gitignore is Complete

Check if .gitignore exists. If not, create it. If it exists, ensure these entries are present:

# Dependencies
node_modules/
# Build output
.next/
dist/
build/
out/
# Environment variables - NEVER commit these
.env
.env.local
.env.*.local
.env.production
# Logs
*.log
npm-debug.log*
# OS files
.DS_Store
Thumbs.db
# IDE
.vscode/
.idea/
*.swp
# Prisma
prisma/*.db
prisma/*.db-journal

5. Verify all automations

bash
echo "=== Automation Check ==="
[ -f ".husky/pre-commit" ] && echo "✓ Git pre-commit hook" || echo "✗ Missing: .husky/pre-commit"
[ -f ".github/workflows/ci.yml" ] && echo "✓ GitHub Actions CI" || echo "✗ Missing: .github/workflows/ci.yml"
[ -f "Makefile" ] && echo "✓ Makefile" || echo "✗ Missing: Makefile"
[ -f ".gitignore" ] && echo "✓ .gitignore" || echo "✗ Missing: .gitignore"
echo "========================"

6. Production Hardening (USC Profi-Standard)

This section installs production-grade ops automation. Modeled on the usc-software-ug.de deployment standard: auto-restart, watchdog, automated backups with retention, one-command deploys, resource limits.

Run this section IF the project has a server/backend/database.

Detection:

bash
HAS_BACKEND="no"
[ -f "docker-compose.yml" ] || [ -d "backend" ] || [ -d "api" ] || [ -d "server" ] || \
[ -f "prisma/schema.prisma" ] || [ -d "supabase" ] && HAS_BACKEND="yes"
echo "Backend detected: $HAS_BACKEND"

If HAS_BACKEND=no → skip steps 6.1-6.4, only do step 6.5 (mobile deploy.sh).

6.1 Hardened docker-compose.yml

If a docker-compose.yml already exists, edit it to ensure every service has restart: always, resource limits, and healthchecks. If it doesn't exist and the project has a backend, generate one. Read the spec to determine DB type (postgres/mysql/sqlite) and service shape.

Required additions to every service:

yaml
services:
api:
restart: always # NEVER unless-stopped — Profi-Standard
deploy:
resources:
limits:
memory: 768M # adjust per service: api=768M, db=1G, nginx=128M
cpus: '1.5'
healthcheck:
test: ["CMD", "curl", "-fsS", "http://localhost:3000/api/health"]
interval: 30s
timeout: 5s
retries: 3
start_period: 30s
db:
restart: always
deploy:
resources:
limits: { memory: 1G, cpus: '1.0' }
healthcheck:
test: ["CMD-SHELL", "pg_isready -U $POSTGRES_USER || mysqladmin ping -h localhost"]
interval: 30s
retries: 5
nginx:
restart: always
deploy:
resources:
limits: { memory: 128M, cpus: '0.5' }

6.2 scripts/watchdog.sh (60-second health watchdog)

Create scripts/watchdog.sh:

bash
#!/usr/bin/env bash
# Watchdog — runs every 60s via cron. Restarts unhealthy containers
# and pings external health endpoints. Logs to /var/log/PROJECT-watchdog.log.
set -e
PROJECT="${PROJECT_NAME:-app}"
LOG="/var/log/${PROJECT}-watchdog.log"
COMPOSE="${COMPOSE_FILE:-/opt/$PROJECT/docker-compose.yml}"
HEALTH_URL="${HEALTH_URL:-http://localhost:3000/api/health}"
log() { echo "[$(date -Iseconds)] $*" | tee -a "$LOG"; }
# 1) External health endpoint
if ! curl -fsS --max-time 10 "$HEALTH_URL" >/dev/null; then
log "UNHEALTHY: $HEALTH_URL — restarting api"
docker compose -f "$COMPOSE" restart api || log "restart failed"
fi
# 2) Container health states
docker compose -f "$COMPOSE" ps --format json 2>/dev/null | \
while IFS= read -r line; do
name=$(echo "$line" | python3 -c "import json,sys; d=json.loads(sys.stdin.read() or '{}'); print(d.get('Name',''))")
state=$(echo "$line" | python3 -c "import json,sys; d=json.loads(sys.stdin.read() or '{}'); print(d.get('State',''))")
health=$(echo "$line" | python3 -c "import json,sys; d=json.loads(sys.stdin.read() or '{}'); print(d.get('Health',''))")
if [ "$state" = "exited" ] || [ "$health" = "unhealthy" ]; then
log "Container $name is $state/$health — restarting"
docker compose -f "$COMPOSE" restart "$name" || true
fi
done
log "watchdog tick OK"

Make it executable and register the cron:

bash
chmod +x scripts/watchdog.sh
echo "* * * * * cd $(pwd) && PROJECT_NAME=$PROJECT ./scripts/watchdog.sh" | crontab -

6.3 scripts/backup.sh (daily 02:30, 14-day retention)

Auto-detects DB type from docker-compose.yml or .env:

bash
#!/usr/bin/env bash
# Daily DB backup — runs 02:30 via cron, keeps 14 days, gzipped.
set -e
PROJECT="${PROJECT_NAME:-app}"
BACKUP_DIR="${BACKUP_DIR:-/var/backups/$PROJECT}"
RETENTION_DAYS="${RETENTION_DAYS:-14}"
DATE=$(date +%Y-%m-%d)
mkdir -p "$BACKUP_DIR"
# Auto-detect DB
if docker compose ps db 2>/dev/null | grep -q postgres; then
docker compose exec -T db pg_dumpall -U "${POSTGRES_USER:-postgres}" | gzip > "$BACKUP_DIR/${PROJECT}_${DATE}.sql.gz"
elif docker compose ps db 2>/dev/null | grep -q mysql; then
docker compose exec -T db mysqldump --all-databases -u root -p"${MYSQL_ROOT_PASSWORD}" | gzip > "$BACKUP_DIR/${PROJECT}_${DATE}.sql.gz"
elif [ -f "prisma/dev.db" ]; then
gzip -c prisma/dev.db > "$BACKUP_DIR/${PROJECT}_${DATE}.db.gz"
else
echo "No DB detected — skipping" >&2
exit 0
fi
# Retention: delete files older than N days
find "$BACKUP_DIR" -type f -name "${PROJECT}_*.gz" -mtime +${RETENTION_DAYS} -delete
echo "[$(date -Iseconds)] Backup OK: ${BACKUP_DIR}/${PROJECT}_${DATE}.*.gz"

Register cron:

bash
chmod +x scripts/backup.sh
( crontab -l 2>/dev/null; echo "30 2 * * * cd $(pwd) && PROJECT_NAME=$PROJECT ./scripts/backup.sh >> /var/log/$PROJECT-backup.log 2>&1" ) | crontab -

6.4 deploy.sh — One-Command Deploy (alle Targets)

bash
#!/usr/bin/env bash
# Deploy frontend / backend / all — single entry point.
# Usage: ./deploy.sh [frontend|backend|db|all] (default: all)
set -e
TARGET="${1:-all}"
COMPOSE="${COMPOSE_FILE:-docker-compose.yml}"
deploy_db() {
echo "→ DB migrations"
if [ -f "prisma/schema.prisma" ]; then
npx prisma migrate deploy
elif [ -d "supabase/migrations" ]; then
npx supabase db push
fi
}
deploy_backend() {
echo "→ Backend"
docker compose -f "$COMPOSE" build api
deploy_db
docker compose -f "$COMPOSE" up -d api
docker compose -f "$COMPOSE" exec -T api curl -fsS http://localhost:3000/api/health || \
{ echo "✗ health check failed"; exit 1; }
echo "✓ Backend live"
}
deploy_frontend() {
echo "→ Frontend"
if [ -f "docker-compose.yml" ] && grep -q "service.*nginx\|service.*web\|service.*frontend" "$COMPOSE"; then
docker compose -f "$COMPOSE" build web frontend nginx 2>/dev/null || true
docker compose -f "$COMPOSE" up -d web frontend nginx 2>/dev/null || true
else
npm run build
npx vercel --prod 2>/dev/null || npx netlify deploy --prod 2>/dev/null || \
echo " (no platform CLI found — built into ./build/)"
fi
echo "✓ Frontend live"
}
case "$TARGET" in
frontend) deploy_frontend ;;
backend) deploy_backend ;;
db) deploy_db ;;
all) deploy_db; deploy_backend; deploy_frontend ;;
*) echo "Usage: ./deploy.sh [frontend|backend|db|all]"; exit 1 ;;
esac
echo ""
echo "✓ Deploy '$TARGET' complete @ $(date -Iseconds)"
bash
chmod +x deploy.sh

6.5 Mobile-only deploy.sh (if React Native / Expo project)

If app_type=mobile (no backend, just app), generate a thinner deploy.sh:

bash
#!/usr/bin/env bash
# Mobile deploy — EAS Build for iOS + Android.
# Usage: ./deploy.sh [ios|android|all] (default: all)
set -e
TARGET="${1:-all}"
PROFILE="${EAS_PROFILE:-production}"
case "$TARGET" in
ios) eas build --platform ios --profile "$PROFILE" --non-interactive ;;
android) eas build --platform android --profile "$PROFILE" --non-interactive ;;
all) eas build --platform all --profile "$PROFILE" --non-interactive ;;
submit) eas submit --platform all --latest ;;
*) echo "Usage: ./deploy.sh [ios|android|all|submit]"; exit 1 ;;
esac

6.6 Production README section

Append to README.md (or create if missing):

`markdown
## 🛡️ Production Operations
This project ships with a USC Profi-Standard ops setup:
### One-command deploys

./deploy.sh # Everything (frontend + backend + DB migrations) ./deploy.sh frontend # Frontend only ./deploy.sh backend # Backend + DB migrations ./deploy.sh db # DB migrations only

### Crash safety
- All containers run with `restart: always`
- Watchdog runs every minute, auto-restarts unhealthy containers
- Resource limits prevent any single service from exhausting the host
- API: max 768 MB RAM, 1.5 CPUs
- DB: max 1 GB RAM, 1 CPU
- Nginx: max 128 MB RAM, 0.5 CPUs
### Backups
- Daily DB dump at 02:30 (cron)
- 14-day retention, gzipped
- Located at `/var/backups/$PROJECT/`
### Monitoring
- Health endpoint: `/api/health`
- Watchdog logs: `/var/log/$PROJECT-watchdog.log`
- Backup logs: `/var/log/$PROJECT-backup.log`

6.7 Verify production hardening

bash
echo "=== Production Hardening Check ==="
[ -f "deploy.sh" ] && echo "✓ deploy.sh" || echo "○ deploy.sh (skipped — no backend)"
[ -f "scripts/watchdog.sh" ] && echo "✓ watchdog.sh" || echo "○ watchdog.sh (skipped — no backend)"
[ -f "scripts/backup.sh" ] && echo "✓ backup.sh" || echo "○ backup.sh (skipped — no backend)"
grep -q "restart: always" docker-compose.yml 2>/dev/null && echo "✓ restart: always policy" || true
grep -q "resources:" docker-compose.yml 2>/dev/null && echo "✓ resource limits" || true
grep -q "healthcheck:" docker-compose.yml 2>/dev/null && echo "✓ healthchecks" || true
echo "==================================="

Report what was installed and which sections were skipped (with reason).

All versions