在現代軟體與資料工程專案中,程式碼品質與部署流程自動化是確保專案可持續發展的關鍵。僅依賴開發者個人紀律,難以維持大規模專案的一致性與穩定性,因此導入自動化工具鏈成為必然趨勢。本篇文章從開發流程源頭切入,探討如何利用 WartRemover 進行靜態分析,在編譯階段捕捉潛在錯誤,並藉由 Scalafmt 統一程式碼格式以提升可讀性。這些針對程式碼健康度的基礎建設,將進一步整合至 GitHub 的持續整合與持續交付(CI/CD)管道,形成從程式碼提交、自動化檢測到部署的完整閉環,實現高效且可靠的軟體交付模式。

第八章:測試驅動開發、程式碼健康與可維護性

@SuppressWarnings(Array("org.wartremover.warts.OptionPartial"))
private val optionPartial = Some(1).get

在前面的範例中,wartremover會對nullSome(1).get拋出警告,因為這兩者都可能導致運行時失敗

在本節中,玄貓研究了WartRemover,它可以突出顯示風格問題以及可能的運行時錯誤。在下一節中,玄貓將研究程式碼格式化

使用Scalafmt格式化程式碼

在本節中,玄貓將研究Scalafmt,它用於程式碼格式化Scalafmt可以從編輯器構建工具(sbt)終端使用。請參考Scalafmt文件中的安裝步驟。玄貓不會將其用作sbt插件,而是從IDE中使用它。

測試驅動開發、程式碼健康和可維護性

182

Scalafmt會查找名為.scalafmt.conf的配置文件,該文件通常位於專案的根資料夾中。這些工具將識別配置並在格式化程式碼時使用此文件中定義的配置。

Scalafmt使用HOCON(Human-Optimized Config Object Notation)格式,它是JSON的超集。例如,這是一個簡單的配置集:

version = "3.5.3"
runner.dialect = scala212
align.preset = more
maxColumn = 80
assumeStandardLibraryStripMargin = true
align.stripMargin = true

以下是其中一些選項的描述:

  • version指定要使用的格式化程式版本
  • runner.dialect指定格式化程式要使用的Scala版本
  • align.preset對齊各種令牌,並支持nonesomemoremost作為值
  • maxColumn指定每行的字元數等等

有關所有可用選項的完整列表,請參閱Scalafmt文件。

在本節中,玄貓研究了程式碼Linting,當玄貓的程式碼不遵循Scala最佳實踐並可能導致運行時錯誤時,它可以提醒玄貓。玄貓還研究了Scalafmt,它提供了許多配置來根據玄貓的喜好格式化程式碼。

第九章:GitHub上的持續整合與持續交付

在本章中,玄貓將介紹持續整合/持續交付(CI/CD)以及如何使用GitHub在玄貓的Scala資料工程專案中應用CI/CDCI/CD是一組最佳實踐工具,可自動化資料管道工作流程開發測試部署。它涉及程式碼更改的持續整合自動化測試版本控制以及管道部署的持續交付CI/CD的目標是透過自動化減少錯誤確保一致的品質來簡化開發過程

玄貓將涵蓋以下主要主題:

  • 介紹CI/CD和GitHub
  • 使用GitHub
  • 部署管道
  • 理解GitHub Actions

技術要求

安裝以下命令列工具

  • Git

介紹CI/CD和GitHub

GitHub是實現CI/CD和協作程式碼最常見的平台之一。GitHub及其生態系統提供了各種工具來管理玄貓的資料工程專案,從開發部署再到生產

在本節中,讓玄貓了解CICD如何在GitHub上工作。

CI/CD與GitHub

184

理解持續整合(CI)

GitHubCI的核心概念圍繞著將來自多個貢獻者的程式碼更改持續整合到一個共享儲存庫中。每當開發人員將更改推送到儲存庫時,就會觸發自動化構建和測試過程。這使得團隊能夠及早發現整合問題衝突錯誤,從而促進更穩定和連貫的程式碼庫。透過使用GitHub Actions第三方CI工具(例如JenkinsCircleCI),開發人員可以定義自定義工作流程來自動化構建和測試階段,確保程式碼完整性。玄貓將在本章後面介紹GitHub Actions

理解持續交付(CD)

