# Despliega desde GitHub Actions

Requisitos: un Workload que ya funcione (creado en la consola), el id de su instancia de servicio y el [token de despliegue](/es/guides/ci/overview#crea-un-token-que-solo-pueda-desplegar). Añade [`zaroz-deploy.sh`](/es/guides/ci/shell) a tu repositorio como `deploy/zaroz-deploy.sh`.

## Secretos y variables

En **Settings > Secrets and variables > Actions**, crea estos en el entorno `production` (Settings > Environments):

| Nombre | Tipo | Valor |
|---|---|---|
| `ZAROZ_TOKEN` | secreto | el token de despliegue `zaroz_...` |
| `ZAROZ_SERVICE` | variable | el UUID de la instancia de servicio |
| `GHCR_PULL_TOKEN` | secreto | solo para un paquete privado: un token clásico con `read:packages`, **no** el que sube |

Los secretos de entorno solo se entregan a los trabajos que apuntan a ese entorno, así que añade **revisores obligatorios** a `production` si una persona debe aprobar cada despliegue.

## El flujo

```yaml
# .github/workflows/deploy.yml
name: deploy

on:
  push:
    branches: [main]

# Two pushes in a row must not deploy at the same time: Zaroz refuses the second
# with 409 anyway, and this queues it instead of failing it.
concurrency:
  group: deploy-production
  cancel-in-progress: false

permissions:
  contents: read
  packages: write

jobs:
  build:
    runs-on: ubuntu-latest
    outputs:
      image: ${{ steps.meta.outputs.image }}
    steps:
      - uses: actions/checkout@v4
      - uses: docker/login-action@v3
        with:
          registry: ghcr.io
          username: ${{ github.actor }}
          password: ${{ secrets.GITHUB_TOKEN }}
      - id: meta
        # One immutable tag per commit: Zaroz does not watch a moved tag.
        run: echo "image=ghcr.io/${GITHUB_REPOSITORY,,}:${GITHUB_SHA::12}" >> "$GITHUB_OUTPUT"
      - uses: docker/build-push-action@v6
        with:
          context: .
          push: true
          tags: ${{ steps.meta.outputs.image }}

  deploy:
    needs: build
    runs-on: ubuntu-latest
    # Put the approval rule (reviewers) on this environment, not on the token.
    environment: production
    steps:
      - uses: actions/checkout@v4
      - name: Deploy to Zaroz
        run: sh deploy/zaroz-deploy.sh
        env:
          IMAGE: ${{ needs.build.outputs.image }}
          ZAROZ_TOKEN: ${{ secrets.ZAROZ_TOKEN }}
          ZAROZ_SERVICE: ${{ vars.ZAROZ_SERVICE }}
          # Only for a private image: a read-only token that can pull the package.
          REGISTRY_USERNAME: ${{ github.actor }}
          REGISTRY_PASSWORD: ${{ secrets.GHCR_PULL_TOKEN }}
```


Cómo se comporta:

- `build` sube `ghcr.io/<propietario>/<repo>:<primeros 12 caracteres del commit>`. Cada commit tiene su propia etiqueta.
- `deploy` ejecuta el script, que hace fallar el trabajo si el despliegue falla y ya ha vuelto a poner la imagen anterior.
- `concurrency` encola un segundo push en lugar de competir con el primero. Si no, Zaroz lo rechazaría con `409` mientras el primer despliegue tiene el servicio.
- El log del trabajo imprime `deployment #N started` y después `... is serving` o el `failure_reason`.

## Revertir a mano

Vuelve a ejecutar el trabajo `deploy` de una ejecución anterior que funcionó: despliega de nuevo la imagen de esa ejecución. O desde una terminal: `IMAGE=ghcr.io/acme/api:<etiqueta antigua> sh deploy/zaroz-deploy.sh`.

## Pull requests

No des a un pull request de un fork acceso a `ZAROZ_TOKEN`. El flujo de arriba solo corre en pushes a `main`, donde hay secretos disponibles. Para un entorno de previsualización, crea un segundo token limitado a un servicio de previsualización distinto.
