# /morph-deploy - Azure Deployment Orchestrator

Orquestra deploy completo para Azure Container Apps seguindo playbook rigoroso baseado em licoes aprendidas.

## Uso

```
/morph-deploy [environment] [options]
```

### Environments

| Environment | Descricao | Aprovacao |
|-------------|-----------|-----------|
| `dev` | Ambiente de desenvolvimento | Automatica se custo < $10/mes |
| `staging` | Ambiente de homologacao | Requer revisao de custos |
| `prod` | Ambiente de producao | Requer aprovacao explicita |

### Options

| Option | Descricao |
|--------|-----------|
| `--auto` | Modo automatico para CI/CD (sem pausas interativas) |
| `--skip-build` | Pular build Docker (usar imagem existente) |
| `--infra-only` | Apenas deploy de infra (Bicep) |
| `--app-only` | Apenas deploy de app (requer infra existente) |
| `--dry-run` | Validar sem executar deploy |
| `--rollback` | Fazer rollback para revisao anterior |

---

## Workflow Completo

### FASE 0: ATIVAR AGENTE

1. Detectar e ativar `azure-deploy-specialist`:
   ```bash
   npx morph-spec detect "deploy to {environment}"
   ```

2. Carregar skill de `.claude/skills/infra/azure-deploy-specialist.md`

3. Confirmar ambiente de deploy:
   ```markdown
   Ambiente detectado: {environment}
   Correto? (sim/nao)
   ```

---

### FASE 1: VALIDAR PRE-REQUISITOS

Executar verificacoes silenciosamente:

```bash
# Azure CLI
az --version

# Login status
az account show

# Docker
docker info

# .NET
dotnet --version

# dotnet-ef
dotnet tool list --global | findstr "dotnet-ef"

# Projeto compila
dotnet build
```

**Se algum check falhar:**
```markdown
## Pre-requisitos Faltando

- Azure CLI: https://aka.ms/installazurecliwindows
- Docker: Iniciar Docker Desktop
- dotnet-ef: `dotnet tool install --global dotnet-ef`

Resolver e tentar novamente.
```

**Confirmar subscription:**
```markdown
Subscription detectada: {name} ({id})
Esta correto? (sim/nao)

Se nao, executar: `az login --tenant <TENANT-ID>`
```

---

### FASE 2: DETECTAR CONFIGURACAO

1. Localizar arquivos de configuracao:
   ```bash
   # Encontrar appsettings
   Get-ChildItem -Recurse -Filter "appsettings*.json"

   # Encontrar Program.cs
   Get-ChildItem -Recurse -Filter "Program.cs"
   ```

2. Parsear e apresentar mapeamento:

   ```markdown
   ## Configuracao Detectada

   ### Connection Strings
   | Config Path | Env Var | Tipo |
   |-------------|---------|------|
   | ConnectionStrings:DefaultConnection | CONNECTIONSTRINGS__DEFAULTCONNECTION | Secret |
   | ConnectionStrings:HangfireConnection | CONNECTIONSTRINGS__HANGFIRECONNECTION | Secret |

   ### Azure Services
   | Config Path | Env Var | Tipo |
   |-------------|---------|------|
   | Azure:Storage:ConnectionString | AZURE__STORAGE__CONNECTIONSTRING | Secret |
   | ApplicationInsights:ConnectionString | APPLICATIONINSIGHTS__CONNECTIONSTRING | Secret |

   ### Blazor Server Detectado
   **SIM** - Sticky sessions OBRIGATORIAS

   ### Autenticacao Detectada
   Azure AD - Requer TenantId, ClientId, ClientSecret
   ```

---

### FASE 3: COLETAR INFORMACOES SENSIVEIS

**PAUSA OBRIGATORIA:**

```markdown
---
## INFORMACOES SENSIVEIS NECESSARIAS

Por favor, forneca os valores abaixo:

### 1. SQL Admin Password (obrigatorio)
**Recomendacao:** Alfanumerico, 16+ chars, SEM caracteres especiais (@!#$)
**Exemplo valido:** `FishArt2025SecurePwd`
>

### 2. Azure Tenant ID (se auth detectado)
**Onde encontrar:** Azure Portal > Azure AD > Properties > Tenant ID
>

### 3. Azure Client Secret (se auth detectado)
**Onde encontrar:** Azure Portal > App Registrations > {App} > Certificates & secrets
>

### 4. Storage Account Key (se storage detectado)
**Onde encontrar:** Azure Portal > Storage Account > Access keys
>

---
```

