105 lines
5.2 KiB
YAML
105 lines
5.2 KiB
YAML
name: PR Title Checker
|
||
|
||
on:
|
||
pull_request:
|
||
types: [opened, edited, synchronize]
|
||
|
||
jobs:
|
||
enforce-pr-title:
|
||
name: Validate PR Title Format
|
||
runs-on: ubuntu-latest
|
||
steps:
|
||
- name: Check PR Title and Manage Labels/Comments
|
||
env:
|
||
API_TOKEN: ${{ secrets.BOT_ACCESS_TOKEN }}
|
||
API_BASE_URL: https://git.psmattas.com/api/v1
|
||
REPO: ${{ gitea.repository }}
|
||
PR_NUMBER: ${{ gitea.event.pull_request.number }}
|
||
PR_TITLE: ${{ gitea.event.pull_request.title }}
|
||
COMMENT_BODY_INVALID: |
|
||
Hi @${{ gitea.actor }}, thanks for the contribution!
|
||
|
||
The title of this pull request does not follow the required format. This PR is currently **blocked from merging**.
|
||
|
||
To fix this, please update the title to match the following structure:
|
||
**`EC-[JIRA_NUMBER]: [TYPE]: [Your Description]`**
|
||
|
||
- **Valid [TYPE] values are:** `FEAT`, `FIX`, `DOCS`, `REFACTOR`, `STYLE`, `PERF`, `TEST`, `CHORE`
|
||
- **Example:** `EC-42: FEAT: Add new user login endpoint`
|
||
|
||
Once you have updated the title, this check will re-run automatically and remove the blocking label.
|
||
|
||
<!-- PR_TITLE_VALIDATOR_COMMENT -->
|
||
COMMENT_BODY_WIP: |
|
||
Hi @${{ gitea.actor }}, this pull request has been marked as a **Work in Progress**.
|
||
|
||
While in this state, it is **blocked from merging**.
|
||
|
||
When the PR is ready for review, please remove the `WIP:` prefix from the title. This check will re-run automatically and remove the blocking label.
|
||
|
||
<!-- WIP_VALIDATOR_COMMENT -->
|
||
run: |
|
||
WIP_LABEL="status: work-in-progress"
|
||
INVALID_LABEL="INVALID-TITLE-DO-NOT-MERGE"
|
||
WIP_REGEX="^WIP:"
|
||
FORMAT_REGEX="^EC-[0-9]+: (FEAT|FIX|DOCS|REFACTOR|STYLE|PERF|TEST|CHORE): .+$"
|
||
ISSUES_API_URL="$API_BASE_URL/repos/$REPO/issues/$PR_NUMBER"
|
||
|
||
if [ -z "$PR_NUMBER" ]; then
|
||
echo "::error::Could not determine PR Number. Aborting."
|
||
exit 1
|
||
fi
|
||
|
||
if [[ "$PR_TITLE" =~ $WIP_REGEX ]]; then
|
||
echo "ℹ️ PR is marked as a Work in Progress."
|
||
LABEL_JSON=$(echo "$WIP_LABEL" | jq -R '{"labels": [.]}')
|
||
curl -s -f -X POST -H "Authorization: token $API_TOKEN" -H "Content-Type: application/json" -d "$LABEL_JSON" "$ISSUES_API_URL/labels"
|
||
|
||
WIP_COMMENT_IDENTIFIER="<!-- WIP_VALIDATOR_COMMENT -->"
|
||
EXISTING_COMMENTS=$(curl -s -H "Authorization: token $API_TOKEN" "$ISSUES_API_URL/comments")
|
||
if ! echo "$EXISTING_COMMENTS" | grep -q "$WIP_COMMENT_IDENTIFIER"; then
|
||
echo "Posting WIP comment."
|
||
COMMENT_JSON=$(jq -n --arg body "$COMMENT_BODY_WIP" '{"body": $body}')
|
||
curl -s -f -X POST -H "Authorization: token $API_TOKEN" -H "Content-Type: application/json" -d "$COMMENT_JSON" "$ISSUES_API_URL/comments"
|
||
fi
|
||
exit 1
|
||
|
||
elif [[ "$PR_TITLE" =~ $FORMAT_REGEX ]]; then
|
||
echo "✅ PR title format is correct and not a WIP."
|
||
echo "Checking for labels to remove..."
|
||
|
||
CURRENT_LABELS_JSON=$(curl -s -H "Authorization: token $API_TOKEN" "$ISSUES_API_URL/labels")
|
||
|
||
INVALID_LABEL_ID=$(echo "$CURRENT_LABELS_JSON" | jq --arg name "$INVALID_LABEL" '.[] | select(.name == $name) | .id')
|
||
if [ -n "$INVALID_LABEL_ID" ]; then
|
||
echo "Found and removing '$INVALID_LABEL' (ID: $INVALID_LABEL_ID)..."
|
||
curl -s -f -X DELETE -H "Authorization: token $API_TOKEN" "$ISSUES_API_URL/labels/$INVALID_LABEL_ID"
|
||
fi
|
||
|
||
WIP_LABEL_ID=$(echo "$CURRENT_LABELS_JSON" | jq --arg name "$WIP_LABEL" '.[] | select(.name == $name) | .id')
|
||
if [ -n "$WIP_LABEL_ID" ]; then
|
||
echo "Found and removing '$WIP_LABEL' (ID: $WIP_LABEL_ID)..."
|
||
curl -s -f -X DELETE -H "Authorization: token $API_TOKEN" "$ISSUES_API_URL/labels/$WIP_LABEL_ID"
|
||
fi
|
||
|
||
exit 0
|
||
|
||
else
|
||
echo "❌ ERROR: PR title does not match the required format."
|
||
echo "Adding '$INVALID_LABEL' label..."
|
||
LABEL_JSON=$(echo "$INVALID_LABEL" | jq -R '{"labels": [.]}')
|
||
curl -s -f -X POST -H "Authorization: token $API_TOKEN" -H "Content-Type: application/json" -d "$LABEL_JSON" "$ISSUES_API_URL/labels"
|
||
|
||
# Remove WIP label just in case
|
||
ENCODED_WIP_LABEL=$(python3 -c "import urllib.parse; print(urllib.parse.quote('$WIP_LABEL'))")
|
||
curl -s -X DELETE -H "Authorization: token $API_TOKEN" "$ISSUES_API_URL/labels/$ENCODED_WIP_LABEL" || true
|
||
|
||
INVALID_COMMENT_IDENTIFIER="<!-- PR_TITLE_VALIDATOR_COMMENT -->"
|
||
EXISTING_COMMENTS=$(curl -s -H "Authorization: token $API_TOKEN" "$ISSUES_API_URL/comments")
|
||
if ! echo "$EXISTING_COMMENTS" | grep -q "$INVALID_COMMENT_IDENTIFIER"; then
|
||
echo "Posting invalid title comment."
|
||
COMMENT_JSON=$(jq -n --arg body "$COMMENT_BODY_INVALID" '{"body": $body}')
|
||
curl -s -f -X POST -H "Authorization: token $API_TOKEN" -H "Content-Type: application/json" -d "$COMMENT_JSON" "$ISSUES_API_URL/comments"
|
||
fi
|
||
exit 1
|
||
fi |