Skip to content

Commit

Permalink
Merge branch 'main' into chore/gh-api-url
Browse files Browse the repository at this point in the history
  • Loading branch information
johnlk authored Apr 16, 2024
2 parents 1d7d184 + 891ac86 commit 9e5577d
Show file tree
Hide file tree
Showing 19 changed files with 288 additions and 36 deletions.
1 change: 1 addition & 0 deletions .env
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
DEFAULT_PATH=tests
13 changes: 13 additions & 0 deletions .github/CONTRIBUTIONS.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
# Testing

Tests written in [bashunit](https://bashunit.typeddevs.com/).

Install vendor dependencies:
```bash
./install-dependencies.sh
```

Run all tests:
```bash
./lib/bashunit tests
```
20 changes: 20 additions & 0 deletions .github/pull_request_template.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
## What type of PR is this? (check all applicable)

- [ ] Refactor
- [ ] Feature
- [ ] Bug Fix
- [ ] Optimization
- [ ] Documentation Update

## Description
_A brief description of the work covered in this change._

## Notes to Reviewer
_If there is a particular part of the code that you need the reviewer to examine closely (e.g. some logic you are not sure about), please specify here._

## How to test
_Please replace this line with instructions on how to test your changes. Use screenshots or recordings if necessary._

## Link to issues addressed
- [ISSUE-XYZ](https://github.com/CodelyTV/pr-size-labeler/issues/XYZ)
- [ISSUE-XYZ](https://github.com/CodelyTV/pr-size-labeler/issues/XYZ)
19 changes: 19 additions & 0 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
on:
pull_request:
push:
branches:
- main

name: Tests
jobs:
tests:
name: "Run tests"
runs-on: 'ubuntu-latest'
steps:
- uses: actions/checkout@v3

- name: "Install dependencies"
run: ./install-dependencies.sh

- name: "Tests"
run: ./lib/bashunit
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
.idea/

lib/bashunit
41 changes: 26 additions & 15 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
</p>

<h1 align="center">
🏷 Pull Request size labeler
🏷 Pull Request Size Labeler
</h1>

<p align="center">
Expand All @@ -20,9 +20,7 @@

## 🚀 Usage

Create a file named `labeler.yml` inside the `.github/workflows` directory and paste the following configuration.

☝️ Here you can see the default values of all available configuration parameters, however, the only required parameter is the `GITHUB_TOKEN` one.
Create a file named `labeler.yml` inside the `.github/workflows` directory and paste the following configuration:

```yml
name: labeler
Expand Down Expand Up @@ -51,19 +49,31 @@ jobs:
This PR exceeds the recommended size of 1000 lines.
Please make sure you are NOT addressing multiple issues with one PR.
Note this PR might be rejected due to its size.
github_api_url: 'api.github.com'
github_api_url: 'https://api.github.com'
files_to_ignore: ''
```
## 🎛️ Available parameters
## 🎛️ 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. |
| `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. |

- `*_label` (`xs_label`, `s_label`…): Adjust size label names
- `*_max_size` (`xs_max_size`, `s_max_size`…): Adjust which amount of changes you consider appropriate for each size based on your project context
- `fail_if_xl`: Set to `'true'` will report GitHub Workflow failure if the PR size is xl allowing to forbid PR merge
- `message_if_xl`: Let the user(s) know that the PR exceeds the recommended size and what the consequences are
- `github_api_url`: Override this parameter in order to use with your own GitHub Enterprise Server. Example: `'https://github.example.com/api/v3'`
- `files_to_ignore`: Whitespace or newline separated list of files to ignore when calculating the PR size, regex match is supported.
### files_to_ignore Example:
### Example for `files_to_ignore`:
```yml
files_to_ignore: 'package-lock.json *.lock'
# OR
Expand All @@ -72,10 +82,11 @@ files_to_ignore: |
"*.lock"
"docs/*"
```

## 🤔 Basic concepts or assumptions

- PR size labeler consider as a change any kind of line addition, deletion, or modification
- A PR will be labeled as `xl` if it exceeds the amount of changes defined as `l_max_size`
- PR Size Labeler considers any line addition, deletion, or modification as a change.
- A PR will be labeled as 'xl' if it exceeds the amount of changes defined in `l_max_size`.

## ⚖️ License

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: 'Whether to ignore lines which are deleted when calculating the PR size. If set to "true", deleted lines will be ignored.'
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'
4 changes: 4 additions & 0 deletions install-dependencies.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
#!/bin/bash

## bashunit
curl -s https://bashunit.typeddevs.com/install.sh | bash -s -- lib 0.10.0
42 changes: 25 additions & 17 deletions src/github.sh
Original file line number Diff line number Diff line change
Expand Up @@ -5,36 +5,44 @@ 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
filename=$(jq::base64 '.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::base64 '.additions')))

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

echo $changes
fi

echo $((additions + deletions))
}

github::add_label_to_pr() {
Expand All @@ -47,7 +55,7 @@ github::add_label_to_pr() {
local -r xl_label="${7}"

local -r body=$(curl -sSL -H "Authorization: token $GITHUB_TOKEN" -H "$GITHUB_API_HEADER" "$GITHUB_API_URL/repos/$GITHUB_REPOSITORY/pulls/$pr_number")
local labels=$(echo "$body" | jq .labels | jq -r ".[] | .name" | grep -e "$xs_label" -e "$s_label" -e "$m_label" -e "$l_label" -e "$xl_label" -v)
local labels=$(echo "$body" | jq .labels | jq -r ".[] | .name" | grep -w -e "$xs_label" -e "$s_label" -e "$m_label" -e "$l_label" -e "$xl_label" -v)
labels=$(printf "%s\n%s" "$labels" "$label_to_add")
local -r comma_separated_labels=$(github::format_labels "$labels")

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"
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
}
74 changes: 74 additions & 0 deletions tests/fixtures/pull_request_files_api
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
[
{
"filename": ".editorconfig",
"additions": 9,
"deletions": 0,
"changes": 9
},
{
"filename": ".github/workflows/ci.yml",
"additions": 17,
"deletions": 0,
"changes": 17
},
{
"filename": "asdasdasd.lock",
"additions": 1188,
"deletions": 0,
"changes": 1188
},
{
"filename": "entrypoint.sh",
"additions": 4,
"deletions": 4,
"changes": 8
},
{
"filename": "src/ensure.sh",
"additions": 4,
"deletions": 4,
"changes": 8
},
{
"filename": "src/github.sh",
"additions": 89,
"deletions": 76,
"changes": 165
},
{
"filename": "src/github_actions.sh",
"additions": 1,
"deletions": 1,
"changes": 2
},
{
"filename": "src/inner.lock",
"additions": 1188,
"deletions": 0,
"changes": 1188
},
{
"filename": "src/labeler.sh",
"additions": 48,
"deletions": 48,
"changes": 96
},
{
"filename": "src/log.sh",
"additions": 17,
"deletions": 0,
"changes": 17
},
{
"filename": "src/main.sh",
"additions": 34,
"deletions": 23,
"changes": 57
},
{
"filename": "src/misc.sh",
"additions": 10,
"deletions": 14,
"changes": 24
}
]
Loading

0 comments on commit 9e5577d

Please sign in to comment.