GitLab 使用教學手冊

📋 目錄

  1. GitLab 基本介紹

  2. 專案工作流程說明

  3. 專案開發規範

  4. GitLab CI/CD 基本介紹

  5. 常見問題與解決方式

  6. 開發最佳實務建議

  7. 檢查清單

  8. 進階功能與整合

  9. 附錄

  10. 補充主題


1. GitLab 基本介紹

1.1 Git vs. GitLab - 基本概念

Git

  • 定義:分散式版本控制系統(Distributed Version Control System)
  • 功能:追蹤檔案變更、分支管理、合併操作
  • 特性:本地操作、離線工作、完整歷史記錄

GitLab

  • 定義:基於 Git 的 Web 平台,提供完整的 DevOps 生命週期管理
  • 功能:程式碼託管、專案管理、CI/CD、Code Review、Issue 追蹤
  • 優勢:團隊協作、視覺化介面、自動化部署

Git 與 GitLab 的關係圖

graph TB A[Git - 版本控制系統] --> B[GitLab - Web 平台] B --> C[程式碼託管] B --> D[專案管理] B --> E[CI/CD] B --> F[Code Review] C --> G[Repository] D --> H[Issues] D --> I[Milestones] E --> J[Pipelines] E --> K[Runners] F --> L[Merge Requests]

1.2 為什麼選擇 GitLab?

🎯 團隊協作優勢

  • 統一平台:從程式碼管理到部署,一站式解決方案
  • 權限管控:細緻的角色權限設定,確保專案安全
  • 可視化:直觀的 Web 介面,降低學習門檻

🚀 開發效率提升

  • Merge Request:標準化的程式碼審查流程
  • CI/CD 整合:自動化測試與部署
  • Issue 追蹤:需求管理與 Bug 追蹤

🔒 企業級安全

  • 存取控制:多層次的安全防護
  • 稽核記錄:完整的操作歷史追蹤
  • 備份機制:資料安全保障

1.3 專案架構概覽

GitLab 專案結構
├── 程式碼倉庫 (Repository)
├── 分支管理 (Branches)
├── 合併請求 (Merge Requests)
├── 議題追蹤 (Issues)
├── CI/CD 管道 (Pipelines)
├── Wiki 文件
└── 專案設定 (Settings)

💡 實務建議

  • 新進同仁建議先熟悉 GitLab Web 介面操作
  • 了解專案的分支策略和命名規範
  • 參與 Code Review 過程,學習團隊的程式碼品質標準

1.4 GitLab 核心功能詳解

📋 Issue 管理

功能說明:Issue 是 GitLab 的任務追蹤系統,用於管理 Bug、功能需求、改善建議等

主要特性

  • 分類管理:使用 Label 標籤分類 Issue 類型
  • 指派責任:指派給特定開發者處理
  • 狀態追蹤:Open、In Progress、Closed 等狀態
  • 關聯功能:可與 Merge Request、Commit 關聯

使用範例

# Issue 範例:修復登入功能錯誤

### 問題描述
使用者在登入時偶爾會遇到 500 錯誤

### 重現步驟
1. 開啟登入頁面
2. 輸入正確的帳號密碼
3. 點選登入按鈕
4. 有時會顯示 500 錯誤

### 預期行為
應該能正常登入系統

### 實際行為
偶爾出現 500 錯誤

### 環境資訊
- 瀏覽器:Chrome 120.0
- 作業系統:Windows 10
- 服務器:Production

🏷️ Labels 標籤系統

標籤類型

  • 類型標籤bugfeatureenhancementdocumentation
  • 優先級priority::highpriority::mediumpriority::low
  • 狀態標籤status::todostatus::in-progressstatus::review
  • 模組標籤frontendbackenddatabaseapi

標籤使用策略

標籤組合範例:
├── bug + priority::high + backend
├── feature + priority::medium + frontend
├── enhancement + priority::low + documentation
└── security + priority::critical + api

🎯 Milestone 里程碑

功能說明:Milestone 用於組織和追蹤專案進度,通常對應版本發布

使用方式

  • 版本規劃:v1.0.0、v1.1.0、v2.0.0
  • 衝刺管理:Sprint 1、Sprint 2、Sprint 3
  • 功能分組:使用者管理模組、付款系統、報表功能

里程碑設定

Milestone: v1.2.0
├── 開始日期:2024-02-01
├── 結束日期:2024-03-15
├── 描述:使用者體驗改善版本
├── 相關 Issues:15 個
└── 完成度:60%

📊 Project 專案管理

專案看板

Kanban Board:
┌──────────────┐  ┌──────────────┐  ┌──────────────┐  ┌──────────────┐
│   待辦事項     │  │   進行中      │  │   審查中      │  │   已完成      │
│              │  │              │  │              │  │              │
│ • Issue #123 │→ │ • Issue #124 │→ │ • MR !456    │→ │ • Issue #122 │
│ • Issue #125 │  │ • Issue #126 │  │ • MR !457    │  │ • Issue #121 │
│ • Issue #127 │  │              │  │              │  │ • Issue #120 │
└──────────────┘  └──────────────┘  └──────────────┘  └──────────────┘

專案權限管理

角色權限說明
Owner完整權限專案擁有者,可管理所有設定
Maintainer管理權限可管理分支、標籤、專案設定
Developer開發權限可推送程式碼、建立 MR
Reporter檢視權限可檢視程式碼、建立 Issue
Guest受限權限僅可檢視公開內容

👥 Group 群組管理

群組階層

組織架構:
Company Group
├── Frontend Team
│   ├── React Project
│   └── Vue Project
├── Backend Team
│   ├── API Gateway
│   └── Microservices
└── DevOps Team
    ├── CI/CD Tools
    └── Infrastructure

群組優勢

  • 權限繼承:子專案自動繼承群組權限
  • 統一設定:CI/CD 變數、Runner 設定等
  • 資源共享:共用 Docker Registry、Package Registry

📦 Package Registry

支援類型

  • Maven Repository:Java 套件管理
  • npm Registry:Node.js 套件管理
  • Docker Registry:容器映像檔管理
  • NuGet Gallery:.NET 套件管理

Maven 使用範例

<!-- pom.xml 設定 -->
<repositories>
    <repository>
        <id>gitlab-maven</id>
        <url>https://gitlab.company.com/api/v4/projects/123/packages/maven</url>
    </repository>
</repositories>

<distributionManagement>
    <repository>
        <id>gitlab-maven</id>
        <url>https://gitlab.company.com/api/v4/projects/123/packages/maven</url>
    </repository>
</distributionManagement>

🔒 Security 安全功能

安全掃描類型

  • SAST (Static Application Security Testing):靜態程式碼安全分析
  • DAST (Dynamic Application Security Testing):動態應用程式安全測試
  • Dependency Scanning:相依性漏洞掃描
  • Container Scanning:容器映像檔安全掃描
  • Secret Detection:敏感資料洩漏檢測

安全設定範例

# .gitlab-ci.yml 安全掃描設定
include:
  - template: Security/SAST.gitlab-ci.yml
  - template: Security/Dependency-Scanning.gitlab-ci.yml
  - template: Security/Secret-Detection.gitlab-ci.yml

variables:
  SAST_JAVA_VERSION: "17"
  SECURE_LOG_LEVEL: "debug"

sast:
  stage: test
  variables:
    SAST_EXCLUDED_PATHS: "spec, test, tests, tmp"

📝 Wiki 文件系統

Wiki 功能

  • Markdown 支援:完整的 Markdown 語法支援
  • 版本控制:Wiki 頁面也有版本歷史
  • 協作編輯:多人可同時編輯不同頁面
  • 檔案上傳:支援圖片和附件

Wiki 結構範例

Wiki 頁面結構:
├── Home (首頁)
├── 架構設計
│   ├── 系統架構圖
│   ├── 資料庫設計
│   └── API 設計
├── 部署指南
│   ├── 環境設定
│   ├── 部署流程
│   └── 監控配置
└── 開發規範
    ├── 編碼標準
    ├── Git 工作流程
    └── Code Review 指南

🔧 GitLab Runner

Runner 類型

  • Shared Runners:GitLab.com 提供的共用執行器
  • Group Runners:群組層級的專用執行器
  • Project Runners:專案專用的執行器

Runner 標籤

# .gitlab-ci.yml 指定 Runner
build-job:
  stage: build
  tags:
    - docker
    - linux
    - java-17
  script:
    - mvn clean compile

Runner 設定

# 註冊 Runner
sudo gitlab-runner register \
  --url https://gitlab.company.com/ \
  --registration-token PROJECT_TOKEN \
  --description "Java Build Runner" \
  --tag-list "java,maven,docker" \
  --executor docker \
  --docker-image maven:3.8.4-openjdk-17

📊 Analytics 分析功能

可用報表

  • Repository Analytics:程式碼提交統計
  • CI/CD Analytics:Pipeline 執行統計
  • Issue Analytics:Issue 處理統計
  • Merge Request Analytics:MR 審查統計

效能指標

DevOps 指標:
├── Lead Time:從需求到部署的時間
├── Deployment Frequency:部署頻率
├── Mean Time to Recovery:故障恢復時間
└── Change Failure Rate:變更失敗率

🔗 Snippets 程式碼片段

功能說明:Snippets 用於分享程式碼片段、設定檔或小型腳本

使用情境

  • 程式碼範例:分享常用的程式碼模板
  • 設定檔:分享設定檔範例
  • 工具腳本:分享自動化腳本
  • 技術筆記:記錄技術要點

Snippet 範例

// 常用的 Spring Boot 控制器模板
@RestController
@RequestMapping("/api/v1")
@Slf4j
public class BaseController {
    
    @GetMapping("/health")
    public ResponseEntity<Map<String, String>> health() {
        Map<String, String> status = Map.of(
            "status", "UP",
            "timestamp", Instant.now().toString()
        );
        return ResponseEntity.ok(status);
    }
}

📋 Boards 專案看板

看板類型

  • Issue Board:Issue 管理看板
  • Epic Board:Epic 管理看板(Enterprise 版本)
  • Milestone Board:里程碑看板

看板自訂

  • 欄位設定:可自訂看板欄位
  • 篩選器:依標籤、指派者、里程碑篩選
  • 自動化:設定自動移動規則

💡 GitLab 功能使用建議

  • Issue 優先:養成先建立 Issue 再開發的習慣
  • 標籤統一:團隊統一 Label 使用規範
  • 里程碑規劃:定期設定和檢視里程碑進度
  • 安全掃描:啟用所有適用的安全掃描功能
  • 文件維護:保持 Wiki 文件的即時更新
  • 分析報表:定期檢視分析報表優化開發流程

2. 專案工作流程說明

2.1 環境準備

安裝必要工具

# 安裝 Git (Windows)
# 下載並安裝:https://git-scm.com/download/win

# 驗證安裝
git --version

設定 Git 基本資訊

# 設定使用者資訊
git config --global user.name "您的姓名"
git config --global user.email "您的信箱@company.com"

# 設定預設編輯器
git config --global core.editor "code --wait"

# 設定換行符號處理(Windows)
git config --global core.autocrlf true

2.2 Clone - 複製專案到本地

Clone 流程圖

flowchart TD A[開始] --> B[進入 GitLab 專案頁面] B --> C[點選 Clone 按鈕] C --> D{選擇連線方式} D -->|HTTPS| E[複製 HTTPS URL] D -->|SSH| F[複製 SSH URL] E --> G[開啟終端機] F --> G G --> H[執行 git clone 指令] H --> I[等待下載完成] I --> J[進入專案目錄] J --> K[檢查分支狀態] K --> L[完成]

🎯 操作步驟

  1. 取得專案 URL

    • 進入 GitLab 專案頁面
    • 點選 “Clone” 按鈕
    • 複製 HTTPS 或 SSH URL
  2. 執行 Clone 指令

# HTTPS 方式(建議新手使用)
git clone https://gitlab.company.com/project-group/project-name.git

# SSH 方式(需先設定 SSH Key)
git clone git@gitlab.company.com:project-group/project-name.git

# Clone 到指定資料夾
git clone https://gitlab.company.com/project-group/project-name.git my-project
  1. 進入專案目錄
cd project-name
ls -la  # 查看專案檔案

⚠️ 注意事項

  • 首次 Clone 會下載完整的專案歷史
  • 確保網路連線穩定,大型專案可能需要較長時間
  • Clone 後檢查分支狀態:git branch -a

2.3 Pull - 同步遠端更新

🎯 日常同步作業

# 檢查目前狀態
git status

# 拉取最新變更(建議每天開始工作前執行)
git pull origin main

# 拉取特定分支
git pull origin feature/new-feature

# 強制拉取(謹慎使用)
git pull --force origin main

🔄 分支同步策略

# 切換到主分支並同步
git checkout main
git pull origin main

# 切換回開發分支並合併主分支更新
git checkout feature/my-feature
git merge main

💡 最佳實務

  • 每日同步:每天開始工作前先執行 git pull
  • 提交前同步:Push 前確保本地是最新狀態
  • 解決衝突:遇到衝突時,請尋求資深同事協助

