name: CI/CD Web + Desktop

on:
  push:
    branches: [ main ]
    tags:
      - 'v*.*.*'
  workflow_dispatch:
    inputs:
      force_web_deploy:
        description: 'Forçar deploy do Web (ignorar filtro)?'
        required: false
        default: 'false'
      force_convex_deploy:
        description: 'Forçar deploy do Convex (ignorar filtro)?'
        required: false
        default: 'false'

env:
  APP_DIR: /srv/apps/sistema
  VPS_UPDATES_DIR: /var/www/updates
  RUN_MACHINE_SMOKE: ${{ vars.RUN_MACHINE_SMOKE || secrets.RUN_MACHINE_SMOKE || 'false' }}

jobs:
  changes:
    name: Detect changes
    runs-on: ubuntu-latest
    outputs:
      convex: ${{ steps.filter.outputs.convex }}
      web: ${{ steps.filter.outputs.web }}
    steps:
      - name: Checkout
        uses: actions/checkout@v4
      - name: Paths filter
        id: filter
        uses: dorny/paths-filter@v3
        with:
          filters: |
            convex:
              - 'convex/**'
            web:
              - 'src/**'
              - 'public/**'
              - 'prisma/**'
              - 'next.config.ts'
              - 'package.json'
              - 'pnpm-lock.yaml'
              - 'tsconfig.json'
              - 'middleware.ts'
              - 'stack.yml'

  deploy:
    name: Deploy (VPS Linux)
    needs: changes
    # Executa em qualquer push na main (independente do filtro) ou quando disparado manualmente
    if: ${{ github.event_name == 'workflow_dispatch' || github.ref == 'refs/heads/main' }}
    runs-on: [ self-hosted, linux, vps ]
    steps:
      - name: Checkout
        uses: actions/checkout@v4

      - name: Determine APP_DIR (fallback safe path)
        id: appdir
        run: |
          TS=$(date +%s)
          # Use a web-specific build dir to avoid clashes with convex job
          FALLBACK_DIR="$HOME/apps/web.build.$TS"
          mkdir -p "$FALLBACK_DIR"
          echo "Using APP_DIR (fallback)=$FALLBACK_DIR"
          echo "EFFECTIVE_APP_DIR=$FALLBACK_DIR" >> "$GITHUB_ENV"

      - name: Setup pnpm
        uses: pnpm/action-setup@v4
        with:
          version: 9

      - name: Setup Node.js
        uses: actions/setup-node@v4
        with:
          node-version: 20
          cache: 'pnpm'

      - name: Permissions diagnostic (server paths)
        run: |
          set +e
          echo "== Basic context =="
          whoami || true
          id || true
          groups || true
          umask || true
          echo "HOME=$HOME"
          echo "APP_DIR(default)=${APP_DIR:-/srv/apps/sistema}"
          echo "EFFECTIVE_APP_DIR=$EFFECTIVE_APP_DIR"

          echo "\n== Permissions check =="
          check_path() {
            P="$1"
            echo "-- $P"
            if [ -e "$P" ]; then
              stat -c '%A %U:%G %n' "$P" 2>/dev/null || ls -ld "$P" || true
              echo -n "WRITABLE? "; [ -w "$P" ] && echo yes || echo no
              if command -v namei >/dev/null 2>&1; then
                namei -l "$P" || true
              fi
              TMP="$P/.permtest.$$"
              (echo test > "$TMP" 2>/dev/null && echo "CREATE_FILE: ok" && rm -f "$TMP") || echo "CREATE_FILE: failed"
            else
              echo "(missing)"
            fi
          }
          check_path "/srv/apps/sistema"
          check_path "/srv/apps/sistema/src/app/machines/handshake"
          check_path "/srv/apps/sistema/apps/desktop/node_modules"
          check_path "/srv/apps/sistema/node_modules"
          check_path "$EFFECTIVE_APP_DIR"
          check_path "$EFFECTIVE_APP_DIR/node_modules"

      - name: Sync workspace to APP_DIR (preserving local env)
        run: |
          mkdir -p "$EFFECTIVE_APP_DIR"
          RSYNC_FLAGS="-az --inplace --no-times --no-perms --no-owner --no-group --delete"
          # Excluir .env apenas quando copiando para o diretório padrão (/srv) para preservar segredos locais
          EXCLUDE_ENV="--exclude '.env*' --exclude 'apps/desktop/.env*' --exclude 'convex/.env*'"
          if [ "$EFFECTIVE_APP_DIR" != "${APP_DIR:-/srv/apps/sistema}" ]; then
            EXCLUDE_ENV=""
          fi
          rsync $RSYNC_FLAGS \
            --filter='protect .next.old*' \
            --exclude '.next.old*' \
            --filter='protect node_modules' \
            --filter='protect node_modules/**' \
            --filter='protect .pnpm-store' \
            --filter='protect .pnpm-store/**' \
            --filter='protect .env' \
            --filter='protect .env*' \
            --filter='protect apps/desktop/.env*' \
            --filter='protect convex/.env*' \
            --exclude '.git' \
            --exclude '.next' \
            --exclude 'node_modules' \
            --exclude 'node_modules/**' \
            --exclude '.pnpm-store' \
            --exclude '.pnpm-store/**' \
            $EXCLUDE_ENV \
            ./ "$EFFECTIVE_APP_DIR"/

      - name: Copy production .env if present
        run: |
          DEFAULT_DIR="${APP_DIR:-/srv/apps/sistema}"
          if [ "$EFFECTIVE_APP_DIR" != "$DEFAULT_DIR" ] && [ -f "$DEFAULT_DIR/.env" ]; then
            echo "Copying production .env from $DEFAULT_DIR to $EFFECTIVE_APP_DIR"
            cp -f "$DEFAULT_DIR/.env" "$EFFECTIVE_APP_DIR/.env"
          fi

      - name: Prune workspace for server-only build
        run: |
          cd "$EFFECTIVE_APP_DIR"
          # Keep only root (web) as a package in this effective workspace
          printf "packages:\n  - .\n\nignoredBuiltDependencies:\n  - '@prisma/client'\n  - '@prisma/engines'\n  - '@tailwindcss/oxide'\n  - esbuild\n  - prisma\n  - sharp\n  - unrs-resolver\n" > pnpm-workspace.yaml
          # Remove desktop app to avoid pnpm touching its node_modules on this runner
          rm -rf apps/desktop || true

      - name: Clean Next.js cache (.next) to avoid EACCES
        run: |
          cd "$EFFECTIVE_APP_DIR"
          if [ -e .next ]; then
            echo "Removing existing .next (may be root-owned from previous container)"
            rm -rf .next || (mv .next ".next.old.$(date +%s)" || true)
          fi
          mkdir -p .next
          chmod -R u+rwX .next || true

      - name: Install and build (Next.js)
        run: |
          cd "$EFFECTIVE_APP_DIR"
          corepack enable || true
          pnpm --filter web install --no-frozen-lockfile
          pnpm prisma:generate
          pnpm build

      - name: Publish build to stable APP_DIR directory
        run: |
          set -e
          DEST="$HOME/apps/sistema"
          mkdir -p "$DEST"
          # One-time fix for old root-owned files (esp. .pnpm-store) left by previous containers
          docker run --rm -v "$DEST":/target alpine:3 sh -lc 'chown -R 1000:1000 /target 2>/dev/null || true; chmod -R u+rwX /target 2>/dev/null || true' || true
          # Publish new build; exclude .pnpm-store to avoid Permission denied on old entries
          rsync -a --delete \
            --exclude '.pnpm-store' --exclude '.pnpm-store/**' \
            "$EFFECTIVE_APP_DIR"/ "$DEST"/
          echo "Published build to: $DEST"

      - name: Swarm deploy (stack.yml)
        run: |
          cd "$EFFECTIVE_APP_DIR"
          # Exporta variáveis do .env para substituição no stack (ex.: MACHINE_PROVISIONING_SECRET)
          set -o allexport
          if [ -f .env ]; then . ./.env; fi
          set +o allexport
          APP_DIR_STABLE="$HOME/apps/sistema"
          if [ ! -d "$APP_DIR_STABLE" ]; then
            echo "ERROR: Stable APP_DIR does not exist: $APP_DIR_STABLE" >&2; exit 1
          fi
          echo "Using APP_DIR (stable)=$APP_DIR_STABLE"
          APP_DIR="$APP_DIR_STABLE" RELEASE_SHA=${{ github.sha }} docker stack deploy --with-registry-auth -c stack.yml sistema

      - name: Ensure Convex service envs and restart
        run: |
          cd "$EFFECTIVE_APP_DIR"
          set -o allexport
          if [ -f .env ]; then . ./.env; fi
          set +o allexport
          echo "Ensuring Convex envs on service: sistema_convex_backend"
          if [ -n "${MACHINE_PROVISIONING_SECRET:-}" ]; then
            docker service update --env-add MACHINE_PROVISIONING_SECRET="${MACHINE_PROVISIONING_SECRET}" sistema_convex_backend || true
          fi
          if [ -n "${MACHINE_TOKEN_TTL_MS:-}" ]; then
            docker service update --env-add MACHINE_TOKEN_TTL_MS="${MACHINE_TOKEN_TTL_MS}" sistema_convex_backend || true
          fi
          if [ -n "${FLEET_SYNC_SECRET:-}" ]; then
            docker service update --env-add FLEET_SYNC_SECRET="${FLEET_SYNC_SECRET}" sistema_convex_backend || true
          fi
          echo "Current envs:" 
          docker service inspect sistema_convex_backend --format '{{range .Spec.TaskTemplate.ContainerSpec.Env}}{{println .}}{{end}}' || true
          echo "Forcing service restart..."
          docker service update --force sistema_convex_backend || true

      - name: Smoke test — register + heartbeat
        run: |
          set -e
          if [ "${RUN_MACHINE_SMOKE:-false}" != "true" ]; then
            echo "RUN_MACHINE_SMOKE != true — pulando smoke test"; exit 0
          fi
          # Load MACHINE_PROVISIONING_SECRET from production .env on the host
          if [ -f /srv/apps/sistema/.env ]; then
            set -o allexport
            . /srv/apps/sistema/.env
            set +o allexport
          fi
          if [ -z "${MACHINE_PROVISIONING_SECRET:-}" ]; then
            echo "MACHINE_PROVISIONING_SECRET ausente — pulando smoke test"; exit 0
          fi
          HOSTNAME_TEST="ci-smoke-$(date +%s)"
          BODY='{"provisioningSecret":"'"$MACHINE_PROVISIONING_SECRET"'","tenantId":"tenant-atlas","hostname":"'"$HOSTNAME_TEST"'","os":{"name":"Linux","version":"6.1.0","architecture":"x86_64"},"macAddresses":["AA:BB:CC:DD:EE:FF"],"serialNumbers":[],"metadata":{"inventory":{"cpu":"i7","ramGb":16}},"registeredBy":"ci-smoke"}'
          HTTP=$(curl -sS -o resp.json -w "%{http_code}" -H 'Content-Type: application/json' -d "$BODY" https://tickets.esdrasrenan.com.br/api/machines/register || true)
          echo "Register HTTP=$HTTP"
          if [ "$HTTP" != "201" ]; then
            echo "Register failed:"; tail -c 600 resp.json || true; exit 1; fi
          TOKEN=$(node -e 'try{const j=require("fs").readFileSync("resp.json","utf8");process.stdout.write(JSON.parse(j).machineToken||"");}catch(e){process.stdout.write("")}' )
          if [ -z "$TOKEN" ]; then echo "Missing token in register response"; exit 1; fi
          HB=$(curl -sS -o /dev/null -w "%{http_code}" -H 'Content-Type: application/json' -d '{"machineToken":"'"$TOKEN"'","status":"online","metrics":{"cpuPct":5,"memFreePct":70}}' https://tickets.esdrasrenan.com.br/api/machines/heartbeat || true)
          echo "Heartbeat HTTP=$HB"
          if [ "$HB" != "200" ]; then echo "Heartbeat failed"; exit 1; fi

      - name: Cleanup old build workdirs (keep last 2)
        run: |
          set -e
          ROOT="$HOME/apps"
          KEEP=2
          PATTERN='web.build.*'
          ACTIVE="$HOME/apps/sistema"
          echo "Scanning $ROOT for old $PATTERN dirs"
          LIST=$(find "$ROOT" -maxdepth 1 -type d -name "$PATTERN" | sort -r || true)
          echo "$LIST" | sed -n "1,${KEEP}p" | sed 's/^/Keeping: /' || true
          echo "$LIST" | sed "1,${KEEP}d" | while read dir; do
            [ -z "$dir" ] && continue
            if [ -n "$ACTIVE" ] && [ "$(readlink -f "$dir")" = "$ACTIVE" ]; then
              echo "Skipping active dir (in use by APP_DIR): $dir"; continue
            fi
            echo "Removing $dir"
            chmod -R u+rwX "$dir" 2>/dev/null || true
            rm -rf "$dir" || {
              echo "Local rm failed, falling back to docker (root) cleanup for $dir..."
              docker run --rm -v "$dir":/target alpine:3 sh -lc 'chown -R 1000:1000 /target 2>/dev/null || true; chmod -R u+rwX /target 2>/dev/null || true; rm -rf /target/* /target/.[!.]* /target/..?* 2>/dev/null || true' || true
              rm -rf "$dir" 2>/dev/null || rmdir "$dir" 2>/dev/null || true
            }
          done
          echo "Disk usage (top 10 under $ROOT):"
          du -sh "$ROOT"/* 2>/dev/null | sort -rh | head -n 10 || true

      - name: Restart web service with new code (skip — stack deploy already updated)
        if: ${{ always() && false }}
        run: |
          docker service update --force sistema_web

      - name: Restart Convex backend service (optional)
        run: |
          # Fail the job if the convex backend cannot restart
          docker service update --force sistema_convex_backend

  convex_deploy:
    name: Deploy Convex functions
    needs: changes
    # Executa em workflow_dispatch, push na main, ou quando convex/** mudar
    if: ${{ github.event_name == 'workflow_dispatch' || github.ref == 'refs/heads/main' || needs.changes.outputs.convex == 'true' }}
    runs-on: [ self-hosted, linux, vps ]
    env:
      APP_DIR: /srv/apps/sistema
    steps:
      - name: Checkout
        uses: actions/checkout@v4

      - name: Determine APP_DIR (fallback safe path)
        id: appdir
        run: |
          TS=$(date +%s)
          # Use a convex-specific build dir to avoid clashes with web job
          FALLBACK_DIR="$HOME/apps/convex.build.$TS"
          mkdir -p "$FALLBACK_DIR"
          echo "Using APP_DIR (fallback)=$FALLBACK_DIR"
          echo "EFFECTIVE_APP_DIR=$FALLBACK_DIR" >> "$GITHUB_ENV"

      - name: Validate secrets present (Convex)
        env:
          CONVEX_SELF_HOSTED_URL: ${{ secrets.CONVEX_SELF_HOSTED_URL }}
          CONVEX_SELF_HOSTED_ADMIN_KEY: ${{ secrets.CONVEX_SELF_HOSTED_ADMIN_KEY }}
        run: |
          set -e
          if [ -z "${CONVEX_SELF_HOSTED_URL:-}" ]; then echo "Missing secret: CONVEX_SELF_HOSTED_URL" >&2; exit 1; fi
          if [ -z "${CONVEX_SELF_HOSTED_ADMIN_KEY:-}" ]; then echo "Missing secret: CONVEX_SELF_HOSTED_ADMIN_KEY" >&2; exit 1; fi

      - name: Sync workspace to APP_DIR (preserving local env)
        run: |
          mkdir -p "$EFFECTIVE_APP_DIR"
          RSYNC_FLAGS="-az --inplace --no-times --no-perms --no-owner --no-group --delete"
          rsync $RSYNC_FLAGS \
            --filter='protect .next.old*' \
            --exclude '.next.old*' \
            --exclude '.env*' \
            --exclude 'apps/desktop/.env*' \
            --exclude 'convex/.env*' \
            --filter='protect node_modules' \
            --filter='protect node_modules/**' \
            --filter='protect .pnpm-store' \
            --filter='protect .pnpm-store/**' \
            --exclude '.git' \
            --exclude '.next' \
            --exclude 'node_modules' \
            --exclude 'node_modules/**' \
            --exclude '.pnpm-store' \
            --exclude '.pnpm-store/**' \
            ./ "$EFFECTIVE_APP_DIR"/

      - name: Set Convex env vars (self-hosted)
        env:
          CONVEX_SELF_HOSTED_URL: ${{ secrets.CONVEX_SELF_HOSTED_URL }}
          CONVEX_SELF_HOSTED_ADMIN_KEY: ${{ secrets.CONVEX_SELF_HOSTED_ADMIN_KEY }}
          MACHINE_PROVISIONING_SECRET: ${{ secrets.MACHINE_PROVISIONING_SECRET }}
          MACHINE_TOKEN_TTL_MS: ${{ secrets.MACHINE_TOKEN_TTL_MS }}
          FLEET_SYNC_SECRET: ${{ secrets.FLEET_SYNC_SECRET }}
        run: |
          set -e
          docker run --rm -i \
            -v "$EFFECTIVE_APP_DIR":/app \
            -w /app \
            -e PNPM_STORE_DIR=/tmp/pnpm-store \
            -e CONVEX_SELF_HOSTED_URL \
            -e CONVEX_SELF_HOSTED_ADMIN_KEY \
            -e MACHINE_PROVISIONING_SECRET \
            -e MACHINE_TOKEN_TTL_MS \
            -e FLEET_SYNC_SECRET \
            node:20-bullseye bash -lc "set -euo pipefail; unset CONVEX_DEPLOYMENT; corepack enable; corepack prepare pnpm@9 --activate; mkdir -p \"${PNPM_STORE_DIR:-/tmp/pnpm-store}\"; pnpm config set store-dir \"${PNPM_STORE_DIR:-/tmp/pnpm-store}\"; pnpm install --frozen-lockfile --prod=false; \
              if [ -n \"$MACHINE_PROVISIONING_SECRET\" ]; then pnpm exec convex env set MACHINE_PROVISIONING_SECRET \"$MACHINE_PROVISIONING_SECRET\" -y; fi; \
              if [ -n \"$MACHINE_TOKEN_TTL_MS\" ]; then pnpm exec convex env set MACHINE_TOKEN_TTL_MS \"$MACHINE_TOKEN_TTL_MS\" -y; fi; \
              if [ -n \"$FLEET_SYNC_SECRET\" ]; then pnpm exec convex env set FLEET_SYNC_SECRET \"$FLEET_SYNC_SECRET\" -y; fi; \
              pnpm exec convex env list"

      - name: Ensure .env is not present for Convex deploy
        run: |
          cd "$EFFECTIVE_APP_DIR"
          if [ -f .env ]; then
            echo "Renaming .env -> .env.bak (Convex self-hosted deploy)"
            mv -f .env .env.bak
          fi
      - name: Deploy functions to Convex self-hosted
        env:
          CONVEX_SELF_HOSTED_URL: ${{ secrets.CONVEX_SELF_HOSTED_URL }}
          CONVEX_SELF_HOSTED_ADMIN_KEY: ${{ secrets.CONVEX_SELF_HOSTED_ADMIN_KEY }}
        run: |
          docker run --rm -i \
            -v "$EFFECTIVE_APP_DIR":/app \
            -w /app \
            -e PNPM_STORE_DIR=/tmp/pnpm-store \
            -e CI=true \
            -e CONVEX_SELF_HOSTED_URL \
            -e CONVEX_SELF_HOSTED_ADMIN_KEY \
            node:20-bullseye bash -lc "set -euo pipefail; unset CONVEX_DEPLOYMENT; corepack enable; corepack prepare pnpm@9 --activate; mkdir -p \"${PNPM_STORE_DIR:-/tmp/pnpm-store}\"; pnpm config set store-dir \"${PNPM_STORE_DIR:-/tmp/pnpm-store}\"; pnpm install --frozen-lockfile --prod=false; pnpm exec convex deploy"

      - name: Cleanup old convex build workdirs (keep last 2)
        run: |
          set -e
          ROOT="$HOME/apps"
          KEEP=2
          PATTERN='convex.build.*'
          LIST=$(find "$ROOT" -maxdepth 1 -type d -name "$PATTERN" | sort -r || true)
          echo "$LIST" | sed -n "1,${KEEP}p" | sed 's/^/Keeping: /' || true
          echo "$LIST" | sed "1,${KEEP}d" | while read dir; do
            [ -z "$dir" ] && continue
            echo "Removing $dir"
            chmod -R u+rwX "$dir" 2>/dev/null || true
            rm -rf "$dir" || {
              echo "Local rm failed, falling back to docker (root) cleanup for $dir..."
              docker run --rm -v "$dir":/target alpine:3 sh -lc 'chown -R 1000:1000 /target 2>/dev/null || true; chmod -R u+rwX /target 2>/dev/null || true; rm -rf /target/* /target/.[!.]* /target/..?* 2>/dev/null || true' || true
              rm -rf "$dir" 2>/dev/null || rmdir "$dir" 2>/dev/null || true
            }
          done

  desktop_release:
    name: Desktop Release (Windows)
    if: ${{ startsWith(github.ref, 'refs/tags/v') }}
    runs-on: [ self-hosted, windows, desktop ]
    defaults:
      run:
        working-directory: apps/desktop
    steps:
      - name: Checkout
        uses: actions/checkout@v4

      - name: Setup pnpm
        uses: pnpm/action-setup@v4
        with:
          version: 9

      - name: Setup Node.js
        uses: actions/setup-node@v4
        with:
          node-version: 20
          cache: 'pnpm'

      - name: Install deps (desktop)
        run: pnpm install --frozen-lockfile

      - name: Build with Tauri
        uses: tauri-apps/tauri-action@v0
        env:
          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
          TAURI_PRIVATE_KEY: ${{ secrets.TAURI_PRIVATE_KEY }}
          TAURI_KEY_PASSWORD: ${{ secrets.TAURI_KEY_PASSWORD }}
        with:
          projectPath: apps/desktop


      - name: Upload latest.json + bundles to VPS
        uses: appleboy/scp-action@v0.1.7
        with:
          host: ${{ secrets.VPS_HOST }}
          username: ${{ secrets.VPS_USER }}
          key: ${{ secrets.VPS_SSH_KEY }}
          source: |
            **/bundle/**/latest.json
            **/bundle/**/*
          target: ${{ env.VPS_UPDATES_DIR }}
          overwrite: true

  diagnose_convex:
    name: Diagnose Convex (env + register test)
    if: ${{ github.event_name == 'workflow_dispatch' }}
    runs-on: [ self-hosted, linux, vps ]
    steps:
      - name: Print service env and .env subset
        run: |
          echo "=== Convex service env ==="
          docker service inspect sistema_convex_backend --format '{{range .Spec.TaskTemplate.ContainerSpec.Env}}{{println .}}{{end}}' || true
          echo
          echo "=== /srv/apps/sistema/.env subset ==="
          [ -f /srv/apps/sistema/.env ] && grep -E '^(MACHINE_PROVISIONING_SECRET|MACHINE_TOKEN_TTL_MS|FLEET_SYNC_SECRET|NEXT_PUBLIC_CONVEX_URL)=' -n /srv/apps/sistema/.env || echo '(no .env)'
      - name: Acquire Convex admin key
        id: key
        run: |
          CID=$(docker ps --format '{{.ID}} {{.Names}}' | awk '/sistema_convex_backend/{print $1; exit}')
          if [ -z "$CID" ]; then echo "No convex container"; exit 1; fi
          KEY=$(docker exec -i "$CID" /bin/sh -lc './generate_admin_key.sh' | tr -d '\r' | grep -o 'convex-self-hosted|[^ ]*' | tail -n1)
          echo "ADMIN_KEY=$KEY" >> $GITHUB_OUTPUT
          echo "Admin key acquired? $([ -n "$KEY" ] && echo yes || echo no)"
      - name: List Convex env and set missing
        env:
          CONVEX_SELF_HOSTED_URL: https://convex.esdrasrenan.com.br
          ADMIN_KEY: ${{ steps.key.outputs.ADMIN_KEY }}
        run: |
          set -e
          if [ -f /srv/apps/sistema/.env ]; then
            set -o allexport
            . /srv/apps/sistema/.env
            set +o allexport
          fi
          docker run --rm -i \
            -v /srv/apps/sistema:/app -w /app \
            -e CONVEX_SELF_HOSTED_URL -e CONVEX_SELF_HOSTED_ADMIN_KEY="$ADMIN_KEY" \
            -e MACHINE_PROVISIONING_SECRET -e MACHINE_TOKEN_TTL_MS -e FLEET_SYNC_SECRET \
            node:20-bullseye bash -lc "set -euo pipefail; corepack enable; corepack prepare pnpm@9 --activate; pnpm i --frozen-lockfile --prod=false; \
              unset CONVEX_DEPLOYMENT; pnpm exec convex env list; \
              if [ -n \"$MACHINE_PROVISIONING_SECRET\" ]; then pnpm exec convex env set MACHINE_PROVISIONING_SECRET \"$MACHINE_PROVISIONING_SECRET\" -y; fi; \
              if [ -n \"$MACHINE_TOKEN_TTL_MS\" ]; then pnpm exec convex env set MACHINE_TOKEN_TTL_MS \"$MACHINE_TOKEN_TTL_MS\" -y; fi; \
              if [ -n \"$FLEET_SYNC_SECRET\" ]; then pnpm exec convex env set FLEET_SYNC_SECRET \"$FLEET_SYNC_SECRET\" -y; fi; \
              pnpm exec convex env list"
      - name: Test register from runner
        run: |
          HOST="vm-teste-$(date +%s)"
          DATA='{"provisioningSecret":"'"${MACHINE_PROVISIONING_SECRET:-"71daa9ef54cb224547e378f8121ca898b614446c142a132f73c2221b4d53d7d6"}"'","tenantId":"tenant-atlas","hostname":"'"$HOST"'","os":{"name":"Linux","version":"6.1.0","architecture":"x86_64"},"macAddresses":["AA:BB:CC:DD:EE:FF"],"serialNumbers":[],"metadata":{"inventario":{"cpu":"i7","ramGb":16}},"registeredBy":"diag-test"}'
          HTTP=$(curl -sS -o resp.json -w "%{http_code}" -H 'Content-Type: application/json' -d "$DATA" https://tickets.esdrasrenan.com.br/api/machines/register || true)
          echo "Register HTTP=$HTTP" && tail -c 400 resp.json || true
