From 989fd51f79ce3c0e5b7fc09840ea1ba3a78dd7f8 Mon Sep 17 00:00:00 2001 From: Vadim Nifadev <36514612+nifadyev@users.noreply.github.com> Date: Fri, 4 Oct 2024 17:18:19 +0300 Subject: [PATCH] #78: Add pr diff size checker in CI and pre-commit (#91) --- .github/actions/large-pr-check/action.yaml | 49 ++++++++++++++++++++++ .github/workflows/pr.yml | 16 +++++++ .pre-commit-config.yaml | 7 ++++ scripts/large-pr-checker.sh | 30 +++++++++++++ 4 files changed, 102 insertions(+) create mode 100644 .github/actions/large-pr-check/action.yaml create mode 100644 scripts/large-pr-checker.sh diff --git a/.github/actions/large-pr-check/action.yaml b/.github/actions/large-pr-check/action.yaml new file mode 100644 index 0000000..e4414f9 --- /dev/null +++ b/.github/actions/large-pr-check/action.yaml @@ -0,0 +1,49 @@ +name: "Large PR checker" +description: "Blocks PR if number of lines changed is excessive. Modified version of https://github.com/adolfosilva/gh-large-pr-check/blob/main/action.yml" + +inputs: + max_lines_changed: + description: "Maximum number of lines changed allowed" + required: true + default: "500" + target_branch: + description: The branch to compare against + required: true + default: main +outputs: + total_lines_changed: + description: "Total lines changed in this PR" + value: ${{ steps.get_total_lines_changed.outputs.total_lines_changed }} + +runs: + using: "composite" + steps: + - id: fetch_target_branch + run: | + git fetch origin ${{ inputs.target_branch }} + shell: bash + - id: get_total_lines_changed + run: | + size=$(git diff --shortstat origin/${{ inputs.target_branch }} ':(exclude)*.lock' \ + | awk '{ print $4+$6 }' \ + | awk -F- '{print $NF}' \ + | bc) + + echo "" + echo "Total lines changed (note: *.lock files are excluded from this count): $size" + echo "total_lines_changed=$size" >> $GITHUB_OUTPUT + shell: bash + - name: Comment PR + if: ${{ fromJSON(steps.get_total_lines_changed.outputs.total_lines_changed) > fromJSON(inputs.max_lines_changed) }} + uses: thollander/actions-comment-pull-request@v2 + with: + comment_tag: pr_size + mode: recreate + message: | + :boom: :boom: :boom: + Total lines changed ${{ steps.get_total_lines_changed.outputs.total_lines_changed }} is greater than ${{ inputs.max_lines_changed }}. + Please consider breaking this PR down. + - id: fail + if: ${{ fromJSON(steps.get_total_lines_changed.outputs.total_lines_changed) > fromJSON(inputs.max_lines_changed) }} + run: exit 1 + shell: bash diff --git a/.github/workflows/pr.yml b/.github/workflows/pr.yml index 0eda5fd..77f3152 100644 --- a/.github/workflows/pr.yml +++ b/.github/workflows/pr.yml @@ -18,6 +18,19 @@ env: RUFF_VERSION: "0.6.7" jobs: + check-pr-diff: + runs-on: ubuntu-latest + + steps: + - name: Checkout repository + uses: actions/checkout@v4 + + - name: Check PR diff size + uses: ./.github/actions/large-pr-check + with: + target_branch: ${{ github.event.pull_request.base.ref }} + max_lines_changed: 300 + lint: runs-on: ubuntu-latest timeout-minutes: 10 @@ -37,6 +50,9 @@ jobs: - name: Run Ruff run: ruff check --output-format=github . + - name: Spell Check + uses: crate-ci/typos@master + test: runs-on: ubuntu-latest strategy: diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index e187218..9c03f31 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -41,3 +41,10 @@ repos: stages: [pre-push] language: python types: [python] + - id: check-pr-size + name: check-pr-size + entry: chmod +x scripts/large-pr-checker.sh && ./large-pr-checker.sh + pass_filenames: false + stages: [pre-push] + language: system + types: [python] diff --git a/scripts/large-pr-checker.sh b/scripts/large-pr-checker.sh new file mode 100644 index 0000000..ef66b15 --- /dev/null +++ b/scripts/large-pr-checker.sh @@ -0,0 +1,30 @@ +#!/bin/bash + +# Script helps to block Pull Requests with exceeded number of changed lines of code. +# Firstly, it compares HEAD with source branch +# Then it counts changed lines of code, excluding specified files and respecting max lines of code + +# Read first input arg or take default value - 500 +MAX_CHANGED_LOC="${1:-500}" + +# Second argument (source branch) is required +if [ -z "$2" ]; then + echo "No remote source branch supplied" + exit 1 +else + source_branch=$2 +fi + +# Parse such line `2 files changed, 18 insertions(+), 248 deletions(-)` and write to variable +changed_loc=$(git diff --shortstat ${source_branch} ':(exclude)*.lock' \ + | awk '{ print $4+$6 }' \ + | awk -F- '{print $NF}' \ + | bc) + +if [[ $changed_loc -le $MAX_CHANGED_LOC ]]; then + echo "✅ ${changed_loc} lines of code changed. It is allowed to create Pull Request" + exit 0 +else + echo "❌ ${changed_loc} lines of code changed. It is more than allowed ${MAX_CHANGED_LOC}. Please divide changes into several branches" + exit 1 +fi