2.4 Commit - 提交變更

🎯 提交流程

  1. 檢查變更狀態
# 查看檔案狀態
git status

# 查看具體變更內容
git diff
git diff --staged  # 查看已加入暫存區的變更
  1. 加入暫存區
# 加入特定檔案
git add src/main/java/com/example/Service.java

# 加入所有變更檔案
git add .

# 加入特定類型檔案
git add "*.java"
  1. 執行提交
# 提交變更
git commit -m "feat: 新增使用者註冊功能"

# 提交並開啟編輯器寫詳細說明
git commit

📝 Commit Message 規範(請參考第3節)

⚠️ 提交前檢查

  • 確保程式碼可以編譯
  • 執行相關測試
  • 檢查是否包含敏感資訊(密碼、金鑰等)

2.5 Push - 推送變更到遠端

🎯 推送流程

# 推送到對應的遠端分支
git push origin feature/my-feature

# 首次推送新分支
git push -u origin feature/my-feature

# 推送到主分支(需要權限)
git push origin main

🔒 推送前檢查

# 確認推送目標
git remote -v
git branch -vv

# 檢查即將推送的提交
git log --oneline origin/feature/my-feature..HEAD

2.6 Merge Request - 合併請求

🎯 建立 Merge Request

  1. 在 GitLab Web 介面

    • 推送分支後,GitLab 會顯示建立 MR 的提示
    • 點選 “Create merge request”
  2. 填寫 MR 資訊

    • 標題:簡潔描述變更內容
    • 描述:詳細說明變更原因、實作方式、測試結果
    • 指派審查者:選擇適當的 Code Reviewer
    • 標籤:加入相關標籤(feature、bugfix、hotfix等)
  3. MR 模板範例

### 變更摘要
簡要描述此次變更的內容和目的

### 變更類型
- [ ] 新功能
- [ ] Bug 修復
- [ ] 文件更新
- [ ] 重構
- [ ] 效能改善

### 測試說明
- [ ] 單元測試已通過
- [ ] 整合測試已通過
- [ ] 手動測試已完成

### 相關 Issue
關聯的 Issue 編號:#123

### 檢查清單
- [ ] 程式碼遵循專案規範
- [ ] 已進行自我 Code Review
- [ ] 已更新相關文件
- [ ] 沒有包含敏感資訊

3. 專案開發規範

3.1 分支策略

🌳 Git Flow 分支模型

我們採用改良版的 Git Flow 策略:

main (主分支)
├── develop (開發分支)
│   ├── feature/user-authentication (功能分支)
│   ├── feature/payment-system (功能分支)
│   └── feature/admin-dashboard (功能分支)
├── release/v1.2.0 (發布分支)
├── hotfix/critical-security-fix (緊急修復分支)
└── support/v1.1.x (維護分支)

Git Flow 視覺化流程圖

gitGraph commit id: "Initial" branch develop checkout develop commit id: "Setup" branch feature/login checkout feature/login commit id: "Add login UI" commit id: "Add auth logic" checkout develop merge feature/login commit id: "Integrate login" branch feature/dashboard checkout feature/dashboard commit id: "Create dashboard" checkout develop branch release/v1.0 checkout release/v1.0 commit id: "Prepare v1.0" checkout main merge release/v1.0 tag: "v1.0" checkout develop merge release/v1.0 merge feature/dashboard checkout main branch hotfix/security commit id: "Fix security" checkout main merge hotfix/security tag: "v1.0.1" checkout develop merge hotfix/security

🎯 分支說明

分支類型命名規則用途生命週期
mainmain正式環境部署永久
developdevelop開發整合永久
featurefeature/功能名稱新功能開發臨時
releaserelease/版本號發布準備臨時
hotfixhotfix/修復描述緊急修復臨時
supportsupport/版本號長期維護長期

� 分支命名規範

# 功能分支
feature/user-login-page
feature/shopping-cart-api
feature/email-notification

# 修復分支
hotfix/login-security-vulnerability
hotfix/payment-gateway-timeout

# 發布分支
release/v2.1.0
release/v2.1.1-hotfix

🔄 分支操作流程

  1. 建立功能分支
# 從 develop 建立新功能分支
git checkout develop
git pull origin develop
git checkout -b feature/user-profile-update
  1. 完成功能開發
# 提交變更
git add .
git commit -m "feat: 新增使用者資料更新功能"
git push -u origin feature/user-profile-update
  1. 建立 Merge Request
# 在 GitLab 建立 MR: feature/user-profile-update → develop

3.2 Commit Message 規範

📋 Conventional Commits 格式

<類型>[可選範圍]: <描述>

[可選正文]

[可選頁腳]

🏷️ 提交類型

類型說明範例
feat新功能feat: 新增使用者註冊功能
fixBug 修復fix: 修復登入驗證錯誤
docs文件更新docs: 更新 API 文件
style格式調整style: 調整程式碼縮排
refactor重構refactor: 重構使用者服務類別
test測試相關test: 新增使用者服務單元測試
chore建置/工具chore: 更新 Maven 相依性
perf效能改善perf: 優化資料庫查詢效能
ciCI/CDci: 更新 GitLab CI 設定
revert回復提交revert: 回復提交 abc123

📝 Commit 範例

# 基本格式
git commit -m "feat: 新增使用者登入功能"

# 包含範圍
git commit -m "feat(auth): 新增 JWT 驗證機制"

# 重大變更
git commit -m "feat!: 重新設計 API 回應格式

BREAKING CHANGE: API 回應格式從 { data: {} } 改為 { result: {} }"

# 關聯 Issue
git commit -m "fix: 修復購物車數量計算錯誤

修復在商品數量為零時的計算問題

Fixes #123"

⚠️ Commit 注意事項

  • 原子性:每個 commit 只包含一個邏輯變更
  • 明確描述:清楚說明「做了什麼」而非「怎麼做」
  • 使用現在式:「新增功能」而非「新增了功能」
  • 英文優先:英文 commit message 便於國際協作

3.3 Merge Request 流程

Merge Request 完整流程圖

flowchart TD A[開始開發] --> B[建立功能分支] B --> C[撰寫程式碼] C --> D[本地測試] D --> E{測試通過?} E -->|否| C E -->|是| F[Commit 變更] F --> G[Push 到遠端] G --> H[建立 Merge Request] H --> I[填寫 MR 資訊] I --> J[指派審查者] J --> K[等待 Code Review] K --> L{需要修改?} L -->|是| M[根據建議修改] M --> F L -->|否| N[CI/CD 執行] N --> O{Pipeline 成功?} O -->|否| P[修復問題] P --> F O -->|是| Q[審查者批准] Q --> R[合併到目標分支] R --> S[刪除功能分支] S --> T[完成]

🎯 MR 建立流程

  1. 準備階段
# 確保分支是最新的
git checkout feature/my-feature
git fetch origin
git rebase origin/develop
  1. 建立 MR

    • 進入 GitLab 專案頁面
    • 點選 “Merge Requests” → “New merge request”
    • 選擇來源分支和目標分支
    • 填寫 MR 資訊
  2. MR 標題規範

[類型] 簡短描述

範例:
[Feature] 新增使用者個人資料管理功能
[Bugfix] 修復購物車結算金額計算錯誤
[Hotfix] 緊急修復登入安全性漏洞
[Docs] 更新 API 使用說明文件

📋 MR 描述模板

### 📋 變更摘要
簡要描述此次變更的內容和目的

### 🏷️ 變更類型
- [ ] ✨ 新功能 (Feature)
- [ ] 🐛 Bug 修復 (Bugfix)  
- [ ] 🔥 緊急修復 (Hotfix)
- [ ] 📚 文件更新 (Documentation)
- [ ] 🎨 程式碼重構 (Refactoring)
- [ ] ⚡ 效能改善 (Performance)
- [ ] 🧪 測試相關 (Testing)

### 🧪 測試說明
- [ ] 單元測試已通過:`mvn test`
- [ ] 整合測試已通過:`mvn verify`
- [ ] 手動測試已完成
- [ ] 效能測試已完成(如適用)

### 📸 測試截圖
(如有 UI 變更,請提供截圖)

### 🔗 相關連結
- 相關 Issue:#123
- 設計文件:[連結]
- API 文件:[連結]

### ✅ 檢查清單
- [ ] 程式碼遵循專案編碼規範
- [ ] 已進行自我 Code Review
- [ ] 已更新相關文件
- [ ] 沒有包含敏感資訊(密碼、API Key 等)
- [ ] 已更新 CHANGELOG.md(如適用)
- [ ] 已考慮向後相容性
- [ ] 已檢查效能影響

### 📝 額外說明
(任何需要審查者特別注意的事項)

3.4 Code Review 要求

👥 審查者指派

  • 強制審查者:至少 1 位資深開發者
  • 建議審查者:相關模組負責人
  • 安全審查:涉及安全性變更需指派安全專家

🔍 Code Review 檢查重點

功能性檢查

  • 程式碼邏輯正確
  • 符合需求規格
  • 邊界條件處理
  • 錯誤處理完整

品質檢查

  • 程式碼可讀性
  • 命名規範一致
  • 適當的註解
  • 函式複雜度合理

安全性檢查

  • 輸入驗證
  • 權限控制
  • 敏感資料處理
  • SQL 注入防護

效能檢查

  • 演算法效率
  • 資料庫查詢優化
  • 記憶體使用
  • 快取策略

🔄 Review 流程

  1. 提交 Review

    • 仔細檢查程式碼變更
    • 提供建設性意見
    • 標示 Request ChangesApprove
  2. 回應 Review

    • 及時回應審查意見
    • 修正問題後重新提交
    • 解釋設計決策(如需要)
  3. 最終審查

    • 確認所有意見已處理
    • 執行最終測試
    • 核准合併

💡 Review 最佳實務

  • 及時審查:在 24 小時內完成審查
  • 建設性意見:提供具體的改善建議
  • 學習態度:將 Review 視為學習機會

4. GitLab CI/CD 基本介紹

4.1 CI/CD 概念說明

🔄 持續整合 (Continuous Integration)

定義:開發者頻繁地將程式碼變更合併到主分支,每次合併都會觸發自動化建置和測試

優點

  • 早期發現問題:快速識別程式碼衝突和錯誤
  • 提高程式碼品質:自動化測試確保品質標準
  • 減少整合風險:避免大量變更造成的整合困難

🚀 持續部署 (Continuous Deployment)

定義:通過自動化測試的程式碼變更會自動部署到生產環境

優點

  • 快速交付:縮短從開發到上線的時間
  • 降低風險:小批次部署減少失敗影響
  • 提高效率:自動化減少人工作業

4.2 GitLab CI/CD 架構

🏗️ 核心組件

GitLab CI/CD Pipeline
├── .gitlab-ci.yml (設定檔)
├── GitLab Runner (執行器)
├── Jobs (工作)
├── Stages (階段)
└── Artifacts (產出物)

📋 Pipeline 階段設計

Pipeline Stages:
┌─────────────┐  ┌─────────────┐  ┌─────────────┐  ┌─────────────┐
│   Build     │→ │    Test     │→ │   Deploy    │→ │   Monitor   │
│             │  │             │  │             │  │             │
│ • 編譯程式碼  │  │ • 單元測試   │  │ • 部署到測試  │  │ • 健康檢查   │
│ • 相依性檢查  │  │ • 整合測試   │  │ • 部署到正式  │  │ • 效能監控   │
│ • 程式碼掃描  │  │ • 安全掃描   │  │ • 資料庫更新  │  │ • 錯誤追蹤   │
└─────────────┘  └─────────────┘  └─────────────┘  └─────────────┘

CI/CD Pipeline 視覺化流程

graph LR A[Git Push] --> B[觸發 Pipeline] B --> C[Build Stage] C --> D[編譯程式碼] D --> E[建立 Artifacts] E --> F[Test Stage] F --> G[單元測試] G --> H[整合測試] H --> I[安全掃描] I --> J{測試通過?} J -->|否| K[通知開發者] J -->|是| L[Deploy Stage] L --> M{部署環境} M -->|Dev| N[開發環境] M -->|Staging| O[測試環境] M -->|Production| P[正式環境] N --> Q[Monitor Stage] O --> Q P --> Q Q --> R[健康檢查] R --> S[效能監控] S --> T[完成] K --> U[修復問題] U --> A

4.3 .gitlab-ci.yml 設定檔

🎯 基本結構

# .gitlab-ci.yml
# GitLab CI/CD 設定檔範例

# 定義執行階段
stages:
  - build
  - test
  - deploy

# 全域變數
variables:
  MAVEN_OPTS: "-Dmaven.repo.local=$CI_PROJECT_DIR/.m2/repository"
  MAVEN_CLI_OPTS: "--batch-mode --errors --fail-at-end --show-version"

# 快取設定
cache:
  paths:
    - .m2/repository/
    - target/

# 建置階段
build-job:
  stage: build
  image: maven:3.8.4-openjdk-17
  script:
    - echo "開始建置專案..."
    - mvn $MAVEN_CLI_OPTS compile
    - echo "建置完成!"
  artifacts:
    paths:
      - target/
    expire_in: 1 hour

