【CI/CD·Actions篇】GitHub Actions 入门:Workflow 语法与自托管 Runner

发布时间:2026/8/10 10:22:16
【CI/CD·Actions篇】GitHub Actions 入门:Workflow 语法与自托管 Runner 前言GitHub Actions 是增长最快的 CI/CD 平台。如果你在 GitHub 上托管代码它几乎零成本就能跑起 CI。本篇从 Workflow 基础语法到自托管 Runner 配置带你快速上手。一、核心概念GitHub Actions 体系: Workflow工作流 → 一个 .yml 文件定义完整 CI/CD 流程 ├── Event事件 → 触发 Workflow 的条件push、PR、定时等 ├── Job任务 → 一个 Workflow 包含多个 Job │ ├── Step步骤→ 一个 Job 包含多个 Step命令或 Action │ └── Runner → 执行 Job 的环境GitHub 托管或自托管 └── Action → 可复用的 Step 组件类似函数调用二、Workflow 语法详解基本结构# .github/workflows/ci.yml name: CI Pipeline # 触发条件 on: push: branches: [main, develop] paths: - src/** - pom.xml pull_request: branches: [main] schedule: - cron: 0 2 * * * # 每天凌晨2点 workflow_dispatch: # 手动触发 inputs: environment: description: 部署环境 required: true default: dev type: choice options: [dev, staging, prod] # 全局环境变量 env: APP_NAME: myapp JAVA_VERSION: 17 jobs: build: runs-on: ubuntu-latest env: MAVEN_OPTS: -Dmaven.repo.local.m2 steps: - uses: actions/checkoutv4 - uses: actions/setup-javav4 with: java-version: ${{ env.JAVA_VERSION }} distribution: temurin cache: maven - run: mvn clean package -DskipTests - uses: actions/upload-artifactv4 with: name: app-jar path: target/*.jar retention-days: 7触发条件on# 多种触发方式组合 on: # Push 到特定分支 push: branches: [main, release/*] tags: [v*] paths-ignore: [docs/**, *.md] # PR 到 main pull_request: branches: [main] # 定时 schedule: - cron: 0 2 * * 1-5 # 工作日凌晨2点 # 手动触发 workflow_dispatch: inputs: debug: description: Enable debug mode type: boolean default: false # 其他 Workflow 完成后触发 workflow_run: workflows: [Build] types: [completed] branches: [main] # 仓库事件 issues: types: [opened, labeled] # 外部 Webhook repository_dispatch: types: [deploy]Job 和 Stepjobs: # 并行执行的 Job lint: runs-on: ubuntu-latest steps: - uses: actions/checkoutv4 - run: npm ci - run: npm run lint test: runs-on: ubuntu-latest steps: - uses: actions/checkoutv4 - run: npm ci - run: npm test # Job 的条件执行 if: github.event_name pull_request # 依赖前面 Job 的 Job deploy: needs: [lint, test] # 等 lint 和 test 都完成 runs-on: ubuntu-latest if: github.ref refs/heads/main steps: - run: ./deploy.sh条件表达式steps: # if 条件 - name: Deploy to prod if: github.ref refs/heads/main github.event_name push run: ./deploy.sh prod # 基于上一步的输出 - name: Test result if: ${{ steps.build.outcome success }} run: echo Build succeeded - name: Handle failure if: ${{ steps.build.outcome failure }} run: echo Build failed # 基于 GitHub 上下文 - name: PR comment if: github.event_name pull_request run: echo This is a PR build # Job 条件 jobs: deploy-prod: if: | github.ref refs/heads/main github.event_name push runs-on: ubuntu-latest矩阵构建Matrixjobs: test: runs-on: ubuntu-latest strategy: matrix: # 多版本并行测试 java: [17, 21] os: [ubuntu-latest, windows-latest] exclude: - os: windows-latest java: 21 # 排除特定组合 steps: - uses: actions/checkoutv4 - uses: actions/setup-javav4 with: java-version: ${{ matrix.java }} - run: mvn test三、Actions 复用使用 Marketplace 中的 Actionsteps: # 检出代码几乎所有 Workflow 第一步 - uses: actions/checkoutv4 with: fetch-depth: 0 # 获取完整历史用于 changelog 生成 # 缓存依赖 - uses: actions/cachev4 with: path: | ~/.m2/repository ~/.gradle key: ${{ runner.os }}-deps-${{ hashFiles(**/pom.xml) }} restore-keys: | ${{ runner.os }}-deps- # 上传产物 - uses: actions/upload-artifactv4 with: name: app path: target/*.jar # 下载产物跨 Job - uses: actions/download-artifactv4 with: name: appSecrets 和变量# 在 GitHub → Settings → Secrets and variables → Actions 中配置 steps: # 使用 Secret - name: Docker login run: docker login -u ${{ secrets.DOCKER_USER }} -p ${{ secrets.DOCKER_PASS }} # 使用环境变量非敏感 - name: Build env: APP_ENV: ${{ vars.APP_ENV }} run: npm run build # 从 Secret 读取 Docker Hub 密码 - name: Push image run: | echo ${{ secrets.DOCKER_PASS }} | docker login -u ${{ secrets.DOCKER_USER }} --password-stdin docker push myapp:${{ github.sha }}**踩坑提示**GitHub Secrets 只在 Actions 运行时注入到环境变量中日志中会显示为 ***。但如果你的脚本不小心把 Secret 输出到文件或日志Mask 不会生效。一定不要用 echo $SECRET 或 cat $SECRET_FILE。四、自托管 Runner为什么要自托管| 场景 | GitHub 托管 | 自托管 ||------|-----------|--------|| 开源项目 | 免费 | 不需要 || 私有仓库 | 有免费额度 | 可能需要 || 内网部署 | 不行 | 必须 || 特殊硬件GPU | 不行 | 必须 || 自定义环境 | 不行 | 必须 |添加自托管 Runner在 GitHub 仓库 → Settings → Actions → Runners → New self-hosted runner# Linux 服务器上操作 # 创建 Runner 目录 mkdir actions-runner cd actions-runner # 下载 RunnerURL 从 GitHub 页面获取 curl -o actions-runner-linux-x64-2.317.0.tar.gz -L \ https://github.com/actions/runner/releases/download/v2.317.0/actions-runner-linux-x64-2.317.0.tar.gz # 解压 tar xzf actions-runner-linux-x64-2.317.0.tar.gz # 配置Token 从 GitHub 获取有时效性 ./config.sh --url https://github.com/your-org/your-repo --token YOUR_TOKEN --labels linux,java,docker # 安装为系统服务 sudo ./svc.sh install sudo ./svc.sh start # 验证状态 sudo ./svc.sh status在 Workflow 中使用自托管 Runnerjobs: build: # 使用 GitHub 托管 runs-on: ubuntu-latest deploy: # 使用自托管 Runner runs-on: [self-hosted, linux, java] # labels 中必须全部匹配 docker-build: # 需要 Docker 的自托管 Runner runs-on: [self-hosted, docker]Runner 组管理在组织级别添加 Runner可用于组织下所有仓库# 组织级 Runner ./config.sh --url https://github.com/your-org --token YOUR_TOKEN --labels org-runner # 在 Workflow 中使用 runs-on: [self-hosted, org-runner]**培训要点**自托管 Runner 的安全风险是——Runner 可以访问你的私有仓库代码。不要让不受信任的人有权限触发 Runner 上的 Workflow尤其 PR 触发时。用 environment 保护生产部署的 Job。五、实战完整 Spring Boot 项目 Workflow# .github/workflows/ci-cd.yml name: CI/CD on: push: branches: [main] tags: [v*] pull_request: branches: [main] env: REGISTRY: ghcr.io IMAGE_NAME: ${{ github.repository }} jobs: # 构建 build: runs-on: ubuntu-latest steps: - uses: actions/checkoutv4 - uses: actions/setup-javav4 with: java-version: 17 distribution: temurin cache: maven - run: mvn clean package -DskipTests - uses: actions/upload-artifactv4 with: name: app-jar path: target/*.jar # 测试并行 unit-test: needs: build runs-on: ubuntu-latest steps: - uses: actions/checkoutv4 - uses: actions/setup-javav4 with: java-version: 17 distribution: temurin cache: maven - run: mvn test - uses: dorny/test-reporterv1 if: always() with: name: Test Results path: target/surefire-reports/TEST-*.xml reporter: java-junit sonar: needs: build runs-on: ubuntu-latest steps: - uses: actions/checkoutv4 - uses: actions/setup-javav4 with: java-version: 17 distribution: temurin - run: mvn verify sonar:sonar -Dsonar.token${{ secrets.SONAR_TOKEN }} # Docker 构建 docker: needs: [unit-test] runs-on: ubuntu-latest permissions: contents: read packages: write steps: - uses: actions/checkoutv4 - uses: actions/download-artifactv4 with: name: app-jar path: target/ - uses: docker/login-actionv3 with: registry: ${{ env.REGISTRY }} username: ${{ github.actor }} password: ${{ secrets.GITHUB_TOKEN }} - uses: docker/metadata-actionv5 id: meta with: images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }} tags: | typesha typeref,eventtag typeraw,valuelatest,enable${{ github.ref refs/heads/main }} - uses: docker/build-push-actionv5 with: context: . push: true tags: ${{ steps.meta.outputs.tags }} labels: ${{ steps.meta.outputs.labels }} # 部署 deploy: needs: [docker] runs-on: [self-hosted, k8s] if: startsWith(github.ref, refs/tags/v) environment: production steps: - run: | kubectl set image deployment/myapp \ app${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:sha-${{ github.sha }} \ -n prod kubectl rollout status deployment/myapp -n prod --timeout300s六、本篇要点回顾1. Workflow 用on定义触发jobs定义任务每个 Job 有多个steps2.needs控制 Job 依赖if控制条件执行matrix实现并行多版本测试3. Marketplace Actions 用uses调用Secrets 用secrets.XXX引用4. 自托管 Runner 用runs-on: [self-hosted, label]匹配5.environment: production保护生产部署 Job需要人工审批下一篇预告《进阶实战复合 Action 开发与 Marketplace 利用》——从使用别人的 Action 到开发自己的 Action实现 CI/CD 代码复用。