Skip to content

Commit b527e08

Browse files
authored
Merge pull request #6097 from DependencyTrack/nscuro-patch-1
Enforce usage of the PR template
2 parents 31e78ad + 8330fe3 commit b527e08

1 file changed

Lines changed: 98 additions & 0 deletions

File tree

Lines changed: 98 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,98 @@
1+
# This file is part of Dependency-Track.
2+
#
3+
# Licensed under the Apache License, Version 2.0 (the "License");
4+
# you may not use this file except in compliance with the License.
5+
# You may obtain a copy of the License at
6+
#
7+
# http://www.apache.org/licenses/LICENSE-2.0
8+
#
9+
# Unless required by applicable law or agreed to in writing, software
10+
# distributed under the License is distributed on an "AS IS" BASIS,
11+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
# See the License for the specific language governing permissions and
13+
# limitations under the License.
14+
#
15+
# SPDX-License-Identifier: Apache-2.0
16+
# Copyright (c) OWASP Foundation. All Rights Reserved.
17+
name: PR Template Check
18+
19+
on:
20+
pull_request:
21+
types: [opened, edited, synchronize, reopened]
22+
23+
permissions: {}
24+
25+
jobs:
26+
validate:
27+
runs-on: ubuntu-latest
28+
steps:
29+
- name: Validate PR body
30+
env:
31+
PR_BODY: ${{ github.event.pull_request.body }}
32+
PR_AUTHOR_TYPE: ${{ github.event.pull_request.user.type }}
33+
PR_AUTHOR_LOGIN: ${{ github.event.pull_request.user.login }}
34+
run: |
35+
set -euo pipefail
36+
37+
if [[ "$PR_AUTHOR_TYPE" == "Bot" || "$PR_AUTHOR_LOGIN" == "dependabot[bot]" ]]; then
38+
echo "::notice::Skipping template check for bot author '${PR_AUTHOR_LOGIN}'."
39+
exit 0
40+
fi
41+
42+
if [[ -z "$(printf '%s' "$PR_BODY" | tr -d '[:space:]')" ]]; then
43+
echo "::error::PR body is empty. Please use the pull request template."
44+
exit 1
45+
fi
46+
47+
fail=0
48+
49+
require_heading() {
50+
local heading="$1"
51+
if ! grep -qiE "^### +${heading}[[:space:]]*$" <<< "$PR_BODY"; then
52+
echo "::error::Missing required section: '### ${heading}'."
53+
fail=1
54+
fi
55+
}
56+
57+
require_heading "Description"
58+
require_heading "Addressed Issue"
59+
require_heading "Checklist"
60+
61+
# Extract section bodies (between this H3 and the next H3 or EOF).
62+
section() {
63+
awk -v h="### $1" '
64+
$0 ~ "^"h"[[:space:]]*$" {flag=1; next}
65+
flag && /^### / {flag=0}
66+
flag {print}
67+
' <<< "$PR_BODY"
68+
}
69+
70+
strip_comments_and_ws() {
71+
# Drop HTML comments, then collapse whitespace.
72+
perl -0777 -pe 's/<!--.*?-->//gs' | tr -d '[:space:]'
73+
}
74+
75+
desc=$(section "Description" | strip_comments_and_ws || true)
76+
if [[ -z "${desc}" ]]; then
77+
echo "::error::'### Description' section is empty (template placeholder doesn't count)."
78+
fail=1
79+
fi
80+
81+
issue_raw=$(section "Addressed Issue" | perl -0777 -pe 's/<!--.*?-->//gs')
82+
issue=$(printf '%s' "$issue_raw" | tr -d '[:space:]')
83+
if [[ -z "${issue}" ]]; then
84+
echo "::error::'### Addressed Issue' section is empty."
85+
fail=1
86+
elif grep -qiE '^[[:space:]]*n/?a[[:space:]]*$' <<< "$issue_raw"; then
87+
echo "::notice::Accepted 'N/A' for Addressed Issue."
88+
elif ! grep -qiE '(#[0-9]+|(close[sd]?|fix(e[sd])?|resolve[sd]?)[[:space:]:]+#?[0-9]+|github\.com/[^/]+/[^/]+/issues/[0-9]+)' <<< "$issue_raw"; then
89+
echo "::error::'### Addressed Issue' must reference an issue (e.g. '#1234', 'fixes #1234', or full issue URL). Use 'N/A' explicitly if none applies."
90+
fail=1
91+
fi
92+
93+
if [[ $fail -ne 0 ]]; then
94+
echo ""
95+
echo "PR body does not follow the template at .github/PULL_REQUEST_TEMPLATE.md."
96+
echo "Please restore the template structure and fill in the required sections."
97+
exit 1
98+
fi

0 commit comments

Comments
 (0)