时光地下铁

Software is a great combination of art and engineering.

0%

项目管理平台搭建:以iOS开发为例

项目管理平台搭建:以iOS开发为例

在中大型项目中,目前主流的开发方式都是组件化开发,根据项目业务的大小,工程中组件一般会有几十,上百,甚至上千组件,如何在项目开发中合理的管理组件,管理项目版本,进行项目开发是个棘手的问题。

解决方案概览

  • 目标:以标准化的组件模型、清晰的版本策略、可持续的交付流程,降低多组件协作成本,提升发布稳定性与可预测性。
  • 关键做法
    • 组件管理:统一命名规范、目录结构、依赖图与可见性边界,使用注册中心进行组件发现与治理。
    • 版本管理:采用语义化版本(SemVer),配合发布列车(Release Train)与自动化变更日志。
    • 项目开发流程:以持续集成为核心,建立变更评审、质量门禁、二进制产物缓存与可回滚发布机制。

根据该方案,建设项目后台进行统一管理,可快速进行项目开发,组件维护,推进发布列车(Release Train)。


组件管理

1. 组件边界与命名规范

  • 命名Company.Feature.[Subfeature].Kit(对外 API);Company.Feature.[Subfeature].Internal(内部实现)
  • 分层
    • 基础层(Foundation/Utility):无业务依赖,只提供通用能力
    • 业务域层(Domain):封装核心业务域模型与用例
    • UI 组合层(UI/FeatureKit):面向场景的 UI 与交互
  • 可见性:默认最小可见性,面向接口编程;公共 API 经评审后暴露。

2. 组件目录结构(iOS 建议)

  • Sources/ 源码(Swift/Objective-C)
  • Resources/ 资源(Assets、xib、lottie、strings)
  • Tests/ 单元与快照测试
  • DemoApp/ 独立示例(便于本地快速验证)
  • Docs/ 使用说明与 API 文档

3. 依赖与注册中心

  • 依赖管理:优先使用 SPM(Swift Package Manager),历史项目可逐步从 CocoaPods/Carthage 迁移。
  • 注册中心
    • SPM:集中式 Package Collections 或公司内源 Git 仓库作为源
    • Pods:私有 Specs 仓库(如 git@company/podspecs.git
  • 依赖约束
    • 严禁环依赖;限制跨层依赖(仅向下依赖)。
    • 核心组件对外以协议 + 适配器形式暴露,避免实现泄漏。

4. 组件质量门禁

  • 静态检查:SwiftLint/Clang-Tidy 必过
  • 单元测试覆盖率阈值:核心组件 ≥ 70%,业务组件 ≥ 50%
  • 快照/UI 测试:关键 UI 组件建立基线图
  • API 变更审查:公共 API 的破坏性变更必须标注 @available(*, deprecated, message:) 并提供迁移指南

版本管理

1. 语义化版本(SemVer)

  • MAJOR.MINOR.PATCH
    • MAJOR:破坏性变更(breaking changes)
    • MINOR:向后兼容的新功能
    • PATCH:向后兼容的修复

2. 分支管理与发布策略(大型项目实践详解)

分支管理

以主干分支(如 mainmaster)为基础,进行多分支开发时,推荐如下操作步骤:

  1. 主干分支(Trunk/Main)

    • 主干分支始终保持可构建、可发布状态,代表当前最新的稳定开发基线。
    • 例如,主干当前版本为 1.1.0
  2. 开发分支的创建与命名

    • 针对不同的需求或任务,从主干分支拉取独立的开发分支,分支命名可采用版本号递增方式,如 1.1.11.1.2,也可结合具体功能(如 feature/xxx)。
    • 示例流程:
      • main(当前为 1.1.0)拉取 1.1.1 分支,开发 A 需求。
      • main 拉取 1.1.2 分支,开发 B 需求。
    • 每个开发分支只聚焦于单一需求或缺陷,便于后续管理和回溯。
  3. 开发与合并流程

    • 在各自的开发分支(如 1.1.11.1.2)上完成开发与自测。
    • 开发完成后,通过 Pull Request(PR)方式将变更合并回主干分支(main)。
    • 合并前需通过代码评审、自动化测试和质量门禁,确保主干稳定。
  4. 发版与分支管理

    • 当主干达到可发布状态(如合并了 1.1.11.1.2 的变更),可从主干切出预发布分支(如 release/1.2.0),用于回归测试和最终修复。
    • 预发布分支只接受 bugfix、文档和发布相关变更,禁止新特性合入。
    • 发布完成后,将 release/1.2.0 分支的修复合并回主干,并打上对应的 tag(如 v1.2.0)。
  5. 发版后的操作

    • 若后续有新需求或修复,继续从主干拉取新的开发分支(如 1.2.11.2.2),重复上述流程。
    • 若线上已发布版本出现紧急问题,可直接从对应 tag 或主干切出 hotfix/1.2.0 分支,修复后合并回主干和相关 release 分支,并发布补丁版本。
  6. 分支合并与同步

    • 所有 bugfix 或 hotfix 修复,需确保合并回主干,并根据需要同步到其他活跃分支,避免遗漏。

发布策略

  • 发布列车(Release Train)机制
    采用固定节奏的发布列车(如每两周或每月一班),所有已合并到主干且通过质量门禁的变更,统一纳入下一个发布周期。未能按期合入的变更自动顺延至下班列车,确保发布节奏可预测、风险可控。
  • 版本冻结与回归测试
    在发布列车发车前,release 分支进入“冻结”状态,仅允许修复阻断性缺陷。此阶段需进行全面回归测试,确保版本稳定性。
  • 自动化与可追溯性
    发布流程应高度自动化,包括构建、测试、打包、生成变更日志、打 tag、推送产物到注册中心等。每次发布均需记录版本号、发布时间、变更内容及责任人,便于后续追溯与回滚。
  • 灰度与回滚机制
    支持灰度发布(如先在部分环境/用户中上线),并提供一键回滚方案,降低发布风险。

3. 变更日志与标签

  • 自动生成 CHANGELOG.md(根据 Conventional Commits 或 PR 标签)
  • Git Tag:component-name@x.y.z,并在注册中心同步版本元数据(作者、变更类型、依赖变更)

4. 依赖版本约束策略

  • 应用侧依赖:~> x.y(允许补丁更新,控制小版本)
  • 组件间依赖:对上游保持更严格范围,避免雪崩式升级
  • 引入新主版本时先在灰度分支验证,再推广到 main

项目开发流程(端到端)

1) 设计与评审

  • ADR(架构决策记录)描述边界/依赖/API
  • 评审通过后生成任务并绑定里程碑/列车班次
    2) 开发与自测
  • 本地通过 DemoApp 验证
  • 新增/变更公共 API 必须附带使用示例与文档
    3) 持续集成(CI)
  • 步骤:拉取 → 构建 → Lint → 测试 → 产物签名 → 发布到内源仓/注册中心
  • 质量阈值未达标则阻断合并
    4) 产物与缓存
  • 产物仓库:二进制 Framework/xcframework(提升集成速度)
  • 缓存策略:按 commit sha + target + config 生成缓存 key
    5) 集成与回归
  • 应用工程对目标版本进行集成回归(冒烟 + 关键路径)
  • 若失败:回滚到上一稳定版本或热修分支修复
    6) 发布与回滚
  • 标记发布版本与变更范围
  • 提供一键回滚脚本/流程说明

