# Deploy to Gyro Containers automatically with GitHub Actions: build, push, release

https://www.gyrohosting.com/en/knowledgebase/article/gyro-containers-github-actions

- **What you will learn**: How to build your Docker image on every update of the `main` branch and push it to the Gyro registry, release the new revision with no downtime using the `gyro` command line, and roll back automatically if something goes wrong.
- **Time**: 12 minutes
- **Who this is for**: Developers who keep their code on GitHub.
- **What you need**: A running Gyro Containers service ([first app](https://www.gyrohosting.com/en/knowledgebase/article/gyro-containers-publish-first-app)), a `Dockerfile` in your repository, and access to **Settings > Secrets and variables > Actions** on GitHub.

## 1. The approach

```
git push → GitHub Actions: docker build → docker push (Gyro registry)
                         → gyro container service update (new revision, no downtime)
                         → check; if it fails, gyro container service rollback
```

You tag the image with the commit id; each revision is then tied to a commit in the revision history, which makes rollback easy.

## 2. Preparation: secret variables

1. **Registry password:** get the user name and password from the **Image Registry** page in the Gyro panel ([Gyro image registry](https://www.gyrohosting.com/en/knowledgebase/article/gyro-containers-image-registry)).
2. **API key:** in the client area create a new key under **API Credentials** in the account menu; tick the **services read** and **write** permissions. Keep this key **separate** for CI ([First steps with the Gyro API](https://www.gyrohosting.com/en/knowledgebase/article/gyro-api-ilk-adim)).
3. In your GitHub repository add these under **Settings > Secrets and variables > Actions**:

| Name | Type | Value |
| --- | --- | --- |
| `GYRO_REGISTRY_USER` | Secret | Registry user name |
| `GYRO_REGISTRY_PASSWORD` | Secret | Registry password |
| `GYRO_TOKEN` | Secret | API key |
| `GYRO_ENV_ID` | Variable | Your container environment number (for example `12345`) |
| `GYRO_CODE` | Variable | Your address code (the image prefix) |

> **Warning**
> 
> Do not write passwords and keys into the workflow file; use them only as `secrets`. GitHub masks these values in workflow logs.

## 3. The workflow file

Create `.github/workflows/deploy.yml` in the repository:

```
name: Deploy to Gyro
on:
  push:
    branches: [main]

env:
  REGISTRY: registry.ist.gyrohosting.com
  SERVICE: web                        # the service name in Gyro Containers

jobs:
  deploy:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4

      - name: Log in to the registry
        run: echo "${{ secrets.GYRO_REGISTRY_PASSWORD }}" | docker login $REGISTRY -u "${{ secrets.GYRO_REGISTRY_USER }}" --password-stdin

      - name: Build and push
        run: |
          IMAGE=$REGISTRY/${{ vars.GYRO_CODE }}/$SERVICE:${{ github.sha }}
          docker build -t "$IMAGE" .
          docker push "$IMAGE"
          echo "IMAGE=$IMAGE" >> "$GITHUB_ENV"

      - name: Install the gyro CLI
        run: |
          curl -fsSL https://www.gyrohosting.com/cli/install.sh | GYRO_INSTALL_DIR="$HOME/.local/bin" sh
          echo "$HOME/.local/bin" >> "$GITHUB_PATH"

      - name: Release the new revision
        env:
          GYRO_TOKEN: ${{ secrets.GYRO_TOKEN }}
        run: |
          gyro container service update ${{ vars.GYRO_ENV_ID }} $SERVICE \
            --image "$IMAGE" --reason "${{ github.sha }}" --yes

      - name: Verify the release (up to 5 min)
        env:
          GYRO_TOKEN: ${{ secrets.GYRO_TOKEN }}
        run: |
          for i in $(seq 1 30); do
            STATE=$(gyro container service get ${{ vars.GYRO_ENV_ID }} $SERVICE -o json --query state | tr -d '"')
            echo "state: $STATE"
            [ "$STATE" = "running" ] && exit 0
            sleep 10
          done
          echo "Release did not complete, rolling back to the previous revision"
          gyro container service rollback ${{ vars.GYRO_ENV_ID }} $SERVICE --yes
          exit 1
```

> **Info**
> 
> The `state` field in the verification step is the service state in the output of `gyro container service get ID NAME -o json`; check the field name in your output by hand first.

> **Info**
> 
> The `container` commands are in `gyro` version `1.10` and later. The install script installs the current version; to pin a version use the `GYRO_VERSION` environment variable ([Installing the gyro CLI](https://www.gyrohosting.com/en/knowledgebase/article/gyro-cli-kurulum)).

## 4. How it works

1. `docker push` sends the image to the Gyro registry **with the commit id**.
2. `gyro container service update` releases the new revision. Replicas are renewed one by one; an old replica is not stopped until a new one passes its health check (no downtime).
3. The verification step waits until the service state is **running**. If that does not happen within 5 minutes it returns to the previous revision with `rollback` and the workflow is marked **failed**.
4. In the revision history each revision shows its commit id ([Scaling, updating and rollback](https://www.gyrohosting.com/en/knowledgebase/article/gyro-containers-scaling-updating-rollback)).

## 5. Pulling from another registry (GHCR)

If you push the image to GitHub Container Registry instead of the Gyro registry, define the credentials once on the Gyro side: on **Node Pool > Private image registry** enter `ghcr.io`, a user name and a token with **pull-only (`read:packages`)** permission, or run `gyro container external-registry set ID --server ghcr.io --username USER --password TOKEN`. In the workflow you `docker push ghcr.io/...` and release with `--image ghcr.io/...`. If you use the Gyro registry you do not need this step.

## 6. Frequently asked questions

**The push fails with unauthorized ; what should I do?**

The user name/password must belong to this environment and the image name must start with `registry.ist.gyrohosting.com/<your-code>/…`. If you rotated the password, update the GitHub secret.

**Does the registry fill up with every release?**

No; automatic clean-up keeps the images of the last 10 revisions and deletes unused ones. Adjust **Revisions kept** if needed ([image registry](https://www.gyrohosting.com/en/knowledgebase/article/gyro-containers-image-registry)).

**Can I keep staging and production separate?**

Use a separate environment for each (or a separate service in the same environment); change `GYRO_ENV_ID` and `SERVICE` per branch in the workflow.

**Should I provide secrets (a database password) from the workflow?**

No. Enter them once from the panel or with `gyro container secret set`; they are kept across new revisions ([Variables and secrets](https://www.gyrohosting.com/en/knowledgebase/article/gyro-containers-variables-and-secrets)).

## Next step

- [Common errors and fixes](https://www.gyrohosting.com/en/knowledgebase/article/gyro-containers-common-errors)
- [API, CLI and Terraform](https://www.gyrohosting.com/en/knowledgebase/article/gyro-containers-api-cli-terraform)
