Check for duplicates before adding tickets #12

Merged
ztimson merged 6 commits from ticket-duplicates into master 2025-12-31 00:02:18 -05:00
Showing only changes of commit eb4486f196 - Show all commits

View File

@@ -26,11 +26,13 @@ dotenv.config({path: '.env.local', override: true, quiet: true});
console.log(`Processing issue #${ticket}`);
// Fetch issue
const issueRes = await fetch(`${git}/api/v1/repos/${owner}/${repo}/issues/${ticket}`, {
const issueData = await fetch(`${git}/api/v1/repos/${owner}/${repo}/issues/${ticket}`, {
headers: {'Authorization': `token ${auth}`}
}).then(async resp => !resp.ok ? throw new Error(`${updateRes.status} ${await updateRes.text()}`) : null);
const issueData = await issueRes.json();
if(issueData.labels[0] !== 'Review/AI' || issueData.labels.length !== 1) {
}).then(async resp => {
if(resp.ok) return resp.json();
else throw new Error(`${resp.status} ${await resp.text()}`);
});
if(issueData.labels.length !== 1 || issueData.labels?.[0] !== 'Review/AI') {
console.log('Skipping');
return process.exit();
}
@@ -170,17 +172,17 @@ Output ONLY markdown. No explanations, labels, or extra formatting.`});
method: 'POST',
headers: {'Authorization': `token ${auth}`, 'Content-Type': 'application/json'},
body: `{"body": "Duplicate of #${dupeId}"}`
ztimson marked this conversation as resolved
Review

Bug: JSON string is manually constructed instead of using JSON.stringify(). The body should be body: JSON.stringify({body: \Duplicate of #${dupeId}`})` to properly escape special characters and prevent JSON injection vulnerabilities.

Bug: JSON string is manually constructed instead of using `JSON.stringify()`. The body should be `body: JSON.stringify({body: \`Duplicate of #${dupeId}\`})` to properly escape special characters and prevent JSON injection vulnerabilities.
Review

JSON injection vulnerability: The JSON body is manually constructed using a template literal instead of JSON.stringify(). If dupeId contains special characters like quotes or backslashes, this will produce invalid JSON or allow injection. Change to: body: JSON.stringify({body: \Duplicate of #${dupeId}`})`

JSON injection vulnerability: The JSON body is manually constructed using a template literal instead of JSON.stringify(). If `dupeId` contains special characters like quotes or backslashes, this will produce invalid JSON or allow injection. Change to: `body: JSON.stringify({body: \`Duplicate of #${dupeId}\`})`
}).then(async resp => !resp.ok ? throw new Error(`${updateRes.status} ${await updateRes.text()}`) : null);
}).then(async resp => { if(!resp.ok) throw new Error(`${resp.status} ${await resp.text()}`); });
await fetch(`${git}/api/v1/repos/${owner}/${repo}/issues/${ticket}/labels`, {
ztimson marked this conversation as resolved
Review

Same bugs as line 172: updateRes referenced before definition and invalid throw syntax in ternary expression.

Same bugs as line 172: `updateRes` referenced before definition and invalid throw syntax in ternary expression.
method: 'POST',
headers: {'Authorization': `token ${auth}`, 'Content-Type': 'application/json'},
body: '{"labels":["Reviewed/Duplicate"]}'
}).then(async resp => !resp.ok ? throw new Error(`${updateRes.status} ${await updateRes.text()}`) : null);
}).then(async resp => { if(!resp.ok) throw new Error(`${resp.status} ${await resp.text()}`); });
await fetch(`${git}/api/v1/repos/${owner}/${repo}/issues/${ticket}`, {
ztimson marked this conversation as resolved
Review

Same bugs as line 172: updateRes referenced before definition and invalid throw syntax in ternary expression.

Same bugs as line 172: `updateRes` referenced before definition and invalid throw syntax in ternary expression.
method: 'PATCH',
headers: {'Authorization': `token ${auth}`, 'Content-Type': 'application/json'},
body: '{"state": "closed"}'
}).then(async resp => !resp.ok ? throw new Error(`${updateRes.status} ${await updateRes.text()}`) : null);
}).then(async resp => { if(!resp.ok) throw new Error(`${resp.status} ${await resp.text()}`); });
console.log('Duplicate');
return process.exit();
}
@@ -190,13 +192,13 @@ Output ONLY markdown. No explanations, labels, or extra formatting.`});
method: 'PATCH',
headers: {'Authorization': `token ${auth}`, 'Content-Type': 'application/json'},
body: JSON.stringify({title, body})
}).then(async resp => !resp.ok ? throw new Error(`${updateRes.status} ${await updateRes.text()}`) : null);
}).then(async resp => { if(!resp.ok) throw new Error(`${resp.status} ${await resp.text()}`); });
if(type) { // Label
await fetch(`${git}/api/v1/repos/${owner}/${repo}/issues/${ticket}/labels`, {
method: 'POST',
headers: {'Authorization': `token ${auth}`, 'Content-Type': 'application/json'},
ztimson marked this conversation as resolved
Review

Bug: JSON string is manually constructed with template literal instead of using JSON.stringify(). This is error-prone and could break if type contains special characters. Should be body: JSON.stringify({labels: [\Reviewed/${type[0].toUpperCase() + type.slice(1).toLowerCase()}`]})`.

Bug: JSON string is manually constructed with template literal instead of using `JSON.stringify()`. This is error-prone and could break if `type` contains special characters. Should be `body: JSON.stringify({labels: [\`Reviewed/${type[0].toUpperCase() + type.slice(1).toLowerCase()}\`]})`.
Review

JSON injection vulnerability: The JSON body is manually constructed using a template literal. If type contains special characters, this could produce invalid JSON. While type is constrained by the enum in the tool definition, it's still better practice to use JSON.stringify(): body: JSON.stringify({labels: [\Reviewed/${type[0].toUpperCase() + type.slice(1).toLowerCase()}`]})`

JSON injection vulnerability: The JSON body is manually constructed using a template literal. If `type` contains special characters, this could produce invalid JSON. While `type` is constrained by the enum in the tool definition, it's still better practice to use JSON.stringify(): `body: JSON.stringify({labels: [\`Reviewed/${type[0].toUpperCase() + type.slice(1).toLowerCase()}\`]})`
Review

Potential runtime error: If type is an empty string or undefined (e.g., if the AI fails to call the type tool), then type[0].toUpperCase() will throw a TypeError. Add validation before this line: if(!type) throw new Error('AI failed to set type');

Potential runtime error: If `type` is an empty string or undefined (e.g., if the AI fails to call the type tool), then `type[0].toUpperCase()` will throw a TypeError. Add validation before this line: `if(!type) throw new Error('AI failed to set type');`
Review

Breaking change: Label prefix changed from Kind/${type} to Reviewed/${type} without explanation. This could break existing workflows, filters, or automation that rely on the Kind/ label prefix. Verify this is intentional and update any dependent systems accordingly.

Breaking change: Label prefix changed from `Kind/${type}` to `Reviewed/${type}` without explanation. This could break existing workflows, filters, or automation that rely on the `Kind/` label prefix. Verify this is intentional and update any dependent systems accordingly.
body: `{"labels":["Reviewed/${type[0].toUpperCase() + type.slice(1).toLowerCase()}"]}`
}).then(async resp => !resp.ok ? throw new Error(`${updateRes.status} ${await updateRes.text()}`) : null);
}).then(async resp => { if(!resp.ok) throw new Error(`${resp.status} ${await resp.text()}`); });
}
console.log(`Title: ${title}\nType: ${type}\nBody:\n${body}`);