Skip to content

Commit ab59cc2

Browse files
authored
Suggest jobs to use in run-slow (#39100)
* pr * pr * pr * pr * pr * pr * pr * pr * pr --------- Co-authored-by: ydshieh <[email protected]>
1 parent db2f535 commit ab59cc2

File tree

4 files changed

+489
-0
lines changed

4 files changed

+489
-0
lines changed

.github/workflows/get-pr-info.yml

Lines changed: 157 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,157 @@
1+
name: Get PR commit SHA
2+
on:
3+
workflow_call:
4+
inputs:
5+
pr_number:
6+
required: true
7+
type: string
8+
outputs:
9+
PR_HEAD_REPO_FULL_NAME:
10+
description: "The full name of the repository from which the pull request is created"
11+
value: ${{ jobs.get-pr-info.outputs.PR_HEAD_REPO_FULL_NAME }}
12+
PR_BASE_REPO_FULL_NAME:
13+
description: "The full name of the repository to which the pull request is created"
14+
value: ${{ jobs.get-pr-info.outputs.PR_BASE_REPO_FULL_NAME }}
15+
PR_HEAD_REPO_OWNER:
16+
description: "The owner of the repository from which the pull request is created"
17+
value: ${{ jobs.get-pr-info.outputs.PR_HEAD_REPO_OWNER }}
18+
PR_BASE_REPO_OWNER:
19+
description: "The owner of the repository to which the pull request is created"
20+
value: ${{ jobs.get-pr-info.outputs.PR_BASE_REPO_OWNER }}
21+
PR_HEAD_REPO_NAME:
22+
description: "The name of the repository from which the pull request is created"
23+
value: ${{ jobs.get-pr-info.outputs.PR_HEAD_REPO_NAME }}
24+
PR_BASE_REPO_NAME:
25+
description: "The name of the repository to which the pull request is created"
26+
value: ${{ jobs.get-pr-info.outputs.PR_BASE_REPO_NAME }}
27+
PR_HEAD_REF:
28+
description: "The branch name of the pull request in the head repository"
29+
value: ${{ jobs.get-pr-info.outputs.PR_HEAD_REF }}
30+
PR_BASE_REF:
31+
description: "The branch name in the base repository (to merge into)"
32+
value: ${{ jobs.get-pr-info.outputs.PR_BASE_REF }}
33+
PR_HEAD_SHA:
34+
description: "The head sha of the pull request branch in the head repository"
35+
value: ${{ jobs.get-pr-info.outputs.PR_HEAD_SHA }}
36+
PR_BASE_SHA:
37+
description: "The head sha of the target branch in the base repository"
38+
value: ${{ jobs.get-pr-info.outputs.PR_BASE_SHA }}
39+
PR_MERGE_COMMIT_SHA:
40+
description: "The sha of the merge commit for the pull request (created by GitHub) in the base repository"
41+
value: ${{ jobs.get-pr-info.outputs.PR_MERGE_COMMIT_SHA }}
42+
PR_HEAD_COMMIT_DATE:
43+
description: "The date of the head sha of the pull request branch in the head repository"
44+
value: ${{ jobs.get-pr-info.outputs.PR_HEAD_COMMIT_DATE }}
45+
PR_MERGE_COMMIT_DATE:
46+
description: "The date of the merge commit for the pull request (created by GitHub) in the base repository"
47+
value: ${{ jobs.get-pr-info.outputs.PR_MERGE_COMMIT_DATE }}
48+
PR_HEAD_COMMIT_TIMESTAMP:
49+
description: "The timestamp of the head sha of the pull request branch in the head repository"
50+
value: ${{ jobs.get-pr-info.outputs.PR_HEAD_COMMIT_TIMESTAMP }}
51+
PR_MERGE_COMMIT_TIMESTAMP:
52+
description: "The timestamp of the merge commit for the pull request (created by GitHub) in the base repository"
53+
value: ${{ jobs.get-pr-info.outputs.PR_MERGE_COMMIT_TIMESTAMP }}
54+
PR:
55+
description: "The PR"
56+
value: ${{ jobs.get-pr-info.outputs.PR }}
57+
PR_FILES:
58+
description: "The files touched in the PR"
59+
value: ${{ jobs.get-pr-info.outputs.PR_FILES }}
60+
61+
62+
jobs:
63+
get-pr-info:
64+
runs-on: ubuntu-22.04
65+
name: Get PR commit SHA better
66+
outputs:
67+
PR_HEAD_REPO_FULL_NAME: ${{ steps.pr_info.outputs.head_repo_full_name }}
68+
PR_BASE_REPO_FULL_NAME: ${{ steps.pr_info.outputs.base_repo_full_name }}
69+
PR_HEAD_REPO_OWNER: ${{ steps.pr_info.outputs.head_repo_owner }}
70+
PR_BASE_REPO_OWNER: ${{ steps.pr_info.outputs.base_repo_owner }}
71+
PR_HEAD_REPO_NAME: ${{ steps.pr_info.outputs.head_repo_name }}
72+
PR_BASE_REPO_NAME: ${{ steps.pr_info.outputs.base_repo_name }}
73+
PR_HEAD_REF: ${{ steps.pr_info.outputs.head_ref }}
74+
PR_BASE_REF: ${{ steps.pr_info.outputs.base_ref }}
75+
PR_HEAD_SHA: ${{ steps.pr_info.outputs.head_sha }}
76+
PR_BASE_SHA: ${{ steps.pr_info.outputs.base_sha }}
77+
PR_MERGE_COMMIT_SHA: ${{ steps.pr_info.outputs.merge_commit_sha }}
78+
PR_HEAD_COMMIT_DATE: ${{ steps.pr_info.outputs.head_commit_date }}
79+
PR_MERGE_COMMIT_DATE: ${{ steps.pr_info.outputs.merge_commit_date }}
80+
PR_HEAD_COMMIT_TIMESTAMP: ${{ steps.get_timestamps.outputs.head_commit_timestamp }}
81+
PR_MERGE_COMMIT_TIMESTAMP: ${{ steps.get_timestamps.outputs.merge_commit_timestamp }}
82+
PR: ${{ steps.pr_info.outputs.pr }}
83+
PR_FILES: ${{ steps.pr_info.outputs.files }}
84+
if: ${{ inputs.pr_number != '' }}
85+
steps:
86+
- name: Extract PR details
87+
id: pr_info
88+
uses: actions/github-script@v6
89+
with:
90+
script: |
91+
const { data: pr } = await github.rest.pulls.get({
92+
owner: context.repo.owner,
93+
repo: context.repo.repo,
94+
pull_number: ${{ inputs.pr_number }}
95+
});
96+
97+
const { data: head_commit } = await github.rest.repos.getCommit({
98+
owner: pr.head.repo.owner.login,
99+
repo: pr.head.repo.name,
100+
ref: pr.head.ref
101+
});
102+
103+
const { data: merge_commit } = await github.rest.repos.getCommit({
104+
owner: pr.base.repo.owner.login,
105+
repo: pr.base.repo.name,
106+
ref: pr.merge_commit_sha,
107+
});
108+
109+
const { data: files } = await github.rest.pulls.listFiles({
110+
owner: context.repo.owner,
111+
repo: context.repo.repo,
112+
pull_number: ${{ inputs.pr_number }}
113+
});
114+
115+
core.setOutput('head_repo_full_name', pr.head.repo.full_name);
116+
core.setOutput('base_repo_full_name', pr.base.repo.full_name);
117+
core.setOutput('head_repo_owner', pr.head.repo.owner.login);
118+
core.setOutput('base_repo_owner', pr.base.repo.owner.login);
119+
core.setOutput('head_repo_name', pr.head.repo.name);
120+
core.setOutput('base_repo_name', pr.base.repo.name);
121+
core.setOutput('head_ref', pr.head.ref);
122+
core.setOutput('base_ref', pr.base.ref);
123+
core.setOutput('head_sha', pr.head.sha);
124+
core.setOutput('base_sha', pr.base.sha);
125+
core.setOutput('merge_commit_sha', pr.merge_commit_sha);
126+
core.setOutput('pr', pr);
127+
128+
core.setOutput('head_commit_date', head_commit.commit.committer.date);
129+
core.setOutput('merge_commit_date', merge_commit.commit.committer.date);
130+
131+
core.setOutput('files', files);
132+
133+
console.log('PR head commit:', {
134+
head_commit: head_commit,
135+
commit: head_commit.commit,
136+
date: head_commit.commit.committer.date
137+
});
138+
139+
console.log('PR merge commit:', {
140+
merge_commit: merge_commit,
141+
commit: merge_commit.commit,
142+
date: merge_commit.commit.committer.date
143+
});
144+
145+
- name: Convert dates to timestamps
146+
id: get_timestamps
147+
run: |
148+
head_commit_date=${{ steps.pr_info.outputs.head_commit_date }}
149+
merge_commit_date=${{ steps.pr_info.outputs.merge_commit_date }}
150+
echo $head_commit_date
151+
echo $merge_commit_date
152+
head_commit_timestamp=$(date -d "$head_commit_date" +%s)
153+
merge_commit_timestamp=$(date -d "$merge_commit_date" +%s)
154+
echo $head_commit_timestamp
155+
echo $merge_commit_timestamp
156+
echo "head_commit_timestamp=$head_commit_timestamp" >> $GITHUB_OUTPUT
157+
echo "merge_commit_timestamp=$merge_commit_timestamp" >> $GITHUB_OUTPUT

.github/workflows/get-pr-number.yml

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
name: Get PR number
2+
on:
3+
workflow_call:
4+
outputs:
5+
PR_NUMBER:
6+
description: "The extracted PR number"
7+
value: ${{ jobs.get-pr-number.outputs.PR_NUMBER }}
8+
9+
jobs:
10+
get-pr-number:
11+
runs-on: ubuntu-22.04
12+
name: Get PR number
13+
outputs:
14+
PR_NUMBER: ${{ steps.set_pr_number.outputs.PR_NUMBER }}
15+
steps:
16+
- name: Get PR number
17+
shell: bash
18+
run: |
19+
if [[ "${{ github.event.issue.number }}" != "" && "${{ github.event.issue.pull_request }}" != "" ]]; then
20+
echo "PR_NUMBER=${{ github.event.issue.number }}" >> $GITHUB_ENV
21+
elif [[ "${{ github.event.pull_request.number }}" != "" ]]; then
22+
echo "PR_NUMBER=${{ github.event.pull_request.number }}" >> $GITHUB_ENV
23+
elif [[ "${{ github.event.pull_request }}" != "" ]]; then
24+
echo "PR_NUMBER=${{ github.event.number }}" >> $GITHUB_ENV
25+
else
26+
echo "PR_NUMBER=" >> $GITHUB_ENV
27+
fi
28+
29+
- name: Check PR number
30+
shell: bash
31+
run: |
32+
echo "${{ env.PR_NUMBER }}"
33+
34+
- name: Set PR number
35+
id: set_pr_number
36+
run: echo "PR_NUMBER=${{ env.PR_NUMBER }}" >> "$GITHUB_OUTPUT"

.github/workflows/pr_run_slow_ci.yml

Lines changed: 163 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,163 @@
1+
name: PR slow CI
2+
on:
3+
pull_request_target:
4+
types: [opened, synchronize, reopened]
5+
6+
jobs:
7+
get-pr-number:
8+
name: Get PR number
9+
uses: ./.github/workflows/get-pr-number.yml
10+
11+
get-pr-info:
12+
name: Get PR commit SHA
13+
needs: get-pr-number
14+
if: ${{ needs.get-pr-number.outputs.PR_NUMBER != ''}}
15+
uses: ./.github/workflows/get-pr-info.yml
16+
with:
17+
pr_number: ${{ needs.get-pr-number.outputs.PR_NUMBER }}
18+
19+
# We only need to verify the timestamp if the workflow is triggered by `issue_comment`.
20+
verity_pr_commit:
21+
name: Verity PR commit corresponds to a specific event by comparing timestamps
22+
if: ${{ github.event.comment.created_at != '' }}
23+
runs-on: ubuntu-22.04
24+
needs: get-pr-info
25+
env:
26+
COMMENT_DATE: ${{ github.event.comment.created_at }}
27+
PR_MERGE_COMMIT_DATE: ${{ needs.get-pr-info.outputs.PR_MERGE_COMMIT_DATE }}
28+
PR_MERGE_COMMIT_TIMESTAMP: ${{ needs.get-pr-info.outputs.PR_MERGE_COMMIT_TIMESTAMP }}
29+
steps:
30+
- run: |
31+
COMMENT_TIMESTAMP=$(date -d "${COMMENT_DATE}" +"%s")
32+
echo "COMMENT_DATE: $COMMENT_DATE"
33+
echo "PR_MERGE_COMMIT_DATE: $PR_MERGE_COMMIT_DATE"
34+
echo "COMMENT_TIMESTAMP: $COMMENT_TIMESTAMP"
35+
echo "PR_MERGE_COMMIT_TIMESTAMP: $PR_MERGE_COMMIT_TIMESTAMP"
36+
if [ $COMMENT_TIMESTAMP -le $PR_MERGE_COMMIT_TIMESTAMP ]; then
37+
echo "Last commit on the pull request is newer than the issue comment triggering this run! Abort!";
38+
exit -1;
39+
fi
40+
41+
get-jobs:
42+
name: Get test files to run
43+
runs-on: ubuntu-22.04
44+
needs: [get-pr-number, get-pr-info]
45+
outputs:
46+
jobs: ${{ steps.get_jobs.outputs.jobs_to_run }}
47+
steps:
48+
- name: Get repository content
49+
id: repo_content
50+
uses: actions/github-script@v6
51+
with:
52+
script: |
53+
const { data: tests_dir } = await github.rest.repos.getContent({
54+
owner: '${{ needs.get-pr-info.outputs.PR_HEAD_REPO_OWNER }}',
55+
repo: '${{ needs.get-pr-info.outputs.PR_HEAD_REPO_NAME }}',
56+
path: 'tests',
57+
ref: '${{ needs.get-pr-info.outputs.PR_HEAD_SHA }}',
58+
});
59+
60+
const { data: tests_models_dir } = await github.rest.repos.getContent({
61+
owner: '${{ needs.get-pr-info.outputs.PR_HEAD_REPO_OWNER }}',
62+
repo: '${{ needs.get-pr-info.outputs.PR_HEAD_REPO_NAME }}',
63+
path: 'tests/models',
64+
ref: '${{ needs.get-pr-info.outputs.PR_HEAD_SHA }}',
65+
});
66+
67+
const { data: tests_quantization_dir } = await github.rest.repos.getContent({
68+
owner: '${{ needs.get-pr-info.outputs.PR_HEAD_REPO_OWNER }}',
69+
repo: '${{ needs.get-pr-info.outputs.PR_HEAD_REPO_NAME }}',
70+
path: 'tests/quantization',
71+
ref: '${{ needs.get-pr-info.outputs.PR_HEAD_SHA }}',
72+
});
73+
74+
core.setOutput('tests_dir', tests_dir);
75+
core.setOutput('tests_models_dir', tests_models_dir);
76+
core.setOutput('tests_quantization_dir', tests_quantization_dir);
77+
78+
# This checkout to the main branch
79+
- uses: actions/checkout@v4
80+
with:
81+
fetch-depth: "0"
82+
83+
- name: Write pr_files file
84+
run: |
85+
cat > pr_files.txt << 'EOF'
86+
${{ needs.get-pr-info.outputs.PR_FILES }}
87+
EOF
88+
89+
- name: Write tests_dir file
90+
run: |
91+
cat > tests_dir.txt << 'EOF'
92+
${{ steps.repo_content.outputs.tests_dir }}
93+
EOF
94+
95+
- name: Write tests_models_dir file
96+
run: |
97+
cat > tests_models_dir.txt << 'EOF'
98+
${{ steps.repo_content.outputs.tests_models_dir }}
99+
EOF
100+
101+
- name: Write tests_quantization_dir file
102+
run: |
103+
cat > tests_quantization_dir.txt << 'EOF'
104+
${{ steps.repo_content.outputs.tests_quantization_dir }}
105+
EOF
106+
107+
- name: Run script to get jobs to run
108+
id: get_jobs
109+
run: |
110+
python utils/get_pr_run_slow_jobs.py | tee output.txt
111+
echo "jobs_to_run: $(tail -n 1 output.txt)"
112+
echo "jobs_to_run=$(tail -n 1 output.txt)" >> $GITHUB_OUTPUT
113+
114+
send_comment:
115+
name: Send a comment to suggest jobs to run
116+
if: ${{ needs.get-jobs.outputs.jobs != '' }}
117+
needs: [get-pr-number, get-jobs]
118+
permissions:
119+
pull-requests: write
120+
runs-on: ubuntu-22.04
121+
steps:
122+
- name: Delete existing comment and send new one
123+
uses: actions/github-script@v7
124+
env:
125+
BODY: "\n\nrun-slow: ${{ needs.get-jobs.outputs.jobs }}"
126+
with:
127+
script: |
128+
const prNumber = ${{ needs.get-pr-number.outputs.PR_NUMBER }};
129+
const commentPrefix = "**[For maintainers]** Suggested jobs to run (before merge)";
130+
131+
// Get all comments on the PR
132+
const { data: comments } = await github.rest.issues.listComments({
133+
owner: context.repo.owner,
134+
repo: context.repo.repo,
135+
issue_number: prNumber
136+
});
137+
138+
// Find existing comment(s) that start with our prefix
139+
const existingComments = comments.filter(comment =>
140+
comment.user.login === 'github-actions[bot]' &&
141+
comment.body.startsWith(commentPrefix)
142+
);
143+
144+
// Delete existing comment(s)
145+
for (const comment of existingComments) {
146+
console.log(`Deleting existing comment #${comment.id}`);
147+
await github.rest.issues.deleteComment({
148+
owner: context.repo.owner,
149+
repo: context.repo.repo,
150+
comment_id: comment.id
151+
});
152+
}
153+
154+
// Create new comment
155+
const newBody = `${commentPrefix}${process.env.BODY}`;
156+
await github.rest.issues.createComment({
157+
owner: context.repo.owner,
158+
repo: context.repo.repo,
159+
issue_number: prNumber,
160+
body: newBody
161+
});
162+
163+
console.log('✅ Comment updated successfully');

0 commit comments

Comments
 (0)