You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

GitHub Actions:结合schedule与pull_request实现PR每日限次触发工作流

实现方案

核心思路

通过两个工作流配合实现需求:

  1. 一个轻量工作流监听PR推送事件,标记需要处理的PR;
  2. 另一个工作流每日定时执行,扫描所有待处理的活跃PR,逐个执行高成本任务,完成后清除标记,确保每个PR每日仅运行一次。

具体实现

1. PR推送监听工作流(pr-push-tracker.yml)

这个工作流仅在PR有新推送时触发,负责给PR添加待处理标签,操作成本极低:

name: Track PR Pushes for Daily Run
on:
  pull_request:
    types: [synchronize]

jobs:
  mark-pending:
    runs-on: ubuntu-latest
    steps:
      - name: Add pending label to PR
        uses: actions/github-script@v6
        with:
          github-token: ${{ secrets.GITHUB_TOKEN }}
          script: |
            await github.rest.issues.addLabels({
              owner: context.repo.owner,
              repo: context.repo.repo,
              issue_number: context.payload.pull_request.number,
              labels: ['pending-daily-run']
            });

2. 每日定时执行工作流(daily-pr-process.yml)

这个工作流每日定时触发,扫描所有带pending-daily-run标签的活跃PR,执行核心任务后移除标签,避免重复运行:

name: Daily PR Processing
on:
  schedule:
    # 每日UTC 0点运行,可根据时区调整cron表达式
    - cron: '0 0 * * *'
  workflow_dispatch: # 支持手动触发调试

jobs:
  process-pending-prs:
    runs-on: ubuntu-latest
    permissions:
      contents: read
      pull-requests: write
    steps:
      - name: Fetch pending PRs
        id: get-prs
        uses: actions/github-script@v6
        with:
          github-token: ${{ secrets.GITHUB_TOKEN }}
          result-encoding: json
          script: |
            const prs = await github.rest.pulls.list({
              owner: context.repo.owner,
              repo: context.repo.repo,
              state: 'open',
              labels: 'pending-daily-run'
            });
            return prs.data.map(pr => ({
              number: pr.number,
              headSha: pr.head.sha,
              baseSha: pr.base.sha,
              title: pr.title
            }));

      - name: Process each pending PR
        if: ${{ steps.get-prs.outputs.result != '[]' }}
        uses: actions/github-script@v6
        with:
          github-token: ${{ secrets.GITHUB_TOKEN }}
          script: |
            const pendingPRs = ${{ steps.get-prs.outputs.result }};
            for (const pr of pendingPRs) {
              console.log(`Processing PR #${pr.number}: ${pr.title}`);
              
              // 1. 执行基础提交与最新提交的对比逻辑(替换为你的实际任务)
              await exec.exec('git clone', ['--depth=1', context.repo.html_url + '.git']);
              process.chdir(context.repo.repo);
              const diffResult = await exec.exec('git', ['diff', pr.baseSha, pr.headSha, '--name-only']);
              const changedFiles = diffResult.stdout.trim().split('\n').join('\n- ');

              // 2. 在PR线程发布评论
              await github.rest.issues.createComment({
                owner: context.repo.owner,
                repo: context.repo.repo,
                issue_number: pr.number,
                body: `每日自动任务已完成:
- 基础提交:\`${pr.baseSha.slice(0,7)}\`
- 最新提交:\`${pr.headSha.slice(0,7)}\`
- 修改文件:
  - ${changedFiles || '无文件变更'}`
              });

              // 3. 移除待处理标签,防止重复执行
              await github.rest.issues.removeLabel({
                owner: context.repo.owner,
                repo: context.repo.repo,
                issue_number: pr.number,
                name: 'pending-daily-run'
              });
            }

关键细节说明

  • 权限配置:需确保GITHUB_TOKEN拥有pull-requests: write权限,可在仓库「Actions → 通用」设置中,将工作流权限设为「读取和写入权限」。
  • 重复执行防护:通过pending-daily-run标签的添加/移除,即使PR多次推送,也只会被标记一次,定时工作流处理后清除标签,确保每日仅运行一次。
  • PR信息访问:定时工作流通过GitHub API直接获取PR的基础提交、最新提交等核心数据,完全支持对比、评论等后续操作。
  • 灵活性:可修改cron表达式调整每日运行时间,也可通过workflow_dispatch手动触发调试任务。

内容的提问来源于stack exchange,提问作者Ben H

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.21 17:32:06