> ## Documentation Index
> Fetch the complete documentation index at: https://docs.squarecloud.app/llms.txt
> Use this file to discover all available pages before exploring further.

# Python-SDK: GitHub-Deploys

> Deploye von GitHub mit client.apps.deploys: Richte einen Webhook ein, verknüpfe ein Repository über die Square Cloud GitHub App und lies den Deploy-Verlauf.

`client.apps.deploys` verbindet eine App mit GitHub, sodass ein Push sie deployt. Dafür gibt es zwei Wege: einen **Webhook**, den du dem Repository hinzufügst, oder die **Square Cloud GitHub App**.

Die Beispiele verwenden den `client` aus [Client erstellen](/de/sdks/py/client#client-erstellen). `app_id` ist die ID einer deiner Apps: [`client.account.me()`](/de/sdks/py/client#konto) listet sie auf.

## Webhook

`deploys.set_webhook(app_id, access_token)` konfiguriert Deploys per GitHub-Webhook mit einem GitHub-Zugriffstoken (`ghp_...` oder `github_pat_...`) und gibt die Webhook-URL zurück, die du deinem Repository hinzufügst.

```python theme={"system"}
url = client.apps.deploys.set_webhook(app_id, os.environ["GITHUB_TOKEN"])

print(url)  # add it as a webhook in the repository settings
```

Übergib `"@"` als Token, um den Webhook zu entfernen. Die Methode gibt dann `''` zurück.

```python theme={"system"}
client.apps.deploys.set_webhook(app_id, "@")
```

Ein ungültiges Token ergibt 400 `INVALID_ACCESS_TOKEN`.

## GitHub App

`deploys.link_github_app(app_id, repository, branch)` verknüpft ein Repository, das über die Square Cloud GitHub App installiert ist. Dafür ist der Scope `apps:deploy` nötig.

```python theme={"system"}
repo = client.apps.deploys.link_github_app(app_id, "octocat/hello-world", "main")

print(repo["id"], repo["full_name"], repo["branch"])
```

`deploys.unlink_github_app(app_id)` entfernt die Verknüpfung. Um ein anderes Repository oder einen anderen Branch zu verknüpfen, hebe die Verknüpfung zuerst auf.

```python theme={"system"}
client.apps.deploys.unlink_github_app(app_id)
```

Verknüpfen und Aufheben teilen sich ein Limit von **3 Aufrufen pro 60 Sekunden**.

| Status | Code | Wann |
| - | - | - |
| 400 | `GIT_ALREADY_CONFIGURED` | Die App hat bereits ein verknüpftes Repository: Hebe die Verknüpfung zuerst auf |
| 400 | `GIT_NOT_CONFIGURED` | `unlink_github_app`, obwohl nichts verknüpft ist |
| 400 | `BRANCH_NOT_FOUND`, `INVALID_BRANCH_LENGTH` | Der Branch existiert nicht, oder sein Name ist länger als 256 Zeichen |
| 403 | `GITHUB_NOT_CONNECTED` | Dein Konto hat keine Installation der GitHub App |
| 403 | `REPOSITORY_NOT_AVAILABLE` | Die GitHub App ist über dein GitHub-Konto nicht auf dem Repository installiert |
| 403 | `REPOSITORY_PERMISSION_REQUIRED` | Dein GitHub-Konto hat keinen Schreibzugriff auf das Repository |
| 404 | `REPOSITORY_NOT_FOUND` | Das Repository existiert nicht oder ist nicht sichtbar |
| 409 | `REPOSITORY_BRANCH_ALREADY_CONFIGURED` | Eine andere App, aus einem beliebigen Konto, verknüpft bereits dieses Repository und diesen Branch. Ihre ID steht nur dann in `message`, wenn die App dir gehört |
| 502 | `FAILED_TO_FETCH` | GitHub hat den Branch nicht bestätigt: kann gefahrlos wiederholt werden |

## Aktuelle Konfiguration

`deploys.current(app_id)` gibt zurück, was konfiguriert ist: `app` für die Verknüpfung mit der GitHub App, `webhook` für die Webhook-URL. Ist nichts gesetzt, gibt die Methode `{}` zurück.

```python theme={"system"}
current = client.apps.deploys.current(app_id)

if "app" in current:
    print(current["app"]["name"], current["app"]["branch"])  # e.g. "octocat/hello-world" "main"
if "webhook" in current:
    print(current["webhook"])
```

## Deploy-Verlauf

`deploys.list(app_id)` gibt eine **Zeitleiste pro Deploy** zurück, jede eine Liste von Ereignissen, das älteste Ereignis zuerst. Nur Git-Deploys (Pushes per Webhook und GitHub App) werden aufgezeichnet.

```python theme={"system"}
for timeline in client.apps.deploys.list(app_id):
    last = timeline[-1] if timeline else None
    if last is None:
        continue
    print(last["id"], last["state"], last["date"])

    if last["state"] == "error":
        print(last.get("code"), last.get("message"))
```

| Feld | Beschreibung |
| - | - |
| `id` | Der SHA des Commits |
| `state` | `pending`, `clone`, `commit`, `restarting`, `success` oder `error` |
| `date` | Wann das Ereignis stattfand |
| `source` | Immer `"git"` |
| `branch` | Bei `clone`-Ereignissen |
| `files` | Bei `commit`-Ereignissen: `{ added, removed, modified }` |
| `code` / `message` | Bei `error`-Ereignissen: warum der Deploy fehlgeschlagen ist (zum Beispiel `CLONE_FAILED`) |

## Nächste Schritte

<CardGroup cols={3}>
  <Card title="Netzwerk" icon="globe" href="/de/sdks/py/network">
    Analytics, DNS, eigene Domains und Cache.
  </Card>

  <Card title="API-Referenz für Deploys" icon="code" href="/de/api-reference/endpoint/apps/deploy/list">
    Die REST-Endpunkte hinter diesen Methoden.
  </Card>

  <Card title="GitHub-Deploys über die CLI" icon="terminal" href="/de/cli-reference/github-deploys">
    Dieselben Aktionen im Terminal.
  </Card>
</CardGroup>
