我用Gemini写CI/CD脚本:40分钟的事8分钟干完,但有些坑必须说

我之前对用AI写CI/CD脚本是怀疑的。运维脚本错一个字符,整个流水线挂掉,比业务代码出Bug刺激多了。但上个月试着用Gemini 2.5 Pro写了一组GitLab CI和GitHub Actions脚本,发现有些场景它还真能打。下面是我实际踩过的坑,以及哪些场景值得用、哪些别碰。


一、先说结论:Gemini能打,但不全能

我测了5个场景:

场景 Gemini表现 我的评价
生成基础GitLab CI配置 能打,改几行就能用 省时间
生成GitHub Actions workflow 几乎不用改 表现最好
多环境部署脚本(dev/staging/prod) 逻辑对,环境变量要核对 需要人工检查
K8s部署CI步骤 能用,但最好你懂K8s 不懂就别用
调试CI报错 把日志贴给它,分析得挺准 强烈推荐

一句话总结:Gemini适合"从0到1"生成脚本骨架,不适合"从99到100"处理复杂边界条件。如果你对CI/CD有一定了解,它能省60-70%的时间;如果你完全不懂,它会给你一个看起来对但跑不起来的东西。


二、GitHub Actions自动部署:从40分钟压缩到8分钟

我想实现的功能

  1. 推送到main分支时自动跑测试
  2. 测试通过后自动构建Docker镜像推到Docker Hub
  3. 自动部署到云服务器(SSH执行命令)
  4. 部署完成发企业微信通知

我的Prompt(这个写法成功率最高)

我需要生成一个GitHub Actions workflow文件,要求:

1. 触发条件:推送到main分支,或手动触发
2. 环境变量通过GitHub Secrets管理:
   - DOCKER_USERNAME / DOCKER_PASSWORD
   - SSH_HOST / SSH_USERNAME / SSH_KEY
   - WECHAT_WEBHOOK_URL
3. 步骤:
   a) 运行npm test(Node.js项目)
   b) 构建Docker镜像推送到Docker Hub,tag用commit SHA+latest
   c) SSH连接云服务器,执行docker pull并重启容器
   d) 调用企业微信webhook发部署结果通知
4. 用GitHub Actions最佳实践(依赖缓存、needs依赖链、只需要的步骤)

Gemini生成的workflow(我微调后的最终版)

name: Deploy to Production

on:
  push:
    branches: [main]
  workflow_dispatch:

env:
  DOCKER_REGISTRY: docker.io
  IMAGE_NAME: myorg/myapp

jobs:
  test:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-node@v4
        with:
          node-version: 20
          cache: npm
      - run: npm ci
      - run: npm test

  build-and-push:
    needs: test  # 这行很关键,Gemini第一版没加
    runs-on: ubuntu-latest
    outputs:
      image-tag: ${{ steps.meta.outputs.tags }}
    steps:
      - uses: actions/checkout@v4
      - uses: docker/setup-buildx-action@v3
      - uses: docker/login-action@v3
        with:
          username: ${{ secrets.DOCKER_USERNAME }}
          password: ${{ secrets.DOCKER_PASSWORD }}
      - id: meta
        uses: docker/metadata-action@v5
        with:
          images: ${{ env.DOCKER_REGISTRY }}/${{ env.IMAGE_NAME }}
          tags: |
            type=sha,format=short
            type=raw,value=latest,enable={{is_default_branch}}
      - uses: docker/build-push-action@v6
        with:
          push: true
          tags: ${{ steps.meta.outputs.tags }}
          labels: ${{ steps.meta.outputs.labels }}

  deploy:
    needs: build-and-push  # 这行Gemini也没加,我手动补的
    runs-on: ubuntu-latest
    steps:
      - name: Deploy to server via SSH
        uses: appleboy/ssh-action@v1.0.0
        with:
          host: ${{ secrets.SSH_HOST }}
          username: ${{ secrets.SSH_USERNAME }}
          key: ${{ secrets.SSH_KEY }}
          script: |
            set -e  # 这行很重要,Gemini没加,我补的:任何命令失败就退出
            cd /opt/myapp
            docker compose pull
            docker compose up -d
            docker system prune -f
      - name: Notify WeChat
        if: always()
        run: |
          curl -X POST "${{ secrets.WECHAT_WEBHOOK_URL }}" \
            -H "Content-Type: application/json" \
            -d "{\"msgtype\":\"text\",\"text\":{\"content\":\"🚀 部署完成\n分支: main\n状态: ${{ job.status }}\"}}"

