用GitHub Actions和GitHub Pages为你的客户端应用程序建立一个预览环境

132 阅读3分钟

在过去的几天里,我一直在思考如何将GitHub Actions和GitHub Pages结合起来,以便在每次针对托管客户端Web应用的仓库打开拉动请求时,能够动态地构建预览环境。

这个想法是,你可以快速预览一些贡献者所做的修改,而不必克隆他们的分支并在本地运行一切,这对开源项目特别有用。

在这篇文章中,我将解释如何设置一切,以及在这个过程中你可能面临的一些考虑和问题。

启用github页面

你需要做的第一件事是使你的项目能够在某个分支上发布页面。我建议为此创建一个新的分支,比方说preview-env ,然后在其上启用发布功能。

为了做到这一点,进入你的版本库,然后设置->页面,寻找源代码部分,你应该看到类似这样的东西。

image.png

点击下拉菜单,选择你的新分支,preview-env 。然后点击保存image.png

保存后,你会在这个部分的顶部看到一条信息,告诉你页面发布的URL是什么。它总是遵循相同的模式。如果你的组织是my-org ,你的资源库是my-repo ,那么网址将是https://my-org.github.io/my-repo/

配置工作流程

现在我们需要配置一个工作流,在每次创建或更新新的拉动请求时为该分支 "部署 "预览环境。

让我们想象一下,我们有一个用node.js构建的React网络应用。配置可以是这样的。

# .github/workflows/deploy-preview.yml
name: Deploy preview

on:
  pull_request: null

jobs:
  deploy:
    runs-on: ubuntu-20.04
    continue-on-error: true
    steps:
      - name: Checkout code
        uses: actions/checkout@v2
      - name: Use node.js 14.15
        uses: actions/setup-node@v1
        with:
          node-version: 14.15
      - name: Generate slug
        id: generate_slug
        run: echo "##[set-output name=slug;]$(echo ${GITHUB_HEAD_REF#refs/heads/} | sed -r 's/[~\^]+//g' | sed -r 's/[^a-zA-Z0-9]+/-/g' | sed -r 's/^-+\|-+$//g' | tr A-Z a-z)"
      - name: Build
        run: npm ci && npm run build
      - name: Deploy
        uses: JamesIves/github-pages-deploy-action@4.1.1
        with:
          branch: preview-env
          folder: build
          target-folder: ${{ steps.generate_slug.outputs.slug }}
      - name: Publish env
        uses: marocchino/sticky-pull-request-comment@v2
        with:
          header: Preview environment
          message: |
            ## Preview environment
            https://my-org.github.io/my-repo/${{ steps.generate_slug.outputs.slug }}/

如果你还不熟悉GitHub Actions,请看一下官方文档

这个工作流程将遵循以下步骤。

  • 从存储库中签出代码。
  • 设置 node.js 14.15
  • 根据分支名称,生成一个slug,我们将用它来为我们收到的每一个拉动请求设置独立的部署文件夹。蛞蝓将作为一个输出暴露给下一步。
  • 构建项目。这一步显然取决于你项目的需要。
  • 使用JamesIves/github-pages-deploy-action,将我们之前构建的内容部署在GitHub页面中,放在与上面几步生成的slug相匹配的子文件夹下,并放在分支preview-env (记得我们为这个分支启用了GitHub页面)。
  • 最后,使用marocchino/sticky-pull-request-comment,在拉动请求中发布一个评论,并附上预览环境的链接,这样你就可以直接点击它,看到部署情况。

这些步骤可能会根据你的需要和你的项目构建方式而改变。例如,我有一个额外的步骤来更新package.json 中的一个属性,然后用来允许在一个子路径而不是域的根中提供应用程序。

你也可能不用node.js构建你的网站,因为你可以使用现有的多个静态网站生成器中的任何一个,但你会明白这个意思。

最后,你可能已经注意到配置包括continue-on-error: true 。这将允许拉动请求被合并,即使这个过程由于某种原因而失败。

使用分叉时的注意事项

虽然上述配置在同一仓库内创建拉动请求时可以完美地工作,但当拉动请求来自分叉时(这在开放源码软件项目中很常见)有一些限制。

出于安全原因,在这些情况下注入的GITHUB_TOKEN ,没有写入权限,这将使 "部署 "步骤失败。

另外,你不能定义你自己的具有更多权限的令牌,并将其作为秘密注入,因为秘密不会暴露给在分叉上运行的工作流。

然而,通过几个小的配置变化,我们可以绕过这些限制。

改变事件

我们需要做的第一件事是使用pull_request_target 事件,而不是pull_request

on:
-  pull_request: null
+  pull_request_target: null

根据文档,这等同于pull_request 事件,但它在基本版本库的范围内运行。

多亏了这一点,GITHUB_TOKEN 将带有写权限,如果需要的话,我们将可以访问秘密。

检查分叉

我们要改变的第二件事是,我们现在需要指定要签出的版本库。

为了做到这一点,我们需要在 "签出代码 "步骤中添加两个输入,像这样。

    steps:
      - name: Checkout code
        uses: actions/checkout@v2
+       with:
+         repository: ${{ github.event.pull_request.head.repo.full_name }}
+         ref: ${{ github.event.pull_request.head.ref }}

这将确保我们从fork仓库签出,而不是基本仓库,这是默认的,因为它是pull_request_target 事件的范围所在。

就这样了。有了这两个改动,你现在可以为来自分叉的拉取请求部署预览环境了。

重要的是! pull_request 事件的限制是有原因的。人们有可能接触到你的秘密或操纵你的代码。请自行承担风险。

其他注意事项

除了对分叉的限制,还有一些其他的小事情需要考虑。

  • GitHub 页面上的更改不会立即反映出来。部署可能需要几分钟的时间,但考虑到你通常不会在PR创建后立即审查它,这应该不是一个大问题。
  • 正如你所看到的,每次创建拉动请求时,部署都会在你的GitHub Pages分支中生成一个新的文件夹。这可能会导致大量旧文件夹的堆积,所以你可能想设置一些方法,定期或在拉动请求被合并后清理它们。
  • 由于GitHub Pages只允许提供静态页面,这个过程不能用于需要某种后端或服务器端逻辑的应用。
  • 如果你的项目已经在使用GitHub Pages做其他事情(为项目的网站或文档提供服务),这可能会与此冲突,使你无法拥有这种预览环境。