build(deps): bump github.com/pion/dtls/v3 from 3.0.4 to 3.0.11 #47
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| name: AI-Suspect Labeler | |
| on: | |
| pull_request: | |
| types: [opened, edited, synchronize] | |
| permissions: | |
| contents: read | |
| pull-requests: write | |
| issues: write | |
| jobs: | |
| detect-ai: | |
| runs-on: ubuntu-latest | |
| steps: | |
| - name: Detect AI-generated content | |
| uses: actions/github-script@v7 | |
| with: | |
| script: | | |
| const pr = context.payload.pull_request; | |
| const owner = context.repo.owner; | |
| const repo = context.repo.repo; | |
| // Fetch commits | |
| const commits = await github.paginate(github.rest.pulls.listCommits, { | |
| owner, repo, pull_number: pr.number, per_page: 100 | |
| }); | |
| // Fetch changed files | |
| const files = await github.paginate(github.rest.pulls.listFiles, { | |
| owner, repo, pull_number: pr.number, per_page: 100 | |
| }); | |
| const body = (pr.body || "").toLowerCase(); | |
| const indicators = []; | |
| let aiDisclosed = false; | |
| // Check if AI was disclosed in template | |
| if (/- \[x\] i used ai assistance/i.test(pr.body || "")) { | |
| aiDisclosed = true; | |
| indicators.push("✅ Author disclosed AI usage in PR template"); | |
| } | |
| // PR body AI indicators | |
| const bodyHints = [ | |
| /\bas an ai\b/i, | |
| /\bgenerated by\b/i, | |
| /\bcopilot\b/i, | |
| /\bchatgpt\b/i, | |
| /\bgpt-[0-9]/i, | |
| /\bclaude\b/i, | |
| /\bllm\b/i, | |
| /\bopenai\b/i, | |
| /\bai assistant\b/i, | |
| /\bai-generated\b/i | |
| ]; | |
| for (const pattern of bodyHints) { | |
| if (pattern.test(pr.body || "")) { | |
| indicators.push("🤖 PR body mentions AI tools"); | |
| break; | |
| } | |
| } | |
| // Commit message and author indicators | |
| for (const c of commits) { | |
| const msg = c.commit?.message || ""; | |
| const author = c.author?.login || c.commit?.author?.name || ""; | |
| if (/co-authored-by:.*(copilot|chatgpt|gpt|claude|ai)/i.test(msg)) { | |
| indicators.push(`🔍 Commit trailer suggests AI: ${c.sha.slice(0,7)}`); | |
| } | |
| if (/generated-by:/i.test(msg)) { | |
| indicators.push(`🔍 Generated-by trailer in commit: ${c.sha.slice(0,7)}`); | |
| } | |
| if (/-bot]?$/i.test(author) || /(copilot|chatgpt|openai|claude)/i.test(author)) { | |
| indicators.push(`🤖 Bot-like commit author: ${author}`); | |
| } | |
| } | |
| // File content indicators | |
| const aiMarkers = /\b(generated by|auto-?generated|do not edit)\b/i; | |
| const aiToolMentions = /\b(chatgpt|copilot|claude|gpt-4|gpt-3)\b/i; | |
| const totalChanges = files.reduce((n, f) => n + (f.changes || 0), 0); | |
| const massiveChange = totalChanges > 3000; | |
| if (massiveChange) { | |
| indicators.push(`📊 Very large diff (${totalChanges} changes) - unusual for human PR`); | |
| } | |
| for (const f of files) { | |
| const patch = f.patch || ""; | |
| // Skip documentation and workflow files to avoid false positives | |
| if (/\.(md|txt|rst)$/i.test(f.filename) || f.filename.startsWith('.github/')) { | |
| continue; | |
| } | |
| // AI header markers in diff (only for code files) | |
| if (aiMarkers.test(patch)) { | |
| indicators.push(`📝 AI marker found in ${f.filename}`); | |
| } | |
| // AI tool mentions in code comments | |
| if (aiToolMentions.test(patch)) { | |
| indicators.push(`🤖 AI tool mentioned in ${f.filename}`); | |
| } | |
| // Unusually high comment/docstring ratio | |
| const addedLines = patch.split("\n").filter(l => l.startsWith("+") && !l.startsWith("+++")); | |
| const commentAdds = addedLines.filter(l => | |
| /^\+\s*(\/\/|#|\/\*\*?|\*|"""|''')/.test(l) | |
| ).length; | |
| if (commentAdds > 50 && addedLines.length > 0 && commentAdds / addedLines.length > 0.6) { | |
| indicators.push(`💬 Unusually high comment ratio in ${f.filename} (${Math.round(commentAdds/addedLines.length*100)}%)`); | |
| } | |
| } | |
| // Decide on label | |
| let label = null; | |
| let needsReview = false; | |
| if (aiDisclosed) { | |
| label = "ai-assisted"; | |
| needsReview = true; | |
| } else if (indicators.length >= 2) { | |
| label = "ai-suspected"; | |
| needsReview = true; | |
| } | |
| // Apply label and comment | |
| if (label) { | |
| await github.rest.issues.addLabels({ | |
| owner, repo, | |
| issue_number: pr.number, | |
| labels: [label] | |
| }); | |
| const summary = indicators.map(i => `- ${i}`).join("\\n"); | |
| const message = aiDisclosed | |
| ? `### ✅ AI Assistance Disclosed\\n\\nThank you for disclosing AI usage. This PR has been labeled \\\`${label}\\\` and will require human review.\\n\\n${summary}` | |
| : `### 🤖 Potential AI-Generated Content Detected\\n\\nThis PR has been labeled \\\`${label}\\\` based on the following indicators:\\n\\n${summary}\\n\\n**Note:** This is heuristic detection and may be incorrect. If you used AI assistance, please check the box in the PR template. A human reviewer will assess this PR.`; | |
| await github.rest.issues.createComment({ | |
| owner, repo, | |
| issue_number: pr.number, | |
| body: message | |
| }); | |
| } | |