Skip to content

feat: redesign LearnHub landing page #3

feat: redesign LearnHub landing page

feat: redesign LearnHub landing page #3

Workflow file for this run

name: PR Integrity Checks
on:
pull_request_target:
types: [opened, edited, synchronize]
permissions:
pull-requests: write
issues: write
contents: read
jobs:
integrity-check:
runs-on: ubuntu-latest
steps:
- name: Checkout PR code
uses: actions/checkout@v4
with:
ref: ${{ github.event.pull_request.head.sha }}
fetch-depth: 0
- name: Run checks
uses: actions/github-script@v7
with:
script: |
const pr = context.payload.pull_request;
const author = pr.user.login;
const owner = context.repo.owner;
const repo = context.repo.repo;
const prNumber = pr.number;
// Check maintainer role
let isMaintainer = false;
try {
const { data: permission } = await github.rest.repos.getCollaboratorPermissionLevel({
owner,
repo,
username: author
});
isMaintainer = ['admin', 'write'].includes(permission.permission);
} catch (e) {
// Not collaborator
}
// 1. Security: Auto-close PRs from forks modifying workflow files unless from a maintainer
const isFork = pr.head.repo.fork;
if (isFork && !isMaintainer) {
// Get changed files
const { data: files } = await github.rest.pulls.listFiles({
owner,
repo,
pull_number: prNumber
});
const modifiesWorkflows = files.some(file => file.filename.startsWith('.github/workflows/'));
if (modifiesWorkflows) {
await github.rest.issues.createComment({
owner,
repo,
issue_number: prNumber,
body: `🚨 @${author}, pull requests modifying GitHub actions/workflows from forks are automatically closed for repository security. Maintainers will review and manually implement updates if needed.`
});
await github.rest.pulls.update({
owner,
repo,
pull_number: prNumber,
state: 'closed'
});
return;
}
}
// 2. Auto-label and comment PRs without linked issues
const prBody = pr.body || '';
const issueLinkRegex = /(?:close|closes|fix|fixes|resolve|resolves)\s+#\d+/i;
const hasIssueLink = issueLinkRegex.test(prBody);
if (!hasIssueLink) {
// Label the PR
await github.rest.issues.addLabels({
owner,
repo,
issue_number: prNumber,
labels: ['needs-issue-link']
});
// Comment requesting issue link
const comments = await github.rest.issues.listComments({
owner,
repo,
issue_number: prNumber
});
const hasReqComment = comments.data.some(c => c.body.includes('please link an open issue'));
if (!hasReqComment) {
await github.rest.issues.createComment({
owner,
repo,
issue_number: prNumber,
body: `🔍 @${author}, please link an open issue in your pull request description (e.g. \`Closes #123\`). This is required before we can review your PR.`
});
}
} else {
// Try to remove label if issue link was added later
try {
await github.rest.issues.removeLabel({
owner,
repo,
issue_number: prNumber,
name: 'needs-issue-link'
});
} catch (e) {
// Label might not exist
}
// 3. Warning: If author is not assignee of linked issue
const issueMatch = prBody.match(/(?:close|closes|fix|fixes|resolve|resolves)\s+#(\d+)/i);
if (issueMatch && issueMatch[1]) {
const linkedIssueNumber = parseInt(issueMatch[1], 10);
try {
const { data: issue } = await github.rest.issues.get({
owner,
repo,
issue_number: linkedIssueNumber
});
const assignees = issue.assignees.map(a => a.login);
if (!assignees.includes(author)) {
const comments = await github.rest.issues.listComments({
owner,
repo,
issue_number: prNumber
});
const hasWarning = comments.data.some(c => c.body.includes('Warning: You are submitting a PR for an issue'));
if (!hasWarning) {
await github.rest.issues.createComment({
owner,
repo,
issue_number: prNumber,
body: `⚠️ Warning: You are submitting a PR for issue #${linkedIssueNumber}, but you are not the assigned contributor. Please ensure the assignee is okay with this or wait to be assigned before contributing.`
});
}
}
} catch (err) {
console.error('Failed to inspect linked issue:', err);
}
}
}