Skip to content
Merged
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
79 changes: 79 additions & 0 deletions .github/workflows/pr-template-validation.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
name: PR Template Validation

on:
pull_request:
types:
- opened
- edited
- synchronize
- reopened

permissions:
pull-requests: read

jobs:
validate-pr-template:
runs-on: ubuntu-latest

steps:
- name: Validate Pull Request Template
uses: actions/github-script@v7

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔒 Security & Privacy | 🟠 Major | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

printf '\n== workflow ==\n'
cat -n .github/workflows/pr-template-validation.yml

printf '\n== pr template ==\n'
cat -n .github/PULL_REQUEST_TEMPLATE.md

printf '\n== pinning references ==\n'
rg -n "github-script@v7|pin.*SHA|full commit SHA|zizmor|actions/" .github README.md . || true

Repository: imuniqueshiv/HyperLearningTech

Length of output: 5070


Pin actions/github-script to a full commit SHA. Using @v7 leaves this guardrail exposed to upstream changes; pin the exact revision you intend to trust.

🧰 Tools
🪛 zizmor (1.26.1)

[error] 20-20: unpinned action reference (unpinned-uses): action is not pinned to a hash (required by blanket policy)

(unpinned-uses)

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In @.github/workflows/pr-template-validation.yml at line 20, The workflow step
using actions/github-script is not pinned to an immutable revision, so update
the uses reference in the GitHub Actions workflow to a full commit SHA instead
of `@v7`. Locate the github-script step in the validation workflow and replace the
version tag with the exact trusted commit for actions/github-script.

Source: Linters/SAST tools

with:
script: |
const body = (context.payload.pull_request.body || "").trim();

const errors = [];

function contains(text) {
return body.includes(text);
}

// PR description must not be empty
if (body.length === 0) {
errors.push("PR description cannot be empty.");
}

// Placeholder text must be removed
const placeholders = [
"Provide a brief description of your changes.",
"Briefly describe the key changes made in this Pull Request.",
"Describe how you tested your changes.",
"Add any additional context for reviewers if needed."
];

for (const placeholder of placeholders) {
if (contains(placeholder)) {
errors.push(`Remove placeholder text: "${placeholder}"`);
}
}
Comment on lines +36 to +48

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

This still allows empty required sections.

Right now the workflow only rejects the exact placeholder sentences. In the template, ## Summary, ## What Changed?, and ## Testing can still be left effectively blank by removing the placeholder text and keeping only the stub bullets/separators, so the “required sections are filled out” objective is not actually enforced.

Suggested direction
+            function getSection(title) {
+              return (
+                body.match(new RegExp(`## ${title}\\s*([\\s\\S]*?)(?:\\n---|\\n## |$)`, "i"))?.[1] ?? ""
+              );
+            }
+
+            function hasMeaningfulContent(text) {
+              return text
+                .replace(/^\s*-\s*$/gm, "")
+                .replace(/^\s*\*\*\*\s*$/gm, "")
+                .trim().length > 0;
+            }
+
+            for (const section of ["Summary", "What Changed\\?", "Testing"]) {
+              if (!hasMeaningfulContent(getSection(section))) {
+                errors.push(`Fill out the '${section.replace("\\?", "?")}' section.`);
+              }
+            }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
// Placeholder text must be removed
const placeholders = [
"Provide a brief description of your changes.",
"Briefly describe the key changes made in this Pull Request.",
"Describe how you tested your changes.",
"Add any additional context for reviewers if needed."
];
for (const placeholder of placeholders) {
if (contains(placeholder)) {
errors.push(`Remove placeholder text: "${placeholder}"`);
}
}
// Placeholder text must be removed
const placeholders = [
"Provide a brief description of your changes.",
"Briefly describe the key changes made in this Pull Request.",
"Describe how you tested your changes.",
"Add any additional context for reviewers if needed."
];
for (const placeholder of placeholders) {
if (contains(placeholder)) {
errors.push(`Remove placeholder text: "${placeholder}"`);
}
}
function getSection(title) {
return (
body.match(new RegExp(`## ${title}\\s*([\\s\\S]*?)(?:\\n---|\\n## |$)`, "i"))?.[1] ?? ""
);
}
function hasMeaningfulContent(text) {
return text
.replace(/^\s*-\s*$/gm, "")
.replace(/^\s*\*\*\*\s*$/gm, "")
.trim().length > 0;
}
for (const section of ["Summary", "What Changed\\?", "Testing"]) {
if (!hasMeaningfulContent(getSection(section))) {
errors.push(`Fill out the '${section.replace("\\?", "?")}' section.`);
}
}
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In @.github/workflows/pr-template-validation.yml around lines 36 - 48, The PR
template validation in the workflow only checks for exact placeholder strings,
so empty required sections can still pass. Update the validation logic around
the placeholder checks to also verify that the required sections in the template
such as Summary, What Changed?, and Testing contain real user content, not just
headings, separators, or stub bullets. Use the existing validation flow in the
workflow script to add section-level emptiness checks alongside the current
contains(placeholder) logic.


// Require at least one Type of Change checkbox
const checkedType =
/\- \[x\] Feature/i.test(body) ||
/\- \[x\] Bug Fix/i.test(body) ||
/\- \[x\] Documentation/i.test(body) ||
/\- \[x\] Refactor/i.test(body) ||
/\- \[x\] Performance Improvement/i.test(body) ||
/\- \[x\] CI \/ Build/i.test(body) ||
/\- \[x\] Other/i.test(body);

if (!checkedType) {
errors.push("Select at least one 'Type of Change' checkbox.");
}

// Require at least one checklist item to be checked
const checkedChecklist =
/\- \[x\]/i.test(body);

if (!checkedChecklist) {
errors.push("Complete the checklist before requesting review.");
Comment on lines +64 to +69

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

Restrict the checklist regex to the ## Checklist section.

/\- \[x\]/i matches any checked box in the PR body, including the required Type of Change selection from .github/PULL_REQUEST_TEMPLATE.md. That means a PR with zero checklist items checked still passes once one change type is selected.

Suggested fix
-            const checkedChecklist =
-              /\- \[x\]/i.test(body);
+            const checklistSection =
+              body.match(/## Checklist\s*([\s\S]*?)(?:\n---|\n## |\s*$)/i)?.[1] ?? "";
+            const checkedChecklist = /\- \[x\]/i.test(checklistSection);
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
// Require at least one checklist item to be checked
const checkedChecklist =
/\- \[x\]/i.test(body);
if (!checkedChecklist) {
errors.push("Complete the checklist before requesting review.");
const checklistSection =
body.match(/## Checklist\s*([\s\S]*?)(?:\n---|\n## |\s*$)/i)?.[1] ?? "";
const checkedChecklist = /\- \[x\]/i.test(checklistSection);
if (!checkedChecklist) {
errors.push("Complete the checklist before requesting review.");
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In @.github/workflows/pr-template-validation.yml around lines 64 - 69, The
checklist validation in the PR template workflow is too broad because the
checked-box regex is matching any checkbox in the body, including the required
Type of Change section. Update the logic in the workflow’s checklist check so it
only scans the content under the ## Checklist section before evaluating for at
least one checked item, using the existing validation block that sets
checkedChecklist and errors.push. This should prevent non-checklist selections
from satisfying the requirement.

}

if (errors.length > 0) {
core.setFailed(
"Pull Request Template Validation Failed:\n\n• " +
errors.join("\n• ")
);
} else {
console.log("PR template validation passed.");
}
Loading