跳到主要内容

🏭 现代工程化与 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-depth1克隆深度,0 = 全量(需要完整历史时用)
ref触发事件的 ref指定检出的分支/tag/commit
tokenGITHUB_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当前提交的完整 hasha1b2c3d4...
CI_COMMIT_SHORT_SHA短 hasha1b2c3d
CI_COMMIT_REF_NAME分支名或 tag 名mainv1.2.0
CI_COMMIT_TAG如果是 tag 触发,则是 tag 名v1.2.0
CI_PIPELINE_SOURCE触发来源pushmerge_request_eventschedule

场景:自动创建 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: fetch

GIT_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 ReleaseCI 自动化程度高的团队
Changesets手动标记变更集,PR 合并时自动发版Monorepo、需要人工审核发版节奏
release-pleaseGoogle 出品,基于 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、信任工具链、希望"合并即发布"

📝 下一步