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

Support ignore deletions with "ignore_line_deletions" param #71

Merged
merged 6 commits into from
Apr 16, 2024
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
33 changes: 17 additions & 16 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -55,22 +55,23 @@ jobs:

## 🎛️ Arguments

| Name | Required | Default Value | Description |
|-------------------|----------|----------------------|-------------------------------------------------------------------------------------------------------------------------|
| `GITHUB_TOKEN` | Yes | Automatically supplied| GitHub token needed to interact with the repository. |
| `xs_label` | No | 'size/xs' | Label for very small-sized PRs. |
| `xs_max_size` | No | '10' | Maximum number of changes allowed for XS-sized PRs. |
| `s_label` | No | 'size/s' | Label for small-sized PRs. |
| `s_max_size` | No | '100' | Maximum number of changes allowed for S-sized PRs. |
| `m_label` | No | 'size/m' | Label for medium-sized PRs. |
| `m_max_size` | No | '500' | Maximum number of changes allowed for M-sized PRs. |
| `l_label` | No | 'size/l' | Label for large-sized PRs. |
| `l_max_size` | No | '1000' | Maximum number of changes allowed for L-sized PRs. |
| `xl_label` | No | 'size/xl' | Label for extra-large-sized PRs. |
| `fail_if_xl` | No | 'false' | Whether to fail the GitHub workflow if the PR size is 'XL' (blocks the merge). |
| `message_if_xl` | No | Custom message | Message to display when a PR exceeds the 'XL' size limit. |
| `github_api_url` | No | 'https://api.github.com' | URL for the GitHub API, can be changed for GitHub Enterprise Servers. |
| `files_to_ignore` | No | '' | Files to ignore during PR size calculation. Supports newline or whitespace delimited list. |
| Name | Required | Default Value | Description |
|-------------------------|----------|----------------------|-------------------------------------------------------------------------------------------------------------------------|
| `GITHUB_TOKEN` | Yes | Automatically supplied| GitHub token needed to interact with the repository. |
| `xs_label` | No | 'size/xs' | Label for very small-sized PRs. |
| `xs_max_size` | No | '10' | Maximum number of changes allowed for XS-sized PRs. |
| `s_label` | No | 'size/s' | Label for small-sized PRs. |
| `s_max_size` | No | '100' | Maximum number of changes allowed for S-sized PRs. |
| `m_label` | No | 'size/m' | Label for medium-sized PRs. |
| `m_max_size` | No | '500' | Maximum number of changes allowed for M-sized PRs. |
| `l_label` | No | 'size/l' | Label for large-sized PRs. |
| `l_max_size` | No | '1000' | Maximum number of changes allowed for L-sized PRs. |
| `xl_label` | No | 'size/xl' | Label for extra-large-sized PRs. |
| `fail_if_xl` | No | 'false' | Whether to fail the GitHub workflow if the PR size is 'XL' (blocks the merge). |
| `message_if_xl` | No | Custom message | Message to display when a PR exceeds the 'XL' size limit. |
| `github_api_url` | No | 'https://api.github.com' | URL for the GitHub API, can be changed for GitHub Enterprise Servers. |
| `files_to_ignore` | No | '' | Files to ignore during PR size calculation. Supports newline or whitespace delimited list. |
| `ignore_line_deletions` | No | 'false' | Whether to ignore lines which are deleted when calculating the PR size. If set to 'true', deleted lines will be ignored. |