# 測試階段
test-job:
  stage: test
  image: maven:3.8.4-openjdk-17
  script:
    - echo "執行單元測試..."
    - mvn $MAVEN_CLI_OPTS test
    - echo "測試完成!"
  artifacts:
    reports:
      junit:
        - target/surefire-reports/TEST-*.xml
    expire_in: 1 week
  coverage: '/Total.*?([0-9]{1,3})%/'

# 程式碼品質檢查
code-quality:
  stage: test
  image: maven:3.8.4-openjdk-17
  script:
    - echo "執行程式碼品質檢查..."
    - mvn $MAVEN_CLI_OPTS checkstyle:check
    - mvn $MAVEN_CLI_OPTS spotbugs:check
  allow_failure: true

# 部署到測試環境
deploy-staging:
  stage: deploy
  script:
    - echo "部署到測試環境..."
    - mvn $MAVEN_CLI_OPTS package -DskipTests
    - scp target/*.jar user@staging-server:/opt/app/
    - ssh user@staging-server "sudo systemctl restart app"
  environment:
    name: staging
    url: https://staging.example.com
  only:
    - develop

# 部署到正式環境
deploy-production:
  stage: deploy
  script:
    - echo "部署到正式環境..."
    - mvn $MAVEN_CLI_OPTS package -DskipTests
    - scp target/*.jar user@prod-server:/opt/app/
    - ssh user@prod-server "sudo systemctl restart app"
  environment:
    name: production
    url: https://app.example.com
  only:
    - main
  when: manual  # 需要手動觸發

4.4 Java 專案 CI/CD 設定

☕ Maven 專案設定

# Java Maven 專案完整範例
image: maven:3.8.4-openjdk-17

variables:
  MAVEN_OPTS: >
    -Dmaven.repo.local=$CI_PROJECT_DIR/.m2/repository
    -Dorg.slf4j.simpleLogger.log.org.apache.maven.cli.transfer.Slf4jMavenTransferListener=WARN
    -Dorg.slf4j.simpleLogger.showDateTime=true
    -Djava.awt.headless=true
  MAVEN_CLI_OPTS: >
    --batch-mode
    --errors
    --fail-at-end
    --show-version
    -DinstallAtEnd=true
    -DdeployAtEnd=true

cache:
  key: ${CI_COMMIT_REF_SLUG}
  paths:
    - .m2/repository/

stages:
  - validate
  - build
  - test
  - quality
  - package
  - deploy

# 驗證階段
validate:
  stage: validate
  script:
    - mvn $MAVEN_CLI_OPTS validate

# 編譯階段
compile:
  stage: build
  script:
    - mvn $MAVEN_CLI_OPTS compile
  artifacts:
    paths:
      - target/classes/
    expire_in: 1 hour

# 單元測試
unit-test:
  stage: test
  script:
    - mvn $MAVEN_CLI_OPTS test
  artifacts:
    reports:
      junit:
        - target/surefire-reports/TEST-*.xml
      coverage_report:
        coverage_format: jacoco
        path: target/site/jacoco/jacoco.xml
  coverage: '/Total.*?([0-9]{1,3})%/'

# 整合測試
integration-test:
  stage: test
  script:
    - mvn $MAVEN_CLI_OPTS verify -DskipUTs=true
  artifacts:
    reports:
      junit:
        - target/failsafe-reports/TEST-*.xml

# 程式碼品質檢查
code-quality:
  stage: quality
  script:
    - mvn $MAVEN_CLI_OPTS checkstyle:check
    - mvn $MAVEN_CLI_OPTS pmd:check
    - mvn $MAVEN_CLI_OPTS spotbugs:check
  artifacts:
    reports:
      codequality: target/checkstyle-result.xml

# 安全掃描
security-scan:
  stage: quality
  script:
    - mvn $MAVEN_CLI_OPTS org.owasp:dependency-check-maven:check
  artifacts:
    reports:
      dependency_scanning: target/dependency-check-report.xml
  allow_failure: true

# 打包
package:
  stage: package
  script:
    - mvn $MAVEN_CLI_OPTS package -DskipTests
  artifacts:
    paths:
      - target/*.jar
    expire_in: 1 week
  only:
    - main
    - develop

4.5 常用 CI/CD 指令

🔧 Pipeline 管理

# 查看 Pipeline 狀態
# 在 GitLab Web 介面:專案 → CI/CD → Pipelines

# 手動觸發 Pipeline
# 在 GitLab Web 介面:CI/CD → Pipelines → Run Pipeline

# 重新執行失敗的工作
# 在 Pipeline 詳細頁面點選 "Retry" 按鈕

📊 Pipeline 監控

# 檢查 Pipeline 執行時間
# GitLab → 專案 → Analytics → CI/CD Analytics

# 查看測試覆蓋率
# GitLab → 專案 → CI/CD → Jobs → test-job → Coverage

# 下載 Artifacts
# GitLab → 專案 → CI/CD → Jobs → 特定工作 → Download artifacts

4.6 本專案的 CI/CD 應用

🎯 專案特定設定

# 本專案的 .gitlab-ci.yml 設定重點

# Java 17 + Maven 環境
image: maven:3.8.4-openjdk-17

# 專案相關變數
variables:
  APP_NAME: "java-tutorial"
  APP_VERSION: "${CI_COMMIT_TAG:-${CI_COMMIT_SHORT_SHA}}"

# 分支策略對應的部署
deploy-rules:
  - if: '$CI_COMMIT_BRANCH == "main"'
    variables:
      DEPLOY_ENV: "production"
  - if: '$CI_COMMIT_BRANCH == "develop"'
    variables:
      DEPLOY_ENV: "staging"
  - if: '$CI_COMMIT_BRANCH =~ /^feature\/.*/'
    variables:
      DEPLOY_ENV: "development"

📋 工作流程整合

  1. 開發者推送程式碼 → 觸發 Pipeline
  2. 自動建置和測試 → 確保程式碼品質
  3. Code Review 通過 → 合併到目標分支
  4. 自動部署 → 根據分支策略部署到對應環境
  5. 監控和回饋 → 持續改善流程

💡 最佳實務建議

  • 失敗快速回饋:優先執行快速測試,儘早發現問題
  • 並行執行:合理使用 Pipeline 並行功能提升效率
  • 環境一致性:確保 CI/CD 環境與本地開發環境一致
  • 日誌管理:適當的日誌輸出幫助問題排查

5. 常見問題與解決方式

5.1 Merge 衝突處理

🔥 衝突產生原因

  • 多位開發者同時修改相同檔案的相同區域
  • 分支長時間未同步主分支
  • 自動合併無法判斷正確的變更

🛠️ 衝突解決步驟

步驟 1:識別衝突

# 拉取最新變更時出現衝突
git pull origin main
# Auto-merging src/main/java/com/example/Service.java
# CONFLICT (content): Merge conflict in src/main/java/com/example/Service.java
# Automatic merge failed; fix conflicts and then commit the result.

# 查看衝突狀態
git status
# On branch feature/my-feature
# You have unmerged paths.
#   (fix conflicts and run "git commit")
#   (use "git merge --abort" to abort the merge)
#
# Unmerged paths:
#   (use "git add <file>..." to mark resolution)
#         both modified:   src/main/java/com/example/Service.java

步驟 2:解決衝突

// 衝突檔案內容示例
public class UserService {
    
<<<<<<< HEAD (當前分支)
    public User createUser(String name, String email) {
        // 你的變更
        User user = new User(name, email);
        user.setCreatedAt(new Date());
        return userRepository.save(user);
    }
=======
    public User createUser(String username, String emailAddress) {
        // 其他人的變更
        User user = new User(username, emailAddress);
        user.setStatus(UserStatus.ACTIVE);
        return userRepository.save(user);
    }
>>>>>>> main (主分支)
}

步驟 3:手動合併

// 合併後的正確版本
public class UserService {
    
    public User createUser(String name, String email) {
        // 合併兩個版本的變更
        User user = new User(name, email);
        user.setCreatedAt(new Date());
        user.setStatus(UserStatus.ACTIVE);
        return userRepository.save(user);
    }
}

步驟 4:完成合併

# 將解決的檔案加入暫存區
git add src/main/java/com/example/Service.java

# 檢查所有衝突是否已解決
git status

# 完成合併提交
git commit -m "resolve: 解決使用者服務類別的合併衝突"

# 推送變更
git push origin feature/my-feature

🧰 衝突解決工具

Visual Studio Code
# 安裝 GitLens 擴充功能
# VS Code 內建三方合併工具
code .  # 開啟專案,VS Code 會顯示衝突標記
命令列工具
# 設定合併工具
git config --global merge.tool vimdiff
# 或使用 VS Code
git config --global merge.tool vscode
git config --global mergetool.vscode.cmd 'code --wait $MERGED'

# 使用合併工具
git mergetool

5.2 錯誤回復方式

⏪ 常見回復場景

場景 1:回復最後一次提交

# 保留檔案變更,只回復提交
git reset --soft HEAD~1

# 完全回復提交和檔案變更
git reset --hard HEAD~1

# 回復提交但保留檔案在工作目錄
git reset --mixed HEAD~1  # 預設行為

場景 2:回復特定提交

# 查看提交歷史
git log --oneline
# abc123f feat: 新增使用者登入功能
# def456g fix: 修復密碼驗證錯誤
# ghi789h docs: 更新 README

# 回復到特定提交
git reset --hard def456g

# 或建立反向提交(推薦)
git revert abc123f

場景 3:回復檔案變更

# 回復工作目錄的檔案變更
git checkout -- src/main/java/com/example/Service.java

# 回復暫存區的檔案
git reset HEAD src/main/java/com/example/Service.java

# 從特定提交回復檔案
git checkout def456g -- src/main/java/com/example/Service.java

場景 4:回復推送的提交

# 方法1:使用 revert(推薦)
git revert abc123f
git push origin main

# 方法2:強制推送(危險,需團隊同意)
git reset --hard HEAD~1
git push --force-with-lease origin main

5.3 分支管理問題

🌿 分支問題排解

問題 1:分支無法切換

# 錯誤:工作目錄有未提交的變更
git checkout main
# error: Your local changes to the following files would be overwritten by checkout

# 解決方案1:暫存變更
git stash
git checkout main
git stash pop  # 回到原分支後執行

# 解決方案2:提交變更
git add .
git commit -m "wip: 暫存工作進度"
git checkout main

問題 2:分支追蹤錯誤

# 查看分支追蹤狀態
git branch -vv

# 設定上游分支
git branch --set-upstream-to=origin/feature/my-feature

# 或在推送時設定
git push -u origin feature/my-feature

問題 3:刪除本地和遠端分支

# 刪除本地分支
git branch -d feature/completed-feature

# 強制刪除本地分支
git branch -D feature/abandoned-feature

# 刪除遠端分支
git push origin --delete feature/completed-feature

# 清理本地對遠端分支的參照
git remote prune origin

5.4 權限和認證問題

🔐 常見認證問題

問題 1:HTTPS 認證失敗

# 更新認證資訊
git config --global credential.helper store
git pull  # 會提示輸入使用者名稱和密碼

# 使用 Personal Access Token
# GitLab → User Settings → Access Tokens
# 生成 token 後當作密碼使用

問題 2:SSH Key 設定

# 生成 SSH Key
ssh-keygen -t ed25519 -C "your.email@company.com"

# 複製公鑰到 GitLab
cat ~/.ssh/id_ed25519.pub
# 將內容貼到 GitLab → User Settings → SSH Keys

# 測試連線
ssh -T git@gitlab.company.com

問題 3:權限不足

# 檢查專案權限
# GitLab → 專案 → Settings → Members

# 請求權限提升
# 聯繫專案維護者或管理員

5.5 效能和同步問題

⚡ 效能優化

問題 1:Clone 速度慢

# 淺層 Clone(只取最新提交)
git clone --depth 1 https://gitlab.company.com/project.git

# 後續需要完整歷史時
git fetch --unshallow

問題 2:大檔案問題

# 使用 Git LFS 處理大檔案
git lfs install
git lfs track "*.jar"
git lfs track "*.war"
git add .gitattributes
git commit -m "chore: 設定 Git LFS 追蹤大檔案"

問題 3:本地快取問題

# 清理無效的遠端分支參照
git remote prune origin

# 清理無效的本地分支
git branch --merged | grep -v "\*\|main\|develop" | xargs -n 1 git branch -d

# 垃圾回收和優化
git gc --aggressive
git repack -ad

5.6 CI/CD Pipeline 問題

🔧 Pipeline 故障排除

問題 1:Pipeline 失敗

# 檢查失敗的工作日誌
# GitLab → CI/CD → Pipelines → 點選失敗的 Pipeline → 點選失敗的 Job

# 常見失敗原因:
# - 測試失敗:檢查測試程式碼
# - 建置失敗:檢查相依性和設定
# - 部署失敗:檢查環境設定和權限

問題 2:Runner 無法使用

# 檢查 Runner 狀態
# GitLab → Admin → Runners
# 或專案層級:Settings → CI/CD → Runners

