Aiden Cline 3 месяцев назад
Родитель
Сommit
1906a347f3
3 измененных файлов с 166 добавлено и 66 удалено
  1. 136 0
      .github/workflows/pr-standards.yml
  2. 0 62
      .github/workflows/pr-title.yml
  3. 30 4
      CONTRIBUTING.md

+ 136 - 0
.github/workflows/pr-standards.yml

@@ -0,0 +1,136 @@
+name: PR Standards
+
+on:
+  pull_request:
+    types: [opened, edited, synchronize]
+
+jobs:
+  check-standards:
+    if: |
+      github.event.pull_request.user.login != 'actions-user' &&
+      github.event.pull_request.user.login != 'opencode' &&
+      github.event.pull_request.user.login != 'rekram1-node' &&
+      github.event.pull_request.user.login != 'thdxr' &&
+      github.event.pull_request.user.login != 'kommander' &&
+      github.event.pull_request.user.login != 'jayair' &&
+      github.event.pull_request.user.login != 'fwang' &&
+      github.event.pull_request.user.login != 'adamdotdevin' &&
+      github.event.pull_request.user.login != 'iamdavidhill' &&
+      github.event.pull_request.user.login != 'opencode-agent[bot]'
+    runs-on: ubuntu-latest
+    permissions:
+      pull-requests: write
+    steps:
+      - name: Check PR standards
+        uses: actions/github-script@v7
+        with:
+          script: |
+            const pr = context.payload.pull_request;
+            const title = pr.title;
+
+            async function addLabel(label) {
+              await github.rest.issues.addLabels({
+                owner: context.repo.owner,
+                repo: context.repo.repo,
+                issue_number: pr.number,
+                labels: [label]
+              });
+            }
+
+            async function removeLabel(label) {
+              try {
+                await github.rest.issues.removeLabel({
+                  owner: context.repo.owner,
+                  repo: context.repo.repo,
+                  issue_number: pr.number,
+                  name: label
+                });
+              } catch (e) {
+                // Label wasn't present, ignore
+              }
+            }
+
+            async function comment(marker, body) {
+              const markerText = `<!-- pr-standards:${marker} -->`;
+              const { data: comments } = await github.rest.issues.listComments({
+                owner: context.repo.owner,
+                repo: context.repo.repo,
+                issue_number: pr.number
+              });
+              
+              const existing = comments.find(c => c.body.includes(markerText));
+              if (existing) return;
+              
+              await github.rest.issues.createComment({
+                owner: context.repo.owner,
+                repo: context.repo.repo,
+                issue_number: pr.number,
+                body: markerText + '\n' + body
+              });
+            }
+
+            // Step 1: Check title format
+            const validPrefixes = ['feat:', 'fix:', 'docs:', 'chore:', 'refactor:', 'test:'];
+            const hasValidTitle = validPrefixes.some(prefix => title.startsWith(prefix));
+
+            if (!hasValidTitle) {
+              await addLabel('needs:title');
+              await comment('title', `Hey! Your PR title \`${title}\` doesn't follow conventional commit format.
+
+            Please update it to start with one of:
+            - \`feat:\` new feature
+            - \`fix:\` bug fix
+            - \`docs:\` documentation changes
+            - \`chore:\` maintenance tasks
+            - \`refactor:\` code refactoring
+            - \`test:\` adding or updating tests
+
+            See [CONTRIBUTING.md](../blob/dev/CONTRIBUTING.md#pr-titles) for details.`);
+              return;
+            }
+
+            await removeLabel('needs:title');
+
+            // Step 2: Check for linked issue (skip for docs/refactor PRs)
+            const skipIssueCheck = title.startsWith('docs:') || title.startsWith('refactor:');
+            if (skipIssueCheck) {
+              await removeLabel('needs:issue');
+              console.log('Skipping issue check for docs/refactor PR');
+              return;
+            }
+            const query = `
+              query($owner: String!, $repo: String!, $number: Int!) {
+                repository(owner: $owner, name: $repo) {
+                  pullRequest(number: $number) {
+                    closingIssuesReferences(first: 1) {
+                      totalCount
+                    }
+                  }
+                }
+              }
+            `;
+
+            const result = await github.graphql(query, {
+              owner: context.repo.owner,
+              repo: context.repo.repo,
+              number: pr.number
+            });
+
+            const linkedIssues = result.repository.pullRequest.closingIssuesReferences.totalCount;
+
+            if (linkedIssues === 0) {
+              await addLabel('needs:issue');
+              await comment('issue', `Thanks for your contribution!
+
+            This PR doesn't have a linked issue. All PRs must reference an existing issue.
+
+            Please:
+            1. Open an issue describing the bug/feature (if one doesn't exist)
+            2. Add \`Fixes #<number>\` or \`Closes #<number>\` to this PR description
+
+            See [CONTRIBUTING.md](../blob/dev/CONTRIBUTING.md#issue-first-policy) for details.`);
+              return;
+            }
+
+            await removeLabel('needs:issue');
+            console.log('PR meets all standards');

