Skip to content

Commit 1893247

Browse files
SuperMarioYLclaude
andcommitted
release: v0.0.21 — CI test/lint gate before publish + reproducible web build
Release workflow gains a Test & Lint Gate (go vet/fmt/build/test -race + web npm ci/lint/vitest/build) that the publish chain needs, so broken code cannot be released. Declared tslib (phantom dep of echarts-for-react, previously provided by removed pro-components) and synced package-lock so npm ci is reproducible. gofmt applied across api-server. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
1 parent 3ba49c2 commit 1893247

10 files changed

Lines changed: 115 additions & 473 deletions

File tree

.github/workflows/release.yml

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,9 +15,68 @@ env:
1515
IMAGE_PREFIX: ghcr.io/${{ github.repository_owner }}/bison
1616

1717
jobs:
18+
gate:
19+
name: Test & Lint Gate
20+
runs-on: ubuntu-latest
21+
steps:
22+
- name: Checkout code
23+
uses: actions/checkout@v4
24+
25+
- name: Set up Go
26+
uses: actions/setup-go@v5
27+
with:
28+
go-version: '1.24'
29+
cache-dependency-path: api-server/go.sum
30+
31+
- name: Go vet
32+
working-directory: api-server
33+
run: go vet ./...
34+
35+
- name: Go fmt check
36+
working-directory: api-server
37+
run: |
38+
if [ -n "$(gofmt -l .)" ]; then
39+
echo "Go code is not formatted:"; gofmt -d .; exit 1
40+
fi
41+
42+
- name: Go build
43+
working-directory: api-server
44+
run: go build ./...
45+
46+
- name: Go test (race + coverage)
47+
working-directory: api-server
48+
run: |
49+
go test -race -coverprofile=coverage.out ./...
50+
echo "### API coverage" >> "$GITHUB_STEP_SUMMARY"
51+
go tool cover -func=coverage.out | tail -1 >> "$GITHUB_STEP_SUMMARY"
52+
53+
- name: Set up Node
54+
uses: actions/setup-node@v4
55+
with:
56+
node-version: '20'
57+
cache: npm
58+
cache-dependency-path: web-ui/package-lock.json
59+
60+
- name: Web install
61+
working-directory: web-ui
62+
run: npm ci --no-audit --no-fund
63+
64+
- name: Web lint
65+
working-directory: web-ui
66+
run: npm run lint
67+
68+
- name: Web test
69+
working-directory: web-ui
70+
run: npx vitest run
71+
72+
- name: Web build
73+
working-directory: web-ui
74+
run: npm run build
75+
1876
prepare:
1977
name: Prepare Release
2078
runs-on: ubuntu-latest
79+
needs: gate
2180
outputs:
2281
version: ${{ steps.extract_version.outputs.version }}
2382
steps:

CHANGELOG.md

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,18 @@ All notable changes to the Bison project will be documented in this file.
55
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
66
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
77

8+
## [0.0.21] - 2026-06-19
9+
10+
### Added — Release test/lint gate
11+
12+
- The release workflow now runs a **Test & Lint Gate** before anything is built or published: `go vet`, `gofmt` check, `go build`, `go test -race` (with coverage in the job summary), plus web `npm ci` / lint / `vitest run` / build. `prepare` (and the whole publish chain) `needs` this gate, so broken code can no longer be tagged into a public release.
13+
14+
### Fixed — Reproducible web build
15+
16+
- Declared `tslib` as an explicit dependency: `echarts-for-react` imports it but doesn't declare it, so it was a phantom dependency previously satisfied only by the removed `@ant-design/pro-components`. Clean installs (`npm ci`) now build reliably.
17+
- Synced `package-lock.json` with `package.json` (removed stale `pro-components`, added `tslib`) so `npm ci` works.
18+
- Applied `gofmt` across the api-server (formatting only).
19+
820
## [0.0.20] - 2026-06-19
921

1022
### Changed — OpenCost query caching

