appaibuiltest/deploy/AI-DEPLOYMENT-PROMPT.md

747 lines
18 KiB
Markdown
Raw Permalink Normal View History

2026-01-30 22:56:31 +01:00
# 🚀 .NET Application Deployment Generator
**Purpose:** Generate complete deployment configuration for a new .NET application on your Forgejo CI/CD infrastructure.
**Infrastructure:**
- Server: 192.168.1.43 (Ubuntu 24.04)
- Forgejo: 192.168.1.63:3000
- Deploy User: `deploy`
- Reverse Proxy: Caddy
- Process Manager: systemd
- Deployment Method: self-contained .NET publish + rsync + SSH
---
## PART 1: INFORMATION COLLECTION
Ask the user the following questions and collect their answers:
### Application Configuration
1. **Application Name** (e.g., "BlogApp", "ShopAPI", "DashboardApp")
- Answer: `_______`
2. **.NET Version** (e.g., "9.0.x", "10.0.x")
- Answer: `_______`
3. **Executable Name** (defaults to Application Name if blank)
- Answer: `_______` (or blank to use app name)
### Environment Setup
4. **Deploy TEST environment?** (yes/no)
- Answer: `_______`
5. **Deploy PROD environment?** (yes/no)
- Answer: `_______`
### Network Configuration (TEST)
*Skip if TEST not enabled*
6a. **TEST Port Number** (e.g., 5002, 5010, 5020)
- Answer: `_______`
6b. **TEST Domain** (e.g., "test-blog.jarjarbinks", "staging-shop.jarjarbinks")
- Answer: `_______`
### Network Configuration (PROD)
*Skip if PROD not enabled*
7a. **PROD Port Number** (e.g., 5003, 5011, 5021)
- Answer: `_______`
7b. **PROD Domain** (e.g., "blog.jarjarbinks", "shop.jarjarbinks")
- Answer: `_______`
### Runner Configuration
8. **Forgejo Runner Setup** (existing/new)
- Answer: `_______`
9. **Runner Name** (if new runner selected, e.g., "blogapp-runner", "shop-runner")
- Answer: `_______` (skip if using existing)
---
## PART 2: VARIABLE MAPPING
Based on user answers, create these variables:
| Variable | Derivation | Example |
|----------|------------|---------|
| `{{APP_NAME}}` | Q1 answer | BlogApp |
| `{{APP_NAME_LOWER}}` | Q1 lowercase | blogapp |
| `{{DOTNET_VERSION}}` | Q2 answer | 9.0.x |
| `{{EXECUTABLE_NAME}}` | Q3 answer or Q1 | BlogApp |
| `{{INCLUDE_TEST}}` | Q4 = "yes" | true |
| `{{INCLUDE_PROD}}` | Q5 = "yes" | true |
| `{{TEST_PORT}}` | Q6a answer | 5002 |
| `{{TEST_DOMAIN}}` | Q6b answer | test-blog.jarjarbinks |
| `{{TEST_FOLDER}}` | `/opt/{{APP_NAME_LOWER}}-test/app` | /opt/blogapp-test/app |
| `{{TEST_SERVICE}}` | `{{APP_NAME_LOWER}}-test` | blogapp-test |
| `{{PROD_PORT}}` | Q7a answer | 5003 |
| `{{PROD_DOMAIN}}` | Q7b answer | blog.jarjarbinks |
| `{{PROD_FOLDER}}` | `/opt/{{APP_NAME_LOWER}}/app` | /opt/blogapp/app |
| `{{PROD_SERVICE}}` | `{{APP_NAME_LOWER}}` | blogapp |
| `{{CREATE_RUNNER}}` | Q8 = "new" | true |
| `{{RUNNER_NAME}}` | Q9 answer | blogapp-runner |
---
## PART 3: OUTPUT FOLDER STRUCTURE
Create this folder structure with generated files:
```
deployment-configs-{{APP_NAME_LOWER}}/
├── README.md
├── .forgejo/
│ └── workflows/
│ └── cicd.yml
├── systemd/
│ ├── {{APP_NAME_LOWER}}-test.service # if INCLUDE_TEST
│ └── {{APP_NAME_LOWER}}.service # if INCLUDE_PROD
├── caddy/
│ └── {{APP_NAME_LOWER}}-config.txt
├── scripts/
│ ├── setup-server.sh
│ └── setup-runner.sh # if CREATE_RUNNER
└── secrets-checklist.md
```
---
## PART 4: FILE TEMPLATES
### Template 1: .forgejo/workflows/cicd.yml
```yaml
name: {{APP_NAME}}-cicd
on:
push:
branches: [ "main" ]
workflow_dispatch: {}
jobs:
{{#if INCLUDE_TEST}}
build_test_deploy_test:
runs-on: docker
steps:
- uses: actions/checkout@v4
- uses: actions/setup-dotnet@v4
with:
dotnet-version: "{{DOTNET_VERSION}}"
- name: Test
run: dotnet test -c Release
- name: Publish (self-contained linux-x64)
run: dotnet publish -c Release -r linux-x64 --self-contained true -o out
- name: Install deploy tools
run: |
apt-get update
apt-get install -y rsync openssh-client
- name: Deploy TEST
env:
DEPLOY_HOST: ${{ secrets.DEPLOY_HOST }}
DEPLOY_USER: ${{ secrets.DEPLOY_USER }}
DEPLOY_SSH_KEY: ${{ secrets.DEPLOY_SSH_KEY }}
run: |
set -e
mkdir -p ~/.ssh
chmod 700 ~/.ssh
echo "$DEPLOY_SSH_KEY" > ~/.ssh/id_ed25519
chmod 600 ~/.ssh/id_ed25519
ssh-keyscan -H "$DEPLOY_HOST" >> ~/.ssh/known_hosts
rsync -az --delete out/ "$DEPLOY_USER@$DEPLOY_HOST:{{TEST_FOLDER}}/"
ssh "$DEPLOY_USER@$DEPLOY_HOST" "chmod +x {{TEST_FOLDER}}/{{EXECUTABLE_NAME}} && sudo systemctl restart {{TEST_SERVICE}}"
{{/if}}
{{#if INCLUDE_PROD}}
deploy_prod_manual:
if: ${{ github.event_name == 'workflow_dispatch' }}
runs-on: docker
steps:
- uses: actions/checkout@v4
- uses: actions/setup-dotnet@v4
with:
dotnet-version: "{{DOTNET_VERSION}}"
- name: Publish (self-contained linux-x64)
run: dotnet publish -c Release -r linux-x64 --self-contained true -o out
- name: Install deploy tools
run: |
apt-get update
apt-get install -y rsync openssh-client
- name: Deploy PROD
env:
DEPLOY_HOST: ${{ secrets.DEPLOY_HOST }}
DEPLOY_USER: ${{ secrets.DEPLOY_USER }}
DEPLOY_SSH_KEY: ${{ secrets.DEPLOY_SSH_KEY }}
run: |
set -e
mkdir -p ~/.ssh
chmod 700 ~/.ssh
echo "$DEPLOY_SSH_KEY" > ~/.ssh/id_ed25519
chmod 600 ~/.ssh/id_ed25519
ssh-keyscan -H "$DEPLOY_HOST" >> ~/.ssh/known_hosts
rsync -az --delete out/ "$DEPLOY_USER@$DEPLOY_HOST:{{PROD_FOLDER}}/"
ssh "$DEPLOY_USER@$DEPLOY_HOST" "chmod +x {{PROD_FOLDER}}/{{EXECUTABLE_NAME}} && sudo systemctl restart {{PROD_SERVICE}}"
{{/if}}
```
**Generation Rule:**
- Remove `{{#if INCLUDE_TEST}}...{{/if}}` block if TEST not enabled
- Remove `{{#if INCLUDE_PROD}}...{{/if}}` block if PROD not enabled
- Substitute all `{{VARIABLES}}` with actual values
---
### Template 2: systemd/{{APP_NAME_LOWER}}-test.service
**Generate only if INCLUDE_TEST = true**
```ini
[Unit]
Description={{APP_NAME}} TEST Environment
After=network.target
[Service]
Type=notify
WorkingDirectory={{TEST_FOLDER}}
ExecStart={{TEST_FOLDER}}/{{EXECUTABLE_NAME}}
Environment=ASPNETCORE_URLS=http://127.0.0.1:{{TEST_PORT}}
Environment=ASPNETCORE_ENVIRONMENT=Staging
User=minapp
Group=minapp
Restart=always
RestartSec=10
SyslogIdentifier={{TEST_SERVICE}}
[Install]
WantedBy=multi-user.target
```
---
### Template 3: systemd/{{APP_NAME_LOWER}}.service
**Generate only if INCLUDE_PROD = true**
```ini
[Unit]
Description={{APP_NAME}} PRODUCTION Environment
After=network.target
[Service]
Type=notify
WorkingDirectory={{PROD_FOLDER}}
ExecStart={{PROD_FOLDER}}/{{EXECUTABLE_NAME}}
Environment=ASPNETCORE_URLS=http://127.0.0.1:{{PROD_PORT}}
Environment=ASPNETCORE_ENVIRONMENT=Production
User=minapp
Group=minapp
Restart=always
RestartSec=10
SyslogIdentifier={{PROD_SERVICE}}
[Install]
WantedBy=multi-user.target
```
---
### Template 4: caddy/{{APP_NAME_LOWER}}-config.txt
```
{{#if INCLUDE_TEST}}
# TEST Environment
http://{{TEST_DOMAIN}} {
reverse_proxy 127.0.0.1:{{TEST_PORT}}
}
{{/if}}
{{#if INCLUDE_PROD}}
# PRODUCTION Environment
http://{{PROD_DOMAIN}} {
reverse_proxy 127.0.0.1:{{PROD_PORT}}
}
{{/if}}
```
**Note:** This content must be manually added to `/etc/caddy/Caddyfile` on the server.
---
### Template 5: scripts/setup-server.sh
```bash
#!/bin/bash
# Setup script for {{APP_NAME}} deployment
# Run this on the webserver (192.168.1.43)
set -e
echo "==================================="
echo "Setting up {{APP_NAME}} on server"
echo "==================================="
{{#if INCLUDE_TEST}}
# Create TEST directories
echo "Creating TEST environment directories..."
sudo mkdir -p {{TEST_FOLDER}}
sudo chown -R minapp:minapp /opt/{{APP_NAME_LOWER}}-test
# Install TEST systemd service
echo "Installing TEST systemd service..."
sudo cp systemd/{{APP_NAME_LOWER}}-test.service /etc/systemd/system/
sudo systemctl daemon-reload
sudo systemctl enable {{TEST_SERVICE}}
echo "✓ TEST service installed: {{TEST_SERVICE}}"
{{/if}}
{{#if INCLUDE_PROD}}
# Create PROD directories
echo "Creating PROD environment directories..."
sudo mkdir -p {{PROD_FOLDER}}
sudo chown -R minapp:minapp /opt/{{APP_NAME_LOWER}}
# Install PROD systemd service
echo "Installing PROD systemd service..."
sudo cp systemd/{{APP_NAME_LOWER}}.service /etc/systemd/system/
sudo systemctl daemon-reload
sudo systemctl enable {{PROD_SERVICE}}
echo "✓ PROD service installed: {{PROD_SERVICE}}"
{{/if}}
# Update Caddy configuration
echo ""
echo "==================================="
echo "MANUAL STEP REQUIRED:"
echo "==================================="
echo "Add the following to /etc/caddy/Caddyfile:"
echo ""
cat caddy/{{APP_NAME_LOWER}}-config.txt
echo ""
echo "Then run: sudo systemctl reload caddy"
echo ""
echo "==================================="
echo "Setup complete!"
echo "==================================="
{{#if INCLUDE_TEST}}
echo "TEST service: {{TEST_SERVICE}}"
echo "TEST folder: {{TEST_FOLDER}}"
echo "TEST URL: http://{{TEST_DOMAIN}}"
{{/if}}
{{#if INCLUDE_PROD}}
echo "PROD service: {{PROD_SERVICE}}"
echo "PROD folder: {{PROD_FOLDER}}"
echo "PROD URL: http://{{PROD_DOMAIN}}"
{{/if}}
echo "==================================="
```
---
### Template 6: scripts/setup-runner.sh
**Generate only if CREATE_RUNNER = true**
```bash
#!/bin/bash
# Setup Forgejo Runner for {{APP_NAME}}
# Run this on the Forgejo server (192.168.1.63)
set -e
RUNNER_NAME="{{RUNNER_NAME}}"
FORGEJO_URL="http://192.168.1.63:3000"
echo "==================================="
echo "Setting up Forgejo Runner: $RUNNER_NAME"
echo "==================================="
# Create runner directory
mkdir -p ~/forgejo-runners/$RUNNER_NAME
cd ~/forgejo-runners/$RUNNER_NAME
# Create docker-compose.yml
cat > docker-compose.yml <<'EOF'
version: '3'
services:
runner:
image: code.forgejo.org/forgejo/runner:latest
container_name: {{RUNNER_NAME}}
restart: unless-stopped
volumes:
- ./data:/data
- /var/run/docker.sock:/var/run/docker.sock
environment:
- DOCKER_HOST=unix:///var/run/docker.sock
EOF
echo "✓ docker-compose.yml created"
# Start the runner
echo "Starting runner container..."
docker-compose up -d
echo "Waiting for runner to start..."
sleep 5
# Register runner
echo ""
echo "==================================="
echo "MANUAL STEP REQUIRED:"
echo "==================================="
echo "1. Go to Forgejo → Repository Settings → Actions → Runners"
echo "2. Click 'Create new Runner'"
echo "3. Copy the registration token"
echo "4. Run the following command:"
echo ""
echo "docker exec -it {{RUNNER_NAME}} forgejo-runner register \\"
echo " --instance $FORGEJO_URL \\"
echo " --token YOUR_REGISTRATION_TOKEN \\"
echo " --name {{RUNNER_NAME}} \\"
echo " --labels docker:docker://node:20-bookworm"
echo ""
echo "==================================="
```
---
### Template 7: README.md
```markdown
# {{APP_NAME}} - Deployment Configuration
**Generated:** $(date)
## Overview
This folder contains all configuration files needed to deploy **{{APP_NAME}}** to your infrastructure:
- **Server:** 192.168.1.43 (Ubuntu 24.04)
- **Forgejo:** 192.168.1.63:3000
- **.NET Version:** {{DOTNET_VERSION}}
## Environments
{{#if INCLUDE_TEST}}
### TEST Environment
- **Port:** {{TEST_PORT}}
- **Domain:** http://{{TEST_DOMAIN}}
- **Folder:** {{TEST_FOLDER}}
- **Service:** {{TEST_SERVICE}}
- **Deploy:** Automatic on `git push` to main
{{/if}}
{{#if INCLUDE_PROD}}
### PROD Environment
- **Port:** {{PROD_PORT}}
- **Domain:** http://{{PROD_DOMAIN}}
- **Folder:** {{PROD_FOLDER}}
- **Service:** {{PROD_SERVICE}}
- **Deploy:** Manual via workflow_dispatch
{{/if}}
## Setup Instructions
### 1. Configure Forgejo Secrets
Go to your repository in Forgejo → Settings → Actions → Secrets
Required secrets (should already exist):
- `DEPLOY_HOST` = `192.168.1.43`
- `DEPLOY_USER` = `deploy`
- `DEPLOY_SSH_KEY` = SSH private key for deploy user
### 2. Copy Workflow to Repository
```bash
# In your repository
mkdir -p .forgejo/workflows
cp .forgejo/workflows/cicd.yml YOUR_REPO/.forgejo/workflows/
cd YOUR_REPO
git add .forgejo/workflows/cicd.yml
git commit -m "Add CI/CD workflow"
git push
```
### 3. Setup Server
```bash
# Copy files to server
scp -r systemd caddy scripts deploy@192.168.1.43:~/{{APP_NAME_LOWER}}-setup/
# SSH to server
ssh deploy@192.168.1.43
# Run setup script
cd ~/{{APP_NAME_LOWER}}-setup
chmod +x scripts/setup-server.sh
./scripts/setup-server.sh
# Manually add Caddy configuration (as instructed by script)
sudo nano /etc/caddy/Caddyfile
# Add content from caddy/{{APP_NAME_LOWER}}-config.txt
sudo systemctl reload caddy
```
{{#if CREATE_RUNNER}}
### 4. Setup Forgejo Runner (Optional)
```bash
# Copy script to Forgejo server
scp scripts/setup-runner.sh forgejo@192.168.1.63:~/
# SSH to Forgejo server
ssh forgejo@192.168.1.63
# Run setup script
chmod +x setup-runner.sh
./setup-runner.sh
# Follow instructions to register runner
```
{{/if}}
## Deployment
{{#if INCLUDE_TEST}}
### Deploy to TEST
```bash
git push origin main
```
Check deployment:
```bash
# On server
sudo systemctl status {{TEST_SERVICE}}
sudo journalctl -u {{TEST_SERVICE}} -n 50
# Test locally
curl http://127.0.0.1:{{TEST_PORT}}
# Test via Caddy
curl http://{{TEST_DOMAIN}}
```
{{/if}}
{{#if INCLUDE_PROD}}
### Deploy to PROD
1. Go to Forgejo → Repository → Actions
2. Select the workflow
3. Click **Run workflow**
4. Confirm deployment
Check deployment:
```bash
# On server
sudo systemctl status {{PROD_SERVICE}}
sudo journalctl -u {{PROD_SERVICE}} -n 50
# Test locally
curl http://127.0.0.1:{{PROD_PORT}}
# Test via Caddy
curl http://{{PROD_DOMAIN}}
```
{{/if}}
## Troubleshooting
### Service Issues
```bash
{{#if INCLUDE_TEST}}
# TEST service
sudo systemctl status {{TEST_SERVICE}}
sudo journalctl -u {{TEST_SERVICE}} -n 100 -f
{{/if}}
{{#if INCLUDE_PROD}}
# PROD service
sudo systemctl status {{PROD_SERVICE}}
sudo journalctl -u {{PROD_SERVICE}} -n 100 -f
{{/if}}
```
### Check Ports
```bash
ss -lntp | grep {{TEST_PORT}}
ss -lntp | grep {{PROD_PORT}}
```
### Restart Services
```bash
{{#if INCLUDE_TEST}}
sudo systemctl restart {{TEST_SERVICE}}
{{/if}}
{{#if INCLUDE_PROD}}
sudo systemctl restart {{PROD_SERVICE}}
{{/if}}
sudo systemctl reload caddy
```
## File Structure
```
{{TEST_FOLDER}}/ # TEST deployment
{{PROD_FOLDER}}/ # PROD deployment
/etc/systemd/system/{{TEST_SERVICE}}.service
/etc/systemd/system/{{PROD_SERVICE}}.service
/etc/caddy/Caddyfile # Contains reverse proxy config
```
```
---
### Template 8: secrets-checklist.md
```markdown
# Forgejo Secrets Checklist
Repository: **YOUR_REPO_NAME**
Go to: Forgejo → Repository → Settings → Actions → Secrets
## Required Secrets
| Secret Name | Value | Status |
|-------------|-------|--------|
| `DEPLOY_HOST` | `192.168.1.43` | ☐ |
| `DEPLOY_USER` | `deploy` | ☐ |
| `DEPLOY_SSH_KEY` | SSH private key (ED25519) | ☐ |
## Verify Secrets
These secrets should already exist from previous deployments. Verify they are configured:
```bash
# Test SSH connection
ssh deploy@192.168.1.43 "echo Connection successful"
```
## If Secrets Missing
Generate SSH key pair:
```bash
ssh-keygen -t ed25519 -C "deploy@forgejo-ci"
```
Add public key to server:
```bash
ssh-copy-id -i ~/.ssh/id_ed25519.pub deploy@192.168.1.43
```
Add private key to Forgejo secrets:
```bash
cat ~/.ssh/id_ed25519
# Copy output and paste in Forgejo secret
```
```
---
## PART 5: GENERATION INSTRUCTIONS
### Step 1: Create Output Folder
```
mkdir deployment-configs-{{APP_NAME_LOWER}}
cd deployment-configs-{{APP_NAME_LOWER}}
```
### Step 2: Apply Variable Substitutions
For each template:
1. Replace all `{{VARIABLE}}` with actual values from mapping table
2. Process conditional blocks:
- Remove `{{#if CONDITION}}...{{/if}}` wrapper and keep content if condition is true
- Remove entire `{{#if CONDITION}}...{{/if}}` block if condition is false
3. Save to appropriate file in folder structure
### Step 3: Generate Files
Create each file based on conditions:
| File | Condition | Template |
|------|-----------|----------|
| `.forgejo/workflows/cicd.yml` | Always | Template 1 |
| `systemd/{{APP_NAME_LOWER}}-test.service` | INCLUDE_TEST | Template 2 |
| `systemd/{{APP_NAME_LOWER}}.service` | INCLUDE_PROD | Template 3 |
| `caddy/{{APP_NAME_LOWER}}-config.txt` | Always | Template 4 |
| `scripts/setup-server.sh` | Always | Template 5 |
| `scripts/setup-runner.sh` | CREATE_RUNNER | Template 6 |
| `README.md` | Always | Template 7 |
| `secrets-checklist.md` | Always | Template 8 |
### Step 4: Set Execute Permissions
```bash
chmod +x scripts/*.sh
```
### Step 5: Create Archive (Optional)
```bash
tar -czf deployment-configs-{{APP_NAME_LOWER}}.tar.gz deployment-configs-{{APP_NAME_LOWER}}/
```
---
## PART 6: EXAMPLE OUTPUT
For user answers:
- App Name: BlogApp
- .NET Version: 9.0.x
- Executable: BlogApp
- TEST: yes, port 5002, domain test-blog.jarjarbinks
- PROD: yes, port 5003, domain blog.jarjarbinks
- Runner: existing
Generated folder structure:
```
deployment-configs-blogapp/
├── README.md
├── .forgejo/
│ └── workflows/
│ └── cicd.yml
├── systemd/
│ ├── blogapp-test.service
│ └── blogapp.service
├── caddy/
│ └── blogapp-config.txt
├── scripts/
│ └── setup-server.sh
└── secrets-checklist.md
```
---
## USAGE
1. Copy this prompt to your AI assistant
2. Answer all questions in PART 1
3. AI will generate all files with substituted values
4. Review generated files
5. Follow README.md instructions to deploy
---
**Version:** 1.0
**Compatible with:** .NET 9+, Ubuntu 24.04, Forgejo Actions
**Author:** Janus