422 lines
19 KiB
Markdown
422 lines
19 KiB
Markdown
---
|
|
description: Deploy application to Eureka platform (creates app if needed)
|
|
allowed-tools: Read, Write, Edit, Bash, Glob, Grep
|
|
---
|
|
|
|
# Eureka Deploy
|
|
|
|
**Input**: "$ARGUMENTS"
|
|
|
|
---
|
|
|
|
## PURPOSE
|
|
|
|
Deploy the current project to the Eureka platform. Automatically detects framework, validates/generates Dockerfile, creates app if needed, then triggers deployment.
|
|
|
|
---
|
|
|
|
## ⛔ CRITICAL RULES
|
|
|
|
### MUST DO
|
|
1. **MUST** detect framework and validate Dockerfile before deployment
|
|
2. **MUST** check for existing `app_id` in `.claude/eureka-factory.yaml` first
|
|
3. **MUST** create a new app via API if no `app_id` exists
|
|
4. **MUST** use `gitea.authenticatedCloneUrl` for git remote (NOT cloneUrl)
|
|
5. **MUST** save the new `app_id` to config after creation
|
|
6. **MUST** display deployment status after triggering
|
|
7. **MUST** consult `.claude/references/dockerfile-templates.md` for Dockerfile generation
|
|
|
|
### CANNOT DO
|
|
1. **CANNOT** deploy without valid API key
|
|
2. **CANNOT** skip app creation if `app_id` is missing
|
|
3. **CANNOT** proceed if API calls fail
|
|
4. **CANNOT** deploy without valid Dockerfile (generate if missing)
|
|
5. **CANNOT** use `gitea.cloneUrl` for git remote (it's Docker internal URL)
|
|
|
|
### CRITICAL: GITEA_EXTERNAL_URL
|
|
|
|
The backend **MUST** have `GITEA_EXTERNAL_URL` configured for external access:
|
|
|
|
```
|
|
Without GITEA_EXTERNAL_URL:
|
|
authenticatedCloneUrl = http://TOKEN@gitea:3000/... ← FAILS (Docker internal)
|
|
|
|
With GITEA_EXTERNAL_URL:
|
|
authenticatedCloneUrl = https://TOKEN@gitea.yourdomain.com/... ← WORKS
|
|
```
|
|
|
|
---
|
|
|
|
## EXECUTION FLOW
|
|
|
|
### ═══════════════════════════════════════════════════════════════
|
|
### PHASE 1: Configuration Check
|
|
### ═══════════════════════════════════════════════════════════════
|
|
|
|
#### 1.1: Display Start Banner
|
|
|
|
```
|
|
╔══════════════════════════════════════════════════════════════╗
|
|
║ 🚀 EUREKA DEPLOY ║
|
|
╠══════════════════════════════════════════════════════════════╣
|
|
║ Deploying to Eureka Platform... ║
|
|
╚══════════════════════════════════════════════════════════════╝
|
|
```
|
|
|
|
#### 1.2: Check Configuration
|
|
|
|
Read the configuration file:
|
|
```bash
|
|
# Check if config exists
|
|
cat .claude/eureka-factory.yaml 2>/dev/null || cat .claude/eureka-factory.yml 2>/dev/null || echo "NO_CONFIG"
|
|
```
|
|
|
|
**Extract from config:**
|
|
- `api_key` - Required for all operations
|
|
- `app_id` - If exists, skip app creation
|
|
- `api_endpoint` - Optional custom endpoint
|
|
|
|
#### 1.3: Validate API Key
|
|
|
|
If no `api_key` found:
|
|
```
|
|
╔══════════════════════════════════════════════════════════════╗
|
|
║ ❌ NO API KEY CONFIGURED ║
|
|
╠══════════════════════════════════════════════════════════════╣
|
|
║ Run `eureka setup` to configure your credentials. ║
|
|
╚══════════════════════════════════════════════════════════════╝
|
|
```
|
|
**STOP EXECUTION**
|
|
|
|
---
|
|
|
|
### ═══════════════════════════════════════════════════════════════
|
|
### PHASE 2: Framework Detection & Dockerfile Validation
|
|
### ═══════════════════════════════════════════════════════════════
|
|
|
|
#### 2.1: Detect Framework
|
|
|
|
Run framework detection script:
|
|
```bash
|
|
python3 skills/guardrail-orchestrator/scripts/detect_framework.py . --format summary
|
|
```
|
|
|
|
**Expected output:**
|
|
```
|
|
Framework: Next.js + Prisma
|
|
Base Image: node:20-alpine3.18
|
|
Port: 3000
|
|
Requirements: openssl1.1-compat, output: standalone
|
|
|
|
Validation Checks:
|
|
✅ Next.js standalone output: OK
|
|
❌ Dockerfile exists: Dockerfile will be generated
|
|
```
|
|
|
|
#### 2.2: Validate/Generate Dockerfile
|
|
|
|
**If Dockerfile exists:**
|
|
- Verify it matches detected framework
|
|
- Check for common issues (wrong base image, missing Prisma support)
|
|
|
|
**If Dockerfile is missing:**
|
|
- Generate from template in `.claude/references/dockerfile-templates.md`
|
|
- Match template to detected framework
|
|
|
|
```
|
|
╔══════════════════════════════════════════════════════════════╗
|
|
║ 🐳 DOCKERFILE STATUS ║
|
|
╠══════════════════════════════════════════════════════════════╣
|
|
║ Framework: Next.js + Prisma ║
|
|
║ Base Image: node:20-alpine3.18 ║
|
|
║ Port: 3000 ║
|
|
║ Status: Generated / Validated ║
|
|
╚══════════════════════════════════════════════════════════════╝
|
|
```
|
|
|
|
#### 2.3: Framework-Specific Validations
|
|
|
|
**For Next.js:**
|
|
- Check `next.config.js` has `output: 'standalone'`
|
|
- If missing, offer to add it
|
|
|
|
**For SPAs (React/Vue/Angular):**
|
|
- Check for `nginx.conf`
|
|
- If missing, generate SPA routing config
|
|
|
|
**For Prisma projects:**
|
|
- Verify `prisma/` directory exists
|
|
- Check Dockerfile uses `node:20-alpine3.18` with `openssl1.1-compat`
|
|
|
|
#### 2.4: Display Framework Summary
|
|
|
|
```
|
|
╔══════════════════════════════════════════════════════════════╗
|
|
║ ✅ FRAMEWORK DETECTION COMPLETE ║
|
|
╠══════════════════════════════════════════════════════════════╣
|
|
║ Detected: Next.js + Prisma ║
|
|
║ Dockerfile: ✅ Valid ║
|
|
║ Config: ✅ output: 'standalone' set ║
|
|
║ Ready to deploy! ║
|
|
╚══════════════════════════════════════════════════════════════╝
|
|
```
|
|
|
|
---
|
|
|
|
### ═══════════════════════════════════════════════════════════════
|
|
### PHASE 3: App Creation (if needed)
|
|
### ═══════════════════════════════════════════════════════════════
|
|
|
|
#### 3.1: Check for app_id
|
|
|
|
If `app_id` exists in config → **SKIP TO PHASE 4**
|
|
|
|
If `app_id` is missing:
|
|
|
|
```
|
|
╔══════════════════════════════════════════════════════════════╗
|
|
║ 📁 CREATING DIRECTORY APP ║
|
|
╠══════════════════════════════════════════════════════════════╣
|
|
║ No app_id found. Creating new app on Eureka... ║
|
|
╚══════════════════════════════════════════════════════════════╝
|
|
```
|
|
|
|
#### 3.2: Determine App Name
|
|
|
|
Use the project directory name as the default app name:
|
|
```bash
|
|
APP_NAME=$(basename $(pwd))
|
|
echo "App name: $APP_NAME"
|
|
```
|
|
|
|
Or use argument if provided: `$ARGUMENTS` as app name
|
|
|
|
#### 3.3: Create Repository with Deploy Access via API
|
|
|
|
```bash
|
|
API_KEY="<from config>"
|
|
API_ENDPOINT="<from config or default>"
|
|
|
|
curl -X POST "${API_ENDPOINT}/v1/repositories/create-with-gitea" \
|
|
-H "Content-Type: application/json" \
|
|
-H "X-API-Key: ${API_KEY}" \
|
|
-d '{
|
|
"name": "<APP_NAME>",
|
|
"description": "<description>",
|
|
"type": "other",
|
|
"isPrivate": false,
|
|
"createDirectoryApp": true
|
|
}'
|
|
```
|
|
|
|
**Response structure:**
|
|
```json
|
|
{
|
|
"success": true,
|
|
"repository": { "id": "...", "name": "..." },
|
|
"gitea": {
|
|
"repoUrl": "http://gitea:3000/ai-apps/project-abc-myapp",
|
|
"cloneUrl": "http://gitea:3000/ai-apps/project-abc-myapp.git",
|
|
"authenticatedCloneUrl": "https://TOKEN@gitea.yourdomain.com/ai-apps/project-abc-myapp.git",
|
|
"deployUser": "deploy-project-abc-myapp",
|
|
"accessToken": "e0d1fd7fe75777..."
|
|
},
|
|
"directoryApp": { "id": "...", "slug": "my-app", "status": "COMING_SOON" }
|
|
}
|
|
```
|
|
|
|
#### 3.4: Add Git Remote
|
|
|
|
**IMPORTANT**: Use `authenticatedCloneUrl` (NOT `cloneUrl`):
|
|
|
|
```bash
|
|
git remote add eureka "<gitea.authenticatedCloneUrl>"
|
|
# Example: git remote add eureka "https://TOKEN@gitea.yourdomain.com/ai-apps/myapp.git"
|
|
```
|
|
|
|
#### 3.5: Push Code to Repository
|
|
|
|
```bash
|
|
git add .
|
|
git commit -m "Initial commit for Eureka deployment"
|
|
git push -u eureka $(git branch --show-current)
|
|
```
|
|
|
|
#### 3.6: Save Config
|
|
|
|
Extract IDs from API response and update config:
|
|
|
|
```yaml
|
|
# .claude/eureka-factory.yaml
|
|
api_key: <existing>
|
|
project_id: <existing>
|
|
repo_id: <repository.id>
|
|
app_id: <directoryApp.id>
|
|
slug: <directoryApp.slug>
|
|
```
|
|
|
|
```
|
|
╔══════════════════════════════════════════════════════════════╗
|
|
║ ✅ REPOSITORY & APP CREATED ║
|
|
╠══════════════════════════════════════════════════════════════╣
|
|
║ App ID: <directoryApp.id> ║
|
|
║ Slug: <directoryApp.slug> ║
|
|
║ Repo ID: <repository.id> ║
|
|
║ Git Remote: <gitea.authenticatedCloneUrl> ║
|
|
║ Saved to: .claude/eureka-factory.yaml ║
|
|
╚══════════════════════════════════════════════════════════════╝
|
|
```
|
|
|
|
#### 3.7: Get Clone URL for Existing App (Alternative)
|
|
|
|
If app exists but git remote not configured:
|
|
|
|
```bash
|
|
# Get clone URL by app_id
|
|
curl -s -X GET "${API_ENDPOINT}/v1/apps/${APP_ID}/git/clone-url" \
|
|
-H "X-API-Key: ${API_KEY}"
|
|
|
|
# Or by slug
|
|
curl -s -X GET "${API_ENDPOINT}/v1/apps/by-slug/${SLUG}/git/clone-url" \
|
|
-H "X-API-Key: ${API_KEY}"
|
|
```
|
|
|
|
Response includes `git.authenticatedCloneUrl` - use this for the remote.
|
|
|
|
---
|
|
|
|
### ═══════════════════════════════════════════════════════════════
|
|
### PHASE 4: Trigger Deployment
|
|
### ═══════════════════════════════════════════════════════════════
|
|
|
|
#### 4.1: Trigger Deploy
|
|
|
|
```bash
|
|
# Using eureka CLI
|
|
eureka deploy trigger --yes
|
|
|
|
# Or direct API call
|
|
curl -X POST "${API_ENDPOINT}/v1/apps/${APP_ID}/deployments" \
|
|
-H "Content-Type: application/json" \
|
|
-H "X-API-Key: ${API_KEY}" \
|
|
-d '{"environment": "production"}'
|
|
```
|
|
|
|
#### 4.2: Display Deployment Status
|
|
|
|
```
|
|
╔══════════════════════════════════════════════════════════════╗
|
|
║ ✅ DEPLOYMENT TRIGGERED ║
|
|
╠══════════════════════════════════════════════════════════════╣
|
|
║ Deployment ID: <deployment_id> ║
|
|
║ Status: PENDING ║
|
|
║ Environment: production ║
|
|
║ Version: <version> ║
|
|
╠══════════════════════════════════════════════════════════════╣
|
|
║ Use `/eureka:deploy-status` to check progress ║
|
|
║ Use `/eureka:deploy-logs` to view logs ║
|
|
╚══════════════════════════════════════════════════════════════╝
|
|
```
|
|
|
|
---
|
|
|
|
## ARGUMENTS
|
|
|
|
| Argument | Default | Description |
|
|
|----------|---------|-------------|
|
|
| `[app-name]` | Directory name | Name for new app (only used if creating) |
|
|
| `--env <environment>` | `production` | Deployment environment |
|
|
| `--branch <branch>` | Current branch | Git branch to deploy |
|
|
| `--force` | `false` | Force deploy even if already deploying |
|
|
|
|
## EXAMPLES
|
|
|
|
```bash
|
|
# Deploy current project (creates app if needed)
|
|
/eureka:deploy
|
|
|
|
# Deploy with custom app name
|
|
/eureka:deploy my-awesome-app
|
|
|
|
# Deploy specific branch to staging
|
|
/eureka:deploy --env staging --branch develop
|
|
|
|
# Force redeploy
|
|
/eureka:deploy --force
|
|
```
|
|
|
|
---
|
|
|
|
## ERROR HANDLING
|
|
|
|
### No Configuration
|
|
```
|
|
❌ No configuration found.
|
|
Run `eureka setup` to configure credentials.
|
|
```
|
|
|
|
### App Creation Failed
|
|
```
|
|
❌ Failed to create app: <error message>
|
|
Check your API key and try again.
|
|
```
|
|
|
|
### Deployment Failed
|
|
```
|
|
❌ Deployment failed: <error message>
|
|
Use `/eureka:deploy-logs` to see details.
|
|
```
|
|
|
|
---
|
|
|
|
## FLOW DIAGRAM
|
|
|
|
```
|
|
┌─────────────────────────────────────────────────────────────────┐
|
|
│ /eureka:deploy │
|
|
├─────────────────────────────────────────────────────────────────┤
|
|
│ │ │
|
|
│ ▼ │
|
|
│ ┌─────────────────┐ │
|
|
│ │ Check Config │ │
|
|
│ └────────┬────────┘ │
|
|
│ │ │
|
|
│ ┌─────────▼─────────┐ │
|
|
│ │ Has API Key? │ │
|
|
│ └─────────┬─────────┘ │
|
|
│ │ │
|
|
│ NO │ YES │
|
|
│ ┌────────────────────┼────────────────────┐ │
|
|
│ ▼ ▼ │
|
|
│ ┌───────────┐ ┌─────────────────┐ │
|
|
│ │ ERROR │ │ Has app_id? │ │
|
|
│ │ No Key │ └────────┬────────┘ │
|
|
│ └───────────┘ │ │
|
|
│ NO │ YES │
|
|
│ ┌───────────────────┼──────────┐ │
|
|
│ ▼ ▼ │
|
|
│ ┌─────────────────┐ ┌──────────────┐
|
|
│ │ Create App │ │ │
|
|
│ │ via API │ │ │
|
|
│ └────────┬────────┘ │ │
|
|
│ │ │ │
|
|
│ ▼ │ │
|
|
│ ┌─────────────────┐ │ │
|
|
│ │ Save app_id │ │ │
|
|
│ │ to Config │ │ │
|
|
│ └────────┬────────┘ │ │
|
|
│ │ │ │
|
|
│ └───────────────────┘ │
|
|
│ │ │
|
|
│ ▼ │
|
|
│ ┌─────────────────┐ │
|
|
│ │ Trigger Deploy │ │
|
|
│ └────────┬────────┘ │
|
|
│ │ │
|
|
│ ▼ │
|
|
│ ┌─────────────────┐ │
|
|
│ │ Show Status │ │
|
|
│ └─────────────────┘ │
|
|
└─────────────────────────────────────────────────────────────────┘
|
|
```
|