使用 GitHub Actions(和 GitHub 包注册表)自动化构建和发布过程

Fed*_*ndi 1 github npm github-actions github-package-registry

这是一个问答,我已经把我的解决方案放在了答案中。

我是 GitHub Actions beta 和 GitHub Package Registry beta 的一部分。因为我是一个非常懒惰的人,所以我不仅自动化了 npm 包的构建过程,而且我还想自动化它的发布。
为了做到这一点,我不得不面对一些问题:

  1. 如何确保在刚刚构建的版本上执行“发布”作业?
  2. 如何在 GitHub Actions 中检测包版本何时更新?
  3. 如何使用该检查的结果来编辑操作工作流的行为?
  4. 如何从工作流中将包发布到 npm?
  5. 发布到 npm 后,如何将完全相同的版本发布到 GitHub 包注册表?

Fed*_*ndi 5

注意:所有这些步骤的结果可以在这里找到,在我实际用于我的包的工作流文件中。

1.确保“发布”作业在刚刚构建的版本上执行

我发现的最简单的方法是将两个作业放在同一个工作流中,并让它们在每个push事件上都触发:然后发布作业被限制为仅在master分支上和第一个之后执行。

  • 构建作业:

它需要构建包的新版本,然后提交到存储库:提交至关重要,因为这允许其他作业选择构建的版本。要提交在工作流运行中所做的更改,您可以使用我的操作之一add-and-commit:它将使用“假”git 用户将更改推送到 GitHub 存储库。
您的工作流作业应如下所示:

jobs:
  build:
    name: Build
    runs-on: ubuntu-latest

    steps: 
    - name: Checkout repository
      uses: actions/checkout@v1.0.0

    - name: Set up Node.js
      uses: actions/setup-node@v1.2.0
      with:
        node-version: '10.x'
    
    - name: Install dependencies
      run: npm install

    - name: Compile build
      run: npm run build # This can be whatever command you use to build your package

    - name: Commit changes
      uses: EndBug/add-and-commit@v2.1.0
      with: # More info about the arguments on the action page
        author_name: Displayed name
        author_email: Displayed email
        message: "Message for the commit"
        path: local/path/to/built/version
        pattern: "*.js" # Pattern that matches the files to commit
        force: true # Whether to use the --force flag
      env:
        GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} # This gets generated automatically
Run Code Online (Sandbox Code Playgroud)
  • 发布作业:

我们希望它只在完成master后的分支中运行build,所以我们可以这样设置:

publish:
  name: Publish to NPM & GitHub Package Registry
  runs-on: ubuntu-latest
  if: contains(github.ref, 'master') # This sets the branch
  needs: build # This makes it wait for the build job
Run Code Online (Sandbox Code Playgroud)

2. 检测版本变化

我没有找到一个好的方法来做到这一点,所以我做了另一个动作,version-check:这个动作扫描每个推送的提交,并试图找出它们是否包含版本更改。
你需要设置这两个步骤:

steps:
- name: Checkout repository
  uses: actions/checkout@v1.0.0
  with:
    ref: master

- name: Check version changes
  uses: EndBug/version-check@v1.0.0 # More info about the arguments on the action page
  id: check # This will be the reference for later
Run Code Online (Sandbox Code Playgroud)

3. 使用检查结果编辑工作流的行为

version-check提供两个输出:(changed是否有更新)和type(更新类型,如“补丁”、“次要”等)。
这些输出可以通过steps上下文访问,您可以使用它们来决定是否运行一个步骤,使用if属性。这是一个例子:

# check is the id we gave to the check step in the previous paragraph
- name: Version update detected
  if: steps.check.outputs.changed == 'true'
  run: 'echo "Version change! -> ${{ steps.check.outputs.type }}"'
Run Code Online (Sandbox Code Playgroud)

4. 发布包到 NPM

将包发布到 NPM 非常简单:您只需要设置 Node.js,然后使用npm publish,就像在您自己的机器上一样。唯一的区别是您需要一个令牌来进行身份验证:您可以在npmjs.com上创建一个。创建后不要将其放入工作流程本身:您可以将其存储为“秘密”,您可以在此处找到有关这些的更多信息。
在这个例子中,我假设你的秘密被称为NPM_TOKEN

- name: Set up Node.js for NPM
  if: steps.check.outputs.changed == 'true'
  uses: actions/setup-node@v1.2.0
  with:
    registry-url: 'https://registry.npmjs.org' # This is just the default registry URL

- name: Install dependencies
  if: steps.check.outputs.changed == 'true'
  run: npm install

- name: Publish the package to NPM
  if: steps.check.outputs.changed == 'true'
  run: npm publish
  env:
    NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }} # NPM will automatically authenticate with this
Run Code Online (Sandbox Code Playgroud)

5. 将包发布到 GitHub 包注册表

就目前而言,如果您想继续将现有包发布到 npm,则使用 GitHub 包注册表不是很愉快:这就是为什么它需要对包进行作用域,这可能会搞砸(您的包可能没有作用域或范围在不同的名称下)。
我发现解决这个问题的最简单方法是执行以下解决方法:

  • 在您的工作流程中,重新设置 Node.js 但添加 GPR 的注册表 URL 和您的名称范围
  • 创建一个 npm 脚本来编辑您的 package.json,以便它将包的原始名称更改为您需要发布到 GPR 的名称(包括范围)
  • 在工作流程中调用该脚本后,npm publish像以前一样使用,但这次使用内置的GITHUB_TOKENas NODE_AUTH_TOKEN
{
  "name": "YourPackageName",
  ...
  "scripts": {
    "gpr-setup": "node scripts/gpr.js"
  }
}
Run Code Online (Sandbox Code Playgroud)
jobs:
  build:
    name: Build
    runs-on: ubuntu-latest

    steps: 
    - name: Checkout repository
      uses: actions/checkout@v1.0.0

    - name: Set up Node.js
      uses: actions/setup-node@v1.2.0
      with:
        node-version: '10.x'
    
    - name: Install dependencies
      run: npm install

    - name: Compile build
      run: npm run build # This can be whatever command you use to build your package

    - name: Commit changes
      uses: EndBug/add-and-commit@v2.1.0
      with: # More info about the arguments on the action page
        author_name: Displayed name
        author_email: Displayed email
        message: "Message for the commit"
        path: local/path/to/built/version
        pattern: "*.js" # Pattern that matches the files to commit
        force: true # Whether to use the --force flag
      env:
        GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} # This gets generated automatically
Run Code Online (Sandbox Code Playgroud)
- name: Set up Node.js for GPR
  if: steps.check.outputs.changed == 'true'
  uses: actions/setup-node@v1.2.0
  with:
    registry-url: 'https://npm.pkg.github.com/'
    scope: '@endbug'

- name: Set up the package for GPR
  if: steps.check.outputs.changed == 'true'
  run: npm run gpr-setup

- name: Publish the package to GPR
  if: steps.check.outputs.changed == 'true'
  run: npm publish
  env:
    NODE_AUTH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
Run Code Online (Sandbox Code Playgroud)

结果

您的包现在已发布到 NPM 和 GPR(尽管需要手动将描述添加到 GPR)。您可以在 5.0.4 版本的 dbots 中找到我所指的所有内容: