@vincent119/go-copilot-rules 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,533 @@
1
+ ---
2
+ name: go-ci-tooling
3
+ description: |
4
+ Go CI/CD 工具配置:Makefile、golangci-lint、GitHub Actions、Docker、測試覆蓋率、
5
+ 自動化流程、Pre-commit Hook。
6
+
7
+ **適用場景**:設計 CI/CD Pipeline、配置 golangci-lint、撰寫 Makefile、
8
+ Docker 多階段建置、測試自動化、程式碼品質檢查、GitHub Actions。
9
+
10
+ **關鍵字**:ci/cd, makefile, golangci-lint, github actions, docker, pre-commit,
11
+ test coverage, lint, build automation, continuous integration, pipeline
12
+ ---
13
+
14
+ # Go CI/CD 與工具配置規範
15
+
16
+ > **相關 Skills**:本規範建議搭配 `go-testing-advanced`(測試)與 `go-graceful-shutdown`(建置)
17
+
18
+ ---
19
+
20
+ ## Makefile
21
+
22
+ ### 基本結構
23
+
24
+ ```makefile
25
+ .PHONY: help
26
+ help: ## 顯示此說明
27
+ @grep -E '^[a-zA-Z_-]+:.*?## .*$$' $(MAKEFILE_LIST) | \
28
+ awk 'BEGIN {FS = ":.*?## "}; {printf "\033[36m%-20s\033[0m %s\n", $$1, $$2}'
29
+
30
+ # 變數
31
+ BINARY_NAME=myapp
32
+ VERSION?=dev
33
+ COMMIT=$(shell git rev-parse --short HEAD)
34
+ BUILD_TIME=$(shell date -u '+%Y-%m-%d_%H:%M:%S')
35
+
36
+ # Go 變數
37
+ GOBASE=$(shell pwd)
38
+ GOBIN=$(GOBASE)/bin
39
+ GOCMD=go
40
+ GOBUILD=$(GOCMD) build
41
+ GOTEST=$(GOCMD) test
42
+ GOMOD=$(GOCMD) mod
43
+
44
+ # Ldflags(注入版本資訊)
45
+ LDFLAGS=-ldflags "-X main.Version=$(VERSION) -X main.Commit=$(COMMIT) -X main.BuildTime=$(BUILD_TIME)"
46
+
47
+ .PHONY: build
48
+ build: ## 建置二進位檔
49
+ @echo "Building $(BINARY_NAME)..."
50
+ $(GOBUILD) $(LDFLAGS) -o $(GOBIN)/$(BINARY_NAME) ./cmd/server
51
+
52
+ .PHONY: test
53
+ test: ## 執行單元測試
54
+ $(GOTEST) -v -race -coverprofile=coverage.out ./...
55
+
56
+ .PHONY: test-coverage
57
+ test-coverage: test ## 測試覆蓋率報告
58
+ $(GOCMD) tool cover -html=coverage.out -o coverage.html
59
+ @echo "Coverage report: coverage.html"
60
+
61
+ .PHONY: lint
62
+ lint: ## 執行 Linter
63
+ @which golangci-lint > /dev/null || (echo "Installing golangci-lint..." && go install github.com/golangci/golangci-lint/cmd/golangci-lint@latest)
64
+ golangci-lint run --timeout=5m
65
+
66
+ .PHONY: fmt
67
+ fmt: ## 格式化程式碼
68
+ gofmt -s -w .
69
+ goimports -w .
70
+
71
+ .PHONY: tidy
72
+ tidy: ## 整理依賴
73
+ $(GOMOD) tidy
74
+ $(GOMOD) verify
75
+
76
+ .PHONY: clean
77
+ clean: ## 清理建置產物
78
+ @echo "Cleaning..."
79
+ @rm -rf $(GOBIN)
80
+ @rm -f coverage.out coverage.html
81
+
82
+ .PHONY: docker-build
83
+ docker-build: ## 建置 Docker Image
84
+ docker build -t $(BINARY_NAME):$(VERSION) .
85
+
86
+ .PHONY: run
87
+ run: build ## 執行應用程式
88
+ $(GOBIN)/$(BINARY_NAME)
89
+
90
+ .PHONY: install-tools
91
+ install-tools: ## 安裝開發工具
92
+ @echo "Installing development tools..."
93
+ go install github.com/golangci/golangci-lint/cmd/golangci-lint@latest
94
+ go install golang.org/x/tools/cmd/goimports@latest
95
+ go install go.uber.org/mock/mockgen@latest
96
+
97
+ .PHONY: generate
98
+ generate: ## 執行 go generate
99
+ go generate ./...
100
+
101
+ .PHONY: all
102
+ all: tidy fmt lint test build ## 執行所有檢查與建置
103
+ ```
104
+
105
+ ### 進階:依賴追蹤
106
+
107
+ ```makefile
108
+ # 只在原始碼變更時重新建置
109
+ $(GOBIN)/$(BINARY_NAME): $(shell find . -name '*.go')
110
+ @echo "Source changed, rebuilding..."
111
+ $(GOBUILD) $(LDFLAGS) -o $@ ./cmd/server
112
+
113
+ .PHONY: build
114
+ build: $(GOBIN)/$(BINARY_NAME)
115
+ ```
116
+
117
+ ---
118
+
119
+ ## golangci-lint 配置
120
+
121
+ ### .golangci.yml
122
+
123
+ ```yaml
124
+ run:
125
+ timeout: 5m
126
+ tests: true
127
+ skip-dirs:
128
+ - mocks
129
+ - vendor
130
+ skip-files:
131
+ - ".*\\.pb\\.go$"
132
+ - ".*_gen\\.go$"
133
+
134
+ linters:
135
+ enable:
136
+ - errcheck # 檢查未處理的錯誤
137
+ - gosimple # 簡化程式碼
138
+ - govet # Go vet
139
+ - ineffassign # 檢測無效的賦值
140
+ - staticcheck # 靜態分析
141
+ - typecheck # 型別檢查
142
+ - unused # 檢查未使用的變數
143
+ - gofmt # 格式檢查
144
+ - goimports # Import 排序
145
+ - misspell # 拼寫檢查
146
+ - gocritic # 程式碼評論
147
+ - godox # 檢查 TODO/FIXME
148
+ - revive # 取代 golint
149
+ - cyclop # 循環複雜度
150
+ - dupl # 重複程式碼檢測
151
+ - gosec # 安全性檢查
152
+ - gocognit # 認知複雜度
153
+ - nestif # 巢狀 if 檢查
154
+ - prealloc # Slice 預分配
155
+ - gci # Import 排序
156
+ - lll # 行長度檢查
157
+
158
+ linters-settings:
159
+ errcheck:
160
+ check-blank: true
161
+ check-type-assertions: true
162
+
163
+ govet:
164
+ check-shadowing: true
165
+
166
+ gocognit:
167
+ min-complexity: 15
168
+
169
+ cyclop:
170
+ max-complexity: 15
171
+
172
+ lll:
173
+ line-length: 120
174
+
175
+ revive:
176
+ rules:
177
+ - name: exported
178
+ severity: warning
179
+ - name: unexported-return
180
+ severity: warning
181
+ - name: indent-error-flow
182
+ severity: warning
183
+
184
+ gosec:
185
+ excludes:
186
+ - G104 # 允許部分未檢查的錯誤(需有註釋)
187
+ - G304 # 允許檔案路徑來自變數
188
+
189
+ issues:
190
+ exclude-rules:
191
+ # 測試檔案放寬限制
192
+ - path: _test\.go
193
+ linters:
194
+ - dupl
195
+ - gosec
196
+ - gocognit
197
+ - cyclop
198
+
199
+ # Mock 檔案不檢查
200
+ - path: mock/
201
+ linters:
202
+ - all
203
+
204
+ max-issues-per-linter: 50
205
+ max-same-issues: 3
206
+ ```
207
+
208
+ ---
209
+
210
+ ## GitHub Actions
211
+
212
+ ### .github/workflows/ci.yml
213
+
214
+ ```yaml
215
+ name: CI
216
+
217
+ on:
218
+ push:
219
+ branches: [ main, develop ]
220
+ pull_request:
221
+ branches: [ main, develop ]
222
+
223
+ jobs:
224
+ lint:
225
+ name: Lint
226
+ runs-on: ubuntu-latest
227
+ steps:
228
+ - name: Checkout
229
+ uses: actions/checkout@v3
230
+
231
+ - name: Setup Go
232
+ uses: actions/setup-go@v4
233
+ with:
234
+ go-version: '1.21'
235
+ cache: true
236
+
237
+ - name: golangci-lint
238
+ uses: golangci/golangci-lint-action@v3
239
+ with:
240
+ version: latest
241
+ args: --timeout=5m
242
+
243
+ test:
244
+ name: Test
245
+ runs-on: ubuntu-latest
246
+ services:
247
+ postgres:
248
+ image: postgres:15
249
+ env:
250
+ POSTGRES_PASSWORD: postgres
251
+ POSTGRES_DB: testdb
252
+ options: >-
253
+ --health-cmd pg_isready
254
+ --health-interval 10s
255
+ --health-timeout 5s
256
+ --health-retries 5
257
+ ports:
258
+ - 5432:5432
259
+
260
+ redis:
261
+ image: redis:7
262
+ options: >-
263
+ --health-cmd "redis-cli ping"
264
+ --health-interval 10s
265
+ --health-timeout 5s
266
+ --health-retries 5
267
+ ports:
268
+ - 6379:6379
269
+
270
+ steps:
271
+ - name: Checkout
272
+ uses: actions/checkout@v3
273
+
274
+ - name: Setup Go
275
+ uses: actions/setup-go@v4
276
+ with:
277
+ go-version: '1.21'
278
+ cache: true
279
+
280
+ - name: Run tests
281
+ run: |
282
+ go test -v -race -coverprofile=coverage.out -covermode=atomic ./...
283
+ env:
284
+ DATABASE_URL: postgres://postgres:postgres@localhost:5432/testdb?sslmode=disable
285
+ REDIS_URL: redis://localhost:6379
286
+
287
+ - name: Upload coverage
288
+ uses: codecov/codecov-action@v3
289
+ with:
290
+ files: ./coverage.out
291
+ flags: unittests
292
+ fail_ci_if_error: true
293
+
294
+ build:
295
+ name: Build
296
+ runs-on: ubuntu-latest
297
+ needs: [lint, test]
298
+ steps:
299
+ - name: Checkout
300
+ uses: actions/checkout@v3
301
+
302
+ - name: Setup Go
303
+ uses: actions/setup-go@v4
304
+ with:
305
+ go-version: '1.21'
306
+ cache: true
307
+
308
+ - name: Build
309
+ run: make build
310
+
311
+ - name: Upload artifact
312
+ uses: actions/upload-artifact@v3
313
+ with:
314
+ name: binary
315
+ path: bin/myapp
316
+ ```
317
+
318
+ ### .github/workflows/release.yml
319
+
320
+ ```yaml
321
+ name: Release
322
+
323
+ on:
324
+ push:
325
+ tags:
326
+ - 'v*'
327
+
328
+ jobs:
329
+ release:
330
+ name: Release
331
+ runs-on: ubuntu-latest
332
+ steps:
333
+ - name: Checkout
334
+ uses: actions/checkout@v3
335
+ with:
336
+ fetch-depth: 0
337
+
338
+ - name: Setup Go
339
+ uses: actions/setup-go@v4
340
+ with:
341
+ go-version: '1.21'
342
+
343
+ - name: Run GoReleaser
344
+ uses: goreleaser/goreleaser-action@v4
345
+ with:
346
+ version: latest
347
+ args: release --clean
348
+ env:
349
+ GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
350
+ ```
351
+
352
+ ---
353
+
354
+ ## Docker
355
+
356
+ ### Dockerfile(多階段建置)
357
+
358
+ ```dockerfile
359
+ # Stage 1: Builder
360
+ FROM golang:1.21-alpine AS builder
361
+
362
+ # 安裝必要工具
363
+ RUN apk add --no-cache git make
364
+
365
+ WORKDIR /app
366
+
367
+ # 複製 go.mod 和 go.sum(利用快取)
368
+ COPY go.mod go.sum ./
369
+ RUN go mod download
370
+
371
+ # 複製原始碼
372
+ COPY . .
373
+
374
+ # 建置
375
+ RUN CGO_ENABLED=0 GOOS=linux GOARCH=amd64 \
376
+ go build -ldflags="-s -w" -o bin/myapp ./cmd/server
377
+
378
+ # Stage 2: Runtime
379
+ FROM alpine:latest
380
+
381
+ # 安裝 CA 憑證與時區資料
382
+ RUN apk --no-cache add ca-certificates tzdata
383
+
384
+ WORKDIR /app
385
+
386
+ # 複製二進位檔
387
+ COPY --from=builder /app/bin/myapp .
388
+
389
+ # 複製設定檔(可選)
390
+ COPY ./configs ./configs
391
+
392
+ # 建立非 root 使用者
393
+ RUN addgroup -g 1000 appuser && \
394
+ adduser -D -u 1000 -G appuser appuser && \
395
+ chown -R appuser:appuser /app
396
+
397
+ USER appuser
398
+
399
+ EXPOSE 8080
400
+
401
+ ENTRYPOINT ["./myapp"]
402
+ ```
403
+
404
+ ### .dockerignore
405
+
406
+ ```
407
+ # Git
408
+ .git
409
+ .gitignore
410
+
411
+ # IDE
412
+ .vscode
413
+ .idea
414
+ *.swp
415
+
416
+ # Build artifacts
417
+ bin/
418
+ coverage.out
419
+ coverage.html
420
+
421
+ # Docs
422
+ docs/
423
+ *.md
424
+
425
+ # Tests
426
+ *_test.go
427
+
428
+ # Temp files
429
+ tmp/
430
+ *.log
431
+ ```
432
+
433
+ ---
434
+
435
+ ## Pre-commit Hook
436
+
437
+ ### .pre-commit-config.yaml
438
+
439
+ ```yaml
440
+ repos:
441
+ - repo: https://github.com/golangci/golangci-lint
442
+ rev: v1.54.2
443
+ hooks:
444
+ - id: golangci-lint
445
+ args: ['--timeout=5m']
446
+
447
+ - repo: https://github.com/pre-commit/pre-commit-hooks
448
+ rev: v4.4.0
449
+ hooks:
450
+ - id: trailing-whitespace
451
+ - id: end-of-file-fixer
452
+ - id: check-yaml
453
+ - id: check-added-large-files
454
+ ```
455
+
456
+ ### 安裝
457
+
458
+ ```bash
459
+ # 安裝 pre-commit
460
+ pip install pre-commit
461
+
462
+ # 安裝 Hooks
463
+ pre-commit install
464
+
465
+ # 手動執行(所有檔案)
466
+ pre-commit run --all-files
467
+ ```
468
+
469
+ ---
470
+
471
+ ## 測試覆蓋率
472
+
473
+ ### Coverage Badge(README)
474
+
475
+ ```markdown
476
+ [![codecov](https://codecov.io/gh/username/repo/branch/main/graph/badge.svg)](https://codecov.io/gh/username/repo)
477
+ ```
478
+
479
+ ### 本地生成報告
480
+
481
+ ```bash
482
+ # HTML 報告
483
+ make test-coverage
484
+ open coverage.html
485
+
486
+ # 終端顯示
487
+ go test -coverprofile=coverage.out ./...
488
+ go tool cover -func=coverage.out
489
+
490
+ # 按套件統計
491
+ go test -coverprofile=coverage.out ./...
492
+ go tool cover -func=coverage.out | grep -E '^total:'
493
+ ```
494
+
495
+ ---
496
+
497
+ ## 檢查清單
498
+
499
+ **Makefile**
500
+ - [ ] 包含 `help` 目標(自動生成說明)
501
+ - [ ] 定義常用任務(build、test、lint、clean)
502
+ - [ ] 注入版本資訊到二進位檔(Ldflags)
503
+ - [ ] 支援依賴追蹤(原始碼變更時重建)
504
+
505
+ **golangci-lint**
506
+ - [ ] 配置 `.golangci.yml`
507
+ - [ ] 啟用關鍵 Linter(errcheck、gosimple、staticcheck、gosec)
508
+ - [ ] 設定合理的超時時間(5 分鐘)
509
+ - [ ] 排除生成的程式碼(*.pb.go、mock/)
510
+
511
+ **GitHub Actions**
512
+ - [ ] CI Pipeline 包含 lint、test、build
513
+ - [ ] 整合測試使用 Service Containers(Postgres、Redis)
514
+ - [ ] 上傳測試覆蓋率到 Codecov
515
+ - [ ] Release 自動化(GoReleaser)
516
+
517
+ **Docker**
518
+ - [ ] 使用多階段建置(減少映像大小)
519
+ - [ ] 設定非 root 使用者
520
+ - [ ] 利用建置快取(分離 go mod download)
521
+ - [ ] 配置 `.dockerignore`
522
+
523
+ **Pre-commit**
524
+ - [ ] 安裝 `.pre-commit-config.yaml`
525
+ - [ ] 執行 golangci-lint
526
+ - [ ] 檢查檔案格式(trailing whitespace、EOF)
527
+ - [ ] 防止提交大檔案
528
+
529
+ **測試覆蓋率**
530
+ - [ ] 目標覆蓋率 ≥ 80%
531
+ - [ ] CI 自動檢查覆蓋率
532
+ - [ ] 重要邏輯 100% 覆蓋
533
+ - [ ] 生成 HTML 報告供查看