* feat(windows): 增加原生服务安装包 * fix(windows): 收紧服务安装与升级流程 * fix(windows): 固定服务安装路径与语言资源 * fix(windows): 等待安装器进程完成 * fix(windows): 清理首次安装失败残留
248 lines
8.3 KiB
YAML
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
|