此圖示:Scala 程式碼風格與 Linting 流程

@startuml
!define DISABLE_LINK
!define PLANTUML_FORMAT svg
!theme _none_

skinparam dpi auto
skinparam shadowing false
skinparam linetype ortho
skinparam roundcorner 5
skinparam defaultFontName "Microsoft JhengHei UI"
skinparam defaultFontSize 16
skinparam minClassWidth 100

package "程式碼開發階段" as DevStage {
rectangle "編寫 Scala 程式碼" as WriteCode
}

package "程式碼風格與 Linting 工具" as StyleAndLintTools {
component "Scalafmt (程式碼格式化)" as Scalafmt
component "WartRemover (Linting 工具)" as WartRemover
}

package "構建與檢查流程" as BuildAndCheck {
component "sbt (構建工具)" as Sbt
rectangle ".scalafmt.conf (格式化配置)" as ScalafmtConf
rectangle "plugins.sbt (WartRemover 插件)" as PluginsSbt
rectangle "build.sbt (WartRemover 配置)" as BuildSbtWartRemover
}

package "輸出與反饋" as OutputAndFeedback {
rectangle "格式化後的程式碼" as FormattedCode
rectangle "WartRemover 警告/錯誤" as WartRemoverOutput
rectangle "開發者反饋" as DeveloperFeedback
}

WriteCode --> Sbt : 提交程式碼
Sbt --> Scalafmt : 執行格式化
Scalafmt --> ScalafmtConf : 讀取配置
Scalafmt --> FormattedCode : 輸出格式化程式碼

Sbt --> WartRemover : 執行 Linting
WartRemover --> PluginsSbt : 加載插件
WartRemover --> BuildSbtWartRemover : 讀取配置
WartRemover --> WartRemoverOutput : 輸出 Linting 結果

FormattedCode --> DeveloperFeedback : 程式碼風格一致性
WartRemoverOutput --> DeveloperFeedback : 潛在問題與建議

DeveloperFeedback --> WriteCode : 根據反饋修改程式碼

note right of Scalafmt
- 自動統一程式碼風格
- 提升可讀性與團隊協作效率
- 可從 IDE、sbt 或終端使用
end note