# 重新註冊 Runner
sudo gitlab-runner register

問題 3:變數設定錯誤

# 檢查 CI/CD 變數
# GitLab → 專案 → Settings → CI/CD → Variables

# 確認變數範圍:
# - Project level(專案層級)
# - Group level(群組層級)
# - Instance level(實例層級)

5.7 團隊協作問題

👥 協作障礙解決

問題 1:Merge Request 衝突

# 在本地解決衝突後更新 MR
git checkout feature/my-feature
git fetch origin
git rebase origin/main
# 解決衝突後
git push --force-with-lease origin feature/my-feature

問題 2:Code Review 意見分歧

解決策略

  1. 技術討論:在 MR 中詳細解釋設計決策
  2. 離線溝通:必要時進行面對面討論
  3. 團隊共識:遵循團隊既定的編碼規範
  4. 妥協方案:尋求雙方都能接受的解決方案

問題 3:分支策略混亂

預防措施

  • 建立清楚的分支命名規範
  • 定期清理過期分支
  • 使用 GitLab 的分支保護功能
  • 團隊培訓和文件化流程

💡 問題預防建議

  • 定期同步:每日開始工作前先 git pull
  • 小步提交:避免一次性大量變更
  • 描述清楚:提供詳細的提交和 MR 描述
  • 主動溝通:遇到問題及時向團隊求助

6. 開發最佳實務建議

6.1 程式碼管理最佳實務

📝 提交原則

原子性提交
# ✅ 好的提交:單一功能
git commit -m "feat: 新增使用者登入驗證功能"

# ❌ 壞的提交:混合多個功能
git commit -m "feat: 新增登入功能、修復密碼錯誤、更新文件"
提交頻率
  • 每日至少一次:確保工作進度不會遺失
  • 功能完成時:完整的功能點或修復
  • 重大重構前:保留重構前的可工作版本
提交訊息品質
# ✅ 優質提交訊息
git commit -m "feat(auth): 實作 JWT 令牌驗證機制

- 新增 JwtTokenProvider 類別
- 實作令牌生成和驗證邏輯
- 新增令牌過期處理機制
- 更新安全設定配置

Fixes #123"

# ❌ 品質不佳的提交訊息
git commit -m "fix"
git commit -m "更新一些東西"
git commit -m "WIP"

🌿 分支管理策略

分支生命週期
分支生命週期管理:
┌─────────────┐    ┌─────────────┐    ┌─────────────┐
│  創建分支     │ →  │  開發階段     │ →  │  合併關閉     │
│             │    │             │    │             │
│ • 從develop  │    │ • 定期同步   │    │ • Code Review│
│   分支建立   │    │ • 小步提交   │    │ • 測試通過   │
│ • 命名規範   │    │ • 功能測試   │    │ • 刪除分支   │
└─────────────┘    └─────────────┘    └─────────────┘
分支維護
# 定期同步主分支
git checkout feature/my-feature
git fetch origin
git rebase origin/develop

# 清理已合併的本地分支
git branch --merged | grep -v "\*\|main\|develop" | xargs -n 1 git branch -d

# 查看遠端分支狀態
git remote show origin

6.2 Code Review 最佳實務

👀 審查者角度

審查重點
  1. 功能正確性
// ✅ 檢查邊界條件
public List<User> getUsers(int page, int size) {
    if (page < 0 || size <= 0 || size > 100) {
        throw new IllegalArgumentException("Invalid pagination parameters");
    }
    // ...
}

// ❌ 缺少參數驗證
public List<User> getUsers(int page, int size) {
    return userRepository.findAll(PageRequest.of(page, size));
}
  1. 安全性檢查
// ✅ 防止 SQL 注入
@Query("SELECT u FROM User u WHERE u.email = :email")
User findByEmail(@Param("email") String email);

// ❌ 存在 SQL 注入風險
@Query("SELECT u FROM User u WHERE u.email = '" + email + "'")
User findByEmail(String email);
  1. 效能考量
// ✅ 批次處理
public void updateUsers(List<User> users) {
    userRepository.saveAll(users);  // 批次儲存
}

// ❌ 逐一處理
public void updateUsers(List<User> users) {
    for (User user : users) {
        userRepository.save(user);  // 效能較差
    }
}

📝 審查意見表達

建設性意見
**✅ 建設性的 Review 意見**

「建議將這個方法拆分為更小的函式,提高可讀性和可測試性。例如:

