This commit is contained in:
zydi 2025-12-19 10:38:41 +00:00
parent 03bfe4471f
commit 1e34ba6d18
4 changed files with 492 additions and 2 deletions

179
README.md
View File

@ -43,6 +43,181 @@
3. 如果你的服务端口与模板中的默认值不同,可在 `services` 变量里调整 `name:port` 列表,例如:`auth:5710`、`project:5711` 等。
4. 如需调整重试次数、间隔时间或检查路径,可在对应 `curl` 循环处按需修改脚本逻辑。
## 其他文件/目录
`actions/`、`docs/` 等其他文件或目录仅作内部使用或扩展示例,对实际在项目中使用上述两个模板不是必需的,你可以忽略它们。
## 通用复用 Actions 说明(`common-workflows/actions`
本目录下包含了一组可在各个仓库中复用的 **Gitea / GitHub composite actions**,统一托管在:
- `https://git.aiot.ml/Obscura/common-workflows`
在具体仓库的 workflow 中,通过 `uses` 引用,例如:
```yaml
uses: https://git.aiot.ml/Obscura/common-workflows/actions/<action-name>@main
```
目前提供的通用 action 如下:
- **build-images**:构建并验证 Docker 镜像
- **deploy-docker**:使用 `docker compose` 部署服务
- **api-test**:对一组后端 API 的 `/health` 做健康检查
- **frontend-test**:对一组前端入口 URL 做可访问性检查
下面分别说明用法。
---
## `build-images` — Docker 镜像构建
**路径**`actions/build-images/action.yml`
**作用**:在 Runner 上本地执行 `docker build`,并对生成的镜像做简单校验与清理悬空镜像。
**引用示例**(节选自 `broccoli-offline`
```yaml
- name: Build Docker image
uses: https://git.aiot.ml/Obscura/common-workflows/actions/build-images@main
with:
dockerfile: 'Dockerfile.api'
context: '.'
image_name: 'broccoli-api'
image_tag: 'v3.2.2'
enable_cache: 'true'
# build_args: |
# HTTP_PROXY=http://...
# HTTPS_PROXY=http://...
```
**输入参数**
- **`dockerfile`**必填Dockerfile 路径,相对于仓库根目录,例如 `Dockerfile`, `Dockerfile.api`
- **`context`**(可选,默认 `.`):构建上下文目录,相对于仓库根目录。
- **`image_name`**(必填):镜像名称,不含 tag例如 `broccoli-api`
- **`image_tag`**(必填):镜像 tag / 版本,例如 `v1.0.0`、`latest`。
- **`enable_cache`**(可选,默认 `'true'`):是否启用构建缓存(当前主要依赖 Runner 本地 docker layer cache
- **`build_args`**可选Docker build 参数,每行一个,格式 `KEY=VALUE`,会被拼接为 `--build-arg KEY=VALUE`
**依赖环境**
- Runner 上需要已安装 `docker`,并有构建镜像的权限。
---
## `deploy-docker` — Docker Compose 部署
**路径**`actions/deploy-docker/action.yml`
**作用**:在已经 checkout 好代码的前提下,使用 `docker compose` 停止旧服务并重新部署,最后校验服务状态。
**典型用法**(示例):
```yaml
- name: Checkout code
uses: https://git.aiot.ml/Obscura/checkout@v4
with:
ref: offline
sparse-checkout: |
.gitea/workflows/deploy-docker.yml
config/
docker-compose-offline.yml
sparse-checkout-cone-mode: false
- name: Deploy with reusable action
uses: https://git.aiot.ml/Obscura/common-workflows/actions/deploy-docker@main
with:
compose_file: 'docker-compose-offline.yml'
# compose_dir: 'config' # 可选:指定工作目录
# startup_wait: '30' # 可选:启动后等待 30s 再校验
```
**输入参数**
- **`compose_file`**(必填):`docker-compose` 文件路径,相对于当前工作目录或 `compose_dir`
- **`compose_dir`**(可选,默认使用 `compose_file` 所在目录):执行 `docker compose` 时的工作目录。
- **`startup_wait`**(可选,默认 `0``up -d` 后额外等待的秒数,用于等待服务完成初始化。
**行为**
1. 计算 `compose_file` 与工作目录。
2. 执行 `docker compose -f <file> down` 停止旧服务(失败不终止)。
3. 执行 `docker compose -f <file> up -d` 启动服务。
4. 可选地等待 `startup_wait` 秒。
5. 执行 `docker compose ps` 并检查是否有 `exited` 状态的服务,若有则输出日志并失败。
**依赖环境**
- Runner 上需要安装 `docker``docker compose`,并安装 `jq`(用于解析 `docker compose ps --format json`)。
---
## `api-test` — API `/health` 健康检查(完整 URL
**路径**`actions/api-test/action.yml`
**作用**:对一组后端服务的 `/health` 接口做健康检查。
**约定**:输入的是 **不包含 `/health` 的完整 URL**action 内部会自动拼接 `/health`
**示例**(节选自 `broccoli-offline/.gitea/workflows/e2e-tests.yml`
```yaml
- name: Run offline API health tests
uses: https://git.aiot.ml/Obscura/common-workflows/actions/api-test@main
with:
urls: |
http://127.0.0.1:5710
http://127.0.0.1:5711
http://127.0.0.1:5712
```
**输入参数**
- **`urls`**(必填):多行字符串,每行一个完整 URL不含 `/health`),例如:
- `http://127.0.0.1:5800`
- `https://service-name`
**行为**
- 对每一行 URL
- 去掉末尾 `/`,拼接 `/health`
- 最多重试 10 次 `curl -fsS <url>/health`,每次失败后等待 5 秒;
- 若所有重试均失败,则记录到失败列表。
- 如果任意服务失败,整个步骤 `exit 1`
**依赖环境**
- Runner 上需要安装 `curl`
---
## `frontend-test` — 前端入口可访问性检查(完整 URL
**路径**`actions/frontend-test/action.yml`
**作用**:对一组前端入口 URL 做可访问性检查(通常是首页)。
**示例**(节选自 `broccoli-offline/.gitea/workflows/e2e-tests.yml`
```yaml
- name: Run offline frontend availability tests
uses: https://git.aiot.ml/Obscura/common-workflows/actions/frontend-test@main
with:
urls: |
http://127.0.0.1:5373
```
**输入参数**
- **`urls`**(必填):多行字符串,每行一个完整 URL例如
- `http://127.0.0.1:3000`
- `https://frontend-service`
**行为**
- 对每一行 URL
- 最多重试 10 次 `curl -fsS <url>`,每次失败后等待 5 秒;
- 任意一次成功则认为该前端通过,否则记录失败。
- 如果有任意 URL 访问失败,整个步骤 `exit 1`
**依赖环境**
- Runner 上需要安装 `curl`

185
actions/README.md Normal file
View File

@ -0,0 +1,185 @@
## 通用复用 Actions 说明(`common-workflows/actions`
本目录下包含了一组可在各个仓库中复用的 **Gitea / GitHub composite actions**,统一托管在:
- `https://git.aiot.ml/Obscura/common-workflows`
在具体仓库的 workflow 中,通过 `uses` 引用,例如:
```yaml
uses: https://git.aiot.ml/Obscura/common-workflows/actions/<action-name>@main
```
目前提供的通用 action 如下:
- **build-images**:构建并验证 Docker 镜像
- **deploy-docker**:使用 `docker compose` 部署服务
- **api-test**:对一组后端 API 的 `/health` 做健康检查
- **frontend-test**:对一组前端入口 URL 做可访问性检查
下面分别说明用法。
---
## `build-images` — Docker 镜像构建
**路径**`actions/build-images/action.yml`
**作用**:在 Runner 上本地执行 `docker build`,并对生成的镜像做简单校验与清理悬空镜像。
**引用示例**(节选自 `broccoli-offline`
```yaml
- name: Build Docker image
uses: https://git.aiot.ml/Obscura/common-workflows/actions/build-images@main
with:
dockerfile: 'Dockerfile.api'
context: '.'
image_name: 'broccoli-api'
image_tag: 'v3.2.2'
enable_cache: 'true'
# build_args: |
# HTTP_PROXY=http://...
# HTTPS_PROXY=http://...
```
**输入参数**
- **`dockerfile`**必填Dockerfile 路径,相对于仓库根目录,例如 `Dockerfile`, `Dockerfile.api`
- **`context`**(可选,默认 `.`):构建上下文目录,相对于仓库根目录。
- **`image_name`**(必填):镜像名称,不含 tag例如 `broccoli-api`
- **`image_tag`**(必填):镜像 tag / 版本,例如 `v1.0.0`、`latest`。
- **`enable_cache`**(可选,默认 `'true'`):是否启用构建缓存(当前主要依赖 Runner 本地 docker layer cache
- **`build_args`**可选Docker build 参数,每行一个,格式 `KEY=VALUE`,会被拼接为 `--build-arg KEY=VALUE`
**依赖环境**
- Runner 上需要已安装 `docker`,并有构建镜像的权限。
---
## `deploy-docker` — Docker Compose 部署
**路径**`actions/deploy-docker/action.yml`
**作用**:在已经 checkout 好代码的前提下,使用 `docker compose` 停止旧服务并重新部署,最后校验服务状态。
**典型用法**(示例):
```yaml
- name: Checkout code
uses: https://git.aiot.ml/Obscura/checkout@v4
with:
ref: offline
sparse-checkout: |
.gitea/workflows/deploy-docker.yml
config/
docker-compose-offline.yml
sparse-checkout-cone-mode: false
- name: Deploy with reusable action
uses: https://git.aiot.ml/Obscura/common-workflows/actions/deploy-docker@main
with:
compose_file: 'docker-compose-offline.yml'
# compose_dir: 'config' # 可选:指定工作目录
# startup_wait: '30' # 可选:启动后等待 30s 再校验
```
**输入参数**
- **`compose_file`**(必填):`docker-compose` 文件路径,相对于当前工作目录或 `compose_dir`
- **`compose_dir`**(可选,默认使用 `compose_file` 所在目录):执行 `docker compose` 时的工作目录。
- **`startup_wait`**(可选,默认 `0``up -d` 后额外等待的秒数,用于等待服务完成初始化。
**行为**
1. 计算 `compose_file` 与工作目录。
2. 执行 `docker compose -f <file> down` 停止旧服务(失败不终止)。
3. 执行 `docker compose -f <file> up -d` 启动服务。
4. 可选地等待 `startup_wait` 秒。
5. 执行 `docker compose ps` 并检查是否有 `exited` 状态的服务,若有则输出日志并失败。
**依赖环境**
- Runner 上需要安装 `docker``docker compose`,并安装 `jq`(用于解析 `docker compose ps --format json`)。
---
## `api-test` — API `/health` 健康检查(完整 URL
**路径**`actions/api-test/action.yml`
**作用**:对一组后端服务的 `/health` 接口做健康检查。
**约定**:输入的是 **不包含 `/health` 的完整 URL**action 内部会自动拼接 `/health`
**示例**(节选自 `broccoli-offline/.gitea/workflows/e2e-tests.yml`
```yaml
- name: Run offline API health tests
uses: https://git.aiot.ml/Obscura/common-workflows/actions/api-test@main
with:
urls: |
http://10.0.0.145:5710
http://10.0.0.145:5711
http://10.0.0.145:5712
http://10.0.0.145:5713
http://10.0.0.145:5714
http://10.0.0.145:5715
http://10.0.0.145:5716
http://10.0.0.145:5717
http://10.0.0.145:5718
http://10.0.0.145:5719
http://10.0.0.145:5720
http://10.0.0.145:5721
```
**输入参数**
- **`urls`**(必填):多行字符串,每行一个完整 URL不含 `/health`),例如:
- `http://127.0.0.1:5800`
- `https://service-name`
**行为**
- 对每一行 URL
- 去掉末尾 `/`,拼接 `/health`
- 最多重试 10 次 `curl -fsS <url>/health`,每次失败后等待 5 秒;
- 若所有重试均失败,则记录到失败列表。
- 如果任意服务失败,整个步骤 `exit 1`
**依赖环境**
- Runner 上需要安装 `curl`
---
## `frontend-test` — 前端入口可访问性检查(完整 URL
**路径**`actions/frontend-test/action.yml`
**作用**:对一组前端入口 URL 做可访问性检查(通常是首页)。
**示例**(节选自 `broccoli-offline/.gitea/workflows/e2e-tests.yml`
```yaml
- name: Run offline frontend availability tests
uses: https://git.aiot.ml/Obscura/common-workflows/actions/frontend-test@main
with:
urls: |
http://10.0.0.145:5373
```
**输入参数**
- **`urls`**(必填):多行字符串,每行一个完整 URL例如
- `http://127.0.0.1:3000`
- `https://frontend-service`
**行为**
- 对每一行 URL
- 最多重试 10 次 `curl -fsS <url>`,每次失败后等待 5 秒;
- 任意一次成功则认为该前端通过,否则记录失败。
- 如果有任意 URL 访问失败,整个步骤 `exit 1`
**依赖环境**
- Runner 上需要安装 `curl`

View File

@ -0,0 +1,74 @@
name: 'Reusable API Health Test'
description: '通用的 API /health 检查逻辑,可在各仓库中复用,支持传入完整 URL不含 /health'
inputs:
urls:
description: '要检查的服务 URL 列表,每行一个完整 URL不包含 /health例如 http://127.0.0.1:5800 或 https://service-name'
required: true
runs:
using: 'composite'
steps:
- name: Check API services
shell: bash
env:
URLS: ${{ inputs.urls }}
run: |
echo "====== 开始检查各 API 服务 /health ======"
failed_services=""
api_failed=0
# 按行读取 URL每行是一个完整的基础 URL不包含 /health
while IFS= read -r url; do
# 跳过空行
if [ -z "$url" ]; then
continue
fi
# 去掉末尾的 /,避免出现 //health
url_no_slash="${url%/}"
health_url="${url_no_slash}/health"
echo ""
echo "------ 检查服务 ${health_url} ------"
success=0
for i in {1..10}; do
if curl -fsS "${health_url}" > /dev/null; then
success=1
break
fi
echo "第 ${i} 次重试,等待 5 秒..."
sleep 5
done
if [ "${success}" -ne 1 ]; then
echo "✗ 服务 ${health_url} /health 检查失败"
failed_services="${failed_services} ${health_url}"
else
echo "✓ 服务 ${health_url} /health 正常"
fi
done <<< "$URLS"
if [ -n "${failed_services}" ]; then
echo ""
echo "✗ 以下服务健康检查失败:"
for s in ${failed_services}; do
echo " - ${s}"
done
api_failed=1
else
echo ""
echo "====== 所有 API 服务健康检查通过 ======"
fi
if [ "${api_failed}" -ne 0 ]; then
echo ""
echo "✗ API /health 检查存在失败,详见上方日志"
exit 1
fi
echo ""
echo "✓ 所有 API /health 检查通过"

View File

@ -0,0 +1,56 @@
name: 'Reusable Frontend Availability Test'
description: '通用的前端首页可访问性检查逻辑,可在各仓库中复用,支持传入完整 URL'
inputs:
urls:
description: '要检查的前端 URL 列表,每行一个完整 URL例如 http://127.0.0.1:5373 或 https://frontend-service'
required: true
runs:
using: 'composite'
steps:
- name: Check frontend
shell: bash
env:
URLS: ${{ inputs.urls }}
run: |
echo "====== 开始检查前端首页可访问性 ======"
frontend_failed=0
# 按行读取 URL每行是一个完整的前端访问地址
while IFS= read -r url; do
# 跳过空行
if [ -z "$url" ]; then
continue
fi
echo ""
echo "------ 检查前端 ${url} ------"
success=0
for i in {1..10}; do
if curl -fsS "${url}" > /dev/null; then
echo "✓ 前端首页可访问: ${url}"
success=1
break
fi
echo "第 ${i} 次重试,等待 5 秒..."
sleep 5
done
if [ "${success}" -ne 1 ]; then
echo "✗ 前端首页访问失败: ${url}"
frontend_failed=1
fi
done <<< "$URLS"
if [ "${frontend_failed}" -ne 0 ]; then
echo ""
echo "✗ 前端检查存在失败,详见上方日志"
exit 1
fi
echo ""
echo "✓ 所有前端检查通过"