iOS 落地示例

1) 使用 SPM 定义组件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
// Package.swift(示例)
// swift-tools-version:5.9
import PackageDescription

let package = Package(
name: "CompanyFeatureKit",
platforms: [ .iOS(.v14) ],
products: [
.library(name: "CompanyFeatureKit", targets: ["CompanyFeatureKit"])
],
dependencies: [
// .package(url: "https://github.com/company/CompanyNetworking", from: "2.3.0")
],
targets: [
.target(
name: "CompanyFeatureKit",
path: "Sources",
resources: [ .process("Resources") ]
),
.testTarget(
name: "CompanyFeatureKitTests",
dependencies: ["CompanyFeatureKit"],
path: "Tests"
)
]
)

2) 使用 CocoaPods(私有仓)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
# CompanyFeatureKit.podspec(示例)
Pod::Spec.new do |s|
s.name = 'CompanyFeatureKit'
s.version = '1.2.0'
s.summary = 'Feature UI & domain implementation.'
s.homepage = 'https://git.company.com/ios/CompanyFeatureKit'
s.license = { :type => 'MIT' }
s.author = { 'iOSTeam' => 'ios@company.com' }
s.source = { :git => 'git@git.company.com:ios/CompanyFeatureKit.git', :tag => s.version.to_s }
s.ios.deployment_target = '14.0'
s.source_files = 'Sources/**/*.{h,m,mm,swift}'
s.resources = 'Resources/**/*'
s.dependency 'CompanyNetworking', '~> 2.3'
end

3) CI 关键步骤(示例)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
# .github/workflows/ci.yml(片段)
name: iOS Component CI
on: [push, pull_request]
jobs:
build_test:
runs-on: macos-14
steps:
- uses: actions/checkout@v4
- uses: maxim-lobanov/setup-xcode@v1
with: { xcode-version: '16.0' }
- name: Build (SPM)
run: xcodebuild -scheme CompanyFeatureKit -destination 'platform=iOS Simulator,name=iPhone 15' build
- name: Test
run: xcodebuild -scheme CompanyFeatureKit -destination 'platform=iOS Simulator,name=iPhone 15' test
- name: Lint
run: swiftlint --strict

度量与治理看板

  • 组件健康度:构建成功率、测试覆盖率、Lint 问题趋势
  • 依赖风险:主版本差异、环依赖检测、停更组件预警
  • 交付效率:平均合入时间、回滚次数、列车准点率
  • 质量追踪:崩溃率、线上回归缺陷数、热修次数

常见问题与对策

  • 跨组件耦合严重:建立逆向依赖监控与架构守门人评审,采用协议与事件总线解耦。
  • 版本地狱:统一 SemVer 策略与依赖上限,发布列车固定节奏,强制 Changelog。
  • 构建缓慢:二进制化关键组件,启用远端缓存(XCRemoteCache/Bazel Remote Cache)。
  • API 频繁破坏性变更:引入稳定期与废弃期(Deprecation Window),提供迁移助手脚本。
  • 多人协作冲突:Trunk-based + 小步提交 + 特性开关,降低合并风险。