修改自动构建
Build and publish packages and Docker images / Test, build and publish (push) Failing after 9m24s

This commit is contained in:
2026-07-24 08:51:24 +08:00 Unverified
parent ef8222c138
commit 3162a5d3a3
3 changed files with 163 additions and 9 deletions
+66 -4
View File
@@ -1,10 +1,16 @@
name: Build and publish Docker images
name: Build and publish packages and Docker images
on:
push:
tags:
- "v*"
workflow_dispatch:
inputs:
include_extended_platforms:
description: "同时构建 Windows ARM64 和 macOS x64/ARM64"
required: false
default: false
type: boolean
jobs:
publish:
@@ -23,9 +29,56 @@ jobs:
with:
dotnet-version: "10.0.x"
- name: Set up Node.js
uses: https://github.com/actions/setup-node@v4
with:
node-version: "24"
cache: npm
cache-dependency-path: src/Eis.Web/ClientApp/package-lock.json
- name: Build Vue application
working-directory: src/Eis.Web/ClientApp
run: |
npm ci
npm run build
- name: Run tests
run: dotnet test Eis.slnx --configuration Release
- name: Determine package version
id: package_version
shell: bash
env:
INCLUDE_EXTENDED_PLATFORMS: ${{ inputs.include_extended_platforms }}
run: |
set -euo pipefail
if [[ "$GITHUB_REF" == refs/tags/v* ]]; then
version="${GITHUB_REF_NAME#v}"
else
version="0.0.0-dev.${GITHUB_RUN_NUMBER:-0}"
fi
profile=default
if [[ "${INCLUDE_EXTENDED_PLATFORMS:-false}" == "true" ]]; then
profile=all
fi
echo "version=$version" >> "$GITHUB_OUTPUT"
echo "profile=$profile" >> "$GITHUB_OUTPUT"
- name: Build self-contained platform packages
shell: bash
run: |
bash ./scripts/publish-platform-packages.sh \
"${{ steps.package_version.outputs.version }}" \
"artifacts/packages" \
"${{ steps.package_version.outputs.profile }}"
- name: Upload platform packages as workflow artifact
uses: https://github.com/actions/upload-artifact@v4
with:
name: eis-${{ steps.package_version.outputs.version }}-${{ steps.package_version.outputs.profile }}-platform-packages
path: artifacts/packages/*
if-no-files-found: error
- name: Set up QEMU
uses: https://github.com/docker/setup-qemu-action@v3
@@ -53,9 +106,8 @@ jobs:
images: |
docker.io/${{ vars.DOCKERHUB_IMAGE }}
git.biss.click/biss/exam-information-system
flavor: latest=false
flavor: latest=auto
tags: |
type=raw,value=latest,enable=${{ gitea.ref == 'refs/heads/master' }}
type=sha,format=short,prefix=sha-
type=semver,pattern={{version}}
type=semver,pattern={{major}}.{{minor}}
@@ -91,8 +143,18 @@ jobs:
tag_name: ${{ gitea.ref_name }}
name: ${{ gitea.ref_name }}
prerelease: ${{ steps.release_type.outputs.prerelease }}
files: |
artifacts/packages/*
body: |
Docker 镜像已发布:
已发布以下自包含程序包,无需预装 .NET 运行时
- Windows x64:下载对应的 `.zip`
- Linux x64 / ARM64:下载对应的 `.tar.gz`
- 使用 `SHA256SUMS` 校验下载文件
Windows ARM64 与 macOS Intel / Apple Silicon 包可在 Actions 页面选择扩展平台后手动构建。
Docker 多架构镜像(linux/amd64、linux/arm64):
```text
docker pull docker.io/${{ vars.DOCKERHUB_IMAGE }}:${{ steps.metadata.outputs.version }}
+17 -5
View File
@@ -173,9 +173,20 @@ docker compose run --rm --entrypoint dotnet app /app/tools/Eis.Tools.dll databas
docker compose up --detach app
```
#### Gitea Actions 自动发布 Docker Hub 与 Gitea 软件包
#### Gitea Actions 自动发布跨平台程序包与 Docker 镜像
工作流位于 `.gitea/workflows/docker-publish.yml`。它会使用 .NET 10 运行测试,然后构建 `linux/amd64``linux/arm64` 双架构镜像,并同时推送到 Docker Hub 与 `git.biss.click/biss/exam-information-system`
工作流位于 `.gitea/workflows/publish.yml`。它会构建 Vue 前端、使用 .NET 10 运行测试,然后默认生成以下无需预装 .NET 运行时的自包含程序包:
- Windows`win-x64``.zip`
- Linux`linux-x64``linux-arm64``.tar.gz`
每个程序包都把 Web 与数据库工具放在同一个 `app` 目录中,使二者共享 .NET 运行时和公共依赖;根目录还包含 `README.md``LICENSE` 和环境变量示例,构建结果同时附带 `SHA256SUMS`。标签构建会把这些文件上传到同名 Gitea Release;手动构建可在 Actions 运行记录中下载归档。普通代码推送不会触发这套耗时的发布构建。
解压后,Windows 使用 `.\app\Eis.Web.exe` 启动服务,Linux/macOS 使用 `./app/Eis.Web`;数据库工具分别为 `.\app\Eis.Tools.exe``./app/Eis.Tools`
如需 Windows ARM64、macOS Intel 或 Apple Silicon 包,从 Gitea Actions 页面手动运行工作流并勾选“同时构建 Windows ARM64 和 macOS x64/ARM64”。扩展构建会在默认三种平台之外增加 `win-arm64``osx-x64``osx-arm64`
同一工作流还会构建 `linux/amd64``linux/arm64` 双架构 Docker 镜像,并同时推送到 Docker Hub 与 `git.biss.click/biss/exam-information-system`
使用前需要完成以下配置:
@@ -185,7 +196,7 @@ docker compose up --detach app
4. 使用对 `biss` 组织拥有软件包写权限的 Gitea 账号,在“设置 → 应用 → 生成新令牌”中创建具有 Package Read & Write 权限的个人访问令牌。在仓库 Actions Variables 中添加 `REGISTRY_USERNAME`,值为该令牌所属的用户名;在 Actions Secrets 中添加 `REGISTRY_TOKEN`,值为个人访问令牌。自定义 Secret 不能使用 Gitea 保留的 `GITEA_` 前缀,也不能用工作流内置的 `GITEA_TOKEN` 代替该软件包令牌。
5. 确保 Gitea Actions 与仓库的软件包注册表已启用,并且 `ubuntu-latest` Runner 能访问 Docker daemon、GitHub、Docker Hub 和 `git.biss.click`。双架构构建还需要 Runner 允许 QEMU 注册步骤运行。
推送到 `master` 后会发布 `latest``sha-<短提交号>`推送形如 `v1.2.3` 的 Git 标签后会发布 `1.2.3``1.2` 和对应的提交标签,并在镜像推送成功后自动创建同名正式 Gitea Release。例如:
推送形如 `v1.2.3` 的 Git 标签后,会自动构建跨平台程序包,发布镜像标签 `1.2.3``1.2``latest` 和对应的提交标签,并在构建成功后创建带下载附件的同名正式 Gitea Release。例如:
```powershell
git tag v1.2.3
@@ -199,9 +210,9 @@ git tag v1.3.0-rc.1
git push origin v1.3.0-rc.1
```
该版本的镜像标签为 `1.3.0-rc.1`,不会覆盖稳定版的 `1.3``latest` 标签。
该版本的镜像标签为 `1.3.0-rc.1`,不会覆盖稳定版的 `1.3``latest` 标签。除版本标签外,也可以从 Gitea Actions 页面手动运行工作流;普通分支推送不会触发发布。
工作流也支持从 Gitea Actions 页面手动运行。构建缓存保存为同一 Docker Hub 仓库中的 `buildcache` 标签,以加快后续构建。Release 使用工作流内置的 `GITEA_TOKEN` 创建,无需添加额外 Secret;仓库或组织“Actions → General”中的任务令牌最大权限必须允许 Releases Write。
构建缓存保存为同一 Docker Hub 仓库中的 `buildcache` 标签,以加快后续构建。Release 使用工作流内置的 `GITEA_TOKEN` 创建,无需添加额外 Secret;仓库或组织“Actions → General”中的任务令牌最大权限必须允许 Releases Write。
首次成功推送后,容器镜像会出现在 `biss` 所有者的软件包列表。Gitea 的软件包归属于用户或组织,不会天然归属于某个仓库;打开该软件包的设置页面,将它关联到 `Exam-Information-System`,即可让它显示在此仓库的“软件包”页。之后可使用 `docker pull git.biss.click/biss/exam-information-system:latest` 拉取。
@@ -393,6 +404,7 @@ src/Eis.Web/wwwroot 浏览器入口、基础样式及 CKEditor
tests/Eis.Infrastructure.Tests xUnit 自动化测试
scripts/publish.ps1 Web 与数据库工具统一发布脚本
scripts/publish-platform-packages.sh CI 跨平台自包含程序包构建脚本
scripts/smoke-dotnet-native.ps1 纯 .NET 发布产物烟测
data/exam.sqlite 本地运行后生成的 SQLite 数据库
.env.example 开发与生产环境变量模板
+80
View File
@@ -0,0 +1,80 @@
#!/usr/bin/env bash
set -euo pipefail
version="${1:?Usage: publish-platform-packages.sh <version> [output-directory] [default|all]}"
script_dir="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
repository_root="$(cd "${script_dir}/.." && pwd)"
output_directory="${2:-${repository_root}/artifacts/packages}"
platform_profile="${3:-default}"
web_project="${repository_root}/src/Eis.Web/Eis.Web.csproj"
tools_project="${repository_root}/src/Eis.Tools/Eis.Tools.csproj"
case "${platform_profile}" in
default)
runtime_identifiers=(win-x64 linux-x64 linux-arm64)
;;
all)
runtime_identifiers=(win-x64 win-arm64 linux-x64 linux-arm64 osx-x64 osx-arm64)
;;
*)
echo "Unknown platform profile: ${platform_profile}. Expected default or all." >&2
exit 2
;;
esac
if [[ "${output_directory}" != /* ]]; then
output_directory="${repository_root}/${output_directory}"
fi
mkdir -p "${output_directory}"
output_directory="$(cd "${output_directory}" && pwd)"
temporary_root="$(mktemp -d)"
trap 'rm -rf "${temporary_root}"' EXIT
for runtime_identifier in "${runtime_identifiers[@]}"; do
package_name="eis-${version}-${runtime_identifier}"
package_root="${temporary_root}/${package_name}"
application_root="${package_root}/app"
echo "Publishing ${package_name}..."
dotnet publish "${web_project}" \
--configuration Release \
--runtime "${runtime_identifier}" \
--self-contained true \
--output "${application_root}" \
-p:Version="${version}"
dotnet publish "${tools_project}" \
--configuration Release \
--runtime "${runtime_identifier}" \
--self-contained true \
--output "${application_root}" \
-p:Version="${version}"
cp "${repository_root}/README.md" "${package_root}/README.md"
cp "${repository_root}/LICENSE" "${package_root}/LICENSE"
cp "${repository_root}/.env.example" "${package_root}/.env.example"
if [[ "${runtime_identifier}" == win-* ]]; then
(
cd "${temporary_root}"
zip -q -r "${output_directory}/${package_name}.zip" "${package_name}"
)
else
tar -C "${temporary_root}" -czf "${output_directory}/${package_name}.tar.gz" "${package_name}"
fi
rm -rf "${package_root}"
done
(
cd "${output_directory}"
find . -maxdepth 1 -type f \
\( -name "eis-${version}-*.zip" -o -name "eis-${version}-*.tar.gz" \) \
-printf '%f\n' \
| sort \
| xargs sha256sum > SHA256SUMS
sha256sum --check SHA256SUMS
)
echo "Platform packages were written to ${output_directory}"