Initial commit
This commit is contained in:
44
.gitea/issue_template/bug_report.yaml
Normal file
44
.gitea/issue_template/bug_report.yaml
Normal file
@@ -0,0 +1,44 @@
|
||||
name: Bug Report
|
||||
about: Report a bug specific to this repository (API, tests, CI, etc.)
|
||||
labels:
|
||||
- "type: bug"
|
||||
body:
|
||||
- type: markdown
|
||||
attributes:
|
||||
value: |
|
||||
**Note:** For product-level bugs and feature requests, use [Evercatch Board](https://git.psmattas.com/Evercatch/evercatch-board/issues).
|
||||
This template is for repo-specific issues (broken tests, CI failures, dependency problems, etc.).
|
||||
- type: input
|
||||
id: summary
|
||||
attributes:
|
||||
label: Summary
|
||||
placeholder: Brief description of the bug
|
||||
validations:
|
||||
required: true
|
||||
- type: textarea
|
||||
id: steps
|
||||
attributes:
|
||||
label: Steps to Reproduce
|
||||
value: |
|
||||
1.
|
||||
2.
|
||||
3.
|
||||
validations:
|
||||
required: true
|
||||
- type: textarea
|
||||
id: expected
|
||||
attributes:
|
||||
label: Expected Behavior
|
||||
validations:
|
||||
required: true
|
||||
- type: textarea
|
||||
id: actual
|
||||
attributes:
|
||||
label: Actual Behavior
|
||||
validations:
|
||||
required: true
|
||||
- type: textarea
|
||||
id: context
|
||||
attributes:
|
||||
label: Additional Context
|
||||
description: Logs, screenshots, environment details, etc.
|
||||
35
.gitea/issue_template/documentation.yaml
Normal file
35
.gitea/issue_template/documentation.yaml
Normal file
@@ -0,0 +1,35 @@
|
||||
name: Documentation
|
||||
about: Report missing, incorrect, or outdated documentation in this repo
|
||||
labels:
|
||||
- "type: docs"
|
||||
body:
|
||||
- type: markdown
|
||||
attributes:
|
||||
value: |
|
||||
Use this for documentation issues within this repository (README, inline docs, API docs, setup guides).
|
||||
For product-level documentation requests, use [Evercatch Board](https://git.psmattas.com/Evercatch/evercatch-board/issues).
|
||||
- type: input
|
||||
id: page
|
||||
attributes:
|
||||
label: Affected Page / File
|
||||
placeholder: e.g. README.md, monitoring/README.md, app/api/v1/webhooks.py
|
||||
validations:
|
||||
required: true
|
||||
- type: dropdown
|
||||
id: type
|
||||
attributes:
|
||||
label: Type
|
||||
options:
|
||||
- Missing documentation
|
||||
- Incorrect / outdated information
|
||||
- Unclear or confusing
|
||||
- Typo / formatting
|
||||
validations:
|
||||
required: true
|
||||
- type: textarea
|
||||
id: description
|
||||
attributes:
|
||||
label: Description
|
||||
description: What needs to change and why?
|
||||
validations:
|
||||
required: true
|
||||
46
.gitea/issue_template/security_vulnerability.yaml
Normal file
46
.gitea/issue_template/security_vulnerability.yaml
Normal file
@@ -0,0 +1,46 @@
|
||||
name: Security Vulnerability
|
||||
about: Report a security vulnerability in this repository
|
||||
labels:
|
||||
- "type: security"
|
||||
- "priority: critical"
|
||||
body:
|
||||
- type: markdown
|
||||
attributes:
|
||||
value: |
|
||||
**Please do not disclose sensitive details publicly.** If this is a critical vulnerability,
|
||||
contact the maintainers directly before filing a public issue.
|
||||
- type: input
|
||||
id: summary
|
||||
attributes:
|
||||
label: Summary
|
||||
placeholder: Brief description of the vulnerability
|
||||
validations:
|
||||
required: true
|
||||
- type: dropdown
|
||||
id: severity
|
||||
attributes:
|
||||
label: Severity
|
||||
options:
|
||||
- Critical — active exploit / data exposure
|
||||
- High — exploitable with moderate effort
|
||||
- Medium — limited impact or requires specific conditions
|
||||
- Low — informational / hardening suggestion
|
||||
validations:
|
||||
required: true
|
||||
- type: textarea
|
||||
id: description
|
||||
attributes:
|
||||
label: Description
|
||||
description: What is the vulnerability and how can it be exploited?
|
||||
validations:
|
||||
required: true
|
||||
- type: textarea
|
||||
id: reproduction
|
||||
attributes:
|
||||
label: Steps to Reproduce
|
||||
description: Provide enough detail for someone to verify the issue.
|
||||
- type: textarea
|
||||
id: remediation
|
||||
attributes:
|
||||
label: Suggested Remediation
|
||||
description: If you have a fix in mind, describe it here.
|
||||
20
.gitea/pull_request_template.md
Normal file
20
.gitea/pull_request_template.md
Normal file
@@ -0,0 +1,20 @@
|
||||
### Ticket
|
||||
|
||||
<!-- Use cross-repo reference format. Leave blank for repo-only changes. -->
|
||||
|
||||
Resolves Evercatch/evercatch-board#
|
||||
|
||||
### Summary
|
||||
|
||||
<!-- One or two sentences — what and why. Details are in the ticket. -->
|
||||
|
||||
### Changes
|
||||
|
||||
-
|
||||
-
|
||||
|
||||
### Checklist
|
||||
|
||||
- [ ] Self-reviewed
|
||||
- [ ] Tests added/updated and passing
|
||||
- [ ] Docs updated (if applicable)
|
||||
88
.gitea/workflows/pr-management.yml
Normal file
88
.gitea/workflows/pr-management.yml
Normal file
@@ -0,0 +1,88 @@
|
||||
name: PR Management Bot
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
types: [opened, edited, synchronize, reopened]
|
||||
branches: [main]
|
||||
|
||||
jobs:
|
||||
pr-bot:
|
||||
runs-on: ubuntu-latest
|
||||
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_AUTHOR: ${{ gitea.actor }}
|
||||
|
||||
steps:
|
||||
# FIX 1: Use standard short syntax to avoid upstream gitea.com connection errors
|
||||
- name: Check out repository
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Auto-label from commit messages
|
||||
run: |
|
||||
API_URL="$API_BASE_URL/repos/$REPO/pulls/$PR_NUMBER/commits"
|
||||
MESSAGES=$(curl -s -H "Authorization: token $API_TOKEN" "$API_URL" | jq -r '.[].commit.message')
|
||||
|
||||
# Match "EC-NUM: TYPE" or standalone "TYPE:" at start of commit message
|
||||
UNIQUE_TYPES=$(echo "$MESSAGES" | grep -oP '^(EC-\d+: )?\K(FEAT|FIX|DOCS|STYLE|REFACTOR|PERF|TEST|CHORE)(?=:)' | sort -u || true)
|
||||
|
||||
if [[ -z "$UNIQUE_TYPES" ]]; then
|
||||
echo "No semantic commit types found."
|
||||
exit 0
|
||||
fi
|
||||
|
||||
LABELS_JSON=$(echo "$UNIQUE_TYPES" | jq -R '("type: " + (. | ascii_downcase))' | jq -s '{"labels": .}')
|
||||
ISSUES_API_URL="$API_BASE_URL/repos/$REPO/issues/$PR_NUMBER/labels"
|
||||
curl -s -f -X POST -H "Authorization: token $API_TOKEN" -H "Content-Type: application/json" -d "$LABELS_JSON" "$ISSUES_API_URL"
|
||||
|
||||
- name: Auto-assign author
|
||||
if: gitea.event.pull_request.assignees_count == 0 && gitea.actor != 'gitea-actions' && gitea.actor != 'EC-bot'
|
||||
run: |
|
||||
ISSUES_EDIT_API_URL="$API_BASE_URL/repos/$REPO/issues/$PR_NUMBER"
|
||||
JSON_PAYLOAD=$(echo "$PR_AUTHOR" | jq -R '{"assignees": [.]}')
|
||||
curl -s -f -X PATCH -H "Authorization: token $API_TOKEN" -H "Content-Type: application/json" -d "$JSON_PAYLOAD" "$ISSUES_EDIT_API_URL"
|
||||
|
||||
- name: Add conflict label and comment
|
||||
if: gitea.event.pull_request.merge_status == 'CONFLICT'
|
||||
run: |
|
||||
COMMENT_BODY="🚨 **Merge Conflict Detected** 🚨\n\nHi @$PR_AUTHOR, this pull request has merge conflicts with the \`main\` branch. Please resolve them by rebasing or merging \`main\` into your branch so the PR can be reviewed."
|
||||
COMMENT_JSON=$(jq -n --arg body "$COMMENT_BODY" '{"body": $body}')
|
||||
ISSUES_API_URL="$API_BASE_URL/repos/$REPO/issues/$PR_NUMBER/comments"
|
||||
curl -s -f -X POST -H "Authorization: token $API_TOKEN" -H "Content-Type: application/json" -d "$COMMENT_JSON" "$ISSUES_API_URL"
|
||||
|
||||
LABEL_JSON='{ "labels": ["status: needs-rebase"] }'
|
||||
LABELS_API_URL="$API_BASE_URL/repos/$REPO/issues/$PR_NUMBER/labels"
|
||||
curl -s -f -X POST -H "Authorization: token $API_TOKEN" -H "Content-Type: application/json" -d "$LABEL_JSON" "$LABELS_API_URL"
|
||||
|
||||
- name: Remove 'needs-rebase' label if clean
|
||||
if: gitea.event.pull_request.merge_status != 'CONFLICT'
|
||||
run: |
|
||||
LABEL_TO_REMOVE="status: needs-rebase"
|
||||
ISSUES_API_URL="$API_BASE_URL/repos/$REPO/issues/$PR_NUMBER"
|
||||
|
||||
CURRENT_LABELS_JSON=$(curl -s -H "Authorization: token $API_TOKEN" "$ISSUES_API_URL/labels")
|
||||
LABEL_ID=$(echo "$CURRENT_LABELS_JSON" | jq --arg name "$LABEL_TO_REMOVE" '.[] | select(.name == $name) | .id')
|
||||
|
||||
if [ -n "$LABEL_ID" ]; then
|
||||
echo "Found and removing '$LABEL_TO_REMOVE' (ID: $LABEL_ID)..."
|
||||
curl -s -f -X DELETE -H "Authorization: token $API_TOKEN" "$ISSUES_API_URL/labels/$LABEL_ID"
|
||||
fi
|
||||
|
||||
- name: Auto-assign reviewers
|
||||
run: |
|
||||
target_reviewer="psmattas"
|
||||
|
||||
# FIX 3: Check if the author is the target reviewer to avoid API error (422)
|
||||
if [[ "$PR_AUTHOR" == "$target_reviewer" ]]; then
|
||||
echo "Author is $target_reviewer. Skipping self-review request."
|
||||
exit 0
|
||||
fi
|
||||
|
||||
REVIEWERS_JSON="{\"reviewers\": [\"$target_reviewer\"]}"
|
||||
echo "Requesting review from: $target_reviewer"
|
||||
API_URL="$API_BASE_URL/repos/$REPO/pulls/$PR_NUMBER/requested_reviewers"
|
||||
curl -s -f -X POST -H "Authorization: token $API_TOKEN" -H "Content-Type: application/json" -d "$REVIEWERS_JSON" "$API_URL"
|
||||
110
.gitea/workflows/pr-title-checker.yml
Normal file
110
.gitea/workflows/pr-title-checker.yml
Normal file
@@ -0,0 +1,110 @@
|
||||
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**.
|
||||
|
||||
Please update the title to match one of these formats:
|
||||
|
||||
**Board issue:** `EC-[NUMBER]: [TYPE]: Description`
|
||||
**Repo-only:** `[TYPE]: Description`
|
||||
|
||||
- **Valid types:** `FEAT`, `FIX`, `DOCS`, `REFACTOR`, `STYLE`, `PERF`, `TEST`, `CHORE`
|
||||
- **Examples:**
|
||||
- `EC-10: FEAT: Add monitoring stack`
|
||||
- `FIX: Correct typo in health endpoint`
|
||||
|
||||
PRs with an `EC-` prefix automatically reference `Evercatch/evercatch-board#`.
|
||||
|
||||
<!-- 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="status: invalid-title"
|
||||
WIP_REGEX="^WIP:"
|
||||
# Accept either "EC-NUM: TYPE: desc" or "TYPE: desc"
|
||||
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
|
||||
Reference in New Issue
Block a user