Files
gpt-load/.github/workflows/ci.yml
T
tbphp 5c16ed84b3 feat(windows): 增加原生服务安装包 (#493)
* feat(windows): 增加原生服务安装包

* fix(windows): 收紧服务安装与升级流程

* fix(windows): 固定服务安装路径与语言资源

* fix(windows): 等待安装器进程完成

* fix(windows): 清理首次安装失败残留
2026-08-29 23:26:23 +08:00

248 lines
8.3 KiB
YAML

name: V2 CI
on:
push:
branches:
- v2
pull_request:
branches:
- v2
permissions:
contents: read
# 竖线分隔在任何错误(含网络错误)时回退到下一个源;默认的逗号只在
# 404/410 时回退,proxy.golang.org 瞬时故障会直接让整个 job 失败。
env:
GOPROXY: https://proxy.golang.org|direct
concurrency:
group: v2-ci-${{ github.event.pull_request.number || github.ref }}
cancel-in-progress: true
jobs:
test:
runs-on: ubuntu-24.04
timeout-minutes: 20
steps:
- name: Checkout repository
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
persist-credentials: false
- name: Validate and build web UI
uses: ./.github/actions/web-ci
- name: Set up Go
uses: actions/setup-go@b7ad1dad31e06c5925ef5d2fc7ad053ef454303e # v7.0.0
with:
go-version-file: go.mod
cache: true
- name: Check Go formatting
run: |
# go-format-check:start
formatted_files="$(gofmt -l .)"
test -z "${formatted_files}"
# go-format-check:end
- name: Check module graph
run: go mod tidy -diff
- name: Check embedded CPA bridge module
working-directory: third_party/cpaembedded
run: |
go mod tidy -diff
go vet ./...
- name: Audit Go dependencies
run: go run golang.org/x/vuln/cmd/govulncheck@v1.7.0 ./...
- name: Run Go vet
run: go vet ./...
- name: Build backend
run: go build -o gpt-load .
- name: Check repository invariants
run: git diff --check
race-tests:
runs-on: ubuntu-24.04
timeout-minutes: 20
steps:
- name: Checkout repository
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
persist-credentials: false
- name: Mark race-instrumented Go cache scope
# race-tests、test、database-contract(*) 默认共用同一个基于 go.sum 的
# setup-go 缓存 key;命中即不保存,race-instrumented GOCACHE 永远无法
# 写回,每次都要重新编译。加入这个 marker 文件参与 cache-dependency-path
# 哈希,让 race-tests 拥有独立 key 命名空间。
run: echo race-tests > .go-cache-scope
- name: Set up Go
uses: actions/setup-go@b7ad1dad31e06c5925ef5d2fc7ad053ef454303e # v7.0.0
with:
go-version-file: go.mod
cache: true
cache-dependency-path: |
go.sum
.go-cache-scope
- name: Run race-enabled tests
run: go test -race -count=1 -timeout=15m . ./internal/...
race-cpa:
runs-on: ubuntu-24.04
timeout-minutes: 10
steps:
- name: Checkout repository
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
persist-credentials: false
- name: Set up Go
uses: actions/setup-go@b7ad1dad31e06c5925ef5d2fc7ad053ef454303e # v7.0.0
with:
go-version-file: go.mod
cache: true
cache-dependency-path: third_party/cpaembedded/go.sum
- name: Run embedded CPA bridge race-enabled tests
working-directory: third_party/cpaembedded
run: go test -race -count=1 -timeout=15m ./...
database-contract:
name: Database contract (${{ matrix.driver }})
runs-on: ubuntu-24.04
timeout-minutes: 15
strategy:
fail-fast: false
max-parallel: 2
matrix:
include:
- driver: mysql
dsn: mysql://root:root@127.0.0.1:3306/gpt_load?charset=utf8mb4&transaction_isolation=%27READ-COMMITTED%27
- driver: postgres
dsn: postgres://postgres:postgres@127.0.0.1:5432/gpt_load?sslmode=disable
services:
mysql:
image: mysql:8.4
env:
MYSQL_ROOT_PASSWORD: root
MYSQL_DATABASE: gpt_load
ports:
- 3306:3306
options: >-
--health-cmd="mysqladmin ping -h 127.0.0.1 -proot"
--health-interval=5s
--health-timeout=10s
--health-retries=20
postgres:
image: postgres:18
env:
POSTGRES_PASSWORD: postgres
POSTGRES_DB: gpt_load
ports:
- 5432:5432
options: >-
--health-cmd="pg_isready -U postgres -d gpt_load"
--health-interval=5s
--health-timeout=10s
--health-retries=20
steps:
- name: Checkout repository
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
persist-credentials: false
- name: Set up Go
uses: actions/setup-go@b7ad1dad31e06c5925ef5d2fc7ad053ef454303e # v7.0.0
with:
go-version-file: go.mod
cache: true
- name: Run external database contract
env:
GPT_LOAD_DATABASE_TEST_DSN: ${{ matrix.dsn }}
run: |
go test -v -count=1 ./internal/storage ./internal/control ./internal/requestlog -run '^TestExternal(PostgresMigrationLockTimesOut|Database(AccessKeyCostLimitIncrementalMigration|AccessKeyCostLimitPeriodPermutation|ConcurrentMigrations|IncrementalMigrations|Lifecycle|ModelPriceIdentityUsesExactComparison|ReadSnapshotUsesRepeatableRead|MySQLInterruptedBaselineRecovery|MySQLRecoversPartialErrorDecisionMigration|GroupPriceReconciliation|RequestLogLifecycle))$'
windows-encryption-acl:
runs-on: windows-2025
timeout-minutes: 15
steps:
- name: Checkout repository
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
persist-credentials: false
- name: Set up Go
uses: actions/setup-go@b7ad1dad31e06c5925ef5d2fc7ad053ef454303e # v7.0.0
with:
go-version-file: go.mod
cache: true
- name: Test Windows secure file and storage ACLs
run: go test -v -count=1 ./internal/platform/securefile ./internal/platform/encryption ./internal/storage
- name: Test Windows service lifecycle
run: go test -v -count=1 .
- name: Smoke Windows service lifecycle
shell: pwsh
run: |
$binary = Join-Path $env:RUNNER_TEMP "gpt-load-service-smoke.exe"
go build -trimpath -o $binary .
if ($LASTEXITCODE -ne 0) {
throw "Windows service smoke build failed with exit code $LASTEXITCODE"
}
$env:CI_WINDOWS_SERVICE_BINARY = $binary
& .github/scripts/ci-windows-service-smoke.ps1
exit $LASTEXITCODE
- name: Build and smoke Windows installer
shell: pwsh
run: |
$ErrorActionPreference = "Stop"
$artifactDir = Join-Path $env:RUNNER_TEMP "gpt-load installer artifacts"
New-Item -ItemType Directory -Path $artifactDir | Out-Null
$binary = Join-Path $artifactDir "gpt-load-windows-amd64.exe"
go build -trimpath `
-ldflags "-X gpt-load/internal/platform/version.Version=ci" `
-o $binary .
if ($LASTEXITCODE -ne 0) {
throw "Windows installer binary build failed with exit code $LASTEXITCODE"
}
$compiler = "${env:ProgramFiles(x86)}\Inno Setup 6\ISCC.exe"
if (-not (Test-Path $compiler)) {
throw "Inno Setup compiler is unavailable: $compiler"
}
& $compiler `
"/DAppVersion=ci" `
"/DSourceBinary=$binary" `
"/DOutputDir=$artifactDir" `
"packaging/windows/gpt-load.iss"
if ($LASTEXITCODE -ne 0) {
throw "Inno Setup failed with exit code $LASTEXITCODE"
}
$setup = Join-Path $artifactDir "gpt-load-windows-setup.exe"
if (-not (Test-Path $setup)) {
throw "Windows setup was not generated"
}
$checksumFile = Join-Path $artifactDir "SHA256SUMS"
$setupHash = (Get-FileHash -Algorithm SHA256 $setup).Hash.ToLowerInvariant()
"$setupHash gpt-load-windows-setup.exe" |
Set-Content -Path $checksumFile -Encoding utf8NoBOM
$env:RELEASE_VERSION = "ci"
$env:RELEASE_WINDOWS_SETUP = $setup
$env:RELEASE_WINDOWS_BINARY = $binary
$env:RELEASE_SMOKE_CHECKSUM_FILE = $checksumFile
& .github/scripts/release-windows-installer-smoke.ps1
exit $LASTEXITCODE