🏭 现代工程化与 CI/CD 集成
现代软件开发早已不是"写完代码就结束"。从提交到发布,需要经过自动化测试、代码检查、构建、部署等一系列步骤。Git 是这一切的触发器和记录者。
🤖 GitHub Actions 中的 Git 操作
基础:在 Actions 中操作 Git
name: CI
on: [push, pull_request]
jobs:
test:
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v4
with:
fetch-depth: 0 # 全量克隆,保留完整历史(默认值 1 会导致 merge-base 计算错误)
- name: Run tests
run: npm test
- name: Build
run: npm run build
关键配置:actions/checkout 参数
| 参数 | 默认值 | 说明 |
|---|---|---|
fetch-depth | 1 | 克隆深度,0 = 全量(需要完整历史时用) |
ref | 触发事件的 ref | 指定检出的分支/tag/commit |
token | GITHUB_TOKEN | 认证 token,推送时需要 permissions 配置 |
场景 1:自动发布版本(Semantic Release)
name: Release
on:
push:
branches: [main]
jobs:
release:
runs-on: ubuntu-latest
permissions:
contents: write # 需要写权限来创建 tag 和 release
issues: write
pull-requests: write
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0
token: ${{ secrets.GITHUB_TOKEN }}
- name: Semantic Release
uses: cycjimy/semantic-release-action@v4
with:
branch: main
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
NPM_TOKEN: ${{ secrets.NPM_TOKEN }}
场景 2:PR 自动合并(Auto-merge)
name: Auto Merge
on:
pull_request:
types: [opened, ready_for_review, reopened]
jobs:
auto-merge:
if: github.actor == 'dependabot[bot]' # 仅对 Dependabot PR 自动合并
runs-on: ubuntu-latest
steps:
- name: Enable auto-merge
run: gh pr merge --auto --squash "$PR_NUMBER"
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
PR_NUMBER: ${{ github.event.pull_request.number }}
💡 为什么
fetch-depth: 0 很重要?很多工具(semantic-release、changesets、commitlint 的 history 模式)需要完整的 Git 历史来计算版本号。fetch-depth: 1(默认)只克隆最新一次提交,会导致这些工具报错或计算错误。
🦊 GitLab CI 中的 Git 操作
基础:gitlab-ci.yml 中的 Git 策略
variables:
GIT_STRATEGY: clone # 默认:每个 job 都 clone 代码
GIT_DEPTH: 0 # 0 = 全量克隆(类似 GitHub 的 fetch-depth: 0)
stages:
- test
- build
- deploy
test:
stage: test
script:
- npm test
build:
stage: build
script:
- npm run build
artifacts:
paths:
- dist/
GitLab 特有:CI_COMMIT_* 环境变量
| 变量 | 含义 | 示例值 |
|---|---|---|
CI_COMMIT_SHA | 当前提交的完整 hash | a1b2c3d4... |
CI_COMMIT_SHORT_SHA | 短 hash | a1b2c3d |
CI_COMMIT_REF_NAME | 分支名或 tag 名 | main、v1.2.0 |
CI_COMMIT_TAG | 如果是 tag 触发,则是 tag 名 | v1.2.0 |
CI_PIPELINE_SOURCE | 触发来源 | push、merge_request_event、schedule |
场景:自动创建 Release Tag
create-release:
stage: deploy
only:
- main
script:
- git config user.email "ci@gitlab.com"
- git config user.name "CI Bot"
- npm run release:version # 用 changesets 或 sematic-release 计算版本号
- git push --follow-tags origin main # 推送新 tag
⚠️ GitLab CI 中的
GIT_STRATEGY: fetchGIT_STRATEGY: fetch 会复用上一次 job 的工作区(通过 git fetch 更新),比 clone 快,但可能导致工作区残留文件。大多数情况下用 clone 更安全。
🏷️ 语义化版本与 Changelog 自动化
Semantic Versioning 速查
vMAJOR.MINOR.PATCH
│ │ │
│ │ └── 修复 Bug / 向后兼容的小改动 → 1.2.1
│ └──── 新功能 / 向后兼容 → 1.3.0
└─────────── 破坏性变更 → 2.0.0
工具链选型的考量
| 工具 | 用途 | 推荐场景 |
|---|---|---|
| semantic-release | 全自动版本号 + Changelog + GitHub Release | CI 自动化程度高的团队 |
| Changesets | 手动标记变更集,PR 合并时自动发版 | Monorepo、需要人工审核发版节奏 |
| release-please | Google 出品,基于 Conventional Commits 自动发版 | 大型项目、多语言 Monorepo |
| standard-version | 本地 CLI 工具,手动触发发版 | 小团队、不喜欢全自动发版 |
Changesets 实战配置
# 1. 安装
npm install -D @changesets/cli @changesets/github
# 2. 初始化
npx changeset init
# 3. 每次 PR 添加变更说明
npx changeset # 会问你:这是什么类型的变更?(major/minor/patch)
# 生成 .changeset/abc1234.md
# 4. CI 中自动发版(.github/workflows/release.yml)
# .github/workflows/release.yml
name: Release
on:
push:
branches: [main]
jobs:
release:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0
- uses: changesets/action@v1
with:
publish: npm run release
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
NPM_TOKEN: ${{ secrets.NPM_TOKEN }}
自动生成 Changelog 示例
## 1.3.0 (2024-03-15)
### 🚀 New Features
- feat(auth): add OAuth2 login support (#1234) @alice
- feat(dashboard): add usage metrics chart (#1240) @bob
### 🐛 Bug Fixes
- fix(api): handle null pointer in user service (#1220) @charlie
### 📝 Documentation
- docs(README): update installation guide (#1215) @diana
💡 Changesets vs. Semantic Release 怎么选?
- 用 Changesets:你们是 Monorepo、需要人工审核发版节奏、或团队对"全自动发版"不放心
- 用 Semantic Release:你们是全自动 CI/CD、信任工具链、希望"合并即发布"
📝 下一步
- 📦 大文件与大仓库处理 —— Git LFS、Monorepo 策略、浅克隆优化
- 🖥️ 工作区多开(Git Worktree + AI 编程) ——
git worktree实现多分支并行开发