Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,16 @@ jobs:
git fetch origin "${{ github.base_ref }}" --depth=1
git diff --check "origin/${{ github.base_ref }}"...HEAD

issue-template-label-validation:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-python@v5
with:
python-version: "3.11"
- name: Validate issue template labels
run: python scripts/validate_issue_template_labels.py

backend-lint:
needs: detect-changes
if: needs.detect-changes.outputs.run_backend == 'true'
Expand Down
18 changes: 18 additions & 0 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,24 @@ SecuScan is built for learning, defensive security workflows, and ethical testin

When issue labels are available, look for tags such as `good first issue`, `documentation`, `frontend`, `backend`, `plugin`, `help wanted`, or `gssoc`.

## Issue Template Label Maintenance

Issue templates in `.github/ISSUE_TEMPLATE/` must only reference labels from the active repository taxonomy.

When adding or updating issue template labels:

- Use active label groups such as `type:*`, `area:*`, `priority:*`, and `level:*`.
- Avoid deprecated labels such as `bug`, `feature`, `documentation`, and `help wanted`.
- Keep template labels aligned with the labels used by maintainers and CI.

Before opening a pull request that changes issue templates, run:

```bash
python scripts/validate_issue_template_labels.py
```

The CI workflow also runs this validation and will fail if an issue template references a label that is not included in the approved label taxonomy.

## Local Setup

### Prerequisites
Expand Down
101 changes: 101 additions & 0 deletions scripts/validate_issue_template_labels.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
from pathlib import Path
import re
import sys

VALID_LABELS = {
"type:bug",
"type:feature",
"type:docs",
"type:devops",
"type:security",
"type:testing",
"type:performance",
"type:refactor",
"area:ci",
"area:docs",
"area:backend",
"area:frontend",
"priority:low",
"priority:medium",
"priority:high",
"level:beginner",
"level:intermediate",
"level:advanced",
}

REPO_ROOT = Path(__file__).resolve().parents[1]
TEMPLATE_DIR = REPO_ROOT / ".github" / "ISSUE_TEMPLATE"

errors = []


def extract_front_matter(content):
if not content.startswith("---"):
return ""

parts = content.split("---", 2)
if len(parts) < 3:
return ""

return parts[1]


def parse_labels(raw_value):
raw_value = raw_value.strip().strip("\"'")

if raw_value.startswith("[") and raw_value.endswith("]"):
raw_value = raw_value[1:-1]

return [
label.strip().strip("\"'")
for label in raw_value.split(",")
if label.strip()
]


def extract_labels_from_front_matter(front_matter):
labels = []
lines = front_matter.splitlines()

for index, line in enumerate(lines):
match = re.match(r"^labels:\s*(.*)$", line)

if not match:
continue

value = match.group(1).strip()

if value:
labels.extend(parse_labels(value))
continue

for next_line in lines[index + 1:]:
stripped = next_line.strip()

if not stripped:
continue

if not stripped.startswith("-"):
break

labels.append(stripped[1:].strip().strip("\"'"))

return labels


for template in list(TEMPLATE_DIR.glob("*.md")) + list(TEMPLATE_DIR.glob("*.yml")) + list(TEMPLATE_DIR.glob("*.yaml")):
content = template.read_text(encoding="utf-8")
front_matter = extract_front_matter(content)
labels = extract_labels_from_front_matter(front_matter)

for label in labels:
if label not in VALID_LABELS:
errors.append("{}: invalid label '{}'".format(template.relative_to(REPO_ROOT), label))

if errors:
print("Invalid issue template labels found:")
for error in errors:
print("- {}".format(error))
sys.exit(1)

print("All issue template labels are valid.")
Loading