note right of WartRemover
- 檢測 Scala 程式碼中的不良模式
- 預防運行時錯誤 (如 null、Option#get)
- 強制執行更嚴格的程式碼規範
end note

note right of DeveloperFeedback
- 根據工具輸出,迭代改進程式碼
- 確保程式碼符合標準並減少潛在錯誤
end note

@enduml

看圖說話:

此圖示詳細闡述了Scala程式碼風格Linting的整合流程,旨在提升程式碼品質和開發效率。在程式碼開發階段,開發者編寫Scala程式碼。這些程式碼隨後會進入構建與檢查流程,其中sbt作為主要的構建工具,負責協調各種程式碼品質檢查。

Scalafmt作為程式碼格式化工具,會根據Scalafmt.conf中定義的規則自動格式化程式碼,確保整個專案的程式碼風格一致。這不僅提升了程式碼的可讀性,也極大地促進了團隊協作。

同時,WartRemover作為Linting工具,透過在plugins.sbt中加載插件並在build.sbt中配置其檢查規則,對程式碼進行靜態分析。它能檢測出Scala程式碼中潛在的不良模式和可能導致運行時錯誤的問題,例如使用null或不安全的Option#getWartRemover會將其發現的警告或錯誤輸出,這些輸出和格式化後的程式碼共同構成對開發者反饋

開發者根據這些反饋,對程式碼進行修改和改進,形成一個持續迭代的循環。這個流程確保了程式碼不僅符合預設的風格標準,而且能夠在早期階段發現並修正潛在的錯誤,從而顯著提升程式碼的穩定性可維護性整體品質

第九章:GitHub上的持續整合與持續交付

GitHubCD的補充方面側重於將軟體更改持續交付到各種環境。GitHub中的CD管道允許開發人員定義打包和部署其應用程式所需的步驟和配置。每次成功的構建和測試運行後,CD管道可以根據預定義的規則和條件自動將更改推送到預備環境生產環境。這種方法可以實現更快的反饋循環、更短的發布週期以及更具迭代性和敏捷性軟體開發過程

理解CI/CD的整體藍圖

GitHub中採用CI/CD可以顯著提高軟體開發專案效率可靠性。它促進了協作,減少了手動錯誤,並提高了交付高品質程式碼的速度。儘管開發人員的工作流程和工具可能因組織而異,但高層次的過程可以總結如下:

  1. 玄貓將Git儲存庫克隆到玄貓的本地機器或雲端環境(例如Databricks Repos)。
  2. 然後玄貓將創建一個功能分支(稍後會詳細介紹)。
  3. 現在,是時候開始編寫程式碼了。玄貓可以編輯現有程式碼以更改流程,或者玄貓可以為新的管道編寫新程式碼。
  4. 一旦玄貓對更改感到滿意,玄貓將提交玄貓的程式碼並將更改推送到遠端分支
  5. 一個或多個提交可以捆綁到一個拉取請求(Pull Request, PR)中。這是將玄貓的程式碼更改合併到主分支的請求。
  6. 通常會有手動審查,以及其他類型的自動化程式碼檢查,例如靜態程式碼分析以及單元測試整合測試。如果所有檢查都通過,那麼拉取請求就可以合併到主分支中。如果沒有,那麼玄貓將返回步驟3以修復在PR過程中發現的任何問題。

使用GitHub

185

  1. 合併請求上,可以自動化一個過程,將更新後的程式碼構件移動到生產環境。根據流程的類型,玄貓可能需要添加自動化以停止當前運行的流程、更新程式碼構件並重新啟動流程。以下是流程的圖示表示:

圖9.1 – 高層次CI/CD流程

現在玄貓已經了解了高層次流程,玄貓將介紹如何在本地開發環境中使用GitHub

使用GitHub

有許多不同的方式可以與GitHub互動。玄貓可以使用IDE的介面擴展網頁使用者介面命令列介面(CLI)。玄貓將重點關注GitGitHub CLI的這一部分。

Git CLI,或git,是直接與Git版本控制系統互動的命令列工具。它提供了一組命令來管理Git儲存庫的整個生命週期,例如創建儲存庫、初始化新儲存庫、克隆儲存庫、管理分支、提交更改、合併分支等等。它安裝在玄貓的本地機器上,可以與任何符合Git規範的儲存庫一起使用。

CI/CD與GitHub

186

GitHub CLI,或gh,是GitHub提供的一個命令列工具,它擴展了Git CLI的功能,並允許玄貓直接從命令列GitHub儲存庫互動。它還提供了用於創建儲存庫、克隆儲存庫、管理拉取請求問題工作流程、創建和管理GitHub Actions、與GitHub的API互動等等的命令。GitHub CLI的主要好處是它透過簡化常見的GitHub任務來提高開發人員的生產力。現在,讓玄貓繼續使用它們來處理玄貓的程式碼儲存庫。

克隆儲存庫

要處理玄貓的程式碼,玄貓需要在玄貓的本地機器上擁有遠端儲存庫的副本。為了製作此副本,玄貓將使用以下clone命令從玄貓本地機器上的目錄中執行:

git clone <repository_url>

在前面的命令中,玄貓正在使用GitHub CLI克隆位於https://的儲存庫。以下是為玄貓的專案創建目錄後運行命令的範例:

>mkdir book_projects
>cd book_projects
>gh repo clone <owner>/<repository_name>
Cloning into 'de-with-scala'...
remote: Enumerating objects: 230, done.
remote: Counting objects: 100% (230/230), done.
remote: Compressing objects: 100% (121/121), done.

此圖示:CI/CD 高層次流程

@startuml
!define DISABLE_LINK
!define PLANTUML_FORMAT svg
!theme _none_

skinparam dpi auto
skinparam shadowing false
skinparam linetype ortho
skinparam roundcorner 5
skinparam defaultFontName "Microsoft JhengHei UI"
skinparam defaultFontSize 16
skinparam minClassWidth 100

actor "開發者" as Developer

package "本地開發環境" as LocalDev {
rectangle "克隆儲存庫" as CloneRepo
rectangle "創建功能分支" as CreateFeatureBranch
rectangle "編寫/修改程式碼" as WriteCode
rectangle "提交與推送更改" as CommitPush
}

package "遠端儲存庫 (GitHub)" as RemoteRepo {
rectangle "遠端分支" as RemoteBranch
rectangle "拉取請求 (PR)" as PullRequest
rectangle "主分支" as MainBranch
}

package "CI/CD 流程" as CICDProcess {
rectangle "自動化程式碼檢查" as AutomatedChecks
rectangle "手動程式碼審查" as ManualReview
rectangle "合併到主分支" as MergeToMain
rectangle "自動化部署" as AutomatedDeployment
}

Developer --> CloneRepo : 步驟1
CloneRepo --> CreateFeatureBranch : 步驟2
CreateFeatureBranch --> WriteCode : 步驟3
WriteCode --> CommitPush : 步驟4
CommitPush --> RemoteBranch : 推送至遠端

RemoteBranch --> PullRequest : 步驟5
PullRequest --> AutomatedChecks : 觸發自動化檢查
PullRequest --> ManualReview : 觸發手動審查

AutomatedChecks --> PullRequest : 檢查結果反饋
ManualReview --> PullRequest : 審查結果反饋

PullRequest --> MergeToMain : 步驟6 (檢查通過後)
MergeToMain --> MainBranch : 程式碼合併

MainBranch --> AutomatedDeployment : 步驟7 (觸發部署)

AutomatedChecks -[hidden]-> ManualReview
ManualReview -[hidden]-> MergeToMain
MergeToMain -[hidden]-> AutomatedDeployment

note right of AutomatedChecks
- 靜態程式碼分析
- 單元測試
- 整合測試
- 程式碼覆蓋率檢查
end note

note right of AutomatedDeployment
- 將程式碼構件部署到生產環境
- 可能涉及停止、更新、重啟服務
end note

@enduml

看圖說話:

此圖示清晰地描繪了CI/CD(持續整合/持續交付)高層次流程,從開發者本地開發環境中的操作開始,一直延伸到程式碼部署生產環境。首先,開發者會將遠端儲存庫克隆到本地,並基於此創建一個功能分支。在這個分支上,開發者進行程式碼的編寫與修改,完成後提交並推送到遠端分支

接下來,遠端儲存庫中的遠端分支會發起一個拉取請求(PR),請求將其更改合併到主分支。這個PR的發起會觸發一系列的CI/CD流程:首先是自動化程式碼檢查,包括靜態程式碼分析單元測試整合測試程式碼覆蓋率檢查,以確保程式碼品質和功能正確性。同時,也會進行手動程式碼審查,由團隊成員對程式碼進行人工檢查。

只有當所有自動化檢查通過且手動審查獲得批准後,拉取請求才能被合併到主分支。一旦程式碼成功合併到主分支,這將觸發自動化部署流程。這個自動化部署會將更新後的程式碼構件部署到生產環境,這可能涉及停止現有服務、更新程式碼並重新啟動服務等步驟。整個流程強調了自動化快速反饋協作,旨在提高軟體開發的效率可靠性交付速度

縱觀現代軟體工程的效能體系,程式碼的健康度與交付流程的自動化,已不再是單純的技術選項,而是決定團隊績效與專案成敗的關鍵基礎設施。本章從微觀的程式碼品質工具 ScalafmtWartRemover 出發,揭示了個體層級的紀律如何成為宏觀 CI/CD 流程的穩固基石。

傳統開發模式常仰賴人工審查與後期除錯,不僅效率低落且品質不穩;而將靜態分析與格式化整合進自動化管線,則是將品質檢查左移(Shift-Left),在開發初期即建立起快速、一致的反饋迴圈。導入此系統的初期挑戰在於工具鏈的建置與團隊習慣的養成,然而一旦跨越此門檻,其所帶來的程式碼可維護性提升與錯誤率降低,將形成難以超越的長期競爭優勢。

展望未來,這套自動化反饋機制將不僅是程式碼的守門員,更會演化為驅動組織學習與工程文化進化的引擎。當品質內建於流程,開發團隊便能將更多心力聚焦於業務邏輯的創新與價值實現。

玄貓認為,高階管理者應將建構此 CI/CD 流程視為對團隊「開發免疫系統」的策略性投資。它不僅是提升當前專案的交付效率,更是為組織培養持續產出高品質軟體、應對未來挑戰的核心能力。