### Example for `files_to_ignore`:
```yml
Expand Down
5 changes: 5 additions & 0 deletions action.yml
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,10 @@ inputs:
description: 'Whitespace separated list of files to ignore when calculating the PR size (sum of changes)'
required: false
default: ''
ignore_line_deletions:
description: 'Ignore lines that are deleted, thereby only considering additions.'
johnlk marked this conversation as resolved.
Show resolved Hide resolved
required: false
default: 'false'
runs:
using: 'docker'
image: 'Dockerfile'
Expand All @@ -77,6 +81,7 @@ runs:
- --fail_if_xl=${{ inputs.fail_if_xl }}
- --message_if_xl="${{ inputs.message_if_xl }}"
- --files_to_ignore=${{ inputs.files_to_ignore }}
- --ignore_line_deletions=${{ inputs.ignore_line_deletions }}
branding:
icon: 'tag'
color: 'green'
45 changes: 29 additions & 16 deletions src/github.sh
Original file line number Diff line number Diff line change
Expand Up @@ -5,36 +5,49 @@ GITHUB_API_HEADER="Accept: application/vnd.github.v3+json"
github::calculate_total_modifications() {
local -r pr_number="${1}"
local -r files_to_ignore="${2}"
local -r ignore_line_deletions="${3}"

local additions=0
local deletions=0

if [ -z "$files_to_ignore" ]; then
local -r body=$(curl -sSL -H "Authorization: token $GITHUB_TOKEN" -H "$GITHUB_API_HEADER" "$GITHUB_API_URL/repos/$GITHUB_REPOSITORY/pulls/$pr_number")

local -r additions=$(echo "$body" | jq '.additions')
local -r deletions=$(echo "$body" | jq '.deletions')
additions=$(echo "$body" | jq '.additions')

echo $((additions + deletions))
if [ "$ignore_line_deletions" != "true" ]; then
((deletions += $(echo "$body" | jq '.deletions')))
fi
else
local -r body=$(curl -sSL -H "Authorization: token $GITHUB_TOKEN" -H "$GITHUB_API_HEADER" "$GITHUB_API_URL/repos/$GITHUB_REPOSITORY/pulls/$pr_number/files?per_page=100")

local changes=0

for file in $(echo "$body" | jq -r '.[] | @base64'); do
local ignore_file=0
for file_to_ignore in $files_to_ignore; do
if [ -z "$file_to_ignore" ]; then
continue
fi
if [[ "$(jq::base64 '.filename')" == $file_to_ignore ]]; then
ignore_file=1
_jq() {
echo ${file} | base64 -d | jq -r ${1}
}
Copy link
Member

Choose a reason for hiding this comment

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

Why not reusing jq::base64 instead?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Oh shoot, didn't realize this helper was already available. Will use!


filename=$(_jq '.filename')
ignore=false

for pattern in $files_to_ignore; do

if [[ $filename == $pattern ]]; then
ignore=true
break
fi
done
if [ $ignore_file -eq 0 ]; then
((changes += $(jq::base64 '.changes')))

if [ "$ignore" = false ]; then
((additions += $(_jq '.additions')))

if [ "$ignore_line_deletions" != "true" ]; then
((deletions += $(_jq '.deletions')))
fi
fi
done

echo $changes
fi

echo $((additions + deletions))
}

github::add_label_to_pr() {
Expand Down
9 changes: 8 additions & 1 deletion src/github_actions.sh
Original file line number Diff line number Diff line change
@@ -1,5 +1,12 @@
#!/usr/bin/env bash

github_actions::get_pr_number() {
jq --raw-output .pull_request.number "$GITHUB_EVENT_PATH"
local -r pull_request_number=$(jq --raw-output .pull_request.number "$GITHUB_EVENT_PATH")

if [[ "$pull_request_number" != "null" ]]; then
echo "$pull_request_number"
else
echo "Not a pull request event"
Copy link
Collaborator Author

Choose a reason for hiding this comment

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

this code block would've saved me so much time while I was testing this. I was testing on push events and was getting very obscure errors. 🙃

exit 1
fi
}
3 changes: 2 additions & 1 deletion src/labeler.sh
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,10 @@ labeler::label() {
local -r fail_if_xl="${10}"
local -r message_if_xl="${11}"
local -r files_to_ignore="${12}"
local -r ignore_line_deletions="${13}"

local -r pr_number=$(github_actions::get_pr_number)
local -r total_modifications=$(github::calculate_total_modifications "$pr_number" "$files_to_ignore")
local -r total_modifications=$(github::calculate_total_modifications "$pr_number" "${files_to_ignore[*]}" "$ignore_line_deletions")

log::message "Total modifications (additions + deletions): $total_modifications"
log::message "Ignoring files (if present): $files_to_ignore"
Expand Down
5 changes: 3 additions & 2 deletions src/main.sh
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ source "$PR_SIZE_LABELER_HOME/src/misc.sh"
##? Adds a size label to a GitHub Pull Request
##?
##? Usage:
##? main.sh --github_token=<token> --xs_label=<label> --xs_max_size=<size> --s_label=<label> --s_max_size=<size> --m_label=<label> --m_max_size=<size> --l_label=<label> --l_max_size=<size> --xl_label=<label> --fail_if_xl=<false> --message_if_xl=<message> --github_api_url=<url> --files_to_ignore=<files>
##? main.sh --github_token=<token> --xs_label=<label> --xs_max_size=<size> --s_label=<label> --s_max_size=<size> --m_label=<label> --m_max_size=<size> --l_label=<label> --l_max_size=<size> --xl_label=<label> --fail_if_xl=<false> --message_if_xl=<message> --github_api_url=<url> --files_to_ignore=<files> --ignore_line_deletions=<false>
main() {
eval "$(/root/bin/docpars -h "$(grep "^##?" "$PR_SIZE_LABELER_HOME/src/main.sh" | cut -c 5-)" : "$@")"

Expand All @@ -31,7 +31,8 @@ main() {
"$xl_label" \
"$fail_if_xl" \
"$message_if_xl" \
"$files_to_ignore"
"$files_to_ignore" \
"$ignore_line_deletions"

exit $?
}
38 changes: 38 additions & 0 deletions tests/fixtures/pull_request_api
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
{
"url": "https://api.github.com/repos/test/pulls/123",
"number": 123,
"state": "open",
"locked": false,
"title": "YOLO PR",
"user": {},
"body": "",
"created_at": "2024-04-12T17:08:32Z",
"updated_at": "2024-04-12T20:03:46Z",
"closed_at": null,
"merged_at": null,
"merge_commit_sha": "9ec1fc67bbc7bd9151270",
"assignee": null,
"assignees": [],
"requested_reviewers": [],
"requested_teams": [],
"labels": [],
"milestone": null,
"draft": false,
"head": {},
"base": {},
"author_association": "CONTRIBUTOR",
"auto_merge": null,
"active_lock_reason": null,
"merged": false,
"mergeable": true,
"rebaseable": false,
"mergeable_state": "blocked",
"merged_by": null,
"comments": 4,
"review_comments": 0,
"maintainer_can_modify": false,
"commits": 9,
"additions": 173,
"deletions": 1,
"changed_files": 4
}
37 changes: 33 additions & 4 deletions tests/github_test.sh
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,39 @@ function set_up() {
source ./src/github.sh
}

pr_number=123
files_to_ignore=''
ignore_line_deletions='false'

function test_should_count_changes() {
mock curl cat ./tests/fixtures/pull_request_api

assert_match_snapshot "$(github::calculate_total_modifications "$pr_number" "${files_to_ignore[*]}" "$ignore_line_deletions")"
}

function test_should_count_changes_ignore_deletions() {
ignore_line_deletions='true'

mock curl cat ./tests/fixtures/pull_request_api

assert_match_snapshot "$(github::calculate_total_modifications "$pr_number" "${files_to_ignore[*]}" "$ignore_line_deletions")"
}

# NOTE: when `files_to_ignore` is set, we have to invoke the PR files API and iterate each file
# one at at time. This is why the mock call is diffent in the subsequent test cases
function test_should_ignore_files_with_glob() {
local -r pr_number=123
local -r files_to_ignore=("*.lock" ".editorconfig")
mock curl cat ./tests/fixtures/test_should_ignore_files_with_regex_response
files_to_ignore=("*.lock" ".editorconfig")

mock curl cat ./tests/fixtures/pull_request_files_api

assert_match_snapshot "$(github::calculate_total_modifications "$pr_number" "${files_to_ignore[*]}")"
assert_match_snapshot "$(github::calculate_total_modifications "$pr_number" "${files_to_ignore[*]}" "$ignore_line_deletions")"
}

function test_should_ignore_files_with_glob_ignore_deletions() {
files_to_ignore=("*.lock" ".editorconfig")
ignore_line_deletions='true'

mock curl cat ./tests/fixtures/pull_request_files_api

assert_match_snapshot "$(github::calculate_total_modifications "$pr_number" "${files_to_ignore[*]}" "$ignore_line_deletions")"
}
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
174
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
173
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
224