Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

A better security-wise style bot GH Action #2914

Open
wants to merge 13 commits into
base: main
Choose a base branch
from
123 changes: 82 additions & 41 deletions .github/workflows/style-bot-action.yml
Original file line number Diff line number Diff line change
@@ -1,17 +1,20 @@
# This workflow was originally implemented by the diffusers team and ported into huggingface_hub
# as a reusable workflow. Related PRs:
# - https://github.com/huggingface/diffusers/pull/10274
# - https://github.com/huggingface/diffusers/pull/10931
# - https://github.com/huggingface/diffusers/pull/10908


name: Style Bot Action

on:
workflow_call:
inputs:
pre_commit_script:
required: false
type: string
description: "Optional script to run before committing changes"
pre_commit_script_name:
style_command_type:
required: false
type: string
description: "Custom name for the pre-commit script step"
default: "Custom pre-commit script"
description: "Which style command to run (options: 'default' (make style && make quality), 'quality_only', 'style_only')"
default: "default"
python_quality_dependencies:
required: true
type: string
Expand All @@ -21,11 +24,6 @@ on:
type: string
description: "Python version to run code formatter"
default: "3.10"
style_command:
required: false
type: string
description: "Command to run for style checks or/and style fixes"
default: "make style && make quality"
secrets:
bot_token:
required: true
Expand All @@ -34,8 +32,9 @@ on:
jobs:
check-permissions:
if: >
contains(github.event.comment.body, '@bot /style') &&
github.event.issue.pull_request != null
(github.event_name == 'issue_comment' &&
contains(github.event.comment.body, '@bot /style') &&
github.event.issue.pull_request != null)
runs-on: ubuntu-latest
outputs:
is_authorized: ${{ steps.check_user_permission.outputs.has_permission }}
Expand All @@ -45,14 +44,16 @@ jobs:
uses: actions/github-script@v6
with:
script: |
const comment_user = context.payload.comment.user.login;

comment_user = context.payload.comment.user.login;
const { data: permission } = await github.rest.repos.getCollaboratorPermissionLevel({
owner: context.repo.owner,
repo: context.repo.repo,
username: comment_user
});
const authorized = permission.permission === 'admin';
console.log(`User ${comment_user} has permission level: ${permission.permission}, authorized: ${authorized} (only admins allowed)`);

const authorized = ['admin', 'maintain', 'push'].includes(permission.permission);
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)`);
Comment on lines +55 to +56
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I added directly the changes from #2939 here and i will close the other PR

core.setOutput('has_permission', authorized);

run-style-bot:
Expand All @@ -66,18 +67,27 @@ jobs:
with:
script: |
const prNumber = context.payload.issue.number;
console.log(`PR number from env: "${prNumber}"`);

const { data: pr } = await github.rest.pulls.get({
owner: context.repo.owner,
repo: context.repo.repo,
pull_number: prNumber
});

// We capture both the branch ref and the "full_name" of the head repo
// so that we can check out the correct repository & branch (including forks).
core.setOutput("prNumber", prNumber);
core.setOutput("headRef", pr.head.ref);
core.setOutput("headRepoFullName", pr.head.repo.full_name);

// Set outputs for use in subsequent steps
core.setOutput('headRepoFullName', pr.head.repo.full_name);
core.setOutput('headRef', pr.head.ref);
core.setOutput('baseRef', pr.base.ref);
core.setOutput('prNumber', prNumber);

console.log('PR Details:', {
number: prNumber,
headRepo: pr.head.repo.full_name,
headRef: pr.head.ref,
baseRef: pr.base.ref
});

- name: Check out PR branch
uses: actions/checkout@v3
env:
Expand All @@ -90,16 +100,37 @@ jobs:
# You may need fetch-depth: 0 for being able to push
fetch-depth: 0
token: ${{ secrets.bot_token }}

- name: Debug
env:
HEADREPOFULLNAME: ${{ steps.pr_info.outputs.headRepoFullName }}

- name: Check commit timestamps
env:
COMMENT_DATE: ${{ github.event.comment.created_at }}
PR_NUMBER: ${{ steps.pr_info.outputs.prNumber }}
BASE_REPO_URL: https://github.com/${{ github.repository }}
HEADREF: ${{ steps.pr_info.outputs.headRef }}
PRNUMBER: ${{ steps.pr_info.outputs.prNumber }}
run: |
echo "PR number: $PRNUMBER"
echo "Head Ref: $HEADREF"
echo "Head Repo Full Name: $HEADREPOFULLNAME"
echo "--- Checking remotes ---"
git remote -v
echo "--- Checking ref on origin (${{ steps.pr_info.outputs.headRepoFullName }}) ---"
git ls-remote origin refs/pull/$PR_NUMBER/merge || echo "Ref not found on origin (fork)."
echo "--- Checking ref on base (${{ github.repository }}) ---"
git ls-remote $BASE_REPO_URL refs/pull/$PR_NUMBER/merge || echo "Ref not found on base repository."

echo "--- Proceeding with fetch from base repository ---"
git fetch $BASE_REPO_URL refs/pull/$PR_NUMBER/merge:refs/remotes/pull/$PR_NUMBER/merge
git checkout refs/remotes/pull/$PR_NUMBER/merge
echo "PR_MERGE_SHA: $(git log -1 --format=%H)"
PR_MERGE_COMMIT_TIMESTAMP=$(git log -1 --date=unix --format=%cd)
echo "PR_MERGE_COMMIT_TIMESTAMP: $PR_MERGE_COMMIT_TIMESTAMP"
COMMENT_TIMESTAMP=$(date -d "${COMMENT_DATE}" +"%s")
echo "COMMENT_DATE: $COMMENT_DATE"
echo "COMMENT_TIMESTAMP: $COMMENT_TIMESTAMP"
if [ $COMMENT_TIMESTAMP -le $PR_MERGE_COMMIT_TIMESTAMP ]; then
echo "❌ Last commit on the pull request is newer than the issue comment triggering this run! Abort!";
exit -1;
fi

echo "--- Checking out contributor branch ($HEADREF) ---"
git checkout $HEADREF

- name: Set up Python
uses: actions/setup-python@v4
Expand All @@ -113,18 +144,28 @@ jobs:
python -m pip install --upgrade pip
pip install .$python_quality_dependencies

- name: ${{ inputs.pre_commit_script_name }}
env:
pre_commit_script: ${{ inputs.pre_commit_script }}
if: inputs.pre_commit_script != ''
run: |
bash -c "${pre_commit_script}"

- name: Run style command
env:
style_command: ${{ inputs.style_command }}
id: run_style
run: |
bash -c "$style_command"
case "${{ inputs.style_command_type }}" in
"default")
echo "Running default style and quality checks"
make style && make quality
;;
"quality_only")
echo "Running quality checks only"
make quality
;;
"style_only")
echo "Running style checks only"
make style
;;
*)
echo "Invalid style_command_type: ${{ inputs.style_command_type }}"
echo "Valid options are: 'default', 'quality_only', 'style_only'"
exit 1
;;
esac

- name: Commit and push changes
id: commit_and_push
Expand Down
4 changes: 2 additions & 2 deletions .github/workflows/style-bot.yml
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ name: Style Bot
on:
issue_comment:
types: [created]

permissions:
contents: write
pull-requests: write
Expand All @@ -13,6 +13,6 @@ jobs:
uses: ./.github/workflows/style-bot-action.yml
with:
python_quality_dependencies: "[quality]"
style_command: "make style"
style_command_type: "style_only"
secrets:
bot_token: ${{ secrets.GITHUB_TOKEN }}
Loading