\`\`\`java
public User createUser(UserDto dto) {
    validateUserData(dto);
    User user = mapToEntity(dto);
    return saveUser(user);
}
\`\`\`

**❌ 不具建設性的意見**

「這個方法太長了,請修改。」
意見分類
  • 🔴 Must Fix:必須修正的問題(安全、功能錯誤)
  • 🟡 Should Fix:建議修正的問題(效能、可讀性)
  • 🟢 Nice to Have:可選的改善建議

👨‍💻 被審查者角度

回應策略
# ✅ 積極回應
感謝建議!我已經按照您的建議重構了這個方法,並新增了相關的單元測試。

# 🔍 解釋設計決策
這裡我選擇使用快取機制是因為這個 API 會被頻繁調用,經過測試可以提升 60% 的效能。

# ❌ 消極回應
好的。
沒問題。

6.3 測試最佳實務

🧪 測試策略

測試金字塔
測試金字塔:
        ┌─────────────┐
        │   E2E Tests │  ← 少量,高價值
        │   (端到端)   │
        ├─────────────┤
        │Integration  │  ← 適量,關鍵路徑
        │   Tests     │
        ├─────────────┤
        │ Unit Tests  │  ← 大量,快速回饋
        │  (單元測試)  │
        └─────────────┘
單元測試實例
@ExtendWith(MockitoExtension.class)
class UserServiceTest {
    
    @Mock
    private UserRepository userRepository;
    
    @InjectMocks
    private UserService userService;
    
    @Test
    @DisplayName("應該成功建立新使用者")
    void shouldCreateUserSuccessfully() {
        // Given
        UserDto userDto = new UserDto("john@example.com", "John Doe");
        User expectedUser = new User("john@example.com", "John Doe");
        when(userRepository.save(any(User.class))).thenReturn(expectedUser);
        
        // When
        User result = userService.createUser(userDto);
        
        // Then
        assertThat(result.getEmail()).isEqualTo("john@example.com");
        assertThat(result.getName()).isEqualTo("John Doe");
        verify(userRepository).save(any(User.class));
    }
    
    @Test
    @DisplayName("當信箱已存在時應該拋出例外")
    void shouldThrowExceptionWhenEmailExists() {
        // Given
        UserDto userDto = new UserDto("john@example.com", "John Doe");
        when(userRepository.existsByEmail("john@example.com")).thenReturn(true);
        
        // When & Then
        assertThatThrownBy(() -> userService.createUser(userDto))
            .isInstanceOf(EmailAlreadyExistsException.class)
            .hasMessage("信箱已被使用: john@example.com");
    }
}

6.4 安全性最佳實務

🔒 程式碼安全

敏感資料管理
# ✅ 使用環境變數
spring:
  datasource:
    url: ${DB_URL:jdbc:h2:mem:testdb}
    username: ${DB_USERNAME:sa}
    password: ${DB_PASSWORD:}

# ❌ 硬編碼敏感資料
spring:
  datasource:
    url: jdbc:mysql://localhost:3306/prod
    username: admin
    password: admin123
輸入驗證
// ✅ 完整的輸入驗證
@RestController
public class UserController {
    
    @PostMapping("/users")
    public ResponseEntity<User> createUser(@Valid @RequestBody UserDto userDto) {
        // @Valid 會自動驗證 UserDto 的約束條件
        User user = userService.createUser(userDto);
        return ResponseEntity.ok(user);
    }
}

@Data
public class UserDto {
    @NotBlank(message = "信箱不能為空")
    @Email(message = "信箱格式不正確")
    private String email;
    
    @NotBlank(message = "姓名不能為空")
    @Size(min = 2, max = 50, message = "姓名長度必須在 2-50 字元之間")
    private String name;
}
權限控制
// ✅ 細緻的權限控制
@RestController
@RequestMapping("/api/admin")
@PreAuthorize("hasRole('ADMIN')")
public class AdminController {
    
    @GetMapping("/users")
    @PreAuthorize("hasAuthority('USER_READ')")
    public List<User> getAllUsers() {
        return userService.getAllUsers();
    }
    
    @DeleteMapping("/users/{id}")
    @PreAuthorize("hasAuthority('USER_DELETE')")
    public ResponseEntity<Void> deleteUser(@PathVariable Long id) {
        userService.deleteUser(id);
        return ResponseEntity.ok().build();
    }
}

6.5 效能最佳實務

⚡ 程式碼效能

資料庫查詢優化
// ✅ 使用投影和分頁
@Repository
public interface UserRepository extends JpaRepository<User, Long> {
    
    @Query("SELECT new com.example.dto.UserSummaryDto(u.id, u.name, u.email) " +
           "FROM User u WHERE u.active = true")
    Page<UserSummaryDto> findActiveUserSummaries(Pageable pageable);
    
    // 使用 @EntityGraph 避免 N+1 查詢
    @EntityGraph(attributePaths = {"roles", "profile"})
    Optional<User> findWithRolesAndProfileById(Long id);
}

// ❌ 查詢過多資料
public List<User> getAllUsers() {
    return userRepository.findAll(); // 可能返回大量資料
}
快取策略
// ✅ 適當使用快取
@Service
@CacheConfig(cacheNames = "users")
public class UserService {
    
    @Cacheable(key = "#id")
    public User getUserById(Long id) {
        return userRepository.findById(id)
            .orElseThrow(() -> new UserNotFoundException(id));
    }
    
    @CacheEvict(key = "#user.id")
    public User updateUser(User user) {
        return userRepository.save(user);
    }
    
    @CacheEvict(allEntries = true)
    public void clearAllUsersCache() {
        // 清空所有使用者快取
    }
}

6.6 文件化最佳實務

📚 程式碼文件

API 文件
// ✅ 完整的 API 文件
@RestController
@RequestMapping("/api/users")
@Api(tags = "使用者管理", description = "使用者相關操作的 API")
public class UserController {
    
    @PostMapping
    @ApiOperation(value = "建立新使用者", notes = "建立一個新的使用者帳號")
    @ApiResponses({
        @ApiResponse(code = 201, message = "使用者建立成功"),
        @ApiResponse(code = 400, message = "請求參數錯誤"),
        @ApiResponse(code = 409, message = "信箱已存在")
    })
    public ResponseEntity<User> createUser(
        @ApiParam(value = "使用者資訊", required = true) 
        @Valid @RequestBody UserDto userDto) {
        
        User user = userService.createUser(userDto);
        return ResponseEntity.status(HttpStatus.CREATED).body(user);
    }
}
JavaDoc 規範
/**
 * 使用者服務類別,提供使用者相關的業務邏輯處理
 * 
 * @author 開發者姓名
 * @version 1.0
 * @since 2024-01-01
 */
@Service
@Transactional
public class UserService {
    
    /**
     * 根據 ID 查詢使用者
     * 
     * @param id 使用者 ID,不能為 null
     * @return 使用者實體
     * @throws UserNotFoundException 當使用者不存在時拋出
     * @throws IllegalArgumentException 當 ID 為 null 時拋出
     * @see User
     * @since 1.0
     */
    public User getUserById(@NonNull Long id) {
        return userRepository.findById(id)
            .orElseThrow(() -> new UserNotFoundException("使用者不存在: " + id));
    }
}

6.7 團隊協作最佳實務

🤝 溝通協作

技術決策文件
# 技術決策記錄 (ADR-001): 選擇 Spring Boot 作為主要框架

### 狀態
接受

### 背景
需要選擇後端開發框架來建置企業級應用程式

### 決策
選擇 Spring Boot 2.7.x 作為主要後端框架

### 理由
- 豐富的生態系統和社群支援
- 優秀的自動設定功能
- 內建測試支援
- 團隊已有相關經驗

### 後果
- 學習曲線相對平緩
- 可快速啟動專案開發
- 需要定期更新相依性
會議記錄
# 技術 Review 會議記錄 - 2024/01/15

### 參與者
- 架構師:張三
- 後端開發:李四、王五
- 前端開發:趙六

### 討論議題
1. 使用者認證機制設計
2. API 設計規範
3. 資料庫設計檢討

### 決議事項
- [ ] 採用 JWT + Refresh Token 認證機制
- [ ] API 遵循 RESTful 設計原則
- [ ] 資料庫新增使用者活動記錄表

### 行動項目
- 李四:完成認證模組實作 (2024/01/20)
- 王五:更新 API 文件 (2024/01/18)
- 趙六:調整前端認證流程 (2024/01/22)

📈 持續改善

回顧會議
# Sprint 回顧 - Week 3

### 做得好的地方
- Code Review 品質提升
- CI/CD Pipeline 穩定運行
- 團隊溝通更加順暢

### 需要改善的地方
- 測試覆蓋率需要提升
- 文件更新不夠及時
- 技術債務累積

### 改善行動
1. 設定測試覆蓋率目標為 80%
2. MR 必須包含文件更新
3. 每週分配 20% 時間處理技術債務

7. 檢查清單

7.1 新進同仁入門檢查清單

🚀 環境設定

  • Git 安裝與設定

    • 安裝 Git 並驗證版本:git --version
    • 設定使用者資訊:git config --global user.nameuser.email
    • 設定編輯器:git config --global core.editor
    • 設定換行符號處理:git config --global core.autocrlf true (Windows)
  • GitLab 帳號設定

    • 建立 GitLab 帳號
    • 設定 SSH Key 或確認 HTTPS 認證
    • 測試連線:ssh -T git@gitlab.company.com 或 Clone 測試專案
    • 加入專案團隊並確認權限
  • 開發工具設定

    • 安裝 VS Code 或慣用的 IDE
    • 安裝必要的擴充功能(GitLens、Checkstyle 等)
    • 設定程式碼格式化規則
    • 設定 Git 整合

📚 學習與理解

  • 文件閱讀

    • 閱讀專案 README.md
    • 理解專案架構和技術棧
    • 熟悉專案的分支策略
    • 閱讀程式碼規範文件
  • 流程熟悉

    • 理解 Git Flow 分支模型
    • 熟悉 Commit Message 規範
    • 了解 Merge Request 流程
    • 了解 Code Review 標準

7.2 日常開發檢查清單

🌅 開始工作

  • 每日同步

    • 切換到 develop 分支:git checkout develop
    • 拉取最新變更:git pull origin develop
    • 檢查是否有新的分支或標籤
    • 確認本地工作目錄乾淨:git status
  • 分支管理

    • 從最新的 develop 建立功能分支
    • 使用正確的分支命名規範
    • 設定上游分支:git push -u origin feature/branch-name

💻 開發過程

  • 程式碼品質

    • 遵循專案的編碼規範
    • 確保程式碼可以正常編譯
    • 執行單元測試並確保通過
    • 執行程式碼靜態分析
  • 提交實務

    • 使用原子性提交(每次提交一個邏輯變更)
    • 遵循 Commit Message 規範
    • 避免提交敏感資訊(密碼、API Key 等)
    • 提交前檢查差異:git diff --staged

🔄 提交和推送

  • 提交前檢查

    • 檢查提交內容:git statusgit diff
    • 確保測試通過:mvn test
    • 檢查程式碼格式:mvn checkstyle:check
    • 確認沒有 TODO 或 FIXME 標記
  • 推送流程

    • 推送到遠端分支:git push origin feature/branch-name
    • 檢查 CI/CD Pipeline 狀態
    • 處理任何建置或測試失敗

7.3 Merge Request 檢查清單

📝 建立 MR

  • MR 準備

    • 確保分支基於最新的 develop
    • 解決與目標分支的衝突
    • 確認所有提交都是必要的
    • 壓縮或整理提交歷史(如需要)
  • MR 資訊

    • 填寫清楚的標題和描述
    • 使用 MR 描述模板
    • 標記相關的 Issue
    • 指派適當的審查者
    • 設定適當的標籤

👀 Code Review

  • 自我檢查

    • 進行自我 Code Review
    • 確認變更範圍合理
    • 檢查是否需要更新文件
    • 確認測試覆蓋率足夠
  • 回應審查

    • 及時回應審查意見
    • 積極討論設計決策
    • 修正所有必要的問題
    • 感謝審查者的意見

7.4 CI/CD 檢查清單

🔧 Pipeline 監控

  • 建置檢查

    • 確認 Pipeline 成功執行
    • 檢查建置日誌是否有警告
    • 確認測試都通過
    • 檢查程式碼品質報告
  • 部署檢查

    • 確認部署到測試環境成功
    • 進行冒煙測試
    • 檢查應用程式健康狀態
    • 驗證核心功能正常

🚨 問題處理

  • 失敗處理
    • 查看失敗的工作日誌
    • 識別失敗根本原因
    • 修正問題並重新執行
    • 通知相關團隊成員

7.5 發布檢查清單

🎯 發布準備

  • 發布前檢查

    • 所有功能測試通過
    • 效能測試完成
    • 安全掃描無高風險問題
    • 文件已更新
  • 發布執行

    • 備份生產環境資料
    • 執行部署腳本
    • 驗證部署成功
    • 執行回歸測試

🔙 發布後

  • 監控檢查
    • 監控應用程式效能
    • 檢查錯誤日誌
    • 確認使用者回饋
    • 準備回滾計畫(如需要)

7.6 緊急情況檢查清單

🚨 生產問題

  • 立即回應

    • 評估問題嚴重程度
    • 通知相關團隊
    • 啟動緊急回應流程
    • 記錄問題時間軸
  • 問題解決

    • 建立 hotfix 分支
    • 快速修復問題
    • 執行緊急測試
    • 部署修復版本

📊 事後檢討

  • 問題分析
    • 分析問題根本原因
    • 記錄解決過程
    • 識別改善機會
    • 更新流程文件

7.7 定期維護檢查清單

🧹 每週維護

  • 分支清理

    • 刪除已合併的功能分支
    • 清理過期的遠端分支參照
    • 檢查長時間未更新的分支
  • 效能檢查

    • 檢查 CI/CD Pipeline 執行時間
    • 檢查測試執行效率
    • 檢查建置快取效果

📈 每月檢討

  • 團隊回顧
    • 檢討開發流程效率
    • 分析常見問題
    • 討論改善建議
    • 更新最佳實務

📞 聯絡資訊

技術支援

團隊協作

  • Slack 頻道:#dev-team、#gitlab-support
  • 團隊會議:每週三 14:00-15:00
  • 技術分享:每月第一個週五

📚 參考資源

官方文件

學習資源

工具推薦



8. 進階功能與整合

8.1 GitLab API 整合

🔗 REST API 使用

認證方式

# 使用 Personal Access Token
curl --header "PRIVATE-TOKEN: your-token" \
     "https://gitlab.company.com/api/v4/projects"

# 使用 OAuth Token
curl --header "Authorization: Bearer your-oauth-token" \
     "https://gitlab.company.com/api/v4/projects"

常用 API 範例

# 取得專案清單
curl --header "PRIVATE-TOKEN: your-token" \
     "https://gitlab.company.com/api/v4/projects?membership=true"

# 建立新 Issue
curl --request POST \
     --header "PRIVATE-TOKEN: your-token" \
     --header "Content-Type: application/json" \
     --data '{"title":"New Bug Report","description":"Bug description"}' \
     "https://gitlab.company.com/api/v4/projects/123/issues"

# 取得 Merge Request 清單
curl --header "PRIVATE-TOKEN: your-token" \
     "https://gitlab.company.com/api/v4/projects/123/merge_requests?state=opened"

📊 Webhook 整合

Webhook 設定

{
  "url": "https://your-service.com/webhook",
  "push_events": true,
  "issues_events": true,
  "merge_requests_events": true,
  "wiki_page_events": true,
  "deployment_events": true,
  "job_events": true,
  "pipeline_events": true,
  "release_events": true
}

Webhook 處理範例

@RestController
@RequestMapping("/webhook")
@Slf4j
public class GitLabWebhookController {
    
    @PostMapping("/push")
    public ResponseEntity<String> handlePushEvent(
            @RequestHeader("X-Gitlab-Event") String event,
            @RequestBody Map<String, Object> payload) {
        
        log.info("收到 GitLab 事件: {}", event);
        
        if ("Push Hook".equals(event)) {
            String projectName = (String) ((Map) payload.get("project")).get("name");
            String ref = (String) payload.get("ref");
            log.info("專案 {} 的分支 {} 有新的 Push", projectName, ref);
            
            // 處理 Push 事件邏輯
            processPushEvent(payload);
        }
        
        return ResponseEntity.ok("處理完成");
    }
}

8.2 第三方工具整合

🔧 IDE 整合

VS Code 擴充功能

  • GitLab Workflow:直接在 VS Code 中管理 Issue 和 MR
  • GitLens:增強的 Git 功能
  • GitLab CI:CI/CD 管道可視化

IntelliJ IDEA 整合

GitLab 外掛功能:
├── Clone 專案
├── 建立 Merge Request
├── 檢視 CI/CD 狀態
├── Issue 管理
└── Code Review

📱 Slack 整合

Slack 通知設定

# .gitlab-ci.yml Slack 通知
variables:
  SLACK_WEBHOOK: "https://hooks.slack.com/services/YOUR/SLACK/WEBHOOK"

notify-slack:
  stage: notify
  script:
    - |
      curl -X POST -H 'Content-type: application/json' \
      --data "{'text':'✅ Pipeline 成功完成: $CI_PROJECT_NAME ($CI_COMMIT_REF_NAME)'}" \
      $SLACK_WEBHOOK
  only:
    - main
  when: on_success

notify-slack-failure:
  stage: notify
  script:
    - |
      curl -X POST -H 'Content-type: application/json' \
      --data "{'text':'❌ Pipeline 失敗: $CI_PROJECT_NAME ($CI_COMMIT_REF_NAME)'}" \
      $SLACK_WEBHOOK
  only:
    - main
  when: on_failure

🎫 Jira 整合

Issue 關聯

# Commit message 關聯 Jira Issue
git commit -m "feat: 新增使用者登入功能

實作使用者登入驗證和 JWT Token 機制

PROJ-123"

自動化工作流程

Jira-GitLab 整合流程:
┌─────────────┐    ┌─────────────┐    ┌─────────────┐
│ Jira Issue  │ →  │ GitLab MR   │ →  │ 自動更新     │
│ 建立        │    │ 關聯        │    │ Issue 狀態   │
└─────────────┘    └─────────────┘    └─────────────┘

8.3 自動化與 DevOps

🔄 GitOps 實踐

GitOps 工作流程

# .gitlab-ci.yml GitOps 部署
deploy-to-k8s:
  stage: deploy
  image: alpine/k8s:latest
  script:
    - echo "部署到 Kubernetes 集群"
    - kubectl apply -f k8s/
    - kubectl rollout status deployment/app-deployment
  environment:
    name: production
    url: https://app.example.com
  only:
    - main

ArgoCD 整合

# argocd-application.yaml
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
  name: java-tutorial-app
spec:
  project: default
  source:
    repoURL: https://gitlab.company.com/team/java-tutorial.git
    targetRevision: main
    path: k8s
  destination:
    server: https://kubernetes.default.svc
    namespace: production
  syncPolicy:
    automated:
      prune: true
      selfHeal: true

📈 監控整合

Prometheus + Grafana

# prometheus.yml
global:
  scrape_interval: 15s

scrape_configs:
  - job_name: 'gitlab-ci'
    static_configs:
      - targets: ['gitlab.company.com:9090']
    metrics_path: /metrics
    params:
      token: ['your-prometheus-token']

應用程式監控

// Spring Boot Actuator 整合
@RestController
public class MetricsController {
    
    private final MeterRegistry meterRegistry;
    
    @GetMapping("/api/users")
    public List<User> getUsers() {
        return Timer.Sample.start(meterRegistry)
            .stop(meterRegistry.timer("api.users.duration"))
            .recordCallable(() -> userService.getAllUsers());
    }
}

8.4 安全性進階設定

🔐 進階權限管理

分支保護規則

主分支保護設定:
├── 推送權限:僅 Maintainer 以上
├── Merge Request 必要:是
├── 至少 2 位審查者:是
├── Pipeline 必須成功:是
├── 解決所有討論:是
└── 快進合併限制:是

自動安全掃描

# .gitlab-ci.yml 完整安全掃描
include:
  - template: Security/SAST.gitlab-ci.yml
  - template: Security/Dependency-Scanning.gitlab-ci.yml
  - template: Security/Secret-Detection.gitlab-ci.yml
  - template: Security/License-Scanning.gitlab-ci.yml
  - template: Security/Container-Scanning.gitlab-ci.yml

variables:
  SECURE_ANALYZERS_PREFIX: "registry.gitlab.com/gitlab-org/security-products/analyzers"
  SAST_EXCLUDED_ANALYZERS: "gosec,bandit"
  
security-scan:
  stage: test
  allow_failure: false
  artifacts:
    reports:
      sast: gl-sast-report.json
      dependency_scanning: gl-dependency-scanning-report.json
      secret_detection: gl-secret-detection-report.json

🛡️ 合規性管理

稽核日誌

  • 使用者操作記錄:登入、權限變更、專案存取
  • 程式碼變更追蹤:提交、分支、標籤操作
  • 系統管理記錄:設定變更、使用者管理

資料保護

# 資料備份策略
backup-policy:
  schedule: "0 2 * * *"  # 每日凌晨 2 點
  retention: "30d"       # 保留 30 天
  encryption: "AES-256"  # 加密儲存
  locations:
    - "s3://backup-bucket/gitlab"
    - "local://backup/gitlab"

8.5 效能優化

⚡ Repository 效能優化

大型檔案管理

# 設定 Git LFS
git lfs install
git lfs track "*.jar"
git lfs track "*.war"
git lfs track "*.pdf"
git lfs track "docs/*.png"

# 檢視 LFS 檔案
git lfs ls-files

# 清理 LFS 快取
git lfs prune

Repository 清理

# 清理無效參照
git remote prune origin

# 垃圾回收
git gc --aggressive --prune=now

# 檢查 Repository 大小
git count-objects -vH

🚀 CI/CD 效能優化

Docker 層快取

# .gitlab-ci.yml Docker 快取優化
build:
  stage: build
  image: docker:latest
  services:
    - docker:dind
  script:
    - docker build 
      --cache-from $CI_REGISTRY_IMAGE:latest 
      --tag $CI_REGISTRY_IMAGE:$CI_COMMIT_SHA 
      --tag $CI_REGISTRY_IMAGE:latest .
    - docker push $CI_REGISTRY_IMAGE:$CI_COMMIT_SHA
    - docker push $CI_REGISTRY_IMAGE:latest

並行作業

# 並行測試執行
test:unit:
  stage: test
  script: mvn test -Dtest="**/unit/**"
  parallel: 3

test:integration:
  stage: test
  script: mvn test -Dtest="**/integration/**"
  parallel: 2

8.6 災難恢復

🔄 備份策略

自動化備份

#!/bin/bash
# gitlab-backup.sh

# 建立應用程式備份
gitlab-backup create

# 備份設定檔
tar -czf /backup/gitlab-config-$(date +%Y%m%d).tar.gz /etc/gitlab/

# 上傳到雲端儲存
aws s3 sync /var/opt/gitlab/backups/ s3://gitlab-backups/app/
aws s3 sync /backup/ s3://gitlab-backups/config/

# 清理舊備份(保留 30 天)
find /var/opt/gitlab/backups/ -name "*.tar" -mtime +30 -delete

🆘 災難恢復流程

恢復步驟

  1. 評估損害程度
  2. 準備恢復環境
  3. 恢復應用程式資料
  4. 恢復設定檔
  5. 驗證系統功能
  6. 通知使用者

恢復指令

# 停止 GitLab 服務
gitlab-ctl stop puma
gitlab-ctl stop sidekiq

# 恢復備份
gitlab-backup restore BACKUP=backup-timestamp

# 恢復設定檔
tar -xzf gitlab-config-backup.tar.gz -C /

# 重新設定權限
gitlab-ctl reconfigure

# 啟動服務
gitlab-ctl start

8.7 GitLab Runner 深度配置

🏃‍♂️ Runner 架構深入理解

Runner 執行流程

GitLab CI/CD 執行流程:
┌─────────────┐    ┌─────────────┐    ┌─────────────┐    ┌─────────────┐
│ Git Push    │ →  │ Pipeline    │ →  │ Runner      │ →  │ Job         │
│ 觸發        │    │ 建立        │    │ 接收工作     │    │ 執行        │
└─────────────┘    └─────────────┘    └─────────────┘    └─────────────┘

Runner 類型詳解

Runner 類型用途優缺點適用場景
Shared Runners多專案共用成本低,但可能排隊小型專案、測試環境
Group Runners群組專用平衡成本和效能團隊專案
Project Runners專案專用效能最佳,成本較高大型專案、生產環境

🔧 Runner 進階配置

詳細配置檔範例

# /etc/gitlab-runner/config.toml
concurrent = 4
check_interval = 0
session_timeout = 1800

[session_server]
  session_timeout = 1800

[[runners]]
  name = "docker-runner-production"
  url = "https://gitlab.company.com/"
  token = "xxx"
  executor = "docker"
  
  [runners.custom_build_dir]
  [runners.cache]
    Type = "s3"
    Path = "cache"
    Shared = false
    [runners.cache.s3]
      ServerAddress = "s3.amazonaws.com"
      BucketName = "gitlab-ci-cache"
      BucketLocation = "us-east-1"
      Insecure = false
      
  [runners.docker]
    tls_verify = false
    image = "alpine:latest"
    privileged = true
    disable_entrypoint_overwrite = false
    oom_kill_disable = false
    disable_cache = false
    volumes = ["/cache", "/var/run/docker.sock:/var/run/docker.sock:rw"]
    shm_size = 0
    pull_policy = "if-not-present"
    
    # 資源限制
    cpus = "2.0"
    memory = "4g"
    
    # 網路設定
    network_mode = "bridge"
    
    # 安全設定
    security_opt = ["seccomp:unconfined"]

多環境 Runner 配置

# 開發環境 Runner 註冊
sudo gitlab-runner register \
  --url https://gitlab.company.com/ \
  --registration-token DEV_TOKEN \
  --description "Development Runner" \
  --tag-list "dev,docker,java-11" \
  --executor docker \
  --docker-image maven:3.8.4-openjdk-11 \
  --docker-volumes /var/run/docker.sock:/var/run/docker.sock

# 生產環境 Runner 註冊
sudo gitlab-runner register \
  --url https://gitlab.company.com/ \
  --registration-token PROD_TOKEN \
  --description "Production Runner" \
  --tag-list "prod,kubernetes,java-17" \
  --executor kubernetes \
  --kubernetes-namespace gitlab-runner

🐳 Docker Executor 優化

最佳化的 Docker 配置

# .gitlab-ci.yml Docker 優化
variables:
  DOCKER_DRIVER: overlay2
  DOCKER_TLS_CERTDIR: "/certs"
  MAVEN_OPTS: "-Dmaven.repo.local=$CI_PROJECT_DIR/.m2/repository"

cache:
  key: "$CI_COMMIT_REF_SLUG"
  paths:
    - .m2/repository/
    - target/

build:
  stage: build
  image: maven:3.8.4-openjdk-17-slim
  services:
    - docker:20.10.16-dind
  before_script:
    - docker info
  script:
    - mvn clean compile
  artifacts:
    paths:
      - target/
    expire_in: 1 hour

☸️ Kubernetes Executor 配置

Kubernetes Runner 設定

# kubernetes-runner.yaml
apiVersion: v1
kind: ConfigMap
metadata:
  name: gitlab-runner-config
data:
  config.toml: |
    [[runners]]
      name = "kubernetes-runner"
      url = "https://gitlab.company.com/"
      token = "xxx"
      executor = "kubernetes"
      
      [runners.kubernetes]
        namespace = "gitlab-runner"
        image = "alpine:latest"
        cpu_limit = "2"
        memory_limit = "4Gi"
        service_cpu_limit = "1"
        service_memory_limit = "2Gi"
        helper_cpu_limit = "500m"
        helper_memory_limit = "100Mi"
        
        # 節點選擇器
        node_selector = {"gitlab-runner" = "true"}
        
        # 污點容忍
        [[runners.kubernetes.node_tolerations]]
          key = "gitlab-runner"
          operator = "Equal"
          value = "true"
          effect = "NoSchedule"

8.8 多環境部署策略

🌍 環境規劃架構

標準環境配置

環境架構圖:
┌─────────────┐    ┌─────────────┐    ┌─────────────┐    ┌─────────────┐
│ Development │ →  │   Testing   │ →  │   Staging   │ →  │ Production  │
│ 開發環境      │    │   測試環境   │    │   預產環境   │    │   正式環境   │
│             │    │             │    │             │    │             │
│ • 快速迭代   │    │ • 自動測試   │    │ • 效能測試   │    │ • 高可用性   │
│ • 功能驗證   │    │ • 整合測試   │    │ • 使用者驗收  │    │ • 監控告警   │
│ • 除錯修復   │    │ • 迴歸測試   │    │ • 最終確認   │    │ • 災難恢復   │
└─────────────┘    └─────────────┘    └─────────────┘    └─────────────┘

📋 環境配置管理

配置檔分層管理

# .gitlab-ci.yml 多環境配置
variables:
  SPRING_PROFILES_ACTIVE: "default"

.deploy_template: &deploy_template
  stage: deploy
  image: alpine/k8s:latest
  script:
    - envsubst < k8s/deployment.yaml | kubectl apply -f -
    - kubectl rollout status deployment/$APP_NAME

deploy:development:
  <<: *deploy_template
  variables:
    ENVIRONMENT: "development"
    SPRING_PROFILES_ACTIVE: "dev"
    REPLICAS: "1"
    RESOURCES_LIMITS_CPU: "500m"
    RESOURCES_LIMITS_MEMORY: "1Gi"
  environment:
    name: development
    url: https://dev.example.com
  only:
    - develop

deploy:testing:
  <<: *deploy_template
  variables:
    ENVIRONMENT: "testing"
    SPRING_PROFILES_ACTIVE: "test"
    REPLICAS: "2"
    RESOURCES_LIMITS_CPU: "1"
    RESOURCES_LIMITS_MEMORY: "2Gi"
  environment:
    name: testing
    url: https://test.example.com
  only:
    - main

deploy:staging:
  <<: *deploy_template
  variables:
    ENVIRONMENT: "staging"
    SPRING_PROFILES_ACTIVE: "staging"
    REPLICAS: "3"
    RESOURCES_LIMITS_CPU: "2"
    RESOURCES_LIMITS_MEMORY: "4Gi"
  environment:
    name: staging
    url: https://staging.example.com
  only:
    - release/*
  when: manual

deploy:production:
  <<: *deploy_template
  variables:
    ENVIRONMENT: "production"
    SPRING_PROFILES_ACTIVE: "prod"
    REPLICAS: "5"
    RESOURCES_LIMITS_CPU: "4"
    RESOURCES_LIMITS_MEMORY: "8Gi"
  environment:
    name: production
    url: https://app.example.com
  only:
    - tags
  when: manual

🔐 環境變數管理

分層變數設定

變數層級優先順序:
┌─────────────────┐  (最高優先級)
│ Job Variables   │
├─────────────────┤
│ Project Vars    │
├─────────────────┤
│ Group Variables │
├─────────────────┤
│ Instance Vars   │  (最低優先級)
└─────────────────┘

環境變數範例

# GitLab CI/CD Variables 設定

# 開發環境變數
ENVIRONMENT: development
DB_HOST: dev-db.company.com
DB_NAME: app_dev
REDIS_URL: redis://dev-redis.company.com:6379
LOG_LEVEL: DEBUG

# 生產環境變數
ENVIRONMENT: production
DB_HOST: prod-db.company.com
DB_NAME: app_prod
REDIS_URL: redis://prod-redis.company.com:6379
LOG_LEVEL: INFO

# 共用變數
APP_NAME: java-tutorial
DOCKER_REGISTRY: registry.company.com

🚀 藍綠部署實作

藍綠部署 Pipeline

# 藍綠部署配置
stages:
  - build
  - test
  - deploy:blue
  - smoke:blue
  - switch:traffic
  - cleanup:green

deploy:blue:
  stage: deploy:blue
  script:
    - |
      # 部署到藍色環境
      kubectl apply -f k8s/blue/
      kubectl rollout status deployment/app-blue
      kubectl wait --for=condition=ready pod -l app=java-tutorial,env=blue
  environment:
    name: production-blue
    url: https://blue.app.example.com

smoke:test:blue:
  stage: smoke:blue
  script:
    - |
      # 對藍色環境進行冒煙測試
      curl -f https://blue.app.example.com/health
      curl -f https://blue.app.example.com/api/status
      
      # 執行關鍵功能測試
      newman run tests/smoke-tests.postman_collection.json \
        --env-var "base_url=https://blue.app.example.com"

switch:traffic:
  stage: switch:traffic
  script:
    - |
      # 切換流量到藍色環境
      kubectl patch service app-service -p '{"spec":{"selector":{"env":"blue"}}}'
      echo "流量已切換到藍色環境"
  when: manual
  environment:
    name: production
    url: https://app.example.com

cleanup:green:
  stage: cleanup:green
  script:
    - |
      # 清理舊的綠色環境
      kubectl delete deployment app-green || true
      kubectl delete service app-green-service || true
  when: manual

8.9 容器化與 Kubernetes 整合

🐳 Docker 最佳實務

多階段建置 Dockerfile

# Multi-stage Dockerfile for Java application
FROM maven:3.8.4-openjdk-17-slim AS builder

WORKDIR /app
COPY pom.xml .
# 先複製 pom.xml 以利用 Docker 層快取
RUN mvn dependency:go-offline -B

COPY src ./src
RUN mvn clean package -DskipTests

# 第二階段:運行時映像檔
FROM openjdk:17-jre-slim

# 安全性:建立非 root 使用者
RUN groupadd -r appuser && useradd -r -g appuser appuser

WORKDIR /app

# 複製建置產物
COPY --from=builder /app/target/*.jar app.jar

# 設定健康檢查
HEALTHCHECK --interval=30s --timeout=3s --start-period=5s --retries=3 \
  CMD curl -f http://localhost:8080/actuator/health || exit 1

# 使用非 root 使用者執行
USER appuser

EXPOSE 8080

# 使用 exec 形式避免 PID 1 問題
ENTRYPOINT ["java", "-jar", "app.jar"]

☸️ Kubernetes 部署配置

完整的 Kubernetes 資源定義

# k8s/namespace.yaml
apiVersion: v1
kind: Namespace
metadata:
  name: java-tutorial
  labels:
    name: java-tutorial

---
# k8s/configmap.yaml
apiVersion: v1
kind: ConfigMap
metadata:
  name: app-config
  namespace: java-tutorial
data:
  application.yml: |
    server:
      port: 8080
    spring:
      profiles:
        active: ${SPRING_PROFILES_ACTIVE:prod}
      datasource:
        url: ${DB_URL}
        username: ${DB_USERNAME}
        password: ${DB_PASSWORD}
    logging:
      level:
        com.tutorial: ${LOG_LEVEL:INFO}

---
# k8s/secret.yaml
apiVersion: v1
kind: Secret
metadata:
  name: app-secrets
  namespace: java-tutorial
type: Opaque
data:
  db-password: <base64-encoded-password>
  jwt-secret: <base64-encoded-jwt-secret>

---
# k8s/deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: java-tutorial-app
  namespace: java-tutorial
  labels:
    app: java-tutorial
spec:
  replicas: 3
  strategy:
    type: RollingUpdate
    rollingUpdate:
      maxSurge: 1
      maxUnavailable: 1
  selector:
    matchLabels:
      app: java-tutorial
  template:
    metadata:
      labels:
        app: java-tutorial
    spec:
      containers:
      - name: app
        image: ${DOCKER_REGISTRY}/java-tutorial:${CI_COMMIT_SHA}
        ports:
        - containerPort: 8080
        env:
        - name: SPRING_PROFILES_ACTIVE
          value: "prod"
        - name: DB_URL
          valueFrom:
            configMapKeyRef:
              name: app-config
              key: db-url
        - name: DB_PASSWORD
          valueFrom:
            secretKeyRef:
              name: app-secrets
              key: db-password
        resources:
          requests:
            memory: "512Mi"
            cpu: "250m"
          limits:
            memory: "1Gi"
            cpu: "500m"
        livenessProbe:
          httpGet:
            path: /actuator/health
            port: 8080
          initialDelaySeconds: 60
          periodSeconds: 30
        readinessProbe:
          httpGet:
            path: /actuator/health
            port: 8080
          initialDelaySeconds: 30
          periodSeconds: 10
        volumeMounts:
        - name: config
          mountPath: /app/config
      volumes:
      - name: config
        configMap:
          name: app-config

---
# k8s/service.yaml
apiVersion: v1
kind: Service
metadata:
  name: java-tutorial-service
  namespace: java-tutorial
spec:
  selector:
    app: java-tutorial
  ports:
  - protocol: TCP
    port: 80
    targetPort: 8080
  type: ClusterIP

---
# k8s/ingress.yaml
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: java-tutorial-ingress
  namespace: java-tutorial
  annotations:
    kubernetes.io/ingress.class: "nginx"
    cert-manager.io/cluster-issuer: "letsencrypt-prod"
    nginx.ingress.kubernetes.io/rewrite-target: /
spec:
  tls:
  - hosts:
    - app.example.com
    secretName: java-tutorial-tls
  rules:
  - host: app.example.com
    http:
      paths:
      - path: /
        pathType: Prefix
        backend:
          service:
            name: java-tutorial-service
            port:
              number: 80

🔄 Helm Chart 管理

Helm Chart 結構

helm/java-tutorial/
├── Chart.yaml
├── values.yaml
├── values-dev.yaml
├── values-prod.yaml
└── templates/
    ├── deployment.yaml
    ├── service.yaml
    ├── ingress.yaml
    ├── configmap.yaml
    ├── secret.yaml
    └── hpa.yaml

Helm 部署 Pipeline

# Helm 部署配置
deploy:helm:
  stage: deploy
  image: alpine/helm:latest
  script:
    - helm repo add stable https://charts.helm.sh/stable
    - helm dependency update ./helm/java-tutorial
    - |
      helm upgrade --install java-tutorial ./helm/java-tutorial \
        --namespace java-tutorial \
        --create-namespace \
        --values ./helm/java-tutorial/values-${ENVIRONMENT}.yaml \
        --set image.tag=${CI_COMMIT_SHA} \
        --set image.repository=${DOCKER_REGISTRY}/java-tutorial \
        --wait --timeout=600s
    - helm test java-tutorial --namespace java-tutorial

8.10 效能監控與分析

📊 監控架構設計

完整監控堆疊

監控架構:
┌─────────────┐    ┌─────────────┐    ┌─────────────┐
│ Application │ →  │ Prometheus  │ →  │  Grafana    │
│   Metrics   │    │  (收集)      │    │  (視覺化)    │
└─────────────┘    └─────────────┘    └─────────────┘
       ↓                    ↓                  ↓
┌─────────────┐    ┌─────────────┐    ┌─────────────┐
│    Logs     │ →  │ AlertManager│    │   Alerts    │
│ (ELK Stack) │    │   (告警)     │    │   (通知)     │
└─────────────┘    └─────────────┘    └─────────────┘

🎯 應用程式監控設定

Spring Boot Actuator 配置

# application-prod.yml
management:
  endpoints:
    web:
      exposure:
        include: health,info,metrics,prometheus
  endpoint:
    health:
      show-details: when-authorized
    metrics:
      enabled: true
  metrics:
    export:
      prometheus:
        enabled: true
    distribution:
      percentiles-histogram:
        http.server.requests: true
      slo:
        http.server.requests: 50ms,100ms,200ms,300ms,500ms,1s

自訂 Metrics 範例

@RestController
@Slf4j
public class UserController {
    
    private final UserService userService;
    private final MeterRegistry meterRegistry;
    private final Counter userCreationCounter;
    private final Timer userQueryTimer;
    
    public UserController(UserService userService, MeterRegistry meterRegistry) {
        this.userService = userService;
        this.meterRegistry = meterRegistry;
        this.userCreationCounter = Counter.builder("user.creation.count")
            .description("使用者建立次數")
            .register(meterRegistry);
        this.userQueryTimer = Timer.builder("user.query.duration")
            .description("使用者查詢時間")
            .register(meterRegistry);
    }
    
    @PostMapping("/users")
    public ResponseEntity<User> createUser(@RequestBody UserDto userDto) {
        try {
            User user = userService.createUser(userDto);
            userCreationCounter.increment("status", "success");
            return ResponseEntity.ok(user);
        } catch (Exception e) {
            userCreationCounter.increment("status", "error");
            throw e;
        }
    }
    
    @GetMapping("/users/{id}")
    public ResponseEntity<User> getUser(@PathVariable Long id) {
        return userQueryTimer.recordCallable(() -> {
            User user = userService.getUserById(id);
            return ResponseEntity.ok(user);
        });
    }
}

📈 Grafana Dashboard 配置

Dashboard JSON 範例

{
  "dashboard": {
    "title": "Java Tutorial Application Metrics",
    "panels": [
      {
        "title": "Request Rate",
        "type": "graph",
        "targets": [
          {
            "expr": "rate(http_server_requests_seconds_count[5m])",
            "legendFormat": "{{method}} {{uri}}"
          }
        ]
      },
      {
        "title": "Response Time",
        "type": "graph",
        "targets": [
          {
            "expr": "http_server_requests_seconds{quantile=\"0.95\"}",
            "legendFormat": "95th percentile"
          },
          {
            "expr": "http_server_requests_seconds{quantile=\"0.50\"}",
            "legendFormat": "50th percentile"
          }
        ]
      },
      {
        "title": "Error Rate",
        "type": "graph",
        "targets": [
          {
            "expr": "rate(http_server_requests_seconds_count{status=~\"4..|5..\"}[5m])",
            "legendFormat": "Error Rate"
          }
        ]
      },
      {
        "title": "JVM Memory Usage",
        "type": "graph",
        "targets": [
          {
            "expr": "jvm_memory_used_bytes{area=\"heap\"}",
            "legendFormat": "Heap Used"
          },
          {
            "expr": "jvm_memory_max_bytes{area=\"heap\"}",
            "legendFormat": "Heap Max"
          }
        ]
      }
    ]
  }
}

🚨 告警規則設定

Prometheus Alert Rules

# alert-rules.yml
groups:
- name: java-tutorial-alerts
  rules:
  - alert: HighErrorRate
    expr: rate(http_server_requests_seconds_count{status=~"5.."}[5m]) > 0.1
    for: 2m
    labels:
      severity: critical
    annotations:
      summary: "應用程式錯誤率過高"
      description: "錯誤率超過 10% 已持續 2 分鐘"
      
  - alert: HighResponseTime
    expr: http_server_requests_seconds{quantile="0.95"} > 1
    for: 5m
    labels:
      severity: warning
    annotations:
      summary: "應用程式回應時間過長"
      description: "95% 回應時間超過 1 秒已持續 5 分鐘"
      
  - alert: HighMemoryUsage
    expr: (jvm_memory_used_bytes{area="heap"} / jvm_memory_max_bytes{area="heap"}) > 0.8
    for: 10m
    labels:
      severity: warning
    annotations:
      summary: "JVM 記憶體使用率過高"
      description: "Heap 記憶體使用率超過 80% 已持續 10 分鐘"
      
  - alert: ApplicationDown
    expr: up{job="java-tutorial"} == 0
    for: 1m
    labels:
      severity: critical
    annotations:
      summary: "應用程式無法連接"
      description: "應用程式已無法連接超過 1 分鐘"

8.11 實際案例研究

🏢 案例一:企業級 Java 微服務架構

專案背景

  • 大型電商平台後端系統
  • 20+ 個微服務
  • 日活躍用戶 100萬+
  • 峰值 QPS 10,000+

GitLab 實作架構

GitLab 組織架構:
Company Group
├── Platform Team
│   ├── api-gateway
│   ├── config-server
│   └── service-discovery
├── Business Team
│   ├── user-service
│   ├── order-service
│   ├── payment-service
│   └── inventory-service
└── Infrastructure Team
    ├── monitoring
    ├── logging
    └── deployment-scripts

Pipeline 策略

# 微服務共用 Pipeline 模板
include:
  - project: 'platform/ci-templates'
    file: '/templates/microservice-pipeline.yml'

variables:
  SERVICE_NAME: "user-service"
  SERVICE_PORT: "8080"
  
stages:
  - validate
  - build
  - test
  - security-scan
  - package
  - deploy-dev
  - integration-test
  - deploy-staging
  - performance-test
  - deploy-prod

# 微服務特定配置
microservice:build:
  extends: .build-template
  variables:
    MAVEN_PROFILES: "microservice"
    
microservice:deploy:
  extends: .deploy-template
  variables:
    REPLICAS: "3"
    RESOURCES_CPU: "500m"
    RESOURCES_MEMORY: "1Gi"

實際效益

  • 部署時間從 2 小時縮短至 15 分鐘
  • 程式碼品質問題減少 70%
  • 生產環境事故減少 60%
  • 開發效率提升 40%

🏦 案例二:金融服務 CI/CD 合規實作

合規要求

  • SOX 法案遵循
  • 四眼原則 (Four-eye principle)
  • 變更記錄追蹤
  • 安全掃描強制執行

合規 Pipeline 設計

# 金融合規 Pipeline
stages:
  - compliance-check
  - security-scan
  - code-review
  - approval
  - deploy

compliance:audit:
  stage: compliance-check
  script:
    - echo "檢查合規性要求"
    - python scripts/compliance-check.py
    - python scripts/sox-validation.py
  artifacts:
    reports:
      junit: compliance-report.xml

security:sast:
  stage: security-scan
  extends: .sast-template
  allow_failure: false  # 安全掃描必須通過

security:dependency:
  stage: security-scan
  extends: .dependency-scanning-template
  allow_failure: false

code:review:
  stage: code-review
  script:
    - echo "確認 Code Review 要求"
    - python scripts/verify-approvals.py --required=2
  rules:
    - if: '$CI_MERGE_REQUEST_TARGET_BRANCH_NAME == "main"'

deploy:production:
  stage: deploy
  script:
    - echo "部署到生產環境"
    - kubectl apply -f k8s/production/
  environment:
    name: production
  rules:
    - if: '$CI_COMMIT_TAG'
      when: manual
  needs:
    - compliance:audit
    - security:sast
    - security:dependency

🎓 案例三:教育平台敏捷開發

專案特色

  • 快速原型開發
  • 頻繁功能更新
  • 多環境並行測試
  • 學生作業自動評分

教育導向 Pipeline

# 教育平台特殊需求
stages:
  - build
  - test
  - deploy-preview
  - auto-grading
  - deploy-production

build:frontend:
  stage: build
  image: node:16
  script:
    - npm ci
    - npm run build
  artifacts:
    paths:
      - dist/

build:backend:
  stage: build
  image: maven:3.8.4-openjdk-17
  script:
    - mvn clean package
  artifacts:
    paths:
      - target/*.jar

deploy:preview:
  stage: deploy-preview
  script:
    - |
      # 每個 MR 建立預覽環境
      PREVIEW_URL="https://preview-${CI_MERGE_REQUEST_IID}.example.com"
      kubectl create namespace preview-${CI_MERGE_REQUEST_IID} || true
      envsubst < k8s/preview.yaml | kubectl apply -f -
      echo "預覽環境:$PREVIEW_URL"
  environment:
    name: preview/$CI_MERGE_REQUEST_IID
    url: https://preview-${CI_MERGE_REQUEST_IID}.example.com
    on_stop: cleanup:preview
  rules:
    - if: '$CI_MERGE_REQUEST_ID'

auto:grading:
  stage: auto-grading
  script:
    - python scripts/auto-grader.py
    - python scripts/plagiarism-check.py
  artifacts:
    reports:
      junit: grading-results.xml
  only:
    - /^assignment\/.*$/

學習成果

  • 學生提交作業到評分反饋時間從 24 小時縮短至 5 分鐘
  • 程式碼抄襲檢測準確率 95%
  • 教師工作量減少 60%
  • 學生滿意度提升 85%

8.12 未來趨勢與發展

🔮 新興技術整合

AI/ML 在 DevOps 中的應用

AI 輔助開發流程:
┌─────────────┐    ┌─────────────┐    ┌─────────────┐
│ 智慧 Code   │ →  │ 自動化測試   │ →  │ 預測性維護   │
│ Review      │    │ 案例生成     │    │ 和監控      │
└─────────────┘    └─────────────┘    └─────────────┘

實際應用範例

# AI 輔助的 Pipeline
ai:code-review:
  stage: analysis
  image: ai/code-analyzer:latest
  script:
    - ai-reviewer --language=java --output=review-report.json
    - python scripts/process-ai-feedback.py
  artifacts:
    reports:
      codequality: review-report.json

ai:test-generation:
  stage: test
  script:
    - ai-test-generator --source=src/main/java --output=src/test/java
    - mvn test -Dtest.pattern="*AIGenerated*"
  allow_failure: true

predictive:monitoring:
  stage: deploy
  script:
    - python scripts/anomaly-detection.py
    - python scripts/capacity-planning.py
  environment:
    name: production

🌐 雲原生與邊緣運算

GitOps 2.0 架構

下一代 GitOps 架構:
┌─────────────┐    ┌─────────────┐    ┌─────────────┐
│   Source    │ →  │   GitOps    │ →  │  Multi-Cloud│
│   Control   │    │  Operator   │    │  Deployment │
└─────────────┘    └─────────────┘    └─────────────┘
       │                    │                  │
       ↓                    ↓                  ↓
┌─────────────┐    ┌─────────────┐    ┌─────────────┐
│ Edge Nodes  │    │   Policy    │    │  Security   │
│ Management  │    │ Enforcement │    │ Compliance  │
└─────────────┘    └─────────────┘    └─────────────┘

🔒 零信任安全模型

未來安全架構

# 零信任 Pipeline 安全
zero-trust:security:
  stage: security
  script:
    - identity-verification --service=gitlab-ci
    - network-policy-validation --cluster=production
    - runtime-security-scan --image=$CI_REGISTRY_IMAGE:$CI_COMMIT_SHA
    - supply-chain-verification --sbom=sbom.json
  artifacts:
    reports:
      security: zero-trust-report.json

policy:enforcement:
  stage: governance
  script:
    - opa-policy-check --policies=security/policies/
    - compliance-validation --framework=sox,gdpr
    - risk-assessment --deployment=production

🚀 Platform Engineering 演進

內部開發者平台架構

Developer Platform Stack:
┌─────────────────────────────────────────────────────┐
│                Developer Portal                      │
├─────────────────────────────────────────────────────┤
│           Service Catalog & Templates               │
├─────────────────────────────────────────────────────┤
│    GitLab CI/CD    │    GitOps     │   Monitoring    │
├─────────────────────────────────────────────────────┤
│        Kubernetes         │      Infrastructure     │
└─────────────────────────────────────────────────────┘

自服務 Pipeline 模板

# 平台工程師提供的標準模板
include:
  - project: 'platform/templates'
    file: '/java/microservice.yml'
  - project: 'platform/templates'
    file: '/security/compliance.yml'
  - project: 'platform/templates'
    file: '/deployment/kubernetes.yml'

# 開發者只需要配置業務相關參數
variables:
  SERVICE_NAME: "my-service"
  SERVICE_TYPE: "microservice"
  COMPLIANCE_LEVEL: "high"
  ENVIRONMENT_TIER: "production"

# 自動套用平台標準
platform:standards:
  extends: .platform-template
  variables:
    AUTO_SCALING: "enabled"
    MONITORING: "full"
    SECURITY_SCAN: "required"

📊 可觀測性 3.0

下一代監控架構

# 統一可觀測性平台
observability:traces:
  stage: monitoring
  script:
    - jaeger-setup --service=$SERVICE_NAME
    - opentelemetry-config --auto-instrument=java
  environment:
    name: production

observability:metrics:
  stage: monitoring
  script:
    - prometheus-setup --service=$SERVICE_NAME
    - custom-metrics-config --business-kpis=true
  environment:
    name: production

observability:logs:
  stage: monitoring
  script:
    - elk-setup --service=$SERVICE_NAME
    - log-correlation --trace-id=true
  environment:
    name: production

💡 持續創新建議

組織文化發展

  1. 學習型組織

    • 定期技術分享會
    • 失敗後分析 (Blameless Postmortem)
    • 實驗驅動的創新文化
  2. 平台思維

    • 將 DevOps 工具視為產品
    • 內部客戶導向
    • 持續改善和反饋循環
  3. 社群參與

    • 參與開源專案
    • 技術會議和研討會
    • 知識分享與交流

技術評估框架

# 新技術評估範本

## 技術概述
- 技術名稱:
- 解決的問題:
- 替代方案比較:

## 評估標準
- [ ] 技術成熟度
- [ ] 社群活躍度
- [ ] 學習成本
- [ ] 整合複雜度
- [ ] 維護成本
- [ ] 安全性考量

## 實驗計畫
- POC 時程:
- 成功指標:
- 風險評估:
- 回滾計畫:

## 決策建議
- 推薦指數:⭐⭐⭐⭐⭐
- 實施優先級:高/中/低
- 預期效益:

9. 附錄

9.1 聯絡資訊

技術支援窗口

團隊協作平台

  • Slack 頻道:#dev-team、#gitlab-support
  • 團隊會議:每週三 14:00-15:00
  • 技術分享:每月第一個週五

9.2 參考資源

官方文件資源

學習資源連結

技術文章

9.3 工具推薦

Git GUI 工具

IDE 整合擴充功能

CLI 命令列工具

  • Hub - GitHub 命令列工具
  • glab - GitLab 官方命令列工具
  • tig - 文字模式的 Git 介面

監控與分析工具

安全工具


10. 補充主題

10.1 性能基準測試與優化

🎯 Pipeline 效能基準

基準測試指標

# 效能基準測試 Pipeline
performance:benchmark:
  stage: test
  image: maven:3.8.4-openjdk-17
  script:
    # 建置效能測試
    - mvn clean package -Pperformance
    
    # JMeter 負載測試
    - jmeter -n -t tests/load-test.jmx -l results.jtl
    
    # K6 效能測試
    - k6 run --out json=performance.json tests/performance.js
    
    # 分析結果
    - python scripts/analyze-performance.py
  artifacts:
    reports:
      performance: performance-report.json
    paths:
      - performance-report.html
  rules:
    - if: '$CI_COMMIT_BRANCH == "main"'
    - if: '$CI_MERGE_REQUEST_ID'
      changes:
        - "src/**/*.java"

效能監控範例

// 效能監控註解
@RestController
@Timed(name = "api.controller", description = "API 控制器效能監控")
public class UserController {
    
    @GetMapping("/users")
    @Timed(name = "api.users.list", description = "用戶列表查詢時間")
    public ResponseEntity<List<User>> listUsers(
            @RequestParam(defaultValue = "0") int page,
            @RequestParam(defaultValue = "20") int size) {
        
        // 記錄慢查詢
        Stopwatch stopwatch = Stopwatch.createStarted();
        try {
            List<User> users = userService.getUsers(page, size);
            return ResponseEntity.ok(users);
        } finally {
            Duration duration = stopwatch.elapsed();
            if (duration.toMillis() > 500) {
                log.warn("慢查詢檢測: 用戶列表查詢耗時 {}ms", duration.toMillis());
            }
        }
    }
}

10.2 災難恢復演練

🚨 DR 演練自動化

災難恢復 Pipeline

# 災難恢復演練
dr:drill:
  stage: test
  script:
    # 模擬災難場景
    - python scripts/simulate-disaster.py --scenario=database-failure
    
    # 執行恢復程序
    - ansible-playbook playbooks/disaster-recovery.yml
    
    # 驗證恢復結果
    - python scripts/verify-recovery.py
    
    # 生成演練報告
    - python scripts/generate-dr-report.py
  environment:
    name: dr-testing
  when: manual
  only:
    variables:
      - $DR_DRILL == "true"

10.3 合規自動化

📋 法規遵循檢查

自動合規檢查

# 合規性檢查 Pipeline
compliance:gdpr:
  stage: compliance
  script:
    - python scripts/gdpr-compliance-check.py
    - python scripts/data-privacy-scan.py
  artifacts:
    reports:
      compliance: gdpr-report.json

compliance:sox:
  stage: compliance
  script:
    - python scripts/sox-compliance-check.py
    - python scripts/financial-controls-audit.py
  artifacts:
    reports:
      compliance: sox-report.json

compliance:iso27001:
  stage: compliance
  script:
    - python scripts/iso27001-check.py
    - python scripts/security-controls-audit.py
  artifacts:
    reports:
      compliance: iso27001-report.json

10.4 成本優化策略

💰 CI/CD 成本管控

成本監控 Pipeline

# 成本分析與優化
cost:analysis:
  stage: analysis
  script:
    # 分析 Runner 使用率
    - python scripts/runner-utilization.py
    
    # 分析建置時間和資源消耗
    - python scripts/build-cost-analysis.py
    
    # 產生成本優化建議
    - python scripts/cost-optimization-suggestions.py
  artifacts:
    reports:
      cost: cost-analysis-report.json
  only:
    - schedules

# 資源清理
cleanup:unused:
  stage: cleanup
  script:
    # 清理過期的 Docker 映像
    - docker image prune -f --filter "until=168h"
    
    # 清理舊的 Pipeline artifacts
    - python scripts/cleanup-old-artifacts.py --days=30
    
    # 清理未使用的 K8s 資源
    - kubectl delete pods --field-selector=status.phase=Failed
  only:
    - schedules

結語與持續改進

這份全面的 GitLab 使用教學手冊現在包含了:

📚 完整內容涵蓋

  1. 基礎到進階:從入門到專家級應用
  2. 理論與實踐:概念解釋配合實際範例
  3. 最佳實務:業界標準和團隊經驗
  4. 未來導向:新興趨勢和技術展望

🎯 實用價值

  • 新進人員:完整的入門指南和檢查清單
  • 經驗開發者:進階功能和優化技巧
  • 團隊領導:流程設計和最佳實務
  • DevOps 工程師:自動化和監控策略

🔄 持續更新機制

建議建立以下更新流程:

  1. 季度檢討:評估文件內容是否符合實際需求
  2. 工具更新:跟隨 GitLab 版本更新調整內容
  3. 經驗分享:收集團隊使用經驗並持續改善
  4. 社群回饋:參考社群最佳實務和新趨勢

📈 成效追蹤

建議追蹤以下指標來評估文件效益:

  • 新進人員上手時間
  • 開發流程效率提升
  • 程式碼品質改善
  • 生產環境事故減少

💡 記住:工具和流程會不斷演進,最重要的是建立學習型團隊文化,持續改善和適應變化。


結語

這份 GitLab 使用教學手冊涵蓋了從基礎操作到進階整合的完整內容。隨著技術的不斷發展,建議團隊:

  1. 持續學習:關注 GitLab 的新功能和最佳實務
  2. 定期檢討:評估和優化現有的工作流程
  3. 知識分享:在團隊內分享經驗和技巧
  4. 工具評估:評估新工具和技術的導入可能性
  5. 文件維護:定期更新和完善團隊的開發規範

記住,工具只是手段,重要的是建立高效、安全、可維護的開發流程。希望這份手冊能幫助您和團隊更好地使用 GitLab,提升開發效率和程式碼品質。

📚 文件資訊

文件名稱:GitLab 使用教學手冊
版本:2.0
最後更新:2025年8月29日
維護者:開發團隊
文件格式:Markdown
授權:內部使用

📝 版本歷史

  • v2.0 (2025-08-29):重大更新 - 新增 GitLab Runner 深度配置、多環境部署策略、容器化整合、效能監控、實際案例研究、性能基準測試、災難恢復演練、合規自動化、成本優化等內容
  • v1.1 (2025-08-28):新增核心功能詳解、進階功能與整合章節,完善目錄結構
  • v1.0 (2024-01-15):初版發布,包含基礎操作和規範

💬 意見回饋

如有任何建議、問題或發現錯誤,請透過以下方式聯繫:

  • Issue 追蹤:在專案中建立 Issue

💡 這份文件會持續更新以反映最新的開發實務和工具功能。感謝您的使用和回饋!