wxsm's space

Nov 02, 2020

Publish using GitHub Action

本文是一些 GitHub Actions 常用发布动作的总结。

强烈建议将所有 Publish actions 分开执行,不要集中到一个 Workflow 内。原因是如果其中一个动作因为某些原因失败了,GitHub 目前只能重启整个 Workflow,而如果 Workflow 内某个 Job 已经成功了,那么该 Job 下一次执行必然是失败(因为此类任务一般不能对同一个版本号执行两次,发布成功一次以后第二次尝试将会被拒绝发布),因此这一个提交的 Workflow 将永远不可能成功。

需要注意的是,以下所提到的 secrets.GITHUB_TOKEN 均是 GitHub Action 内置的 Access Token,无需自行创建。而其它 secrets 则需要在 项目主页 -> Settings -> Secrets 处创建。

# GitHub Pages

发布 GitHub Pages 使用的是 crazy-max/ghaction-github-pages (opens new window) 这个 action:

# publish_pages.yaml
name: CD

on:
  push:
    tags:
      - 'v*'

jobs:
  deploy_gh_pages:
    runs-on: ubuntu-latest
    steps:
      # checkout & yarn
      - uses: actions/checkout@v2
      - uses: c-hive/gha-yarn-cache@v1
      - run: yarn --frozen-lockfile
      # build
      - run: npm run build
      - name: GitHub Pages
        uses: crazy-max/ghaction-github-pages@v2.1.3
        env:
          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
        with:
          target_branch: gh-pages
          build_dir: dist
          jekyll: false # 禁用 GitHub 默认开启的 jekyll 构建
          fqdn: some.domain.com # 自定义域名,需要时填写

如果想要在 push 到分支时就直接 deploy,可以使用:

on:
  push:
    branches:
      - master

# GitHub Release

发布 Release 包含几个动作:

  1. 根据提交记录生成 Changelog,使用 ScottBrenner/generate-changelog-action (opens new window)
  2. 创建一个 Release,正文填写上一步得到的 Changelog,使用 actions/create-release (opens new window)
  3. 为 Release 附加需要的 assets,使用 actions/upload-release-asset (opens new window)
# publish_release.yaml
name: CD

on:
  push:
    tags:
      - 'v*'

jobs:
  deploy_release:
    runs-on: ubuntu-latest
    steps:
      # checkout,由于 changelog 需要读取所有历史记录
      # 因此这里 `fetch-depth` 需要填 0,代表所有
      - uses: actions/checkout@v2
        with:
          fetch-depth: 0
          ref: dev
      # yarn & build
      - uses: c-hive/gha-yarn-cache@v1
      - run: yarn --frozen-lockfile
      - name: Build
        run: npm run build
      # 生成 changelog
      - name: Changelog
        uses: scottbrenner/generate-changelog-action@master
        id: Changelog
        env:
          REPO: ${{ github.repository }}
      # 创建 release
      - name: Create Release
        id: create_release
        uses: actions/create-release@v1
        env:
          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
        with:
          tag_name: ${{ github.ref }}
          release_name: Release ${{ github.ref }}
          body: |
            ${{ steps.Changelog.outputs.changelog }}
          draft: false
          prerelease: false
      # 添加 assets
      - name: Upload Release Asset
        id: upload-release-asset
        uses: actions/upload-release-asset@v1
        env:
          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
        with:
          upload_url: ${{ steps.create_release.outputs.upload_url }}
          asset_path: ./dist/some-js.min.js
          asset_name: some-js.min.js
          asset_content_type: text/javascript

# NPM

发布 npm 有一个预定义的 action: JS-DevTools/npm-publish (opens new window),但是用过以后我觉得实际上没有自己敲命令行好用,因为它会做一些额外的不必要的动作,可能会导致发布出错。如:第一次发布时,它默认会检查历史包而报找不到 package 的错误,虽然它文档提示可以通过参数关闭该功能,但实测下来并不行。

注:下面的 NPM_TOKEN 是需要自行配置的。

# publish_npm.yaml
name: CD

on:
  push:
    tags:
      - 'v*'

jobs:
  deploy_npm:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v2
      - uses: c-hive/gha-yarn-cache@v1
      - uses: actions/setup-node@v1
        with:
          node-version: 12.x
          registry-url: https://registry.npmjs.org
      - run: yarn --frozen-lockfile
      - name: Build
        run: npm run build
      # 发布
      - name: Publish NPM
        run: npm publish
        env:
          NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}

# NPM GitHub Registry

GitHub Registry 与 NPM 不一样的是,它要求发布的包必须是以当前仓库所属的 username 为 scope 的。因此如果要同时发布 NPM 和 GitHub Registry,在执行此步骤时 package.json 需要做一点小更改:将包名改为 scoped 的。

这里为求简便,使用了 deef0000dragon1/json-edit-action (opens new window) 来执行替换。实际上熟悉 shell 命令的话一行代码也可以完成。

# publish_github.yaml
name: CD

on:
  push:
    tags:
      - 'v*'

jobs:
  publish_github:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/setup-node@v1
        with:
          node-version: 12
      - uses: actions/checkout@v2
      # 将 package.json 中的 name 字段替换
      - name: change package name
        uses: deef0000dragon1/json-edit-action@v1
        env:
          KEY: name
          VALUE: "@username/some-package"
          FILE: package.json
      - uses: c-hive/gha-yarn-cache@v1
      - run: yarn --frozen-lockfile
      # 配置 npmrc
      - run: echo //npm.pkg.github.com/:_authToken=${{ secrets.GITHUB_TOKEN }} >> .npmrc
      # 发布
      - run: npm publish --registry=https://npm.pkg.github.com

关于 npmrc 这一步,使用 NODE_AUTH_TOKEN 环境变量应该也可以达到相同目的。


Last Updated: 21 days ago