我微调了3个地方

1. 加了needs依赖链

Gemini第一版把test、build、deploy三个job平行写了,导致deploy在test还没跑完就开始了。我加了needs: testneeds: build-and-push,保证顺序执行。

2. Docker tag改用动态生成

Gemini原本写的是tags: latest硬编码。这样每次部署都会覆盖latest,出问题时无法回滚到特定版本。我让它改成用docker/metadata-action动态生成基于commit SHA的tag。

3. SSH脚本加了set -e

这句的意思是:任何命令失败就立即退出script。Gemini生成的script没有错误处理,如果docker compose pull失败了,up -d还是会执行,导致部署一个旧版本。

时间对比:之前手写这套workflow大概40分钟(查文档+调试),用Gemini大概8分钟(生成+检查+微调)。


三、Gemini调试GitLab CI报错:比翻文档快

这个场景我强烈推荐——把报错日志贴给Gemini,让它分析,比你自己搜GitLab文档快得多。

我遇到的报错

ERROR: Job failed: exit code 1
fatal: unable to access 'https://gitlab-ci-token:xxxxx@gitlab.com/myorg/myrepo.git/': The requested URL returned error: 403

我的Prompt

我的GitLab CI报上面的错。这是.gitlab-ci.yml相关部分:

stages:
  - test
  - deploy

test:
  stage: test
  image: node:20
  script:
    - npm ci
    - npm test

deploy:
  stage: deploy
  image: alpine:latest
  before_script:
    - apk add --no-cache curl
  script:
    - curl -X POST "$DEPLOY_WEBHOOK_URL"
  only:
    - main

帮我分析可能的原因,以及怎么修。我的GitLab版本是16.5。

Gemini给出了4个可能原因(按概率排序)

原因1(概率最高):CI_JOB_TOKEN权限收紧

GitLab 16.0之后,CI_JOB_TOKEN的默认权限收紧了。如果你的项目设置了ci_job_token_scope,跨项目访问会被拒。

修法:Settings → CI/CD → Token Access,把目标项目加进去。

原因2:仓库迁移后URL没更新

本地.git/config里的URL还是老的。运行git remote set-url origin <新URL>

原因3:2FA启用但token没更新

如果启用了2FA,Personal Access Token需要重新生成,勾选api权限。

原因4:GitLab Runner的helper image版本太老

运行gitlab-runner --version检查,如果低于15.0,升级Runner。

实际情况:原因1命中

我们公司把仓库从GitLab.com迁移到了自建GitLab,忘了更新ci_job_token_scope设置。Gemini排在第一位的原因正好命中。

这个场景为什么推荐用AI:CI/CD的报错信息通常很含蓄,文档分散在各个版本迁移指南里。Gemini训练数据里包含了大量Stack Overflow问题和GitLab issue,所以它能把"报错→可能原因→解决方法"这个链路直接给你,省去你自己在文档里翻版本变更说明的时间。

但有个坑:Gemini有时会给过时的解决方案(比如GitLab 14.x的配置方法,但你在用16.x)。一定要核对它给的配置项是否在你用的版本里存在。


四、多环境GitLab CI:Gemini生成的配置需要大改

这个场景Gemini的表现一般——能生成能跑的配置,但在最佳实践上差点意思。

我的需求

  • 推送到develop分支 → 部署到dev环境
  • 推送到main分支 → 部署到staging环境
  • v* tag → 部署到production,需要手动批准

Gemini生成的配置(我大改后的版本)

stages:
  - test
  - build
  - deploy

variables:
  DOCKER_DRIVER: overlay2
  IMAGE: $CI_REGISTRY/$CI_PROJECT_PATH

# 模板:重用逻辑(Gemini第一版没加这个)
.job_template: &job_template
  image: docker:24.0.5
  services:
    - docker:24.0.5-dind
  before_script:
    - echo $CI_REGISTRY_PASSWORD | docker login -u $CI_REGISTRY_USER --password-stdin $CI_REGISTRY

