前言

我最近编写了一个 MCP 服务器:nailuoGG/anki-mcp-server

但是有一个问题,用户安装时需要在本地进行构建,流程比较复杂,能否更简单一点呢?

我想到了将其发布到 npm 上,然后使用 `npx anki-mcp-server` 命令来使用。

进一步想,作为一个开源项目,为什么不使用 GitHub Actions 来进行自动化发布呢?而且至少有以下几个好处:

  • 安全性,防止开发者本地电脑被侵入导致意外发包的情况,而且能保持让打包构建过程公开透明
  • 便利性,便于多人协作,这样发布时就不依赖单个开发者,也能够保持发布的一致性

准备

这里详细记录一下如何添加 secrets:

操作路径是:仓库首页 -> settings -> Security -> Secrets and Variables -> Actions

注意此时有 `Environment secrets` 和 `Repository secrets` 这两种 secrets,关于他们的区别:管理部署环境 - GitHub 文档

因为我们只是发布 NPM 包,不涉及多环境部署,因此需要使用 `Repository secrets` 而不是 `Environment secrets`。详细的操作流程请看 Using secrets in GitHub Actions - GitHub Docs

添加工作流

在仓库中添加 `.github/workflow/publish.yaml`,下面放上工程中正在使用的工作流文件,并且实时更新。

anki-mcp-server/.github/workflows/publish.yaml at master · nailuoGG/anki-mcp-server

name: Publish to NPM

on:
  workflow_run:
    workflows: ["Release Test"]
    types:
      - completed

jobs:
  publish:
    runs-on: ubuntu-latest
    # Only run if the test workflow succeeded
    if: ${{ github.event.workflow_run.conclusion == 'success' }}
    permissions:
      contents: read
      id-token: write # Required for npm provenance

    steps:
      - name: Checkout code
        uses: actions/checkout@v4

      - name: Setup Node.js
        uses: actions/setup-node@v4
        with:
          node-version: "20.x"
          registry-url: "https://registry.npmjs.org"
          cache: "npm"

      - name: Install dependencies
        run: npm ci

      - name: Build
        run: npm run build

      - name: Publish to NPM
        run: npm publish --provenance --access public
        env:
          NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}

      - name: Upload npm logs
        if: always()
        uses: actions/upload-artifact@v4
        with:
          name: npm-logs
          path: |
            /home/runner/.npm/_logs/*.log
          retention-days: 7

解析:

  workflow_run:
    workflows: ["Release Test"]
    types:
      - completed

这里配置成了在前一个 Workflow 执行完毕后,再执行发布工作流,这样可以确保每次发布都经过了测试:

anki-mcp-server/.github/workflows/release-test.yaml at master

          node-version: "20.x"
          registry-url: "https://registry.npmjs.org"
          cache: "npm"

这里关键是使用了 node 20 作为发布环境,

npm publish --provenance --access public

如果是这个包的第一次发布,需要加上 `–access public`,来确定包的访问权限范围是公开可见,后续发布就可以不加,默认公开可见。

`–provenance` 是一种安全策略,防止供应链攻击。效果是在 npm 页面上会有一个认证徽章:anki-mcp-server - npm

详情可见:

发布的整体流程

如果基于 GitHub Actions 来发布到 NPM,一般来说就不建议再在开发者电脑上手动操作发布了。因此整个发布流程如下:

  • 本地执行语义化版本升级,并 push 到仓库
  • 在 GitHub 仓库页面创建一个发布,并使用`Generate release notes` 功能来生成发布日志
  • 点击发布,就会触发我们设定的 `Publish to NPM` 的 Workflow。稍等一会就会正常发布

详细的发布流程,可以看仓库中的介绍:anki-mcp-server/RELEASE.md at master · nailuoGG/anki-mcp-server