← 返回工具首页 GitHub Actions 部署失败了?这篇帮你排查所有原因
DevOpsGitHub ActionsCI/CD

GitHub Actions 部署失败了?这篇帮你排查所有原因

半夜起来发现线上挂了,Actions 日志红了一片——别慌,这篇老司机带你逐条摸排,从 runner 超时到 Docker build 失败,从 secrets 漏配到 action 版本踩坑,5 分钟定位根因,对症下药。

一、常见报错场景:先定位是哪一类问题

GitHub Actions 出错的形式就那么几种,搞清楚是哪一类,排查效率翻倍。先对号入座:

报错表现可能原因优先级
Job 一直 pending,超时后取消runner 不可用 / 无效标签 / 队列阻塞🔴 高
Push 代码触发了,但什么都没跑workflow 条件判断 / 分支过滤 / 没启用 Actions🔴 高
Permission denied / 403 Forbiddensecrets 未配 / GITHUB_TOKEN 权限不足 / scope 限制🔴 高
Docker build 失败,exit code 非零Dockerfile 错误 / 构建上下文 / 多阶段构建问题🔴 高
action 版本报错(找不到 action / 版本冲突)版本 tag 写错 / major 版本 breaking change / 未指定版本
cache 失效,每次都重新构建cache key 变了 / actions/cache 版本 / 存储策略🟡 中
并行 Job 有 race condition,或串行太慢job 间数据依赖 / needs 依赖链设计 / matrix 设计🟡 中
日志里有乱码、中文显示异常locale 设置 / 文件编码 / log 层级配置🟢 低

二、诊断三板斧:logs → 环境变量 → 权限

不管什么报错,先跑这三步,80% 的问题在这里就能定位。

1. 先看 Logs,别猜

Actions 日志是金矿。很多人一看红了就慌,其实日志里写得清清楚楚。关键是看三点:

💡 技巧:在 Job 失败时点「Re-run failed jobs」之前,先把完整日志另存为。重新跑会覆盖日志,有时候第一次的报错才是根因。

2. 环境变量是否到位

很多"玄学"问题其实是环境变量没配或者配错了地方。最常见的情况:

# ❌ 错误:环境变量写在 job 外面但在 step 里用了
env:
  NODE_ENV: production

jobs:
  build:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4

# ✅ 正确:环境变量写在 job 内部
jobs:
  build:
    runs-on: ubuntu-latest
    env:
      NODE_ENV: production
    steps:
      - uses: actions/checkout@v4

检查清单:

3. 权限对了没有

GITHUB_TOKEN 默认权限是受限的,很多操作需要显式授权。这是新手最常踩的坑。

# 最常见的权限问题场景
jobs:
  deploy:
    permissions:
      contents: write    # 推送代码 / 创建 tag / Pages 部署
      packages: write   # 推送 Docker 镜像到 GHCR
      pull-requests: write  # 评论 PR / 创建 PR
      id-token: write    # OIDC 云认证(AWS/GCP/Azure)
⚠️ 坑:Organization 仓库默认会覆盖仓库级别的权限设置。如果你的 workflow 在 org 仓库里跑,即使加了 permissions: 也可能不生效,要去 org 设置里放开。

三、5 种常见错误 + 修复方案

错误 1:runner 一直 pending 超时

报错表现
Job 状态是黄色 "In progress",但没有任何日志输出,等待几分钟后显示 "The runner has not received a heartbeat in 600 seconds"。

原因主要有三种:

修复方案
# 检查 runner 标签是否正确
jobs:
  build:
    runs-on: ubuntu-latest    # GitHub 托管,直接用这个
    # runs-on: [self-hosted]  # 自托管,注意确保机器在线
    timeout-minutes: 30       # 加超时限制,别让 Job 无限挂起

# 自托管 runner 排查顺序:
# 1. 服务器上: ./run.sh 是否在跑(ps aux | grep run)
# 2. 网络: curl https://api.github.com 是否通
# 3. 标签: 仓库 Settings → Actions → Runners,确认标签匹配

错误 2:secrets 没配或引用方式错误

报错表现
Error: Input required and not supplied: tokenError: secrets.xxx is not defined,或者 push 到仓库时显示 "Authentication failed"。

secrets 配置和引用是两件事,很多人搞混。

第一步:仓库/Organization 里配置 secrets

第二步:workflow 里正确引用