**Validar senha:**
- Se conter @, !, #, $, %, ^, &, * → ALERTAR:
  ```markdown
  ATENCAO: Senha contem caracteres especiais que podem causar problemas de escape.
  Recomendamos usar apenas letras e numeros.
  Continuar mesmo assim? (sim/nao)
  ```

---

### FASE 4: VALIDAR CUSTOS

1. Verificar se existem templates Bicep:
   ```bash
   Test-Path "infra/main.bicep"
   ```

   **Se NAO existir:**
   ```markdown
   ## Templates Bicep nao encontrados

   O projeto nao possui arquivos de infraestrutura em `infra/`.

   Opcoes:
   1. **Criar agora** - Gerar templates baseado no projeto detectado
   2. **Usar /morph-infra init** - Rodar comando de setup de infra primeiro
   3. **Cancelar** - Abortar deploy

   Qual opcao voce prefere?
   ```

2. Calcular custos:
   ```bash
   npx morph-spec cost infra/main.bicep --verbose
   ```

3. Validar contra limites:
   - Free tier ($0): Automatico
   - Com aprovacao ($10): Requer confirmacao
   - Requer ADR (>$10): Documentar em decisions.md

---

### FASE 5: DEPLOY DE INFRAESTRUTURA

1. Criar Resource Group:
   ```bash
   az group create --name rg-{project}-{env} --location brazilsouth
   ```

2. Executar what-if:
   ```bash
   az deployment group what-if \
     --resource-group rg-{project}-{env} \
     --template-file infra/main.bicep \
     --parameters @infra/parameters.{env}.json
   ```

   **PAUSA OBRIGATORIA:**
   ```markdown
   ## Recursos a serem criados/modificados

   [Output do what-if]

   ### Resumo:
   - Criar: X recursos
   - Modificar: Y recursos
   - Deletar: Z recursos

   ### Custo estimado: $X.XX/mes

   Deseja prosseguir com o deploy? (sim/nao)
   ```

3. Executar deploy:
   ```bash
   az deployment group create \
     --resource-group rg-{project}-{env} \
     --template-file infra/main.bicep \
     --parameters @infra/parameters.{env}.json \
     --name "deploy-$(Get-Date -Format 'yyyyMMdd-HHmmss')"
   ```

4. Capturar outputs para proximas fases

---

### FASE 6: DEPLOY DE APLICACAO

1. Build Docker:
   ```bash
   docker build -t {acr}.azurecr.io/{project}:{tag} .
   ```

2. Push para ACR:
   ```bash
   az acr update --name {acr} --admin-enabled true
   az acr login --name {acr}
   docker push {acr}.azurecr.io/{project}:{tag}
   ```

3. Criar/Atualizar Container App:
   ```bash
   $acrPassword = az acr credential show --name {acr} --query "passwords[0].value" -o tsv

   az containerapp create \
     --name {project}-{env}-app \
     --resource-group rg-{project}-{env} \
     --environment {project}-{env}-app-env \
     --image {acr}.azurecr.io/{project}:{tag} \
     --registry-server {acr}.azurecr.io \
     --registry-username {acr} \
     --registry-password $acrPassword \
     --target-port 8080 \
     --ingress external \
     --min-replicas 1 \
     --max-replicas 3 \
     --cpu 0.25 \
     --memory 0.5Gi
   ```

4. Configurar Environment Variables:
   ```bash
   az containerapp update \
     --name {project}-{env}-app \
     --resource-group rg-{project}-{env} \
     --set-env-vars \
       "ConnectionStrings__DefaultConnection={sql-connection}" \
       "Azure__Storage__ConnectionString={storage-connection}" \
       "ASPNETCORE_ENVIRONMENT=Production"
   ```

5. **Se Blazor Server detectado**, habilitar sticky sessions:
   ```bash
   az containerapp ingress sticky-sessions set \
     --name {project}-{env}-app \
     --resource-group rg-{project}-{env} \
     --affinity sticky
   ```

6. Configurar SQL Firewall:
   ```bash
   az sql server firewall-rule create \
     --resource-group rg-{project}-{env} \
     --server {sql-server} \
     --name AllowAzureServices \
     --start-ip-address 0.0.0.0 \
     --end-ip-address 0.0.0.0
   ```

7. Executar Migrations:
   ```bash
   ~/.dotnet/tools/dotnet-ef database update \
     --project src/{project}.Infrastructure \
     --startup-project src/{project}.Web.Blazor \
     --connection "{sql-connection-string}"
   ```

---

### FASE 7: VERIFICACAO

1. Verificar health:
   ```bash
   az containerapp revision list \
     --name {project}-{env}-app \
     --resource-group rg-{project}-{env} \
     --query "[0].properties.healthState" -o tsv
   ```

