Files
mealie/.github/workflows/pull-request-lint.yml
2026-05-31 10:41:43 -05:00

91 lines
2.8 KiB
YAML

name: Pull Request Linter
on:
workflow_call:
pull_request:
types: [edited, reopened] # This captures the PR title/body changing
branches:
- mealie-next
jobs:
validate-title:
name: Validate PR title
runs-on: ubuntu-latest
steps:
# https://github.com/amannn/action-semantic-pull-request
- uses: amannn/action-semantic-pull-request@v6
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
# Configure which types are allowed (newline-delimited).
# Default: https://github.com/commitizen/conventional-commit-types
types: |
feat
fix
docs
chore
dev
# Configure which scopes are allowed (newline-delimited).
# These are regex patterns auto-wrapped in `^ $`.
scopes: |
deps
auto
l10n
config
# Configure that a scope must always be provided.
requireScope: false
# If the PR contains one of these newline-delimited labels, the
# validation is skipped. If you want to rerun the validation when
# labels change, you might want to use the `labeled` and `unlabeled`
# event triggers in your workflow.
ignoreLabels: |
bot
ignore-semantic-pull-request
validate-template:
name: Validate PR template
runs-on: ubuntu-latest
permissions:
pull-requests: write
steps:
- name: Check required PR template sections
uses: actions/github-script@v7
with:
script: |
const pr = context.payload.pull_request;
if (pr.user.type === "Bot") {
console.log("Skipping template check for bot");
return;
}
const response = await github.rest.repos.getContent({
owner: context.repo.owner,
repo: context.repo.repo,
path: ".github/pull_request_template.md",
});
const template = Buffer.from(response.data.content, "base64").toString("utf8");
const lines = template.split("\n");
const requiredHeadings = [];
let lastHeading = null;
for (const line of lines) {
if (line.startsWith("## ")) {
lastHeading = line.trim();
} else if (line.trim() === "_(REQUIRED)_" && lastHeading) {
requiredHeadings.push(lastHeading);
lastHeading = null;
}
}
const body = pr.body || "";
const missing = requiredHeadings.filter(h => !body.includes(h));
if (missing.length > 0) {
core.setFailed(`Missing headings:\n${missing.join("\n")}`);
} else {
console.log("All required headings present");
}