核心原则:让释放速度快,无痛, 你会更经常地释放。 这对于快速发展至关重要 — — 快速、可靠的部署创造了你所需要的快速反馈循环。 当部署是可怕的或缓慢的时, 团队会分批变化, 增加风险。 如果部署是无聊和自动的, 您会经常运送小的改变 。
本指南涵盖我在生产中使用的释放战略,从简单的基于标签的部署到多包装单雷波出版。 GitHub 行动组织 此仓库的工作流程 。
在深入探究细节之前,
战略 战略 战略 战略 战略 战略 战略 战略 战略 战略 战略 战略 战略 战略 战略 战略 战略 战略 战略 战略 战略 战略 战略 战略 战略 战略 战略 战略 战略 战略 战略 战略 战略 战略 战略 战略 战略 战略 战略 战略 战略 战略 战略 战略 战略 |----------|----------|------------|-----------| | 基于标签的 应用 明确释放 低 启动 单声道 成熟团队 | 分处 继续部署 低 低 启动 快速前进队 | GitFlow 吉特花 控制释放,多种版本 高企业,遵守 - 重 | 以 Trunk 为基础的 + 特色旗帜 中高科技 成熟的初创 | 垄断多包装 图书馆 共享代码库 中期平台团队 OSS项目
启动和小团队: 以基于标签或分支的部署开始。 保持简单 - 您以后总可以增加复杂性。 基于特写标记的基于Trunk的开发在规模上很受欢迎,但对于小团队来说却超棒。
企业企业企业企业企业企业企业:通常需要 GitFlow 或类似设备来进行合规、审计线索和释放管理。 多种环境(dev、QA、中转、中转)加上审批门。 工序证明对供应链安全的需求越来越大。
单行开发者: 标签是理想的。 按标签, 部署就会发生。 没有仪式, 没有管理费 。
平台/图书馆小组: 需要单雷波战略,每个包件有独立的版本。语义版本对于下游消费者至关重要。
最简单和最可靠的策略。 不同的标签前缀会选择通往不同环境的路径或触发不同的动作 。
on:
push:
tags:
- 'release-*' # Production
- 'local-*' # Dev environment
- name: Build Docker image
run: |
TAG_NAME=${GITHUB_REF#refs/tags/}
if [[ "$TAG_NAME" == local-* ]]; then
docker build -t myapp:local .
else
docker build -t myapp:latest -t myapp:$(date +%s) .
fi
为什么它工作简单的心理模式,明确的部署, 容易通过时间戳标签的回滚。
# Deploy to production
git tag release-v2024.12.01 && git push origin release-v2024.12.01
# Deploy to dev
git tag local-feature-test && git push origin local-feature-test
对于含有多个可发布软件包的单体,使用标签前缀来识别要释放的软件包:
# Different workflows, different tag patterns
# umami-net.yml
on:
push:
tags: ['umamiv*.*.*'] # e.g., umamiv1.0.5
# fetchextension.yml
on:
push:
tags: ['fetchextension-v*.*.*'] # e.g., fetchextension-v1.2.0
摘录版本并在整个版本中使用:
- name: Extract version
run: echo "VERSION=${GITHUB_REF#refs/tags/umamiv}" >> $GITHUB_OUTPUT
- name: Build & Pack
run: |
dotnet build -c Release -p:Version=${{ steps.version.outputs.VERSION }}
dotnet pack -c Release -p:PackageVersion=${{ steps.version.outputs.VERSION }}
对于自动版本, MinVer 移动 从 Git 标记中计算版本 :
<PackageReference Include="MinVer" Version="6.0.0" PrivateAssets="all" />
<PropertyGroup>
<MinVerTagPrefix>umamiv</MinVerTagPrefix>
</PropertyGroup>
当代码到达特定分支时自动部署。 在新建和快速移动的团队中很常见 。
on:
push:
branches: [main] # → Production
# branches: [develop] # → Staging
Pros 专业:没有手动步骤,在合并时部署 共:可能的意外部署,不那么明确的历史
我使用混合方法----以分支推力(CI核查)为基础,但只在标签上公布:
on:
push:
tags: ['scheduler-*']
branches: [main, local]
jobs:
build:
# Always build
publish:
if: startsWith(github.ref, 'refs/tags/') # Only publish on tags
对于自营的部署, 观察塔 自动拉动新图像 :
services:
app:
image: myapp:latest
labels:
- "com.centurylinklabs.watchtower.enable=true"
watchtower:
image: containrrr/watchtower
volumes:
- /var/run/docker.sock:/var/run/docker.sock
command: --interval 300 # Check every 5 minutes
部署部署流动推进标记 GitHub Action 构建
如果您部署错误, 快速部署是徒劳无益的。 每个工作流程都应该包括大门 :
- name: Run tests
run: dotnet test --configuration Release
- name: Build
run: dotnet build --configuration Release
# Tests or build fail → workflow stops → no publish
对于多框架一揽子计划,制定所有目标:
- run: dotnet build -c Release --framework net8.0
- run: dotnet build -c Release --framework net9.0
现代方法 - 没有秘密可以旋转, 没有密钥可以泄漏 :
permissions:
id-token: write
contents: read
- uses: NuGet/login@v1
with:
user: 'myusername'
- run: dotnet nuget push *.nupkg --api-key ${{ steps.login.outputs.NUGET_API_KEY }}
GitHub 将其 OIDC 标记交换为短命 Nuget API 密钥。 配置 Nuget. org 上的信任来启用此选项 。
人工造物证明 证明你的手工艺品是在CI里建造的 并没有被篡改 企业越来越需要
permissions:
id-token: write
attestations: write
- uses: docker/build-push-action@v6
id: push
with:
push: true
tags: myapp:latest
- uses: actions/attest-build-provenance@v2
with:
subject-name: index.docker.io/myuser/myapp
subject-digest: ${{ steps.push.outputs.digest }}
push-to-registry: true
消费者对下列事项进行核实: gh attestation verify oci://index.docker.io/myuser/myapp:latest --owner myuser
由此实现 SLSA 2级第3级第3级,使用 可重复使用的工作流程.
各小组需要利益攸关方在合并前预览变化。
企业企业办法 - 基于分处的预览环境:
on:
pull_request:
types: [opened, synchronize]
- run: |
BRANCH=$(echo ${{ github.head_ref }} | sed 's/[^a-zA-Z0-9]/-/g')
docker build -t myapp:preview-$BRANCH .
# Deploy to k8s namespace, cloud platform, etc.
开办/开办/开办办法 - 挖出你的本地机器:
# Cloudflare Tunnel (free)
cloudflared tunnel run --url http://localhost:5000 my-preview
# → https://my-preview.cfargotunnel.com
或使用 无线电护卫 VPN 内部小队进入你的Dev机器
标签清理基特标签永远存在
git tag -d old-test-tag # Delete local
git push origin :refs/tags/old-test-tag # Delete remote
命名公约:保持一致。
release-YYYY.MM.DD 用于生产、生产、生产、生产、生产、生产、生产、生产、生产、生产、生产、生产、生产、生产、生产、生产、生产、生产、生产、生产、生产、生产、生产、生产、生产、生产、生产、生产、生产、生产、生产、生产、生产、生产、生产、生产、生产、生产、生产、生产、生产、生产、生产、生产、生产、生产、生产、生产、生产、生产、生产、生产、生产、生产、生产、生产、生产、生产、生产、生产、生产local-feature-name 用于 dev 的packagev1.2.3 图书馆服务密密秘: 存储于 GitHub 秘密组织绝对没有密码 通常需要秘密
DOCKER_HUB_ACCESS_TOKENNUGET_API_KEY (或使用OIDC)NPM_TOKEN垄断发展:在开发过程中使用项目参考,改用部署核查的一揽子参考:
<ProjectReference Include="..\MyLib\MyLib.csproj" />
<!-- <PackageReference Include="MyLib" Version="1.0.0" /> -->
同样的原则、不同的工具:
杜克作曲 库伯涅茨 |----------------|------------| 望塔 观察塔 观察塔 观察塔 观察塔 观察塔 观察塔 观察塔 观察塔 观察塔 观察塔 观察塔 观察塔 观察塔 观察塔 观察塔 观察塔 观察塔 观察塔 观察塔 观察塔 观察塔 观察塔 观察塔 观察塔 观察塔 观察塔 观察塔 观察塔 观察塔 观察塔 观察塔 观察塔 ArgoCD 阿尔戈CD / 流动流量 | Q可以
在此存储库中运行的工作流程显示 - 检查 .github/workflows/ 以完成执行。
记住快速、可靠的部署是灵活发展的基础。
© 2026 Scott Galloway — Unlicense — All content and source code on this site is free to use, copy, modify, and sell.