> ## 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 部署

> 使用 client.apps.deploys 从 GitHub 进行 deploy：设置 webhook、通过 Square Cloud GitHub App 关联仓库，以及读取 deploy 历史。

`client.apps.deploys` 将应用连接到 GitHub，使一次 push 即可完成 deploy。有两种方式：在仓库中添加一个 **webhook**，或使用 **Square Cloud GitHub App**。

示例使用[创建客户端](/zh/sdks/py/client#创建客户端)中的 `client`。`app_id` 是你的某个应用的 ID：[`client.account.me()`](/zh/sdks/py/client#账户) 会列出它们。

## Webhook

`deploys.set_webhook(app_id, access_token)` 使用 GitHub 访问令牌（`ghp_...` 或 `github_pat_...`）配置 GitHub webhook deploy，并返回需要添加到仓库中的 webhook URL。

```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
```

将 `"@"` 作为令牌传入即可移除 webhook。此时该方法返回 `''`。

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

无效的令牌会返回 400 `INVALID_ACCESS_TOKEN`。

## GitHub App

`deploys.link_github_app(app_id, repository, branch)` 关联一个通过 Square Cloud GitHub App 安装的仓库。它需要 `apps:deploy` 作用域。

```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)` 移除该关联。要关联其他仓库或分支，请先取消关联。

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

关联和取消关联共享 **每 60 秒 3 次调用** 的限制。

| 状态 | 代码 | 触发条件 |
| - | - | - |
| 400 | `GIT_ALREADY_CONFIGURED` | 该应用已关联了仓库：请先取消关联 |
| 400 | `GIT_NOT_CONFIGURED` | 在没有任何关联的情况下调用 `unlink_github_app` |
| 400 | `BRANCH_NOT_FOUND`, `INVALID_BRANCH_LENGTH` | 分支不存在，或其名称超过 256 个字符 |
| 403 | `GITHUB_NOT_CONNECTED` | 你的账户没有安装 GitHub App |
| 403 | `REPOSITORY_NOT_AVAILABLE` | 该 GitHub App 未通过你的 GitHub 账户安装到该仓库 |
| 403 | `REPOSITORY_PERMISSION_REQUIRED` | 你的 GitHub 账户对该仓库没有写入权限 |
| 404 | `REPOSITORY_NOT_FOUND` | 仓库不存在或不可见 |
| 409 | `REPOSITORY_BRANCH_ALREADY_CONFIGURED` | 另一个应用（任何账户的）已关联了该仓库和分支。仅当该应用属于你时，其 ID 才会出现在 `message` 中 |
| 502 | `FAILED_TO_FETCH` | GitHub 未确认该分支：可以安全重试 |

## 当前配置

`deploys.current(app_id)` 返回已配置的内容：`app` 表示 GitHub App 关联，`webhook` 表示 webhook URL。未设置任何内容时返回 `{}`。

```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 历史

`deploys.list(app_id)` 为**每次 deploy 返回一条时间线**，每条时间线是一个事件列表，最早的事件在前。只有 Git deploy（webhook 和 GitHub App 的 push）会被记录。

```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"))
```

| 字段 | 说明 |
| - | - |
| `id` | commit SHA |
| `state` | `pending`、`clone`、`commit`、`restarting`、`success` 或 `error` |
| `date` | 事件发生的时间 |
| `source` | 始终为 `"git"` |
| `branch` | 出现在 `clone` 事件中 |
| `files` | 出现在 `commit` 事件中：`{ added, removed, modified }` |
| `code` / `message` | 出现在 `error` 事件中：deploy 失败的原因（例如 `CLONE_FAILED`） |

## 后续步骤

<CardGroup cols={3}>
  <Card title="网络" icon="globe" href="/zh/sdks/py/network">
    分析、DNS、自定义域名和缓存。
  </Card>

  <Card title="部署 API 参考" icon="code" href="/zh/api-reference/endpoint/apps/deploy/list">
    这些方法背后的 REST 端点。
  </Card>

  <Card title="用 CLI 管理 GitHub 部署" icon="terminal" href="/zh/cli-reference/github-deploys">
    在终端中完成同样的操作。
  </Card>
</CardGroup>
