GitLab 使用教學手冊#📋 目錄#GitLab 基本介紹
1.1 Git vs. GitLab - 基本概念1.2 為什麼選擇 GitLab?1.3 專案架構概覽1.4 GitLab 核心功能詳解專案工作流程說明
2.1 環境準備2.2 Clone - 複製專案到本地2.3 Pull - 同步遠端更新2.4 Commit - 提交變更2.5 Push - 推送變更到遠端2.6 Merge Request - 合併請求專案開發規範
3.1 分支策略3.2 Commit Message 規範3.3 Merge Request 流程3.4 Code Review 要求GitLab CI/CD 基本介紹
4.1 CI/CD 概念說明4.2 GitLab CI/CD 架構4.3 .gitlab-ci.yml 設定檔4.4 Java 專案 CI/CD 設定4.5 常用 CI/CD 指令4.6 本專案的 CI/CD 應用常見問題與解決方式
5.1 Merge 衝突處理5.2 錯誤回復方式5.3 分支管理問題5.4 權限和認證問題5.5 效能和同步問題5.6 CI/CD Pipeline 問題5.7 團隊協作問題開發最佳實務建議
6.1 程式碼管理最佳實務6.2 Code Review 最佳實務6.3 測試最佳實務6.4 安全性最佳實務6.5 效能最佳實務6.6 文件化最佳實務6.7 團隊協作最佳實務檢查清單
7.1 新進同仁入門檢查清單7.2 日常開發檢查清單7.3 Merge Request 檢查清單7.4 CI/CD 檢查清單7.5 發布檢查清單7.6 緊急情況檢查清單7.7 定期維護檢查清單進階功能與整合
8.1 GitLab API 整合8.2 第三方工具整合8.3 自動化與 DevOps8.4 安全性進階設定8.5 效能優化8.6 災難恢復8.7 GitLab Runner 深度配置8.8 多環境部署策略8.9 容器化與 Kubernetes 整合8.10 效能監控與分析8.11 實際案例研究8.12 未來趨勢與發展附錄
9.1 聯絡資訊9.2 參考資源9.3 工具推薦補充主題
10.1 性能基準測試與優化10.2 災難恢復演練10.3 合規自動化10.4 成本優化策略1. GitLab 基本介紹#1.1 Git vs. GitLab - 基本概念#Git#定義:分散式版本控制系統(Distributed Version Control System)功能:追蹤檔案變更、分支管理、合併操作特性:本地操作、離線工作、完整歷史記錄GitLab#定義:基於 Git 的 Web 平台,提供完整的 DevOps 生命週期管理功能:程式碼託管、專案管理、CI/CD、Code Review、Issue 追蹤優勢:團隊協作、視覺化介面、自動化部署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 標籤系統#標籤類型:
類型標籤:bug、feature、enhancement、documentation優先級:priority::high、priority::medium、priority::low狀態標籤:status::todo、status::in-progress、status::review模組標籤:frontend、backend、database、api標籤使用策略:
標籤組合範例:
├── 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開發權限可推送程式碼、建立 MRReporter檢視權限可檢視程式碼、建立 IssueGuest受限權限僅可檢視公開內容👥 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 使用範例:
🔒 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 compileRunner 設定:
# 註冊 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
"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 true2.2 Clone - 複製專案到本地#🎯 操作步驟#取得專案 URL
進入 GitLab 專案頁面點選 “Clone” 按鈕複製 HTTPS 或 SSH URL執行 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進入專案目錄cd project-name
ls -la # 查看專案檔案⚠️ 注意事項#首次 Clone 會下載完整的專案歷史確保網路連線穩定,大型專案可能需要較長時間Clone 後檢查分支狀態:git branch -a2.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 - 提交變更#🎯 提交流程#檢查變更狀態# 查看檔案狀態
git status
# 查看具體變更內容
git diff
git diff --staged # 查看已加入暫存區的變更加入暫存區# 加入特定檔案
git add src/main/java/com/example/Service.java
# 加入所有變更檔案
git add .
# 加入特定類型檔案
git add "*.java"執行提交# 提交變更
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..HEAD2.6 Merge Request - 合併請求#🎯 建立 Merge Request#在 GitLab Web 介面
推送分支後,GitLab 會顯示建立 MR 的提示點選 “Create merge request”填寫 MR 資訊
標題:簡潔描述變更內容描述:詳細說明變更原因、實作方式、測試結果指派審查者:選擇適當的 Code Reviewer標籤:加入相關標籤(feature、bugfix、hotfix等)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 (維護分支)🎯 分支說明#分支類型命名規則用途生命週期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🔄 分支操作流程#建立功能分支# 從 develop 建立新功能分支
git checkout develop
git pull origin develop
git checkout -b feature/user-profile-update完成功能開發# 提交變更
git add .
git commit -m "feat: 新增使用者資料更新功能"
git push -u origin feature/user-profile-update建立 Merge Request# 在 GitLab 建立 MR: feature/user-profile-update → develop3.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 流程#🎯 MR 建立流程#準備階段# 確保分支是最新的
git checkout feature/my-feature
git fetch origin
git rebase origin/develop建立 MR
進入 GitLab 專案頁面點選 “Merge Requests” → “New merge request”選擇來源分支和目標分支填寫 MR 資訊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 流程#提交 Review
仔細檢查程式碼變更提供建設性意見標示 Request Changes 或 Approve回應 Review
及時回應審查意見修正問題後重新提交解釋設計決策(如需要)最終審查
確認所有意見已處理執行最終測試核准合併💡 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 │
│ │ │ │ │ │ │ │
│ • 編譯程式碼 │ │ • 單元測試 │ │ • 部署到測試 │ │ • 健康檢查 │
│ • 相依性檢查 │ │ • 整合測試 │ │ • 部署到正式 │ │ • 效能監控 │
│ • 程式碼掃描 │ │ • 安全掃描 │ │ • 資料庫更新 │ │ • 錯誤追蹤 │
└─────────────┘ └─────────────┘ └─────────────┘ └─────────────┘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
- develop4.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 artifacts4.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"📋 工作流程整合#開發者推送程式碼 → 觸發 Pipeline自動建置和測試 → 確保程式碼品質Code Review 通過 → 合併到目標分支自動部署 → 根據分支策略部署到對應環境監控和回饋 → 持續改善流程💡 最佳實務建議#失敗快速回饋:優先執行快速測試,儘早發現問題並行執行:合理使用 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
# 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 mergetool5.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 main5.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 origin5.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 -ad5.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 意見分歧#解決策略:
技術討論:在 MR 中詳細解釋設計決策離線溝通:必要時進行面對面討論團隊共識:遵循團隊既定的編碼規範妥協方案:尋求雙方都能接受的解決方案問題 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 origin6.2 Code Review 最佳實務#👀 審查者角度#審查重點#功能正確性// ✅ 檢查邊界條件
public List
if (page < 0 || size <= 0 || size > 100) {
throw new IllegalArgumentException("Invalid pagination parameters");
}
// ...
}
// ❌ 缺少參數驗證
public List
return userRepository.findAll(PageRequest.of(page, size));
}安全性檢查// ✅ 防止 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);效能考量// ✅ 批次處理
public void updateUsers(List
userRepository.saveAll(users); // 批次儲存
}
// ❌ 逐一處理
public void updateUsers(List
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
// @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
return userService.getAllUsers();
}
@DeleteMapping("/users/{id}")
@PreAuthorize("hasAuthority('USER_DELETE')")
public ResponseEntity
userService.deleteUser(id);
return ResponseEntity.ok().build();
}
}6.5 效能最佳實務#⚡ 程式碼效能#資料庫查詢優化#// ✅ 使用投影和分頁
@Repository
public interface UserRepository extends JpaRepository
@Query("SELECT new com.example.dto.UserSummaryDto(u.id, u.name, u.email) " +
"FROM User u WHERE u.active = true")
Page
// 使用 @EntityGraph 避免 N+1 查詢
@EntityGraph(attributePaths = {"roles", "profile"})
Optional
}
// ❌ 查詢過多資料
public List
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
@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.name 和 user.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 status 和 git 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 執行時間 檢查測試執行效率 檢查建置快取效果📈 每月檢討# 團隊回顧 檢討開發流程效率 分析常見問題 討論改善建議 更新最佳實務📞 聯絡資訊#技術支援#GitLab 管理員:admin@company.comDevOps 團隊:devops@company.com技術支援熱線:分機 1234團隊協作#Slack 頻道:#dev-team、#gitlab-support團隊會議:每週三 14:00-15:00技術分享:每月第一個週五📚 參考資源#官方文件#GitLab 官方文件Git 官方文件Conventional Commits學習資源#Pro Git 電子書GitLab CI/CD 教學Git Flow 工作流程工具推薦#GitKraken - Git GUI 工具Sourcetree - 免費 Git GUIGitLens - VS Code 擴充功能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
@RequestHeader("X-Gitlab-Event") String event,
@RequestBody Map
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 和 MRGitLens:增強的 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:
- mainArgoCD 整合:
# 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
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 pruneRepository 清理:
# 清理無效參照
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: 28.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🆘 災難恢復流程#恢復步驟:
評估損害程度準備恢復環境恢復應用程式資料恢復設定檔驗證系統功能通知使用者恢復指令:
# 停止 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 start8.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: manual8.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:
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.yamlHelm 部署 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-tutorial8.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
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
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-scriptsPipeline 策略:
# 微服務共用 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💡 持續創新建議#組織文化發展:
學習型組織:
定期技術分享會失敗後分析 (Blameless Postmortem)實驗驅動的創新文化平台思維:
將 DevOps 工具視為產品內部客戶導向持續改善和反饋循環社群參與:
參與開源專案技術會議和研討會知識分享與交流技術評估框架:
# 新技術評估範本
## 技術概述
- 技術名稱:
- 解決的問題:
- 替代方案比較:
## 評估標準
- [ ] 技術成熟度
- [ ] 社群活躍度
- [ ] 學習成本
- [ ] 整合複雜度
- [ ] 維護成本
- [ ] 安全性考量
## 實驗計畫
- POC 時程:
- 成功指標:
- 風險評估:
- 回滾計畫:
## 決策建議
- 推薦指數:⭐⭐⭐⭐⭐
- 實施優先級:高/中/低
- 預期效益:9. 附錄#9.1 聯絡資訊#技術支援窗口#GitLab 管理員:admin@company.comDevOps 團隊:devops@company.com技術支援熱線:分機 1234團隊協作平台#Slack 頻道:#dev-team、#gitlab-support團隊會議:每週三 14:00-15:00技術分享:每月第一個週五9.2 參考資源#官方文件資源#GitLab 官方文件Git 官方文件Conventional Commits學習資源連結#Pro Git 電子書GitLab CI/CD 教學Git Flow 工作流程技術文章#GitLab 最佳實務指南DevOps 文化建立安全開發生命週期9.3 工具推薦#Git GUI 工具#GitKraken - 功能強大的 Git GUI 工具Sourcetree - 免費的 Git GUI 工具Git Extensions - Windows 平台 Git 工具IDE 整合擴充功能#GitLens - VS Code Git 增強擴充功能GitLab Workflow - VS Code GitLab 整合Git History - Git 歷史檢視器CLI 命令列工具#Hub - GitHub 命令列工具glab - GitLab 官方命令列工具tig - 文字模式的 Git 介面監控與分析工具#GitLab Insights - 專案洞察分析Grafana - 監控儀表板Prometheus - 監控和警報工具安全工具#GitLab Security Dashboard - 安全儀表板OWASP ZAP - 安全測試工具Snyk - 漏洞掃描工具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> listUsers(
@RequestParam(defaultValue = "0") int page,
@RequestParam(defaultValue = "20") int size) {
// 記錄慢查詢
Stopwatch stopwatch = Stopwatch.createStarted();
try {
List
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.json10.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 使用教學手冊現在包含了:
📚 完整內容涵蓋#基礎到進階:從入門到專家級應用理論與實踐:概念解釋配合實際範例最佳實務:業界標準和團隊經驗未來導向:新興趨勢和技術展望🎯 實用價值#新進人員:完整的入門指南和檢查清單經驗開發者:進階功能和優化技巧團隊領導:流程設計和最佳實務DevOps 工程師:自動化和監控策略🔄 持續更新機制#建議建立以下更新流程:
季度檢討:評估文件內容是否符合實際需求工具更新:跟隨 GitLab 版本更新調整內容經驗分享:收集團隊使用經驗並持續改善社群回饋:參考社群最佳實務和新趨勢📈 成效追蹤#建議追蹤以下指標來評估文件效益:
新進人員上手時間開發流程效率提升程式碼品質改善生產環境事故減少💡 記住:工具和流程會不斷演進,最重要的是建立學習型團隊文化,持續改善和適應變化。
結語#這份 GitLab 使用教學手冊涵蓋了從基礎操作到進階整合的完整內容。隨著技術的不斷發展,建議團隊:
持續學習:關注 GitLab 的新功能和最佳實務定期檢討:評估和優化現有的工作流程知識分享:在團隊內分享經驗和技巧工具評估:評估新工具和技術的導入可能性文件維護:定期更新和完善團隊的開發規範記住,工具只是手段,重要的是建立高效、安全、可維護的開發流程。希望這份手冊能幫助您和團隊更好地使用 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💡 這份文件會持續更新以反映最新的開發實務和工具功能。感謝您的使用和回饋!