Ecosyste.ms: Awesome

An open API service indexing awesome lists of open source software.

Awesome Lists | Featured Topics | Projects

https://github.com/jaywcjlove/github-actions

测试 GitHub Actions
https://github.com/jaywcjlove/github-actions

actions github-actions

Last synced: 23 days ago
JSON representation

测试 GitHub Actions

Awesome Lists containing this project

README

        

Github Actions
===

[![Buy me a coffee](https://img.shields.io/badge/Buy%20me%20a%20coffee-048754?logo=buymeacoffee)](https://jaywcjlove.github.io/#/sponsor)

测试 GitHub 工作流,一些比较特殊的玩儿法。

## 目录

- [基本概念](#基本概念)
- [配置文件](#配置文件)
- [多项任务](#多项任务)
- [多项任务依赖关系](#多项任务依赖关系)
- [指定每项任务的虚拟机环境](#指定每项任务的虚拟机环境)
- [一个工作流完成触发另外一个工作流](#一个工作流完成触发另外一个工作流)
- [常用实例](#常用实例)
- [获取版本信息](#获取版本信息)
- [获取是否存在 Tag](#获取是否存在-tag)
- [修改 package.json](#修改-packagejson)
- [提交到 gh-pages 分支](#提交到-gh-pages-分支)
- [克隆带有 Submodule 的仓库](#克隆带有-submodule-的仓库)
- [步骤依赖作业](#步骤依赖作业)
- [步骤作业文件共享](#步骤作业文件共享)
- [提交 NPM 包](#提交-npm-包)
- [提交 docker 镜像](#提交-docker-镜像)
- [提交 commit 到 master 分支](#提交-commit-到-master-分支)
- [Node.js](#nodejs)
- [同步 Gitee](#同步-gitee)
- [环境变量](#环境变量)
- [默认环境变量](#默认环境变量)
- [自定义环境变量](#自定义环境变量)
- [Github 上下文](#github-上下文)

## 基本概念

GitHub actions 有四个基本的概念,如下:

- workflow (工作流程):持续集成一次运行的过程,就是一个 workflow。
- job (任务):一个 workflow 由一个或多个 jobs 构成,含义是一次持续集成的运行,可以完成多个任务。
- step(步骤):每个 job 由多个 step 构成,一步步完成。
- action (动作):每个 step 可以依次执行一个或多个命令(action)。

### 配置文件

GitHub Actions 采用 [`YAML`](https://www.ruanyifeng.com/blog/2016/07/yaml.html) 格式的配置文件叫做 workflow 文件,存放在代码仓库的 `.github/workflows` 目录。文件名可以任意取,但是后缀名统一为 `.yml`,比如 `ci.yml`。一个库可以有多个 `workflow` 文件。GitHub 只要发现 `.github/workflows` 目录里面有 `.yml` 文件,就会根据配置事件自动运行该文件。

```yml
name: GitHub Actions Demo
on:
push:
branches:
- main

jobs:
build:
runs-on: ubuntu-18.04
steps:
- uses: actions/checkout@v3
- uses: actions/setup-node@v3
with:
node-version: 16

- run: npm install

- run: npm run build
```

### 定触条件

[`on`](https://docs.github.com/cn/actions/using-workflows/events-that-trigger-workflows) 字段指定触发 `workflow` 的条件,通常是某些事件。

```yml
# push 事件触发 workflow
on: push

# push 事件或 pull_request 事件都可以触发 workflow
on: [push, pull_request]

# 只有在 main 分支 push 事件触发 workflow
on:
push:
branches:
- main

# push 事件触发 workflow,但是 docs 目录下的更改 push 事件不触发 workflow
on:
push:
paths-ignore:
- 'docs/**'
# push 事件触发 workflow,
# 包括 sub-project 目录或其子目录中的文件,触发 workflow
# 除非该文件在 sub-project/docs 目录中,不触发 workflow
on:
push:
paths:
- 'sub-project/**'
- '!sub-project/docs/**'
# 版本发布为 published 时运行工作流程。
on:
release:
types: [published]
```

### 多项任务

通过 `jobs` (`jobs..name`)字段,配置一项或多项需要执行的任务。

```yml
jobs:
my_first_job:
name: My first job
my_second_job:
name: My second job
```

### 多项任务依赖关系

通过 `needs` (`jobs..needs`)字段,指定当前任务的依赖关系。

```yml
jobs:
job1:
job2:
needs: job1
job3:
needs: [job1, job2]
```

上面配置中,`job1` 必须先于 `job2` 完成,而 `job3` 等待 `job1` 和 `job2` 的完成才能运行。因此,这个 workflow 的运行顺序依次为:`job1`、`job2`、`job3`。

### 多项任务传递参数

```yml
jobs:
job1:
runs-on: ubuntu-latest
# Map a step output to a job output
outputs:
output1: ${{ steps.step1.outputs.test }}
output2: ${{ steps.step2.outputs.test }}
steps:
- id: step1
run: echo "::set-output name=test::hello"
- id: step2
run: echo "::set-output name=test::world"
job2:
runs-on: ubuntu-latest
needs: job1
steps:
- run: echo ${{needs.job1.outputs.output1}} ${{needs.job1.outputs.output2}}
```

### 指定每项任务的虚拟机环境

`runs-on` 字段指定运行所需要的虚拟机环境。⚠️ 它是必填字段。

```yml
runs-on: ubuntu-18.04
```

```yml
jobs:
build:
runs-on: ubuntu-18.04
```

| **虚拟环境** | **YAML 工作流程标签** | **注:** |
| -------------------- | --------------------------------- | ---------------------------------------------------------------------------------- |
| Windows Server 2022 | `windows-latest` 或 `windows-2022` | `windows-latest` 标签目前使用的是 Windows Server 2022 运行器镜像 |
| Windows Server 2019 | `windows-2019` | |
| Ubuntu 22.04 | `ubuntu-22.04` | Ubuntu 22.04 目前处于公开测试阶段。 |
| Ubuntu 20.04 | `ubuntu-latest` 或 `ubuntu-20.04` | |
| Ubuntu 18.04 | `ubuntu-18.04` | |
| macOS Monterey 12 | `macos-12` | macOS 12 目前处于公开测试阶段。 |
| macOS Big Sur 11 | `macos-latest` 或 `macos-11` | `macos-latest` 标签当前使用 macOS 11 运行器镜像。 |
| macOS Catalina 10.15 | `macos-10.15` | |

### 指定每项任务的步骤

`steps` 字段指定每个 Job 的运行步骤,可以包含一个或多个步骤。每个步骤都可以指定以下三个字段。

```bash
jobs..steps.name:步骤名称。
jobs..steps.run:该步骤运行的命令或者 action。
jobs..steps.env:该步骤所需的环境变量。
```

```yml
jobs:
build:
runs-on: ubuntu-18.04
steps:
- uses: actions/checkout@v3
- uses: actions/setup-node@v3
with:
node-version: 16
registry-url: 'https://registry.npmjs.org'

- run: npm install

- run: npm run build
```

### 一个工作流完成触发另外一个工作流

```yml
# ci.yml
name: Node.js CI
on: push

jobs:
test:
# Containers must run in Linux based operating systems
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: actions/setup-node@v3
with:
node-version: 16

- name: Install dependencies
run: npm install

trigger_tests:
needs: test
runs-on: ubuntu-latest
steps:
- name: Trigger tests
uses: actions/github-script@v6
with:
script: |
const res = await github.rest.repos.createDispatchEvent({
owner: 'jaywcjlove',
repo: 'typenexus',
event_type: 'run-deploy'
});
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
```

上面 `ci.yml` 工作流执行完成之后,触发 `main.yml`,注意上面的 `run-deploy` 取名保持一致

```yml
# main.yml
name: deploy
on:
repository_dispatch:
types: [run-deploy]

jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
```

## 常用实例

### 获取版本信息

```yml
- name: Test
run: |
# Strip git ref prefix from version
echo "${{ github.ref }}"
# VERSION=$(echo "${{ github.ref }}" | sed -e 's,.*/\(.*\),\1,')

# # Strip "v" prefix from tag name
# [[ "${{ github.ref }}" == "refs/tags/"* ]] && VERSION=$(echo $VERSION | sed -e 's/^v//')
echo "$VERSION"
```

```yml
name: CI
on:
push:
tags:
- v*

jobs:
create-docker-image:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@master
# 向 EVN 写入 CURRENT_VERSION 环境变量赋值版本号
- run: |
echo "CURRENT_VERSION=${GITHUB_REF#refs/tags/v}" >> $GITHUB_ENV
# 可以获取到 CURRENT_VERSION 的值
- run: echo "${{env.CURRENT_VERSION}}"
```

### 通过 commit 跳过任务

```yml
jobs:
build:
if: "!contains(github.event.head_commit.message, 'skip ci')"
```

### 获取是否存在 Tag

```yml
- run: echo "previous_tag=$(git describe --tags --abbrev=0 2>/dev/null || echo '')" >> $GITHUB_ENV
- name: Generate changelog
id: changelog
uses: jaywcjlove/changelog-generator@main
if: env.previous_tag
```

### 修改 package.json

```yml
- name: Modify Version
shell: bash
run: |
node -e 'var pkg = require("./package.json"); pkg.version= (new Date().getFullYear().toString().substr(2)) + "." + (new Date().getMonth() + 1) + "." + (new Date().getDate()); require("fs").writeFileSync("./package.json", JSON.stringify(pkg, null, 2))'
```

### 提交到 gh-pages 分支

```yml
- name: Deploy
uses: peaceiris/actions-gh-pages@v3
with:
github_token: ${{ secrets.GITHUB_TOKEN }}
publish_dir: ./build
```

### 克隆带有 Submodule 的仓库

```yml
- name: Checkout
uses: actions/checkout@v3
with:
path: main
submodules: true
```

`submodules`:`true` 检出子模块或 `recursive` 递归检出子模块。

```yml
- name: Clone sub repository
shell: bash
run: |
auth_header="$(git config --local --get http.https://github.com/.extraheader)"
# git submodule sync --recursive
# git -c "http.extraheader=$auth_header" -c protocol.version=2 submodule update --init --remote --force --recursive --checkout ant.design
```

### 步骤依赖作业

使用 `jobs..needs` 识别在此作业运行之前必须成功完成的任何作业。它可以是一个字符串,也可以是字符串数组。 如果某个作业失败,则所有需要它的作业都会被跳过,除非这些作业使用让该作业继续的条件表达式。

```yml
jobs:
job1:
job2:
needs: job1
job3:
needs: [job1, job2]
```

在此示例中,`job1` 必须在 `job2` 开始之前成功完成,而 `job3` 要等待 `job1` 和 `job2` 完成。

此示例中的作业按顺序运行:

```
❶ job1
❷ job2
❸ job3
```

```yml
jobs:
job1:
job2:
needs: job1
job3:
if: ${{ always() }}
needs: [job1, job2]
```

在此示例中,`job3` 使用 `always()` 条件表达式,因此它始终在 `job1` 和 `job2` 完成后运行,不管它们是否成功。

### 步骤作业文件共享

Artifacts 是 GitHub Actions 为您提供持久文件并在运行完成后使用它们或在作业(文档)之间共享的一种方式。

要创建工件并使用它,您将需要不同的操作:上传和下载。
要上传文件或目录,您只需像这样使用它:

```yml
steps:
- uses: actions/checkout@v2
- run: mkdir -p path/to/artifact
- run: echo hello > path/to/artifact/world.txt
- uses: actions/upload-artifact@v2
with:
name: my-artifact
path: path/to/artifact/world.txt
```

然后下载 `artifact` 以使用它:

```yml
steps:
- uses: actions/checkout@v2
- uses: actions/download-artifact@v2
with:
name: my-artifact
```

### 提交 NPM 包

```yml
- run: npm publish --access public
env:
NODE_AUTH_TOKEN: ${{secrets.NPM_TOKEN}}
```

获取 `NPM_TOKEN`,可以通过 [npm](https://www.npmjs.com/settings/wcjiang/tokens) 账号创建 `token`

```shell
npm token list [--json|--parseable] # 查看
npm token create [--read-only] [--cidr=1.1.1.1/24,2.2.2.2/16] # 创建
npm token revoke # 撤销
```

### 提交 docker 镜像

```yml
# https://www.basefactor.com/github-actions-docker
- name: Docker login
run: docker login -u ${{ secrets.DOCKER_USER }} -p ${{ secrets.DOCKER_PASSWORD }}

- name: Build ant.design image
run: |
cd ./ant\.design
docker build -t ant.design .
- name: Tags & Push docs
run: |
# Strip git ref prefix from version
VERSION=$(echo "${{ github.ref }}" | sed -e 's,.*/\(.*\),\1,')

# Strip "v" prefix from tag name
[[ "${{ github.ref }}" == "refs/tags/"* ]] && VERSION=$(echo $VERSION | sed -e 's/^v//')

docker tag ant.design ${{ secrets.DOCKER_USER }}/ant.design:$VERSION
docker tag ant.design ${{ secrets.DOCKER_USER }}/ant.design:latest
docker push ${{ secrets.DOCKER_USER }}/ant.design:$VERSION
docker push ${{ secrets.DOCKER_USER }}/ant.design:latest
```

### 提交 commit 到 master 分支

```yml
- name: 生成一个文件,并将它提交到 master 分支
run: |
# Strip git ref prefix from version
VERSION=$(echo "${{ github.ref }}" | sed -e 's,.*/\(.*\),\1,')
COMMIT=released-${VERSION}
# Strip "v" prefix from tag name
[[ "${{ github.ref }}" == "refs/tags/"* ]] && VERSION=$(echo $VERSION | sed -e 's/^v//')
echo "输出版本号:$VERSION"
# 将版本输出到当前 VERSION 文件中
echo "$VERSION" > VERSION
echo "1. 输出Commit:$commit"
echo "2. Released $VERSION"
git fetch
git config --local user.email "[email protected]"
git config --local user.name "GitHub Action"
git add .
git commit -am $COMMIT
git branch -av
git pull origin master
- name: 将上面的提交 push 到 master 分支
uses: ad-m/github-push-action@master
with:
github_token: ${{ secrets.GITHUB_TOKEN }}
```

### Node.js

```yml
- name: Setup Node
uses: actions/setup-node@v2
with:
node-version: 18
```

```yml

jobs:
test:
# Containers must run in Linux based operating systems
runs-on: ubuntu-latest
strategy:
matrix:
node-version: [16.x, 18.x, 20.x]

steps:
- uses: actions/checkout@v3
- name: Use Node.js ${{ matrix.node-version }}
uses: actions/setup-node@v3
with:
node-version: ${{ matrix.node-version }}

- run: npm ci
- run: npm run build --if-present
- run: npm test
```

### 同步 Gitee

```yml
- name: Sync to Gitee
run: |
mirror() {
git clone "https://github.com/$1/$2"
cd "$2"
git remote add gitee "https://jaywcjlove:${{ secrets.GITEE_TOKEN }}@gitee.com/uiw/$2.git"
git remote set-head origin -d
git push gitee --prune +refs/remotes/origin/*:refs/heads/* +refs/tags/*:refs/tags/*
cd ..
}
mirror uiwjs uiw
```

## 环境变量

> [默认环境变量](https://help.github.com/cn/actions/configuring-and-managing-workflows/using-environment-variables#default-environment-variables)

强烈建议操作使用环境变量访问文件系统,而非使用硬编码的文件路径。 GitHub 设置供操作用于所有运行器环境中的环境变量。

### 默认环境变量

环境变量 | 描述
---- | ----
CI | 始终设置为 true。
HOME | 用于存储用户数据的 GitHub 主目录路径。 例如 /github/home。
GITHUB_WORKFLOW | 工作流程的名称。
GITHUB_RUN_ID | 仓库中每个运行的唯一编号。 如果您重新执行工作流程运行,此编号不变。
GITHUB_RUN_NUMBER | 仓库中特定工作流程每个运行的唯一编号。 此编号从 1(对应于工作流程的第一个运行)开始,然后随着每个新的运行而递增。 如果您重新执行工作流程运行,此编号不变。
GITHUB_ACTION | 操作唯一的标识符 (id)。
GITHUB_ACTIONS | 当 GitHub 操作 运行工作流程时,始终设置为 true。 您可以使用此变量来区分测试是在本地运行还是通过 GitHub 操作 运行。
GITHUB_ACTOR | 发起工作流程的个人或应用程序的名称。 例如 octocat。
GITHUB_REPOSITORY | 所有者和仓库名称。 例如 octocat/Hello-World。
GITHUB_EVENT_NAME | 触发工作流程的 web 挂钩事件的名称。
GITHUB_EVENT_PATH | 具有完整 web 挂钩事件有效负载的文件路径。 例如 /github/workflow/event.json。
GITHUB_WORKSPACE | GitHub 工作空间目录路径。 如果您的工作流程使用 [actions/checkout](https://github.com/actions/checkout) 操作,工作空间目录将包含存储仓库副本的子目录。 如果不使用 [actions/checkout](https://github.com/actions/checkout) 操作,该目录将为空。 例如 /home |/runner/work/my-repo-name/my-repo-name。
GITHUB_SHA | 触发工作流程的提交 SHA。 例如 ffac537e6cbbf934b08745a378932722df287a53。
GITHUB_REF | 触发工作流程的分支或标记参考。 例如 refs/heads/feature-branch-1。 如果分支或标记都不适用于事件类型,则变量不会存在。
GITHUB_HEAD_REF | 仅为复刻的仓库设置。 头部仓库的分支。
GITHUB_BASE_REF | 仅为复刻的仓库设置。 基础仓库的分支。

### 自定义环境变量

> 注: `GitHub` 会保留 `GITHUB_` 环境变量前缀供 `GitHub` 内部使用。 设置有 `GITHUB_` 前缀的环境变量或密码将导致错误。

在 `https://github.com/<用户名>/<项目名称>/settings/secrets` 中添加 `secrets` `NODE_API_TOKEN`,在工作流中设置环境变量 [`NODE_API_TOKEN`](https://github.com/jaywcjlove/github-actions/blob/799b232fca3d9df0272eaa12610f9ebfca51b288/.github/workflows/ci.yml#L46)

```yml
- name: 测试 nodejs 获取环境变量
env:
NODE_API_TOKEN: ${{ secrets.NODE_API_TOKEN }}
run: npm run env
```

## Github 上下文

> [Github 上下文](https://help.github.com/cn/actions/reference/context-and-expression-syntax-for-github-actions)

属性名称 | 类型 | 描述
---- | ---- | ----
github | object | 工作流程中任何作业或步骤期间可用的顶层上下文。
github.event | object | 完整事件 web 挂钩有效负载。 更多信息请参阅“触发工作流程的事件”。
github.event_path | string | 运行器上完整事件 web 挂钩有效负载的路径。
github.workflow | string | 工作流程的名称。 如果工作流程文件未指定 name,此属性的值将是仓库中工作流程文件的完整路径。
github.job | string | 当前作业的 job_id。
github.run_id | string | 仓库中每个运行的唯一编号。 如果您重新执行工作流程运行,此编号不变。
github.run_number | string | 仓库中特定工作流程每个运行的唯一编号。 此编号从 1(对应于工作流程的第一个运行)开始,然后随着每个新的运行而递增。 如果您重新执行工作流程运行,此编号不变。
github.actor | string | 发起工作流程运行的用户的登录名。
github.repository | string | 所有者和仓库名称。 例如 Codertocat/Hello-World。
github.repository_owner | string | 仓库所有者的名称。 例如 Codertocat。
github.event_name | string | 触发工作流程运行的事件的名称。
github.sha | string | 触发工作流程的提交 SHA。
github.ref | string | 触发工作流程的分支或标记参考。
github.head_ref | string | 工作流程运行中拉取请求的 head_ref 或来源分支。 此属性仅在触发工作流程运行的事件为 pull_request 时才可用。
github.base_ref | string | 工作流程运行中拉取请求的 base_ref 或目标分支。 此属性仅在触发工作流程运行的事件为 pull_request 时才可用。
github.token | string | 代表仓库上安装的 GitHub 应用程序进行身份验证的令牌。 这在功能上等同于 GITHUB_TOKEN 密码。 更多信息请参阅“使用 GITHUB_TOKEN 验证身份”。
github.workspace | string | 使用 checkout 操作时步骤的默认工作目录和仓库的默认位置。
github.action | string | 正在运行的操作的名称。 在当前步骤运行脚本时,GitHub 删除特殊字符或使用名称 run。 如果在同一作业中多次使用相同的操作,则名称将包括带有序列号的后缀。 例如,运行的第一个脚本名称为 run1,则第二个脚本将命名为 run2。 同样,actions/checkout 第二次调用时将变成 actionscheckout2。

## Contributors

As always, thanks to our amazing contributors!



Made with [action-contributors](https://github.com/jaywcjlove/github-action-contributors).

## License

Licensed under the MIT License.