Skip to content
Open
Show file tree
Hide file tree
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
233 changes: 233 additions & 0 deletions .github/scripts/pr-impact.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,233 @@
const github = require("@actions/github");

const token = process.env.GITHUB_TOKEN;

const octokit = github.getOctokit(token);

const context = github.context;

const owner = context.repo.owner;
const repo = context.repo.repo;
const pull_number = context.payload.pull_request.number;

Comment on lines +1 to +12
const RULES = {
paths: [
{
pattern: /guides\/upgrade/,
score: 5,
reason: "Upgrade Guide",
category: "Migration"
},
{
pattern: /api/,
score: 4,
reason: "API Documentation",
category: "API"
},
{
pattern: /plugins/,
score: 3,
reason: "Plugin Development",
category: "Plugins"
},
{
pattern: /apps/,
score: 3,
reason: "App Development",
category: "Apps"
},
{
pattern: /framework/,
score: 4,
reason: "Framework",
category: "Framework"
},
{
pattern: /images/,
score: -2,
reason: "Images"
}
],

keywords: {
migration: 5,
upgrade: 5,
deprecated: 4,
breaking: 5,
api: 4,
sdk: 3,
plugin: 3,
tutorial: 3,
security: 4,
performance: 3,
configuration: 3
}
};

(async () => {

let score = 0;

const reasons = [];

const categories = new Set();

const pr =
(await octokit.rest.pulls.get({
owner,
repo,
pull_number
})).data;

const title = pr.title.toLowerCase();

console.log("Analyzing:", title);

// ---------- TITLE ----------

for (const [keyword, value] of Object.entries(RULES.keywords)) {

if (title.includes(keyword)) {

score += value;

reasons.push(`+${value}: PR title contains "${keyword}"`);
}
}

// ---------- FILES ----------

const files =
await octokit.paginate(
octokit.rest.pulls.listFiles,
{
owner,
repo,
pull_number
}
);

for (const file of files) {

console.log(file.filename);

for (const rule of RULES.paths) {

if (rule.pattern.test(file.filename)) {

score += rule.score;

reasons.push(
`${rule.score > 0 ? "+" : ""}${rule.score}: ${rule.reason}`
);

if (rule.category)
categories.add(rule.category);
}

}

const patch = file.patch || "";

// ---------- NEW HEADINGS ----------

const headings =
(patch.match(/\+\s*##\s/g) || []).length;

if (headings) {

score += headings * 2;

reasons.push(`+${headings * 2}: ${headings} new headings`);
}

// ---------- CODE BLOCKS ----------

const code =
(patch.match(/\+\s*```/g) || []).length;

if (code) {

score += code;

reasons.push(`+${code}: code examples`);
}

// ---------- API ----------

if (/\+\s*(GET|POST|PUT|DELETE)\s+\/api/i.test(patch)) {

score += 4;

categories.add("API");

reasons.push("+4: API endpoint documented");
}

// ---------- DEPRECATION ----------

if (/deprecated/i.test(patch)) {

score += 4;

categories.add("Migration");

reasons.push("+4: Deprecation");
}

// ---------- BREAKING ----------

if (/breaking/i.test(patch)) {

score += 5;

categories.add("Migration");

reasons.push("+5: Breaking change");
}

}

let recommendation;

if (score >= 10) {

recommendation =
"✅ Highly meaningful";

} else if (score >= 6) {

recommendation =
"⚠️ Needs manual review";

} else {

recommendation =
"❌ Probably not meaningful";
}

const comment = `## 📊 Documentation Impact Analyzer

| Metric | Result |
|--------|--------|
| Score | **${score}** |
| Recommendation | **${recommendation}** |
| Categories | ${[...categories].join(", ") || "None"} |

### Reasons

${reasons.map(r => `- ${r}`).join("\n")}

---

> This score is automatically generated based on documentation impact heuristics.
`;

await octokit.rest.issues.createComment({
owner,
repo,
issue_number: pull_number,
body: comment
});
Comment on lines +226 to +231

})();
32 changes: 32 additions & 0 deletions .github/workflows/pr-impact.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
name: Documentation Impact Analyzer

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

permissions:
contents: read
pull-requests: write
Comment on lines +3 to +12

jobs:
analyze:
runs-on: ubuntu-latest

steps:
- uses: actions/checkout@v4

- uses: actions/setup-node@v4
with:
node-version: 20

- name: Install dependencies
run: |
npm install @actions/core @actions/github

- name: Run analyzer
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: node .github/scripts/pr-impact.js
Loading