api-server/cmd/main.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -141,8 +141,8 @@ func main() {
141141
// Feature flags (public)
142142
api.GET("/features", func(c *gin.Context) {
143143
c.JSON(http.StatusOK, gin.H{
144-
"costEnabled": costSvc.IsEnabled(),
145-
"capsuleEnabled": cfg.CapsuleEnabled,
144+
"costEnabled": costSvc.IsEnabled(),
145+
"capsuleEnabled": cfg.CapsuleEnabled,
146146
"prometheusEnabled": cfg.PrometheusURL != "",
147147
})
148148
})

api-server/internal/config/config.go

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -39,12 +39,12 @@ type Config struct {
3939
// Load reads configuration from environment variables
4040
func Load() (*Config, error) {
4141
cfg := &Config{
42-
Port: 8080,
43-
Mode: "release",
44-
AuthEnabled: false,
45-
AdminUsername: "admin",
46-
AdminPassword: "admin",
47-
JWTSecret: "bison-secret-key-change-in-production",
42+
Port: 8080,
43+
Mode: "release",
44+
AuthEnabled: false,
45+
AdminUsername: "admin",
46+
AdminPassword: "admin",
47+
JWTSecret: "bison-secret-key-change-in-production",
4848
OpenCostURL: "",
4949
PrometheusURL: "",
5050
CapsuleEnabled: true,

api-server/internal/handler/onboarding.go

Lines changed: 8 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -11,15 +11,15 @@ import (
1111

1212
// OnboardingHandler handles node onboarding requests
1313
type OnboardingHandler struct {
14-
onboardingSvc *service.OnboardingService
15-
initScriptSvc *service.InitScriptService
14+
onboardingSvc *service.OnboardingService
15+
initScriptSvc *service.InitScriptService
1616
}
1717

1818
// NewOnboardingHandler creates a new OnboardingHandler
1919
func NewOnboardingHandler(onboardingSvc *service.OnboardingService, initScriptSvc *service.InitScriptService) *OnboardingHandler {
2020
return &OnboardingHandler{
21-
onboardingSvc: onboardingSvc,
22-
initScriptSvc: initScriptSvc,
21+
onboardingSvc: onboardingSvc,
22+
initScriptSvc: initScriptSvc,
2323
}
2424
}
2525

@@ -96,10 +96,10 @@ func (h *OnboardingHandler) GetControlPlaneConfig(c *gin.Context) {
9696

9797
// Mask sensitive data
9898
response := gin.H{
99-
"host": config.Host,
100-
"sshPort": config.SSHPort,
101-
"sshUser": config.SSHUser,
102-
"authMethod": config.AuthMethod,
99+
"host": config.Host,
100+
"sshPort": config.SSHPort,
101+
"sshUser": config.SSHUser,
102+
"authMethod": config.AuthMethod,
103103
"hasPassword": config.Password != "",
104104
"hasPrivateKey": config.PrivateKey != "",
105105
}
@@ -274,4 +274,3 @@ func (h *OnboardingHandler) ReorderInitScripts(c *gin.Context) {
274274

275275
c.JSON(http.StatusOK, gin.H{"message": "Script groups reordered"})
276276
}
277-

api-server/internal/service/config_transfer_service.go

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -23,21 +23,21 @@ var AllSections = []string{SectionBilling, SectionAlerts, SectionResources, Sect
2323

2424
// ExportConfig represents the full export file structure
2525
type ExportConfig struct {
26-
Version string `json:"version"`
27-
ExportedAt time.Time `json:"exportedAt"`
28-
ExportedBy string `json:"exportedBy"`
26+
Version string `json:"version"`
27+
ExportedAt time.Time `json:"exportedAt"`
28+
ExportedBy string `json:"exportedBy"`
2929
Sections map[string]json.RawMessage `json:"sections"`
3030
}
3131

3232
// SectionPreview holds diff info for one config section
3333
type SectionPreview struct {
34-
Present bool `json:"present"`
35-
Valid bool `json:"valid"`
36-
HasSensitiveData bool `json:"hasSensitiveData"`
37-
Changes map[string]*FieldChange `json:"changes,omitempty"`
38-
Summary *ResourceSummary `json:"summary,omitempty"`
39-
Warnings []string `json:"warnings,omitempty"`
40-
Errors []string `json:"errors,omitempty"`
34+
Present bool `json:"present"`
35+
Valid bool `json:"valid"`
36+
HasSensitiveData bool `json:"hasSensitiveData"`
37+
Changes map[string]*FieldChange `json:"changes,omitempty"`
38+
Summary *ResourceSummary `json:"summary,omitempty"`
39+
Warnings []string `json:"warnings,omitempty"`
40+
Errors []string `json:"errors,omitempty"`
4141
}
4242

4343
// FieldChange represents a single field change

api-server/internal/service/onboarding_service.go

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -81,11 +81,11 @@ type OnboardingRequest struct {
8181

8282
// OnboardingService handles node onboarding operations
8383
type OnboardingService struct {
84-
k8sClient *k8s.Client
85-
nodeSvc *NodeService
86-
initScriptSvc *InitScriptService
87-
runningJobs map[string]context.CancelFunc
88-
runningJobsMu sync.RWMutex
84+
k8sClient *k8s.Client
85+
nodeSvc *NodeService
86+
initScriptSvc *InitScriptService
87+
runningJobs map[string]context.CancelFunc
88+
runningJobsMu sync.RWMutex
8989
}
9090

9191
// NewOnboardingService creates a new OnboardingService

deploy/charts/bison/Chart.yaml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,8 @@ apiVersion: v2
22
name: bison
33
description: Bison - GPU 资源计费平台,基于 Capsule 多租户 + OpenCost 成本追踪
44
type: application
5-
version: 0.0.20
6-
appVersion: "0.0.20"
5+
version: 0.0.21
6+
appVersion: "0.0.21"
77
keywords:
88
- gpu
99
- billing

0 commit comments

Comments
 (0)