Skip to content

Commit e618073

Browse files
authored
Refactor PR Style Bot workflow with new inputs
Updated the PR Style Bot workflow to enhance functionality and include new inputs for style commands and Python quality dependencies.
1 parent f48af0b commit e618073

File tree

1 file changed

+242
-112
lines changed

1 file changed

+242
-112
lines changed
Lines changed: 242 additions & 112 deletions
Original file line numberDiff line numberDiff line change
@@ -1,112 +1,242 @@
1-
# name: PR Style Bot
2-
3-
# on:
4-
# issue_comment:
5-
# types: [created]
6-
7-
# permissions:
8-
# contents: write
9-
# pull-requests: write
10-
11-
# jobs:
12-
# run-style-bot:
13-
# if: >
14-
# contains(github.event.comment.body, '@bot /style') &&
15-
# github.event.issue.pull_request != null &&
16-
# github.event.comment.user.login == 'paulinebm'
17-
18-
# runs-on: ubuntu-latest
19-
20-
# steps:
21-
# - name: Extract PR details
22-
# id: pr_info
23-
# uses: actions/github-script@v6
24-
# with:
25-
# script: |
26-
# const prNumber = context.payload.issue.number;
27-
# const { data: pr } = await github.rest.pulls.get({
28-
# owner: context.repo.owner,
29-
# repo: context.repo.repo,
30-
# pull_number: prNumber
31-
# });
32-
33-
# // We capture both the branch ref and the "full_name" of the head repo
34-
# // so that we can check out the correct repository & branch (including forks).
35-
# core.setOutput("prNumber", prNumber);
36-
# core.setOutput("headRef", pr.head.ref);
37-
# core.setOutput("headRepoFullName", pr.head.repo.full_name);
38-
# - name: Check out PR branch
39-
# uses: actions/checkout@v3
40-
# env:
41-
# HEADREPOFULLNAME: ${{ steps.pr_info.outputs.headRepoFullName }}
42-
# HEADREF: ${{ steps.pr_info.outputs.headRef }}
43-
# with:
44-
# # Instead of checking out the base repo, use the contributor's repo name
45-
# repository: ${{ env.HEADREPOFULLNAME }}
46-
# ref: ${{ env.HEADREF }}
47-
# # You may need fetch-depth: 0 for being able to push
48-
# fetch-depth: 0
49-
# token: ${{ secrets.GITHUB_TOKEN }}
50-
51-
# - name: Debug
52-
# env:
53-
# HEADREPOFULLNAME: ${{ steps.pr_info.outputs.headRepoFullName }}
54-
# HEADREF: ${{ steps.pr_info.outputs.headRef }}
55-
# PRNUMBER: ${{ steps.pr_info.outputs.prNumber }}
56-
# run: |
57-
# echo "PR number: ${{ env.PRNUMBER }}"
58-
# echo "Head Ref: ${{ env.HEADREF }}"
59-
# echo "Head Repo Full Name: ${{ env.HEADREPOFULLNAME }}"
60-
61-
# - name: Set up Python
62-
# uses: actions/setup-python@v4
63-
# - name: Install dependencies
64-
# env:
65-
# TEST: ${{ secrets.TEST }}
66-
# run: |
67-
# pip install .[quality]
68-
69-
# - name: Run ruff format --check
70-
# run: |
71-
# ruff format .
72-
# ruff check --fix .
73-
# - name: Commit and push changes
74-
# id: commit_and_push
75-
# env:
76-
# HEADREPOFULLNAME: ${{ steps.pr_info.outputs.headRepoFullName }}
77-
# HEADREF: ${{ steps.pr_info.outputs.headRef }}
78-
# PRNUMBER: ${{ steps.pr_info.outputs.prNumber }}
79-
# GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
80-
# run: |
81-
# echo "HEADREPOFULLNAME: ${{ env.HEADREPOFULLNAME }}, HEADREF: ${{ env.HEADREF }}"
82-
# # Configure git with the Actions bot user
83-
# git config user.name "github-actions[bot]"
84-
# git config user.email "github-actions[bot]@users.noreply.github.com"
85-
# # Make sure your 'origin' remote is set to the contributor's fork
86-
# git remote set-url origin "https://x-access-token:${GITHUB_TOKEN}@github.com/${{ env.HEADREPOFULLNAME }}.git"
87-
# # If there are changes after running style/quality, commit them
88-
# if [ -n "$(git status --porcelain)" ]; then
89-
# git add .
90-
# git commit -m "Apply style fixes"
91-
# # Push to the original contributor's forked branch
92-
# git push origin HEAD:${{ env.HEADREF }}
93-
# echo "changes_pushed=true" >> $GITHUB_OUTPUT
94-
# else
95-
# echo "No changes to commit."
96-
# echo "changes_pushed=false" >> $GITHUB_OUTPUT
97-
# fi
98-
# - name: Comment on PR with workflow run link
99-
# if: steps.commit_and_push.outputs.changes_pushed == 'true'
100-
# uses: actions/github-script@v6
101-
# with:
102-
# script: |
103-
# const prNumber = parseInt(process.env.prNumber, 10);
104-
# const runUrl = `${process.env.GITHUB_SERVER_URL}/${process.env.GITHUB_REPOSITORY}/actions/runs/${process.env.GITHUB_RUN_ID}`
105-
# await github.rest.issues.createComment({
106-
# owner: context.repo.owner,
107-
# repo: context.repo.repo,
108-
# issue_number: prNumber,
109-
# body: `Style fixes have been applied. [View the workflow run here](${runUrl}).`
110-
# });
111-
# env:
112-
# prNumber: ${{ steps.pr_info.outputs.prNumber }}
1+
# This workflow was originally implemented by the diffusers team and ported into huggingface_hub
2+
# as a reusable workflow. Related PRs:
3+
# - https://github.com/huggingface/diffusers/pull/10274
4+
# - https://github.com/huggingface/diffusers/pull/10931
5+
# - https://github.com/huggingface/diffusers/pull/10908
6+
7+
8+
name: Style Bot Action
9+
10+
on:
11+
workflow_call:
12+
inputs:
13+
style_command_type:
14+
required: false
15+
type: string
16+
description: "Which style command to run (options: 'default' (make style && make quality), 'quality_only', 'style_only')"
17+
default: "default"
18+
python_quality_dependencies:
19+
required: true
20+
type: string
21+
description: "Python package extras to install for quality checks (e.g. '[quality]')"
22+
python_version:
23+
required: false
24+
type: string
25+
description: "Python version to run code formatter"
26+
default: "3.10"
27+
secrets:
28+
bot_token:
29+
required: true
30+
description: "GitHub token with permissions to comment and push to PR"
31+
32+
jobs:
33+
check-permissions:
34+
if: >
35+
(github.event_name == 'issue_comment' &&
36+
contains(github.event.comment.body, '@bot /style') &&
37+
github.event.issue.pull_request != null)
38+
runs-on: ubuntu-latest
39+
outputs:
40+
is_authorized: ${{ steps.check_user_permission.outputs.has_permission }}
41+
steps:
42+
- name: Check user permission
43+
id: check_user_permission
44+
uses: actions/github-script@v6
45+
with:
46+
script: |
47+
48+
comment_user = context.payload.comment.user.login;
49+
const { data: permission } = await github.rest.repos.getCollaboratorPermissionLevel({
50+
owner: context.repo.owner,
51+
repo: context.repo.repo,
52+
username: comment_user
53+
});
54+
55+
const authorized = ['admin', 'maintain', 'push', 'write'].includes(permission.permission);
56+
console.log(`User ${comment_user} has permission level: ${permission.permission}, authorized: ${authorized} (only users with at least write access are allowed to run this action)`);
57+
core.setOutput('has_permission', authorized);
58+
59+
run-style-bot:
60+
needs: check-permissions
61+
if: needs.check-permissions.outputs.is_authorized == 'true'
62+
runs-on: ubuntu-latest
63+
steps:
64+
- name: Extract PR details
65+
id: pr_info
66+
uses: actions/github-script@v6
67+
with:
68+
script: |
69+
const prNumber = context.payload.issue.number;
70+
console.log(`PR number from env: "${prNumber}"`);
71+
72+
const { data: pr } = await github.rest.pulls.get({
73+
owner: context.repo.owner,
74+
repo: context.repo.repo,
75+
pull_number: prNumber
76+
});
77+
78+
// Set outputs for use in subsequent steps
79+
core.setOutput('headRepoFullName', pr.head.repo.full_name);
80+
core.setOutput('headRef', pr.head.ref);
81+
core.setOutput('baseRef', pr.base.ref);
82+
core.setOutput('prNumber', prNumber);
83+
84+
console.log('PR Details:', {
85+
number: prNumber,
86+
headRepo: pr.head.repo.full_name,
87+
headRef: pr.head.ref,
88+
baseRef: pr.base.ref
89+
});
90+
91+
- name: Check out PR branch
92+
uses: actions/checkout@v3
93+
env:
94+
HEADREPOFULLNAME: ${{ steps.pr_info.outputs.headRepoFullName }}
95+
HEADREF: ${{ steps.pr_info.outputs.headRef }}
96+
with:
97+
# Instead of checking out the base repo, use the contributor's repo name
98+
repository: ${{ env.HEADREPOFULLNAME }}
99+
ref: ${{ env.HEADREF }}
100+
# You may need fetch-depth: 0 for being able to push
101+
fetch-depth: 0
102+
token: ${{ secrets.bot_token }}
103+
104+
- name: Check commit timestamps
105+
env:
106+
COMMENT_DATE: ${{ github.event.comment.created_at }}
107+
PR_NUMBER: ${{ steps.pr_info.outputs.prNumber }}
108+
BASE_REPO_URL: https://github.com/${{ github.repository }}
109+
HEADREF: ${{ steps.pr_info.outputs.headRef }}
110+
run: |
111+
echo "--- Checking remotes ---"
112+
git remote -v
113+
echo "--- Checking ref on origin (${{ steps.pr_info.outputs.headRepoFullName }}) ---"
114+
git ls-remote origin refs/pull/$PR_NUMBER/merge || echo "Ref not found on origin (fork)."
115+
echo "--- Checking ref on base (${{ github.repository }}) ---"
116+
git ls-remote $BASE_REPO_URL refs/pull/$PR_NUMBER/merge || echo "Ref not found on base repository."
117+
118+
echo "--- Proceeding with fetch from base repository ---"
119+
git fetch $BASE_REPO_URL refs/pull/$PR_NUMBER/merge:refs/remotes/pull/$PR_NUMBER/merge
120+
git checkout refs/remotes/pull/$PR_NUMBER/merge
121+
echo "PR_MERGE_SHA: $(git log -1 --format=%H)"
122+
PR_MERGE_COMMIT_TIMESTAMP=$(git log -1 --date=unix --format=%cd)
123+
echo "PR_MERGE_COMMIT_TIMESTAMP: $PR_MERGE_COMMIT_TIMESTAMP"
124+
COMMENT_TIMESTAMP=$(date -d "${COMMENT_DATE}" +"%s")
125+
echo "COMMENT_DATE: $COMMENT_DATE"
126+
echo "COMMENT_TIMESTAMP: $COMMENT_TIMESTAMP"
127+
if [ $COMMENT_TIMESTAMP -le $PR_MERGE_COMMIT_TIMESTAMP ]; then
128+
echo "❌ Last commit on the pull request is newer than the issue comment triggering this run! Abort!";
129+
exit -1;
130+
fi
131+
132+
echo "--- Checking out contributor branch ($HEADREF) ---"
133+
git checkout $HEADREF
134+
135+
- name: Comment on PR with workflow run link
136+
id: init_comment
137+
uses: actions/github-script@v6
138+
with:
139+
script: |
140+
const prNumber = parseInt(process.env.prNumber, 10);
141+
const runUrl = `${process.env.GITHUB_SERVER_URL}/${process.env.GITHUB_REPOSITORY}/actions/runs/${process.env.GITHUB_RUN_ID}`
142+
143+
const { data: botComment } = await github.rest.issues.createComment({
144+
owner: context.repo.owner,
145+
repo: context.repo.repo,
146+
issue_number: prNumber,
147+
body: `Style fix is beginning .... [View the workflow run here](${runUrl}).`
148+
});
149+
core.setOutput('comment_id', botComment.id);
150+
env:
151+
prNumber: ${{ steps.pr_info.outputs.prNumber }}
152+
153+
- name: Set up Python
154+
uses: actions/setup-python@v4
155+
with:
156+
python-version: ${{ inputs.python_version }}
157+
158+
- name: Install dependencies
159+
env:
160+
python_quality_dependencies: ${{ inputs.python_quality_dependencies }}
161+
run: |
162+
python -m pip install --upgrade pip
163+
pip install .$python_quality_dependencies
164+
echo ${{ steps.init_comment.outputs.comment_id }}
165+
166+
- name: Run style command
167+
id: run_style
168+
env:
169+
STYLECOMMANDTYPE : ${{ inputs.style_command_type }}
170+
run: |
171+
case "$STYLECOMMANDTYPE" in
172+
"default")
173+
echo "Running default style and quality checks"
174+
make style && make quality
175+
;;
176+
"quality_only")
177+
echo "Running quality checks only"
178+
make quality
179+
;;
180+
"style_only")
181+
echo "Running style checks only"
182+
make style
183+
;;
184+
*)
185+
echo "Invalid style_command_type: $STYLECOMMANDTYPE"
186+
echo "Valid options are: 'default', 'quality_only', 'style_only'"
187+
exit 1
188+
;;
189+
esac
190+
191+
- name: Commit and push changes
192+
id: commit_and_push
193+
env:
194+
HEADREPOFULLNAME: ${{ steps.pr_info.outputs.headRepoFullName }}
195+
HEADREF: ${{ steps.pr_info.outputs.headRef }}
196+
PRNUMBER: ${{ steps.pr_info.outputs.prNumber }}
197+
GITHUB_TOKEN: ${{ secrets.bot_token }}
198+
run: |
199+
echo "HEADREPOFULLNAME: $HEADREPOFULLNAME, HEADREF: $HEADREF"
200+
# Configure git with the Actions bot user
201+
git config user.name "github-actions[bot]"
202+
git config user.email "github-actions[bot]@users.noreply.github.com"
203+
204+
# Make sure your 'origin' remote is set to the contributor's fork
205+
git remote set-url origin "https://x-access-token:${GITHUB_TOKEN}@github.com/$HEADREPOFULLNAME.git"
206+
207+
# If there are changes after running style/quality, commit them
208+
if [ -n "$(git status --porcelain)" ]; then
209+
git add .
210+
git commit -m "Apply style fixes"
211+
# Push to the original contributor's forked branch
212+
git push origin HEAD:$HEADREF
213+
echo "changes_pushed=true" >> $GITHUB_OUTPUT
214+
else
215+
echo "No changes to commit."
216+
echo "changes_pushed=false" >> $GITHUB_OUTPUT
217+
fi
218+
219+
- name: Prepare final comment message
220+
id: prepare_final_comment
221+
run: |
222+
if [ "${{ steps.commit_and_push.outputs.changes_pushed }}" = 'true' ]; then
223+
echo "final_comment=Style bot fixed some files and pushed the changes." >> $GITHUB_OUTPUT
224+
else
225+
echo "final_comment=Style fix runs successfully without any file modified." >> $GITHUB_OUTPUT
226+
fi
227+
228+
- name: Comment on PR
229+
uses: actions/github-script@v6
230+
with:
231+
script: |
232+
const prNumber = parseInt(process.env.prNumber, 10);
233+
const runUrl = `${process.env.GITHUB_SERVER_URL}/${process.env.GITHUB_REPOSITORY}/actions/runs/${process.env.GITHUB_RUN_ID}`
234+
235+
await github.rest.issues.updateComment({
236+
owner: context.repo.owner,
237+
repo: context.repo.repo,
238+
comment_id: ${{ steps.init_comment.outputs.comment_id }},
239+
body: `${{ steps.prepare_final_comment.outputs.final_comment }}`
240+
});
241+
env:
242+
prNumber: ${{ steps.pr_info.outputs.prNumber }}

0 commit comments

Comments
 (0)