# ✅ 正确引用方式
jobs:
  deploy:
    runs-on: ubuntu-latest
    env:
      DB_PASSWORD: ${{ secrets.DB_PASSWORD }}
      AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }}
    steps:
      - name: Deploy
        run: ./deploy.sh
        env:
          DEPLOY_TOKEN: ${{ secrets.DEPLOY_TOKEN }}  # step 级也行

# ❌ 常见错误:把 secrets 当普通变量写
env:
  DB_PASSWORD: "your_real_password"  # 不要这样做!会提交到 git
💡 环境变量 vs step env:job 级的 env: 所有 step 共享;step 级的 env: 只有当前 step 可用。如果某个 step 需要单独的 secrets,用 step 级。

错误 3:action 版本问题 / 找不到 action

报错表现
Error: Cannot find module '@actions/artifact'」或「The workflow is not valid. Unexpected value 'v4'"`,以及 "The version 'v3' is deprecated for this action"。

action 版本有三个坑:

  1. 不写版本,用 latestactions/checkout@v4 写死的版本不会突然爆炸
  2. 大版本 breaking changeactions/setup-node@v4 有时候会更新导致不兼容
  3. 私有 action 路径写错uses: ./my-action 路径没找到
# ✅ 推荐:锁定到具体版本(SHA 安全且稳定)
jobs:
  build:
    steps:
      - uses: actions/checkout@v4.2.2
      - uses: actions/setup-node@v4.2.3
        with:
          node-version: '20'
      - uses: docker/login-action@v3
        with:
          registry: ghcr.io
          username: ${{ github.actor }}
          password: ${{ secrets.GITHUB_TOKEN }}

# ❌ 不推荐:latest 或 major 版本随时可能变
# - uses: actions/checkout@latest   ← 不稳定
# - uses: actions/checkout@v4       ← major 可能 breaking
🔒 安全建议:用 SHA 而非版本号更安全,防止供应链攻击。GitHub 官方 action 的 SHA 在 release 页面有记录,每次 update 后记得换 SHA。

错误 4:Docker build 失败

报错表现
Error response from daemon: docker build failed with exit code 1,或 Dockerfile 里 RUN npm ci 时报错 "npm not found",或者 multi-stage build 里某 stage 找不到依赖。

Docker build 失败的根因五花八门,按这个顺序查:

  1. 构建上下文正确吗? docker build 默认在 git root,如果 Dockerfile 不在 root,要用 context 指定
  2. docker/login-action 用了吗?推送到 GHCR 需要先登录
  3. .dockerignore 漏了 node_modules 吗?本地 node_modules 被 COPY 进去导致覆盖镜像层
  4. 多阶段构建 target 写对了吗?
# 完整 Docker 构建 + 推送 workflow
jobs:
  build-and-push:
    runs-on: ubuntu-latest
    permissions:
      contents: read
      packages: write

    steps:
      - uses: actions/checkout@v4

      - name: Set up Docker Buildx
        uses: docker/setup-buildx-action@v3

      - name: Login to GitHub Container Registry
        uses: docker/login-action@v3
        with:
          registry: ghcr.io
          username: ${{ github.actor }}
          password: ${{ secrets.GITHUB_TOKEN }}

      - name: Build and push
        uses: docker/build-push-action@v5
        with:
          context: ./backend          # ← 指定构建上下文
          push: true
          tags: ghcr.io/${{ github.repository }}/myapp:latest
          cache-from: type=gha       # ← 用 GitHub Actions cache 加速
          cache-to: type=gha,mode=max

# .dockerignore 示例(避免 node_modules 被 COPY)
node_modules
.git
*.log
.env

如果 build 缓存失效太频繁,用 cache-from: type=gha + cache-to: type=gha 把构建层缓存到 GitHub Actions Cache,第二次构建快很多。

错误 5:权限不足(GITHUB_TOKEN 限制)

报错表现
GraphQL: Resource not accessible by integration (HTTP 403),或者 push 代码时 "remote: Permission denied",或者 "Unable to push to remote repository"。

GITHUB_TOKEN 的默认权限极其保守。常见需要额外权限的场景:

操作所需权限
Push 代码到另一个仓库contents: write(目标仓库要有写入权)
创建/更新 GitHub Releasecontents: write
推送 Docker 镜像到 GHCRpackages: write
创建 PR / 评论 PRpull-requests: write
写入 GitHub Pagespages: write
OIDC 云认证(AWS/GCP/Azure)id-token: write
更新 GitHub Projectsprojects: write
# 完整权限示例:部署到 GitHub Pages
jobs:
  deploy-pages:
    runs-on: ubuntu-latest
    permissions:
      contents: read    # 检出代码
      pages: write      # 写入 GitHub Pages
      id-token: write   # OIDC 认证
    environment: github_pages  # 指定环境,环境级权限更细

    steps:
      - uses: actions/checkout@v4
      - uses: actions/upload-pages-artifact@v3
        with:
          path: ./dist
      - uses: actions/deploy-pages@v4

四、优化 CI 速度:并行 vs 串行

CI 跑 20 分钟和跑 5 分钟,对开发体验影响巨大。这里说几个实打实的优化手段。

1. 矩阵并行:让多个 Job 同时跑

# 矩阵并行:同时测试多个 Node 版本
jobs:
  test:
    strategy:
      matrix:
        node-version: ['18', '20', '22']
        os: [ubuntu-latest, windows-latest]
    runs-on: ${{ matrix.os }}
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-node@v4
        with:
          node-version: ${{ matrix.node-version }}
          cache: 'npm'    # 自动缓存 node_modules
      - run: npm ci
      - run: npm test

# 结论:3 个 Node × 2 个 OS = 6 个 Job 并行跑,总时间不变,效率 6 倍

2. Job 依赖链优化:减少不必要的串行

# ❌ 低效:所有 Job 串行等前一个完成
jobs:
  install:
    runs-on: ubuntu-latest
    steps: ...
  build:
    needs: install    # 等 install 完才能跑
    runs-on: ubuntu-latest
    steps: ...
  test:
    needs: build       # 等 build 完才能跑
    runs-on: ubuntu-latest
    steps: ...

# ✅ 高效:install → build|test 并行
jobs:
  install:
    runs-on: ubuntu-latest
    steps:
      - name: Cache node_modules
        uses: actions/cache@v4
        with:
          path: ~/.npm
          key: npm-${{ runner.os }}-${{ hashFiles('package-lock.json') }}

  build:
    needs: install
    runs-on: ubuntu-latest
    steps: ...

  test:
    needs: install    # ← 只依赖 install,不依赖 build
    runs-on: ubuntu-latest
    steps: ...

needs 依赖链的设计原则:只依赖真正需要的前置结果,不要为了"保险"串一堆。

3. 依赖缓存:让每次构建不是从零开始

# Node.js 缓存(最常见)
- uses: actions/cache@v4
  with:
    path: ~/.npm
    key: npm-${{ runner.os }}-${{ hashFiles('**/package-lock.json') }}
    restore-keys: |
      npm-${{ runner.os }}-

# Python 缓存
- uses: actions/cache@v4
  with:
    path: ~/.cache/pip
    key: pip-${{ runner.os }}-${{ hashFiles('**/requirements.txt') }}

# Docker layer 缓存(用 buildx)
- uses: docker/build-push-action@v5
  with:
    cache-from: type=gha
    cache-to: type=gha,mode=max

4. 快、省、准:条件执行

# 只在特定分支/文件变化时才跑 CI
jobs:
  test:
    if: github.event_name == 'push' || github.event_name == 'pull_request'
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
        with:
          fetch-depth: 0   # 需要 shallow false 来做 diff

      - name: Run tests
        run: |
          if git diff --name-only origin/main...HEAD | grep -qE '\.(js|ts)

      

💡 遇到同类问题?用工具快速解决

试试这些配套工具,无需注册,打开即用

浏览所有工具

常见问题

Q: 如何使用 githubactions部署失败排查指南 相关工具?
A: 这类工具一般有明确的输入框和输出框,按提示输入内容,点击对应按钮即可得到结果。建议先用简单示例测试功能是否正常,再处理实际数据。
Q: githubactions部署失败排查指南 适合在什么场景使用?
A: 根据具体工具类型决定。格式转换工具适合处理第三方数据,编码工具适合加密传输,压缩工具适合文件上传前处理。多积累工具使用经验,遇到问题时能快速判断用哪个工具解决。
Q: 有没有更好的替代工具?
A: 不同工具有不同侧重,重点是理解原理。可以同时安装多个类似工具,实际使用中对比效果,选择最顺手的一个。随着使用经验增加,你也能判断工具的好坏。