# Subir desde CI

Las [guías de CI](/es/guides/ci/overview) construyen una imagen, la suben a un registro y la despliegan. Si el registro es tu propio **Zaroz Registry**, dos cosas se simplifican: subes con una credencial que solo puede hacer eso, y el Workload descarga la imagen **sin ningún inicio de sesión de registro** en su origen (Zaroz da al clúster su propia credencial de pull para tu registro).

Antes de empezar, termina el [Inicio rápido del Registry](/es/guides/registry/quick-start) hasta el paso 2.

## Una credencial para la pipeline

Crea una credencial con el nombre de la pipeline y alcance **Pull y push**. No "Pull, push y borrado": una construcción que puede borrar etiquetas puede borrar lo que corre en producción. Guarda el usuario y el secreto en el almacén de secretos de tu CI como `ZAROZ_REGISTRY_USERNAME` y `ZAROZ_REGISTRY_SECRET`. Guarda el host de acceso como `ZAROZ_REGISTRY_HOST` y el nombre de la imagen como `ZAROZ_REGISTRY_IMAGE` (`<host de acceso>/<espacio de nombres>/mi-app`); estos dos no son secretos.

Usa una credencial por pipeline y entorno. Revocarla detiene esa pipeline y nada más; un token ya emitido caduca en minutos.

## GitHub Actions

```yaml
# .github/workflows/deploy.yml (el job build; el job deploy es el de la guía de GitHub Actions)
jobs:
  build:
    runs-on: ubuntu-latest
    outputs:
      image: ${{ steps.meta.outputs.image }}
    steps:
      - uses: actions/checkout@v4
      - uses: docker/login-action@v3
        with:
          registry: ${{ vars.ZAROZ_REGISTRY_HOST }}
          username: ${{ secrets.ZAROZ_REGISTRY_USERNAME }}
          password: ${{ secrets.ZAROZ_REGISTRY_SECRET }}
      - id: meta
        # Una etiqueta inmutable por commit: Zaroz no vigila una etiqueta que se mueve.
        run: echo "image=${{ vars.ZAROZ_REGISTRY_IMAGE }}:${GITHUB_SHA::12}" >> "$GITHUB_OUTPUT"
      - uses: docker/build-push-action@v6
        with:
          context: .
          push: true
          tags: ${{ steps.meta.outputs.image }}
```

En el job de despliegue de la [guía de GitHub Actions](/es/guides/ci/github-actions), omite `REGISTRY_USERNAME` y `REGISTRY_PASSWORD`: la imagen es tuya y el clúster ya puede descargarla.

## GitLab CI

```yaml
# .gitlab-ci.yml
build:
  stage: build
  image: docker:27
  services: [docker:27-dind]
  variables:
    IMAGE: "$ZAROZ_REGISTRY_IMAGE:$CI_COMMIT_SHORT_SHA"
  script:
    - echo "$ZAROZ_REGISTRY_SECRET" | docker login "${ZAROZ_REGISTRY_IMAGE%%/*}" --username "$ZAROZ_REGISTRY_USERNAME" --password-stdin
    - docker build -t "$IMAGE" .
    - docker push "$IMAGE"
  rules:
    - if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH
```

Pon las variables en **Settings > CI/CD > Variables**, enmascaradas, y protegidas si la rama está protegida. `${ZAROZ_REGISTRY_IMAGE%%/*}` deja solo el host de acceso del nombre de la imagen. El job de despliegue es el de la [guía de GitLab CI](/es/guides/ci/gitlab-ci), de nuevo sin variables de inicio de sesión del registro.

## Forgejo Actions y Gitea Actions

```yaml
# .forgejo/workflows/deploy.yml
jobs:
  build:
    runs-on: docker
    steps:
      - uses: actions/checkout@v4
      - name: Iniciar sesión
        env:
          SECRET: ${{ secrets.ZAROZ_REGISTRY_SECRET }}
        run: echo "$SECRET" | docker login "${IMAGE_REPO%%/*}" --username "${{ secrets.ZAROZ_REGISTRY_USERNAME }}" --password-stdin
      - name: Construir y subir
        run: |
          IMAGE="${IMAGE_REPO}:$(echo "$GITHUB_SHA" | cut -c1-12)"
          docker build -t "$IMAGE" .
          docker push "$IMAGE"
    env:
      IMAGE_REPO: ${{ vars.ZAROZ_REGISTRY_IMAGE }}
```

El runner necesita acceso a un daemon de Docker. El paso de despliegue es el de la [guía de Forgejo y Gitea](/es/guides/ci/forgejo-actions).

## Mantén el registro ordenado

Una pipeline que sube una etiqueta por commit llena el registro. Cuando una versión ya está publicada, borra las etiquetas de construcciones viejas desde la pestaña **Etiquetas**, o con una credencial de alcance "Pull, push y borrado" guardada fuera de la pipeline de construcción, por ejemplo en una tarea programada que llame a `DELETE /subscriptions/{id}/registry/repositories/tags`. El tamaño almacenado, y tu factura, bajan tras la siguiente pasada de limpieza del registro.
