赞
踩
GitHub Actions是GitHub提供的一项功能,通过创建工作流程(workflow)文件,开发人员可以实现对应用自动化的测试、构建和发布等任务。同时,GitHub Actions支持自定义流程工作的平台,因此跨平台的构建也成为了可能。
在GitHub Actions中可以考虑使用语义化版本和Conventional Commits,实现自动化的版本管理和发布流程,提高开发效率;下面将先对这二者进行介绍。
考虑以下的版本号,Major.Minor.Patch
,其中:
除了以上的几点,语义化版本还有以下的要求:
其他的语义化版本规范请参见官网。
Conventional Commits是一个轻量级的提交信息的格式约定,它规定了每次提交的修改范围、描述以及附加的信息的格式。使用Conventional Commits具有以下好处:
Conventional Commits的格式如下:
<type>[optional scope]: <description>
[optional body]
[optional footer(s)]
用尖括号括起来的表示必选项,方括号括起来的表示可选项,下面对其中一些进行说明:
fix
时,表示修复一个漏洞,对应语义化版本中的Patch
。feat
时,表示应用引入一个新的功能,对应语义化版本中的Minor
。BREAKING CHANGE:
,或者在type后面跟随一个!
时,表示应用具有不向后兼容的破坏性更新,对应语义化版本的Major
。当应用具有BREAKING CHANGE时,它可以具有任何的类型。fix
和feat
以外,提交信息的type还可以取以下值:build、chore、ci、docs、style、refactor、prefer、test等。BREAKING CHANGE:
以外,提交信息的footer也被允许,其格式应当为Key: Value
,例如:Closes: #123,可以表示关闭Issue #123。scope
可以用来给提交信息添加额外的上下文,比如:feat(parser): add ability to parse arrays
.常用的提交类型说明如下:
GitHub Actions是GitHub提供的持续集成服务,允许开发者自动化地测试、构建和发布代码。将GitHub Actions与前面提到的语义化版本和Conventional Commits结合,可以提高开发效率,使开发流程更加规范,便于理解和追踪代码更改。下面是一段GitHub Actions的“Hello world”代码:
name: hello-world # 1
on: # 2
push:
branches: main
jobs: # 3
hello-world:
runs-on: ubuntu-latest # 4
steps: # 5
- name: checkout-repository
uses: actions/checkout@v4 # 6
- run: echo "代码仓库 ${{ github.repository }}已被克隆到runner中" # 7
jobs
中定义。runs-on
指定了这个Job运行的平台,可以指定一个平台,也可以指定多个不同的平台同时执行任务。steps
中定义,每个Step可以使使用uses
调用其他的GitHub Actions,或者使用run
来执行一段代码。run
来执行一段shell命令,在不同平台上使用的shell不一样,比如Windows上默认命令行是Powershel。Trigger用来表示这个Action在什么时机被执行,可能是一次推送、一个新的Issue或者一个新的Pull Request。同时我们也可以借助Filter来实现对触发条件的筛选。下面列出几个常用的触发条件:
最简单的触发条件:
on: push # 只有一个事件可以触发Action执行
on: [push, fork, issue, pull_request] # 有多个事件可以触发Action执行
对代码推送或Pull Request等进行筛选:
on:
push:
branches: # 针对推送的代码分支进行过滤
- main
tags:
- "v**"
- "releases/**" # 使用通配符进行匹配
- "!releases/**-alpha" # 在前面添加感叹号表示排除掉这个筛选条件
issue: # 对Issue进行筛选
types: [opened, labeled]
手动执行每个Action
on:
workflow_dispatch: # 添加后可以手动执行Action,但是只能在默认分支上执行
inputs: # 可选项
手动执行Actions时,还可以通过input
定义手动执行时的输入,语法参见Workflow syntax for GitHub Actions - GitHub Docs。
在GitHub Actions中,jobs
定义了需要执行的任务。一个简单的示例如下:
jobs:
job_id:
name: Job Id # 可选项,指定当前步骤的名称,在执行时会被现实在GitHub界面上
runs-on: ubuntu-latest # 每个Job必须要指定运行的平台,后续代码中为了简便将省略这一部分
在Action或者Job执行过程中,可能会需要不同的权限,比如contents: write
权限可以让开发人员发布一个新的Release。权限信息可以被直接定义在Action中,表示全局需要的权限;也可以单独定义在每个Job中,表示当前Job所需要的权限,参见Workflow syntax for GitHub Actions - GitHub Docs。
name: Permission Demo
on: push
permissions:
contents: write
jobs:
make-a-pull-request:
permissions:
pull_requests: write # 表示创建一个新的Pull Request
# 后续省略
每个Job在运行时都是并行执行的,但是我们有时同样需要让这些Job按顺序执行,或者在某些条件下执行,这时就可以用到needs
和if
标签:
jobs:
job1:
job2:
needs: job1
job3:
needs: [job1, job2]
在上面的代码中,job2依赖于job1,而job3又依赖于job2和job1,因此他们三个的执行顺序是:job1→job2→job3。
on: push
jobs:
process-tag:
if: ${{ startsWith(github.ref, 'refs/tags/') }}
上述代码表示只有在推送一个Tag的时候才会执行process-tag这个job。
有时同一个任务需要在不同的平台下执行,比如跨平台的构建,这时可以使用matrix
实现:
jobs:
build-multi-platform:
strategy:
matrix:
platform: [macos-latest, ubuntu-latest, windows-latest] # 定义所需要运行的平台
runs-on: ${{ matrix.platform }}
steps:
step_1:
if: matrix.platform == 'ubuntu-latest' # 在ubuntu-latest环境下执行这个step
每个Job都会有至少一个Step,用来表示需要执行的具体行为。与Job不同的是,Step是按照定义顺序执行的,不存在并行执行的问题。
jobs:
job1:
rus-on: ubuntu-latest
steps:
- name: Step 1 # 1
id: st1 # 2
if: condition == true # 3
shell: pwsh # 4
uses: actions/checkout@v4 # 5
run: echo 'Hello, world!' # 6
with: # 7
key: value
env: # 8
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
pwsh
,使用PowerShell,其他平台上默认是bash
,使用Bash Shell。参见Workflow syntax for GitHub Actions - GitHub Docs。uses
和run
可以同时使用。uses
使用的GitHub Action传递参数。Release Please是Google推出的自动工具,可以实现基于Conventional Commit的提交信息自动发布更新、自动更新项目的版本号。
注意:Release Please并不会自动将代码上传到包管理器(比如npm、Maven Repository、crates.io等),也不能处理复杂的分支管理,这些需要开发人员手动实现。
Release Please的工作是基于Release PR实现的。在被触发而工作时,Release Please会首先分析Git的提交历史,从提交信息中按照Conventional Commits的格式整理出此次更新的内容和级别(Major、Minor或Patch),然后修改版本号和修改文件(一般是CHANGELOG.md),最后向仓库中发起一个Pull Request。如果开发人员合并了这个PR,那么修改就会被合并进分支中,然后发布一个新的Release。
Release Please支持的项目类型主要有以下几种,完整列表参见GitHub:
类型 | 描述 |
---|---|
node | 包含一个package.json和CHANGELOG.md。 |
rust | 包含Cargo.toml和CHANGELOG.md。 |
dart | 包含pubspec.yaml和CHANGELOG.md。 |
php | 包含composer.json和CHANGELOG.md。 |
maven | 在每次发布后生成一个SNAPSHOT版本号并且自动更新pom.xml。 |
simple | 包含一个version.txt和CHANGELOG.md。 |
下面是一个简单的示例:
name: release-please-demo on: push: branches: - main permissions: # 1 contents: write pull-requests: write jobs: release-please: runs-on: ubuntu-latest steps: - uses: google-github-actions/release-please-action@v4 # 2 with: release-type: node # 3 token: ${{ secrets.GITHUB_TOKEN }} # 4
contents: write
权限来发布新版本,使用pull-request: write
权限来发布Release PR。google-github-actions/release-please-action@v4
。node
为例,要求仓库中有一个package.json
文件和CHANGELOG.md
文件(这个如果没有会自动创建)。GITHUB_TOKEN
是GitHub在每个Action执行时自动生成的token,开发人员也可以使用自定义的Token。上面的实例只做了检查提交信息、发起Release PR和在合并后自动发布新版本的功能,有时我们需要在成功发布版本之后做一些后续工作,这时就可以借助Release Please的输出来实现。常用的输出结果有以下几条:
其他的输入输出参见README。
当发布被合并时,同样会在main分支产生一次推送,因此上面的GitHub Actions会被再次执行,因此我们可以在后面根据release_created
输出内容来判断Release PR是否被合并,即是否会有新发布产生:
# 上面的内容不变 jobs: release-please: runs-on: ubuntu-latest steps: - id: release # 1 uses: google-github-actions/release-please-action@v4 with: release-type: node token: ${{ secrets.GITHUB_TOKEN }} outputs: # 2 release_created: ${{ steps.release.outputs.release_created }} tag_name: ${{ steps.release.outputs.release_created }} build-release: needs: release-please # 3 runs-on: ubuntu-latest if: ${{ needs.release-please.outputs.release_created }} # 4 steps: - name: Echo tag name run: echo ${{ needs.release-please.outputs.tag_name }}
build-release
需要在release-please
之后执行,因此需要指定依赖关系。最后附带一个完整的示例代码,用于在不同平台构建Tauri应用并上传至Release:
name: Create release # 指定名称 on: push: branches: - master # 在master分支推送代码时触发,新项目可能是main分支 permissions: # 指定需要的权限 contents: write pull-requests: write jobs: create-release: runs-on: ubuntu-latest steps: - name: Create release id: release uses: google-github-actions/release-please-action@v3 # 使用Release Please Action,并指定类型为node with: release-type: node token: ${{ secrets.GITHUB_TOKEN }} # 使用GitHub自动生成的token outputs: # 将输出暴露除去 release-created: ${{ steps.release.outputs.release_created }} tag-name: ${{ steps.release.outputs.tag_name }} build-tauri: needs: create-release if: ${{ needs.create-release.outputs.release-created }} env: # 指定GH_TOKEN,gh是GitHub自带的CLI,用于实现一些自动化任务,比如向Release上传构建产物等 GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} strategy: # 1 fail-fast: false matrix: platform: [macos-latest, ubuntu-20.04, windows-latest] runs-on: ${{ matrix.platform }} steps: - name: Echo tag name run: echo "Build Application ${{ needs.create-release.outputs.tag-name }} for platform ${{ matrix.platform }}." - name: Checkout repository uses: actions/checkout@v4 - name: Install dependencies(Ubuntu only) # 安装Linux特定的依赖 if: matrix.platform == 'ubuntu-20.04' run: | sudo apt-get update sudo apt-get install -y libgtk-3-dev libwebkit2gtk-4.0-dev libayatana-appindicator3-dev librsvg2-dev - name: Rust setup uses: dtolnay/rust-toolchain@stable - name: Rust cache uses: swatinem/rust-cache@v2 with: workspaces: "./src-tauri -> target" - name: Sync node version and setup cache uses: actions/setup-node@v4 with: node-version: "lts/*" cache: "yarn" - name: Install frontend dependencies run: yarn install - name: Build Application id: build uses: tauri-apps/tauri-action@v0 # 使用tauri-action来构建应用 env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} # 传递GITHUB_TOKEN,这是必须的 - name: Upload artifacts(Linux) if: matrix.platform == 'ubuntu-20.04' run: | # 在这里使用竖线,将后面的每行代码通过\n连接起来 gh release upload ${{ needs.create-release.outputs.tag-name }} ${{ github.workspace }}/src-tauri/target/release/bundle/deb/*.deb gh release upload ${{ needs.create-release.outputs.tag-name }} ${{ github.workspace }}/src-tauri/target/release/bundle/appimage/*.AppImage - name: Upload artifacts(macOS) if: matrix.platform == 'macos-latest' run: | cd ${{ github.workspace }}/src-tauri/target/release/bundle/macos zip -r Application.app.zip Application.app # 在macOS中,xxx.app是一个文件夹,因此需要打包成一个压缩包 gh release upload ${{ needs.create-release.outputs.tag-name }} ${{ github.workspace }}/src-tauri/target/release/bundle/dmg/*.dmg gh release upload ${{ needs.create-release.outputs.tag-name }} ${{ github.workspace }}/src-tauri/target/release/bundle/macos/*.app.zip - name: Upload artifacts(Windows) if: matrix.platform == 'windows-latest' run: | # 2 Get-ChildItem -Path "${{ github.workspace }}\src-tauri\target\release\bundle\msi\*.msi" | ForEach-Object { gh release upload ${{ needs.create-release.outputs.tag-name }} $_.FullName } Get-ChildItem -Path "${{ github.workspace }}\src-tauri\target\release\bundle\nsis\*.exe" | ForEach-Object { gh release upload ${{ needs.create-release.outputs.tag-name }} $_.FullName }
GitHub Actions允许同样的工作在不同的参数下执行,可以是使用的操作系统,也可以是自定义的其他参数。示例代码如下:
jobs:
example_matrix:
strategy:
matrix:
version: [10, 12, 14]
os: [ubuntu-latest, windows-latest]
这段代码会产生6个不同的运行平台,分别是:
每个Job最多能创建256个Matrix,同样可以使用include和exclude来添加或删除运行矩阵,参见添加矩阵 和排除矩阵。
fail-fast
参数默认为true
,当它为true时,只要运行的矩阵中有一个失败,那么所有的矩阵全部停止运行,在这里我们不希望在某个平台构建失败后影响到其他平台的构建结果,因此需要将其设置为false
。
关于运行矩阵的完整内容,参见对作业使用矩阵 - GitHub 文档。
在非Windows平台下的命令行是Bash,在Windows平台下的命令行默认为PowerShell,二者语法有较大差异,因此在跨平台执行任务时需要注意区分。下面列出所支持的全部命令行:
支持的平台 | 命令行选项 | 执行参数 | 是否为默认 |
---|---|---|---|
Linux/macOS | bash -e {0} | 是(非Windows平台下) | |
All | bash | bash --noprofile --norc -eo pipefail {0} | 是(非Windows平台下),没有时使用sh |
All | pwsh | pwsh -command ". ‘{0}’” | |
All | python | python {0} | |
Linux/macOS | sh | sh -e {0} | 非Windows平台下缺失bash时的默认 |
Windows | cmd | %ComSpec% /D /E:ON /V:OFF /S /C "CALL “{0}”” | |
Windows | pwsh | pwsh -command ". ‘{0}’” | 是,Windows平台下 |
Windows | powershell | powershell -command ". ‘{0}’” | 否,旧版PowerShell |
另一个常用的命令行是gh
,即GitHub CLI,关于他的使用方法,可以参见用户手册。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。