前端的 GitHub Actions 简单实践
Created|Updated
|Word Count:1.5k|Reading Time:6mins
在 GitHub Actions 公测一年之后,我已经把它当作首选的 CI/CD 工具了,也迁移了一部分在 Travis CI 上的项目。借助 action 的扩展性和社区的力量,使用感受相当满意,不过也有不少坑和需要吐槽的地方。
这篇文档不会介绍 GitHub Actions 的基本概念和使用方法,因此并不适合没有使用过它的访客,如果你属于这类人,那么建议你先阅读 GitHub Actions 官方文档 并尝试使用。
首先最需要吐槽的一点是配置文件暂时不支持 yaml 的锚点引用。如果你没有精力将配置改为 action ,可能需要频繁复制配置片段。因此我将我常用的配置分为不同部分分别说明。
The Start
这个部分会展示一个 GitHub 配置文件的基本部分。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35
| name: Build
on: push: branches: [master] pull_request: branches: [master] tags: - "v*" schedule: - cron: "0 0 * * *" workflow_dispatch:
jobs: build: strategy: matrix: node-version: [14.x] os: [ubuntu-latest]
if: "!contains(github.event.head_commit.message, '[skip ci]')" runs-on: ${{ matrix.os }}
steps: - name: ... - name: ...
|
Checkout
1 2 3 4 5 6 7 8 9 10 11 12 13 14
|
- uses: actions/checkout@v2
- name: Use Node.js ${{ matrix.node-version }} uses: actions/setup-node@v1 with: node-version: ${{ matrix.node-version }}
|
Install Dependencies
npm
点击查看
1 2 3 4 5 6 7 8 9 10
| - name: Get npm cache directory path id: npm-cache-dir-path run: echo "::set-output name=dir::$(npm config get cache)"
- name: Cache npm modules uses: actions/cache@v1 with: path: ${{ steps.npm-cache-dir-path.outputs.dir }} key: ${{ runner.os }}-npm-${{ hashFiles('**/package-lock.json') }} restore-keys: ${{ runner.os }}-npm
|
yarn
点击查看
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| - name: Get yarn cache directory path id: yarn-cache-dir-path run: echo "::set-output name=dir::$(yarn cache dir)"
- name: Cache node modules uses: actions/cache@v1 with: path: ${{ steps.yarn-cache-dir-path.outputs.dir }} key: ${{ runner.os }}-yarn-${{ hashFiles('**/yarn.lock') }} restore-keys: | ${{ runner.os }}-yarn-
- name: Install node modules run: yarn install --frozen-lockfile
|
由于安装的篇幅实在是有些长,而且并不直观,我已经开始使用现成的第三方的 bahmutov/npm-install
1 2
| - name: Install uses: bahmutov/npm-install@v1
|
更新:我已切换到 pnpm
1 2 3 4 5 6 7 8 9
| - uses: pnpm/action-setup@v2 with: version: "latest"
- name: Use Node.js ${{ matrix.node-version }} uses: actions/setup-node@v2 with: node-version: ${{ matrix.node-version }} cache: "pnpm"
|
Check
大部分前端项目都会做一些相同的工作
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29
| - name: Lint run: yarn lint --report-unused-disable-directives --max-warnings=0
- name: Type check run: yarn typecheck
- name: Test run: yarn test --coverage
- name: Test E2E run: yarn test:e2e-ci
- name: Build run: yarn build
- name: Upload artifacts if: ${{ failure() }} uses: actions/upload-artifact@v2 with: name: cypress-artifacts path: | cypress/images cypress/videos if-no-files-found: ignore
|
Deploy
Github Actions 没有官方的 gh-page action,不过随着社区的完善,第三方的 actions-gh-pages 已经开发得足够齐全,完全可以满足日常使用了
1 2 3 4 5 6 7 8 9
| - name: Deploy GitHub Pages if: github.ref == 'refs/heads/master' uses: peaceiris/actions-gh-pages@v3 with: github_token: ${{ secrets.GITHUB_TOKEN }} publish_dir: dist/public force_orphan: true
|
除次之外你还可以使用简单的提交脚本
1 2 3 4 5 6 7 8 9 10
| pushd build git init git config user.email "github-actions[bot]@users.noreply.github.com" git config user.name "github-actions[bot]" git add . git commit -m "Deployed at $(date --iso-8601)" git remote add origin [email protected]:UserName/RepoName.git git push -f origin master:gh-pages rm -rf .git popd
|
Release
发布 npm 包和 GitHub Release
点击查看
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45
|
- name: Publish run: yarn publish env: NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
- 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 }} draft: false prerelease: false
- name: Pack id: pack-npm run: echo "::set-output name=filename::$(yarn pack | tail -1)"
- name: Package run: tar czfv dist.tar.gz --directory=dist --exclude='*.map' .
- name: 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: ${{ steps.pack-npm.outputs.filename }} asset_name: ${{ steps.pack-npm.outputs.filename }} asset_content_type: application/gzip
|
The End
最后,一个完整的 workflow 的结构应该是这样的
点击查看
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
| name: Build
on: push: branches: [master] pull_request: branches: [master]
jobs: build: if: "!contains(github.event.head_commit.message, '[skip ci]')" runs-on: ubuntu-latest
steps: - name: Install run: ... - name: Lint - name: Type Check - name: Test - name: Build
|
Others
Reference