一、为什么需要持续交付流水线

开发npm包和开发普通应用有个很大的区别,就是发布频率高。每次修复一个小bug或者新增一个小功能,都需要发布新版本。如果全靠手动操作,那简直是一场噩梦。想象一下,每次都要手动跑测试、更新版本号、生成changelog、发布到npm,不仅效率低下,还容易出错。

持续交付流水线就像是个自动化流水线工人,帮你把这些重复性工作都包揽了。你只需要专注写代码,提交到Git仓库,剩下的测试、构建、发布等流程全部自动完成。这样不仅能提高效率,还能保证每次发布的质量一致性。

二、基础工具准备

要搭建这样的流水线,我们需要几个核心工具。首先是GitHub,用来托管代码。其次是GitHub Actions,这是GitHub提供的CI/CD服务,完全免费对于开源项目来说。然后是npm,这个不用多说。最后是一些辅助工具,比如commitizen用来规范提交信息,standard-version用来自动生成版本号和changelog。

让我们先初始化一个简单的npm包项目:

# 创建项目目录
mkdir my-awesome-pkg && cd my-awesome-pkg

# 初始化npm项目
npm init -y

# 安装基础工具
npm install --save-dev commitizen standard-version husky

在package.json中添加一些配置:

{
  "scripts": {
    "commit": "git-cz",
    "release": "standard-version",
    "prepare": "husky install"
  },
  "config": {
    "commitizen": {
      "path": "./node_modules/cz-conventional-changelog"
    }
  }
}

这个配置做了三件事:

  1. 添加了commit脚本,用于规范化提交信息
  2. 添加了release脚本,用于自动生成版本和changelog
  3. 配置了husky,用于添加git hooks

三、搭建完整的GitHub Actions流水线

现在我们来配置GitHub Actions的工作流。在项目根目录创建.github/workflows/release.yml文件:

name: Release

on:
  push:
    branches: [ main ]

jobs:
  test:
    runs-on: ubuntu-latest
    steps:
    - uses: actions/checkout@v2
    - uses: actions/setup-node@v2
      with:
        node-version: '14'
    - run: npm ci
    - run: npm test

  release:
    needs: test
    runs-on: ubuntu-latest
    steps:
    - uses: actions/checkout@v2
    - uses: actions/setup-node@v2
      with:
        node-version: '14'
        registry-url: 'https://registry.npmjs.org'
    - run: npm ci
    - run: npm run release
    - run: git push --follow-tags origin main
    - run: npm publish
      env:
        NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}

这个工作流定义了两个任务:

  1. test任务:在每次推送到main分支时运行测试
  2. release任务:只有test通过后才会运行,负责发布新版本

注意最后一步的NPM_TOKEN需要先在npm上生成,然后添加到GitHub仓库的Secrets中。这个token需要有发布包的权限。

四、完整的开发流程示例

让我们看一个完整的开发流程是怎样的。假设我们要修复一个bug:

  1. 首先创建一个新分支:
git checkout -b fix-some-bug
  1. 修改代码后,使用规范化的方式提交:
npm run commit

这会启动交互式命令行,让你选择提交类型(如fix、feat等),填写提交信息。

  1. 推送分支到远程并创建PR:
git push origin fix-some-bug

然后在GitHub上创建Pull Request。

  1. 代码审查通过后,合并到main分支。这时GitHub Actions会自动:
    • 运行测试
    • 如果测试通过,自动:
      • 更新版本号(如果是feat提交会升级小版本,fix提交会升级修订号)
      • 生成changelog
      • 提交这些变更
      • 发布新版本到npm

五、高级配置技巧

基础流水线搭建好了,我们还可以做一些优化:

  1. 自动打标签: 在package.json中添加:
"standard-version": {
  "skip": {
    "tag": false
  }
}
  1. 多环境发布: 可以配置不同的npm registry,比如:
- run: npm publish
  env:
    NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
  if: github.ref == 'refs/heads/main'

- run: npm publish --tag beta
  env:
    NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
  if: github.ref == 'refs/heads/beta'
  1. 自动化PR合并: 可以添加一个GitHub Action来自动合并通过检查的PR:
name: Auto Merge

on:
  pull_request:
    types: [labeled]

jobs:
  auto-merge:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/github-script@v3
        if: github.event.label.name == 'auto-merge'
        with:
          script: |
            github.pulls.merge({
              owner: context.repo.owner,
              repo: context.repo.repo,
              pull_number: context.payload.pull_request.number,
              merge_method: 'squash'
            })

六、常见问题与解决方案

在实际使用中可能会遇到一些问题:

  1. 版本冲突: 如果两个人同时提交,可能会导致版本号冲突。解决方案是确保流水线是线性执行的,可以通过GitHub Actions的concurrency配置:
concurrency: 
  group: release-${{ github.ref }}
  cancel-in-progress: true
  1. 测试不稳定: 有时候测试会随机失败。可以配置重试机制:
- run: npm test
  timeout-minutes: 10
  retry-on-error: true
  max-attempts: 3
  1. npm发布失败: 可能是网络问题,可以增加重试:
npx publish-retry --retry 3

七、安全注意事项

自动化发布虽然方便,但也要注意安全:

  1. 保护好NPM_TOKEN: 千万不要把这个token提交到代码中,只能放在GitHub Secrets里。

  2. 双因素认证: npm账号一定要开启2FA,避免账号被盗导致恶意发布。

  3. 审查依赖更新: 可以配置Dependabot自动更新依赖,但要确保每次更新都经过测试:

version: 2
updates:
  - package-ecosystem: npm
    directory: "/"
    schedule:
      interval: weekly
    open-pull-request-limit: 10

八、总结与展望

搭建一个完善的npm包持续交付流水线确实需要一些前期投入,但长远来看绝对是值得的。它不仅能节省大量重复劳动时间,还能减少人为错误,提高发布质量。随着项目发展,还可以进一步扩展流水线功能,比如:

  1. 添加自动化文档生成和发布
  2. 集成代码覆盖率报告
  3. 添加性能基准测试
  4. 实现渐进式发布策略

最重要的是,这个流水线可以根据项目需求灵活调整。对于开源项目来说,GitHub Actions的免费额度已经足够使用。如果是私有项目,也可以考虑使用其他CI/CD服务如CircleCI或GitLab CI。