Integração com API

Guia para automatizar deployments e integrar pipelines CI/CD com a API REST do DeployAlly.

Visão Geral

A API permite:

  • Listar e inspecionar o catálogo de templates
  • Criar definitions (template + inputs + metadados de instance)
  • Disparar deployments e acompanhar status
  • Executar actions em instances rodando
  • Receber eventos via webhook

Ambientes

Ambiente Base URL Uso
Produção https://sys.deployally.com/api/v1 Sistemas em produção
Teste https://dev.sys.deployally.com/api/v1 Desenvolvimento

Configuração Inicial

1. Obter API Key

  1. Login em https://app.deployally.com
  2. ConfiguraçõesAPI KeysCriar Nova
  3. Defina permissões mínimas necessárias
  4. Copie a key (não será exibida novamente)

2. Configurar Ambiente

export DEPLOYALLY_API_URL="https://sys.deployally.com/api/v1"
export DEPLOYALLY_API_KEY="da_xxx"

3. Testar

curl -X GET "${DEPLOYALLY_API_URL}/health"
curl -X GET "${DEPLOYALLY_API_URL}/templates" \
  -H "Authorization: Bearer ${DEPLOYALLY_API_KEY}"

Fluxo de Deploy Automatizado

1. Listar templates       → GET /templates
2. Inspecionar template   → GET /templates/<species>
3. Registrar servidor     → POST /servers/register   (uma vez)
4. Criar definition       → POST /definitions
5. Executar deploy        → POST /deployments/execute
6. Acompanhar status      → GET /deployments/<id>
7. Listar instances       → GET /instances

Exemplo Completo

#!/bin/bash
set -euo pipefail

API="${DEPLOYALLY_API_URL}"
KEY="${DEPLOYALLY_API_KEY}"

# 1. Buscar template memos
TEMPLATE=$(curl -s "${API}/templates/memos" \
  -H "Authorization: Bearer ${KEY}" | jq -r '.data.id')

# 2. Criar definition
DEFINITION=$(curl -s -X POST "${API}/definitions" \
  -H "Authorization: Bearer ${KEY}" \
  -H "Content-Type: application/json" \
  -d "{
    \"species\": \"memos\",
    \"instance_uid\": \"memos-001\",
    \"server_id\": \"srv_123\",
    \"inputs\": {
      \"WEB_HOSTNAME\": \"memos.exemplo.com\"
    },
    \"profile\": \"production\"
  }" | jq -r '.data.id')

# 3. Executar deploy
DEPLOY=$(curl -s -X POST "${API}/deployments/execute" \
  -H "Authorization: Bearer ${KEY}" \
  -H "Content-Type: application/json" \
  -d "{\"definition_id\": \"${DEFINITION}\"}" | jq -r '.data.id')

# 4. Aguardar conclusão
while true; do
  STATUS=$(curl -s "${API}/deployments/${DEPLOY}" \
    -H "Authorization: Bearer ${KEY}" | jq -r '.data.status')

  case "$STATUS" in
    success)
      echo "Deploy concluído"
      break
      ;;
    failed)
      echo "Deploy falhou"
      exit 1
      ;;
    *)
      sleep 5
      ;;
  esac
done

Trabalhando com Actions

Templates declaram operações pós-deploy (backups, restart, etc.). A API permite disparar essas operações remotamente.

Listar Actions Disponíveis

curl -X GET "${API}/instances/inst_abc/actions" \
  -H "Authorization: Bearer ${KEY}"

Executar Action

EXEC=$(curl -s -X POST "${API}/instances/inst_abc/actions/dump-database/execute" \
  -H "Authorization: Bearer ${KEY}" \
  -H "Content-Type: application/json" \
  -d '{}' | jq -r '.execution.id')

# Acompanhar
while true; do
  STATUS=$(curl -s "${API}/actions/${EXEC}" \
    -H "Authorization: Bearer ${KEY}" | jq -r '.execution.status')

  [ "$STATUS" = "completed" ] && break
  [ "$STATUS" = "failed" ] && exit 1
  sleep 2
done

Integração com CI/CD

GitHub Actions

name: Deploy to DeployAlly