+ 0 - 62
.github/workflows/pr-title.yml

@@ -1,62 +0,0 @@
-name: PR Title Validation
-
-on:
-  pull_request:
-    types: [opened, edited, synchronize]
-
-jobs:
-  validate-title:
-    if: |
-      github.event.pull_request.user.login != 'actions-user' &&
-      github.event.pull_request.user.login != 'opencode' &&
-      github.event.pull_request.user.login != 'rekram1-node' &&
-      github.event.pull_request.user.login != 'thdxr' &&
-      github.event.pull_request.user.login != 'kommander' &&
-      github.event.pull_request.user.login != 'jayair' &&
-      github.event.pull_request.user.login != 'fwang' &&
-      github.event.pull_request.user.login != 'adamdotdevin' &&
-      github.event.pull_request.user.login != 'iamdavidhill' &&
-      github.event.pull_request.user.login != 'opencode-agent[bot]'
-    runs-on: ubuntu-latest
-    permissions:
-      pull-requests: write
-    steps:
-      - name: Validate PR title
-        uses: actions/github-script@v7
-        with:
-          script: |
-            const title = context.payload.pull_request.title;
-            const validPrefixes = ['feat:', 'fix:', 'docs:', 'chore:', 'refactor:', 'test:'];
-            const isValid = validPrefixes.some(prefix => title.startsWith(prefix));
-
-            if (!isValid) {
-              const body = `👋 Thanks for opening this PR!
-
-            Your PR title \`${title}\` doesn't follow our conventional commit format.
-
-            Please update it to start with one of these prefixes:
-            - \`feat:\` new feature or functionality
-            - \`fix:\` bug fix
-            - \`docs:\` documentation or README changes
-            - \`chore:\` maintenance tasks, dependency updates, etc.
-            - \`refactor:\` code refactoring without changing behavior
-            - \`test:\` adding or updating tests
-
-            **Examples:**
-            - \`docs: update contributing guidelines\`
-            - \`fix: resolve crash on startup\`
-            - \`feat: add dark mode support\`
-
-            See [CONTRIBUTING.md](../blob/dev/CONTRIBUTING.md#pr-titles) for more details.`;
-
-              await github.rest.issues.createComment({
-                owner: context.repo.owner,
-                repo: context.repo.repo,
-                issue_number: context.payload.pull_request.number,
-                body: body
-              });
-
-              core.setFailed('PR title does not follow conventional commit format');
-            } else {
-              console.log('PR title is valid:', title);
-            }

+ 30 - 4
CONTRIBUTING.md

@@ -149,11 +149,37 @@ With that said, you may want to try these methods, as they might work for you.
 
 ## Pull Request Expectations
 
-- Try to keep pull requests small and focused.
-- Link relevant issue(s) in the description
+### Issue First Policy
+
+**All PRs must reference an existing issue.** Before opening a PR, open an issue describing the bug or feature. This helps maintainers triage and prevents duplicate work. PRs without a linked issue may be closed without review.
+
+- Use `Fixes #123` or `Closes #123` in your PR description to link the issue
+- For small fixes, a brief issue is fine - just enough context for maintainers to understand the problem
+
+### General Requirements
+
+- Keep pull requests small and focused
 - Explain the issue and why your change fixes it
-- Avoid having verbose LLM generated PR descriptions
-- Before adding new functions or functionality, ensure that such behavior doesn't already exist elsewhere in the codebase.
+- Before adding new functionality, ensure it doesn't already exist elsewhere in the codebase
+
+### UI Changes
+
+If your PR includes UI changes, please include screenshots or videos showing the before and after. This helps maintainers review faster and gives you quicker feedback.
+
+### Logic Changes
+
+For non-UI changes (bug fixes, new features, refactors), explain **how you verified it works**:
+
+- What did you test?
+- How can a reviewer reproduce/confirm the fix?
+
+### No AI-Generated Walls of Text
+
+Long, AI-generated PR descriptions and issues are not acceptable and may be ignored. Respect the maintainers' time:
+
+- Write short, focused descriptions
+- Explain what changed and why in your own words
+- If you can't explain it briefly, your PR might be too large
 
 ### PR Titles