test:
  stage: test
  image: node:20
  script:
    - npm ci
    - npm test
    - npm run lint
  rules:
    - if: '$CI_PIPELINE_SOURCE == "merge_request_event"'
    - if: '$CI_COMMIT_BRANCH'

build:
  stage: build
  <<: *job_template  # 用了YAML anchor重用,Gemini第一版是重复写的
  script:
    - docker build -t $IMAGE:$CI_COMMIT_SHORT_SHA .
    - docker push $IMAGE:$CI_COMMIT_SHORT_SHA
  rules:
    - if: '$CI_COMMIT_BRANCH == "main" || $CI_COMMIT_BRANCH == "develop"'
    - if: '$CI_COMMIT_TAG =~ /^v\d+\.\d+\.\d+$/'

deploy:dev:
  stage: deploy
  <<: *job_template
  script:
    - docker pull $IMAGE:$CI_COMMIT_SHORT_SHA
    - echo "Deploying to DEV..."
    - ./scripts/deploy.sh dev
  environment:
    name: dev
    url: https://dev.myapp.com
  rules:
    - if: '$CI_COMMIT_BRANCH == "develop"'

deploy:staging:
  stage: deploy
  <<: *job_template
  script:
    - docker pull $IMAGE:$CI_COMMIT_SHORT_SHA
    - echo "Deploying to STAGING..."
    - ./scripts/deploy.sh staging
  environment:
    name: staging
    url: https://staging.myapp.com
  rules:
    - if: '$CI_COMMIT_BRANCH == "main"'

deploy:prod:
  stage: deploy
  <<: *job_template
  script:
    - docker pull $IMAGE:$CI_COMMIT_SHORT_SHA
    - echo "Deploying to PRODUCTION..."
    - ./scripts/deploy.sh prod
  environment:
    name: production
    url: https://myapp.com
  rules:
    - if: '$CI_COMMIT_TAG =~ /^v\d+\.\d+\.\d+$/'
  when: manual  # 需要手动批准

我改了3个关键地方

1. 提取了YAML anchor重用配置

Gemini第一版把before_scriptimage在每个job里重复写了三遍。我让它提取成<<: *job_template。这个改法在GitLab CI文档里有,但Gemini不会主动这样做,需要你提示。

2. rules替代了only/except

Gemini第一版用的是only/except语法(GitLab 14.x的写法)。我让它改成了rules(15.x+推荐)。如果你用的是GitLab 15+,一定要用rules

3. 加了environment声明

GitLab的Environment功能可以让你在UI里看到每次部署的状态和回滚按钮。这个Gemini没主动加,我手动补上了。补上之后,在GitLab项目的"部署"页面可以看到每个环境的当前版本,回滚只要点一下。


五、Prompt怎么写,Gemini生成的CI脚本才靠谱

我测下来,同样的任务,Prompt写法不同,生成质量差很多。下面是我总结的4个技巧。

技巧1:给它完整的上下文,不要只说"帮我写一个CI配置"

差的Prompt:

帮我写一个GitLab CI配置,用于Node.js项目的测试和部署。

好的Prompt:

帮我写一个.gitlab-ci.yml,用于Node.js 20项目。

项目信息:

  • 测试命令:npm test(需要MongoDB,用service方式启动)
  • 构建:npm run build,输出在dist/目录
  • 部署:构建Docker镜像推送到$CI_REGISTRY,然后用SSH部署到目标服务器
  • 分支策略:develop→dev,main→staging,v* tag→prod(手动批准)
  • 使用GitLab 16.x,请用rules语法,不要用only/except

为什么:CI/CD配置高度依赖具体技术栈和版本。你给的上下文越具体,它生成的东西需要改的地方越少。

技巧2:让它"先解释再写"

在Prompt最后加一句:

在写配置之前,先说明你选择的CI策略和每个步骤的设计原因。

效果:Gemini会先输出一段分析,告诉你"为什么用rules而不是only"“为什么把testbuild分成两个job”。这段分析能帮你判断它是否理解你的需求——如果分析部分就有错误,生成出来的配置大概率也有问题,你可以早点让它重改,而不是等到跑CI的时候才发现有问题。

技巧3:调试报错时,把相关配置也贴进去

很多人贴报错的时候只贴错误日志,但不贴对应的CI配置。Gemini没有配置上下文,只能靠错误信息猜。

