动机和介绍
构建预览不是什么新的或创新的东西。 Heroku 拥有它们多年。但是,如果您是在 Google Cloud Platform 上构建,事情就会有点困难。 Google Cloud Build 可用于部署到 Cloud Functions、Cloud Run、Kubernetes、App Engine 等。这就是使预览稍微复杂的原因,因为 Cloud Build 不知道您将应用程序或服务部署到哪里。他们有一个 GitHub 应用程序来连接存储库并在 GitHub 中显示构建状态,但仅此而已。没有预览、评论或任何我们习惯于来自 Heroku、Vercel 或 Fly 等产品的“正常”内容。
有一种“简单”的方法可以使用简单的 HTTP 请求在 Cloud Build 的 GitHub 拉取请求上发表评论。但是,当您可以使用GitHub 部署 API时,为什么会很容易。
使用此 API,您可以创建环境,为每个环境设置不同的变量,并直接在合并请求上显示构建和部署状态。在您的 CD 平台上完成部署后,您可以将 URL 添加到部署状态。这就是我们在本文中要做的。
GitHub 部署状态
同样,还有另一种方法,即直接对 HTTP 请求使用 Deployments API。但这有时会很棘手,您需要定义一个个人访问令牌来向 GitHub 进行身份验证。相反,我们决定组合一个小的 Node.js 服务,该服务使用 GitHub Apps 生成应用程序令牌并与 Deployments API 交互。这允许对部署过程进行更精细的控制。
免责声明
本文专为 Google Cloud Platform 和 GitHub 而写。假定您对 Google Cloud Platform、Google Cloud Build 和 IAM 权限有基本的了解。
您应该设置了一个 Google Cloud Platform 项目。
GitHub 部署程序(Node.js 和 Docker)
GitHub Deployer 是一个微型 Node.js 服务,它通过 GitHub 应用程序授权并与 GitHub 部署 API 交互。命令是预定义的,一些信息需要内置到 Docker 镜像中,否则 Cloud Build 中的运行时配置会变得过于复杂。
Docker 镜像尚未构建;您需要自己构建它并将其推送到您的注册表。最好的地方是 Google Artifact Registry,其中还存储了您的应用程序的图像(不推荐使用 Container Registry):
如果尚未完成,请创建一个 Artifact Registry 存储库
创建 GitHub 应用程序并将其安装在您的组织中
所需权限:“pull_requests”、“部署”、“元数据”
复制应用程序 ID(从应用程序设置屏幕)和应用程序安装 ID(单击“配置”后,您将在 URL 中找到安装 ID。不知道还能在哪里找到)
创建并下载私钥并将其转换为 base64 (
base64 -i your.private-key.pem
)
构建 Docker 镜像
Cloud Build 在amd64
上运行,因此我们需要buildx
来为 x86 平台构建镜像:
docker buildx build --platform linux/amd64 . -t us-central1-docker.pkg.dev/[PROJECT]/docker/gh-deployer \
--build-arg GH_APP_ID=[GITHUB_APP_ID] \
--build-arg GH_APP_PRIVATE_KEY=[GITHUB_PRIVATE_KEY_BASE_64] \
--build-arg GH_APP_INSTALLATION_ID=[GITHUB_INSTALLATION_ID] \
--build-arg GH_OWNER=[GITHUB_ORG]
将图像推送到您的注册表:
docker push us-central1-docker.pkg.dev/[PROJECT]/docker/gh-deployer
在本地运行 Docker 镜像
docker run -it -e REPO_NAME=test -e REF=main -e ENVIRONMENT=test us-central1-docker.pkg.dev/[PROJECT]/docker/gh-deployer:latest create
所需的环境变量:
-
REPO_NAME
:需要存储库的名称(例如gh-deployer
) -
REF
:需要分支、标签或 SHA 来部署(例如main
) -
ENVIRONMENT
:需要部署到的环境(例如preview
) -
TRANSIENT_ENVIRONMENT
: optional/false如果设置为true
,部署将在一定时间后删除 DESCRIPTION
:可选的部署描述
以下命令可用作第一个参数:
-
create
- 创建一个新的部署 pending
- 构建待定in_progress
- 构建正在进行中queued
- 构建已排队success
- 部署成功error
- 出了点问题failure
- 部署失败
对于 Cloud Build,目前的选项有点受限。没有pending
状态,因为 Cloud Build 需要启动才能创建初始部署。 queued
也没有多大意义,所以在我们自己的设置中,我们使用以下内容:
-
gh-deployer/create
为提交创建临时部署 pgh-deployer/ending
- 运行 kaniko build 构建用于部署的 Docker 镜像
gh-deployer/in_progress
在构建完成之后和部署图像之前- 部署镜像后
gh-deployer/success
同样,对于 Cloud Build,我们不知道部署的位置,因此有两种方法可以将部署 URL 传递到success
步骤:
- 在构建步骤中,将 URL 写入
/workspace/deployer_environment_url
-
success
后将第二个参数传递给 Docker 镜像
我们使用 Cloud Run 进行部署,因此这是检索给定 Pull Request 编号的部署 URL 的构建步骤:
- 名称:gcr.io/google.com/cloudsdktool/cloud-sdk
env: - PR_NUMBER=$_PR_NUMBER script: >- gcloud run services list --project [project] --filter preview-$PR_NUMBER --format "value(status.address.url)" > /workspace/deployer_environment_url
云构建配置/Terraform
云构建.yaml
这是一个使用cloudbuild.yaml
配置文件的完整示例。我们使用 Kaniko 构建并使用 Cloud Run 作为部署目标。
如果您使用 Terraform,还有一个可用的 Terraform 文件: preview.tf
GitHub 操作
通过使用 Deployments API,您可以在deployment_status
上触发 GitHub Actions。这使得在每个预览版本上运行质量保证检查、端到端测试等变得容易。下面是使用为success
状态传入的environment_url
在每个预览上运行Playwright的示例:
剧作家-qa:
if: ${{ github.event.deployment\_status.state == 'success' }} timeout-minutes: 60 runs-on: ubuntu\-latest steps: \- uses: actions/[\[email protected\]](/cdn-cgi/l/email-protection) \- uses: actions/setup\-[\[email protected\]](/cdn-cgi/l/email-protection) with: node-version: 20 cache: 'npm' \- run: npm ci \- name: Install Playwright Browsers run: npm exec playwright install \-\-with\-deps \-y \- name: Run Playwright tests run: pnpm exec playwright test env: BASE\_URL: ${{github.event.deployment\_status.environment\_url}} \- uses: actions/upload\-[\[email protected\]](/cdn-cgi/l/email-protection) if: always() with: name: playwright\-report path: playwright\-report/ retention-days: 30
优化
- 基础镜像
gcr.io/google.com/cloudsdktool/cloud-sdk
比较大。您可以使用 Cloud Run 组件构建自己的小型 gcloud 映像以加快构建速度。
结论
GitHub 部署状态完成
GitHub Pull Requests 上的评论一开始很容易,但是当每个 Pull Request 有多个部署、构建失败等时,它们不提供很大的灵活性并且难以维护/更新。 GitHub 部署 API 提供了一种优雅的方式来创建和管理来自任何第三方 CI/CD 系统的部署。通过GitHub Deployer
我们试图简化与部署 API 的交互,并处理一些仅使用 HTTP API 无法解决的副作用或陷阱。
使用 GitHub 部署 API 的另一个好处是您可以对 GitHub 操作使用deployment_status
触发器,并直接通过事件负载获取environment_url
。
您可以在GitHub 存储库中找到更详细的安装/构建说明和所有代码
如果您有任何问题或意见,请联系 BlueSky / Twitter或加入 GitHub 上的讨论。
也发布在这里。