2. Obter URL:
   ```bash
   az containerapp show \
     --name {project}-{env}-app \
     --resource-group rg-{project}-{env} \
     --query properties.configuration.ingress.fqdn -o tsv
   ```

3. Testar HTTPS

4. **PAUSA OBRIGATORIA:**
   ```markdown
   ## Verificacao Final

   URL: https://{app-url}

   - [ ] Container App rodando (Healthy)
   - [ ] Health check passando (HTTP 200)
   - [ ] HTTPS acessivel
   - [ ] Database conectado
   - [ ] Blazor circuit estabelecido (se aplicavel)

   Todos os checks passaram? (sim/nao)
   ```

5. **Se falhar**, executar rollback automatico:
   ```bash
   # Listar revisoes
   $revisions = az containerapp revision list \
     --name {project}-{env}-app \
     --resource-group rg-{project}-{env} \
     --query "[].name" -o tsv

   # Ativar revisao anterior
   az containerapp revision activate \
     --name {project}-{env}-app \
     --resource-group rg-{project}-{env} \
     --revision $revisions[1]
   ```

---

## Modo --auto para CI/CD

Para uso em pipelines Azure DevOps:

```bash
npx morph-spec deploy prod --auto \
  --sql-password "$(SQL_PASSWORD)" \
  --tenant-id "$(TENANT_ID)" \
  --client-secret "$(CLIENT_SECRET)" \
  --skip-confirmation
```

### Pipeline Template

```yaml
trigger:
  - main

variables:
  - group: 'deploy-secrets'

stages:
  - stage: Deploy
    jobs:
      - deployment: DeployToAzure
        environment: 'production'
        strategy:
          runOnce:
            deploy:
              steps:
                - script: |
                    npx morph-spec deploy prod --auto \
                      --sql-password "$(SqlPassword)" \
                      --skip-confirmation
                  displayName: 'Deploy to Production'
```

---

## Rollback Manual

```bash
/morph-deploy --rollback

# Ou via CLI:
npx morph-spec deploy --rollback
```

Lista revisoes disponiveis e permite selecionar qual ativar.

---

## Troubleshooting Rapido

| Erro | Solucao |
|------|---------|
| `winget not recognized` | https://aka.ms/installazurecliwindows |
| `MFA/tenant erro` | `az login --tenant <TENANT-ID>` |
| `Login failed for user` | Usar senha alfanumerica simples |
| `CircuitDisconnected` | Verificar sticky sessions |
| `ContainerCreating` stuck | Verificar push da imagem |
| `dotnet-ef not found` | `~/.dotnet/tools/dotnet-ef` |

---

## Exemplo de Uso

```
Usuario: /morph-deploy staging

Claude: Iniciando Azure Deploy workflow para STAGING...

## Fase 1: Pre-requisitos
- az version: 2.53.0
- Logged in as: user@company.com
- Subscription: MySubscription (abc-123-def)

Correto? (sim/nao)

Usuario: sim

Claude: ## Fase 2: Configuracao Detectada

### Connection Strings
- DefaultConnection: SQL Server
- HangfireConnection: Hangfire

### Blazor Server Detectado
**SIM** - Sticky sessions serao habilitadas automaticamente

## Fase 3: Informacoes Sensiveis

SQL Admin Password:
>

Usuario: FishArt2025SecurePwd

Claude: ## Fase 4: Validacao de Custos

Custo estimado: $4.99/mes (Azure SQL Basic)

Aprovar? (sim/nao)

Usuario: sim

Claude: ## Fase 5: Deploy de Infra

Executando what-if...
[Output do what-if]

Confirmar deploy? (sim/nao)

Usuario: sim

Claude: Executando deploy...
- Resource Group criado
- SQL Server provisionado
- Container App Environment criado
- ACR criado

## Fase 6: Deploy de App

- Docker build concluido
- Push para ACR concluido
- Container App atualizado
- Sticky sessions habilitadas
- SQL Firewall configurado
- Migrations executadas

## Fase 7: Verificacao

URL: https://myapp-staging.azurecontainerapps.io

- Container App: Healthy
- HTTPS: OK (200)
- Database: Conectado
- Blazor circuit: Estabelecido

Deploy concluido com sucesso!
```

---

## State Management

Apos deploy bem-sucedido:

```bash
npx morph-spec state set {feature} phase deployed
npx morph-spec state checkpoint {feature} "Deployed to {env} at {timestamp}"
```

---

*MORPH-SPEC by Polymorphism Tech*