推荐贴的内容:

  1. 完整报错日志(包括stack trace)
  2. 对应的CI配置文件(.gitlab-ci.yml.github/workflows/*.yml
  3. 你的GitLab/GitHub Actions版本(很关键,不同版本的配置语法有差异)
  4. 你预期的行为 vs 实际的行为

技巧4:迭代,但不要指望一次生成完美结果

我的做法是:

  1. 先让Gemini生成基础版本
  2. 我跑一遍,把报错贴回去
  3. 让它修复,通常2-3轮能收敛

但有个上限:如果基础逻辑有问题(比如它选了一个不适合你场景的CI策略),迭代修复不如重写Prompt。我一般3轮还没修好,就重新开始,换个思路描述需求。


六、Gemini vs Claude vs Cursor:写CI/CD脚本谁更强?

我用这三个工具写了同一套GitHub Actions workflow(就是第二节的那个案例),对比结果:

维度 Gemini 2.5 Pro Claude Sonnet 4 Cursor (GPT-4o)
生成速度
首次生成准确率 75% 85% 70%
调试报错能力
对CI/CD概念的理解 最深
生成配置的简洁度 最优 冗余较多
免费额度 有限 有限

我的结论

  • 首次生成:Claude最强,它生成的配置通常不需要大改
  • 调试迭代:Gemini最强,分析报错的能力比Claude稍好,而且免费额度够大
  • 局部修改:Cursor最适合——因为它能看到你的整个仓库上下文,而Gemini/Claude你只能贴文件内容

七、这些场景,别用AI写CI/CD脚本

说了这么多优点,也要说清楚边界。

1. 你完全不懂CI/CD,想让AI"帮我搞一套"

别这样做。AI生成的配置需要你判断安全性、正确性和适用性。如果你不懂,你没法判断它生成的东西会不会把你的生产环境搞挂。

最低门槛:你需要理解CI/CD的基本概念(pipeline、job、stage、artifact),能读懂生成的配置每一行在干什么。

2. 涉及敏感操作的配置(生产环境部署、数据库迁移)

AI不知道你的具体安全策略。它生成的脚本可能包含:

  • 把secrets明文写在配置文件里(应该用GitHub Secrets/GitLab CI Variables)
  • 过度授予权限(比如GitHub Actions用了permissions: write-all
  • 没有错误处理,部署失败了也返回成功

做法:涉及生产环境的脚本,一定要人工review每一行。

3. 公司有特殊合规要求(等保、SOX、HIPAA)

AI训练数据里不会有你们公司的内部合规规范。它生成的配置可能不符合你们的安全基线。这种场景,老老实实看公司的CI/CD规范文档。


八、总结:Gemini写CI/CD脚本的正确用法

值得用Gemini的场景:

  • ✅ 从零生成基础CI/CD配置(GitHub Actions / GitLab CI / Jenkinsfile)
  • ✅ 调试CI报错(把日志贴给它分析)
  • ✅ 重构已有配置(比如从only/except迁移到rules
  • ✅ 写CI相关的辅助脚本(如部署脚本、健康检查脚本)

不值得用(至少不能只用AI)的场景:

  • ❌ 生产环境部署配置,没有人工review
  • ❌ 你完全不懂CI/CD,想让AI全权负责
  • ❌ 公司有特定合规要求,需要符合内部规范

我的工作流:

  1. 用Gemini生成第一版配置(省时间)
  2. 人工review关键部分(安全相关、生产环境相关)
  3. 推到测试分支跑一遍(验证)
  4. 如果报错,把日志贴回Gemini迭代(通常2-3轮收敛)
  5. 合并到主分支,设置好分支保护规则

参考资料:

  1. GitLab CI/CD Documentation (v16.x): https://docs.gitlab.com/ee/ci/
  2. GitHub Actions Documentation: https://docs.github.com/en/actions
  3. 本文所有案例来自本人实际测试(Gemini 2.5 Pro,2026年4月-5月)

我之前对AI写CI/CD是怀疑的,现在态度是"可以用,但要review"。如果你用Gemini写CI/CD的时候踩了什么坑,欢迎评论区交流。

Logo

欢迎加入DeepSeek 技术社区。在这里,你可以找到志同道合的朋友,共同探索AI技术的奥秘。

更多推荐