on:
  push:
    branches: [main]

jobs:
  deploy:
    runs-on: ubuntu-latest
    steps:
      - name: Trigger Deployment
        env:
          DEPLOYALLY_API_KEY: ${{ secrets.DEPLOYALLY_API_KEY }}
        run: |
          curl -X POST "https://sys.deployally.com/api/v1/deployments/execute" \
            -H "Authorization: Bearer ${DEPLOYALLY_API_KEY}" \
            -H "Content-Type: application/json" \
            -d '{"definition_id": "def_app_principal"}'

GitLab CI

deploy:
  stage: deploy
  script:
    - |
      curl -X POST "https://sys.deployally.com/api/v1/deployments/execute" \
        -H "Authorization: Bearer ${DEPLOYALLY_API_KEY}" \
        -H "Content-Type: application/json" \
        -d '{"definition_id": "def_app_principal"}'
  only:
    - main

Webhooks

Configure webhooks para receber notificações em tempo real.

Registrar Endpoint

curl -X POST "${API}/webhooks/endpoints" \
  -H "Authorization: Bearer ${KEY}" \
  -H "Content-Type: application/json" \
  -d '{
    "url": "https://meu-sistema.com/webhook/deployally",
    "events": [
      "deployment.success",
      "deployment.failed",
      "instance.unhealthy",
      "action.completed"
    ],
    "secret": "meu_webhook_secret"
  }'

Receber Webhook (Python/Flask)

from flask import Flask, request
import hmac
import hashlib

app = Flask(__name__)
WEBHOOK_SECRET = "meu_webhook_secret"

@app.route('/webhook/deployally', methods=['POST'])
def handle_webhook():
    signature = request.headers.get('X-DeployAlly-Signature')
    payload = request.get_data()
    expected = hmac.new(
        WEBHOOK_SECRET.encode(),
        payload,
        hashlib.sha256
    ).hexdigest()

    if not hmac.compare_digest(signature, expected):
        return 'Invalid signature', 403

    event = request.json
    event_type = event['type']

    if event_type == 'deployment.success':
        # Notificar equipe
        pass
    elif event_type == 'instance.unhealthy':
        # Alertar / tentar restart
        pass

    return 'OK', 200

Tratamento de Erros

Retry com Backoff

import requests
import time

def api_request(method, endpoint, **kwargs):
    url = f"{DEPLOYALLY_API_URL}{endpoint}"
    headers = {
        "Authorization": f"Bearer {DEPLOYALLY_API_KEY}",
        "Content-Type": "application/json"
    }

    for attempt in range(3):
        try:
            response = requests.request(
                method, url, headers=headers, **kwargs
            )

            if response.status_code == 429:
                retry_after = int(response.headers.get('Retry-After', 60))
                time.sleep(retry_after)
                continue

            response.raise_for_status()
            return response.json()

        except requests.exceptions.RequestException:
            if attempt == 2:
                raise
            time.sleep(2 ** attempt)

    raise Exception("Max retries exceeded")

Códigos de Erro Comuns

Código Causa Ação
401 Key inválida Verificar API Key
403 Sem permissão Verificar permissões da key
404 Recurso não existe Verificar IDs
422 Dados inválidos Verificar payload
429 Rate limit Aguardar e retry
500 Erro interno Retry com backoff

Boas Práticas

Segurança

  1. Nunca exponha API Keys em logs, código ou repositórios
  2. Use variáveis de ambiente ou secrets managers (HashiCorp Vault, AWS Secrets Manager)
  3. Rotacione keys periodicamente (POST /servers/{id}/rotate-key)
  4. Use permissões mínimas necessárias
  5. Configure IP allowlist quando possível

Performance

  1. Cache templates localmente (mudam pouco; Cache-Control: max-age=60 na API)
  2. Use webhooks em vez de polling
  3. Agrupe operações relacionadas

Resiliência

  1. Implemente retry com backoff exponencial
  2. Trate 429 Rate Limited adequadamente
  3. Valide respostas antes de usar (success: true/false)
  4. Logs estruturados para auditoria de ações automatizadas

Próximos Passos

By Borlot.com.br on 05/06/2026