修改自动构建
Build and publish packages and Docker images / Test, build and publish (push) Failing after 9m24s
Build and publish packages and Docker images / Test, build and publish (push) Failing after 9m24s
This commit is contained in:
@@ -1,10 +1,16 @@
|
|||||||
name: Build and publish Docker images
|
name: Build and publish packages and Docker images
|
||||||
|
|
||||||
on:
|
on:
|
||||||
push:
|
push:
|
||||||
tags:
|
tags:
|
||||||
- "v*"
|
- "v*"
|
||||||
workflow_dispatch:
|
workflow_dispatch:
|
||||||
|
inputs:
|
||||||
|
include_extended_platforms:
|
||||||
|
description: "同时构建 Windows ARM64 和 macOS x64/ARM64"
|
||||||
|
required: false
|
||||||
|
default: false
|
||||||
|
type: boolean
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
publish:
|
publish:
|
||||||
@@ -23,9 +29,56 @@ jobs:
|
|||||||
with:
|
with:
|
||||||
dotnet-version: "10.0.x"
|
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
|
- name: Run tests
|
||||||
run: dotnet test Eis.slnx --configuration Release
|
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
|
- name: Set up QEMU
|
||||||
uses: https://github.com/docker/setup-qemu-action@v3
|
uses: https://github.com/docker/setup-qemu-action@v3
|
||||||
|
|
||||||
@@ -53,9 +106,8 @@ jobs:
|
|||||||
images: |
|
images: |
|
||||||
docker.io/${{ vars.DOCKERHUB_IMAGE }}
|
docker.io/${{ vars.DOCKERHUB_IMAGE }}
|
||||||
git.biss.click/biss/exam-information-system
|
git.biss.click/biss/exam-information-system
|
||||||
flavor: latest=false
|
flavor: latest=auto
|
||||||
tags: |
|
tags: |
|
||||||
type=raw,value=latest,enable=${{ gitea.ref == 'refs/heads/master' }}
|
|
||||||
type=sha,format=short,prefix=sha-
|
type=sha,format=short,prefix=sha-
|
||||||
type=semver,pattern={{version}}
|
type=semver,pattern={{version}}
|
||||||
type=semver,pattern={{major}}.{{minor}}
|
type=semver,pattern={{major}}.{{minor}}
|
||||||
@@ -91,8 +143,18 @@ jobs:
|
|||||||
tag_name: ${{ gitea.ref_name }}
|
tag_name: ${{ gitea.ref_name }}
|
||||||
name: ${{ gitea.ref_name }}
|
name: ${{ gitea.ref_name }}
|
||||||
prerelease: ${{ steps.release_type.outputs.prerelease }}
|
prerelease: ${{ steps.release_type.outputs.prerelease }}
|
||||||
|
files: |
|
||||||
|
artifacts/packages/*
|
||||||
body: |
|
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
|
```text
|
||||||
docker pull docker.io/${{ vars.DOCKERHUB_IMAGE }}:${{ steps.metadata.outputs.version }}
|
docker pull docker.io/${{ vars.DOCKERHUB_IMAGE }}:${{ steps.metadata.outputs.version }}
|
||||||
|
|||||||
@@ -173,9 +173,20 @@ docker compose run --rm --entrypoint dotnet app /app/tools/Eis.Tools.dll databas
|
|||||||
docker compose up --detach app
|
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` 代替该软件包令牌。
|
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 注册步骤运行。
|
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
|
```powershell
|
||||||
git tag v1.2.3
|
git tag v1.2.3
|
||||||
@@ -199,9 +210,9 @@ git tag v1.3.0-rc.1
|
|||||||
git push origin 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` 拉取。
|
首次成功推送后,容器镜像会出现在 `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 自动化测试
|
tests/Eis.Infrastructure.Tests xUnit 自动化测试
|
||||||
|
|
||||||
scripts/publish.ps1 Web 与数据库工具统一发布脚本
|
scripts/publish.ps1 Web 与数据库工具统一发布脚本
|
||||||
|
scripts/publish-platform-packages.sh CI 跨平台自包含程序包构建脚本
|
||||||
scripts/smoke-dotnet-native.ps1 纯 .NET 发布产物烟测
|
scripts/smoke-dotnet-native.ps1 纯 .NET 发布产物烟测
|
||||||
data/exam.sqlite 本地运行后生成的 SQLite 数据库
|
data/exam.sqlite 本地运行后生成的 SQLite 数据库
|
||||||
.env.example 开发与生产环境变量模板
|
.env.example 开发与生产环境变量模板
|
||||||
|
|||||||
@@ -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}"
|
||||||
Reference in New Issue
Block a user