mirror of
https://github.com/google-gemini/gemini-cli.git
synced 2026-05-13 13:22:35 -07:00
160 lines
5.1 KiB
JavaScript
160 lines
5.1 KiB
JavaScript
/**
|
|
* @license
|
|
* Copyright 2026 Google LLC
|
|
* SPDX-License-Identifier: Apache-2.0
|
|
*/
|
|
|
|
module.exports = async ({ github, context, core }) => {
|
|
const rawLabels = process.env.LABELS_OUTPUT;
|
|
core.info(`Raw labels JSON: ${rawLabels}`);
|
|
let parsedLabels;
|
|
try {
|
|
// First, try to parse the raw output as JSON.
|
|
parsedLabels = JSON.parse(rawLabels);
|
|
} catch (jsonError) {
|
|
// If that fails, check for a markdown code block.
|
|
core.warning(
|
|
`Direct JSON parsing failed: ${jsonError.message}. Trying to extract from a markdown block.`,
|
|
);
|
|
const jsonMatch = rawLabels.match(/```json\s*([\s\S]*?)\s*```/);
|
|
if (jsonMatch && jsonMatch[1]) {
|
|
try {
|
|
parsedLabels = JSON.parse(jsonMatch[1].trim());
|
|
} catch (markdownError) {
|
|
core.setFailed(
|
|
`Failed to parse JSON even after extracting from markdown block: ${markdownError.message}\nRaw output: ${rawLabels}`,
|
|
);
|
|
return;
|
|
}
|
|
} else {
|
|
// If no markdown block, try to find a raw JSON array in the output.
|
|
// The CLI may include debug/log lines (e.g. telemetry init, YOLO mode)
|
|
// before the actual JSON response.
|
|
const jsonArrayMatch = rawLabels.match(
|
|
/\[\s*\{\s*"issue_number"[\s\S]*\}\s*\]/,
|
|
);
|
|
if (jsonArrayMatch) {
|
|
try {
|
|
parsedLabels = JSON.parse(jsonArrayMatch[0]);
|
|
} catch (extractError) {
|
|
// It's possible the regex matched from a `[STARTUP]` log all the way to the end
|
|
// of the JSON array. We need to be more aggressive and find the FIRST `[ { "issue_number"`
|
|
core.warning(
|
|
`Strict array match failed: ${extractError.message}. Attempting to clean leading noisy brackets.`,
|
|
);
|
|
const fallbackMatch = rawLabels.match(
|
|
/(\[\s*\{\s*"issue_number"[\s\S]*)/,
|
|
);
|
|
if (fallbackMatch) {
|
|
try {
|
|
// We might have grabbed trailing noise too, so we find the last closing bracket
|
|
const cleaned = fallbackMatch[0].substring(
|
|
0,
|
|
fallbackMatch[0].lastIndexOf(']') + 1,
|
|
);
|
|
parsedLabels = JSON.parse(cleaned);
|
|
} catch (fallbackError) {
|
|
core.setFailed(
|
|
`Found JSON-like content but failed to parse: ${fallbackError.message}\nRaw output: ${rawLabels}`,
|
|
);
|
|
return;
|
|
}
|
|
} else {
|
|
core.setFailed(
|
|
`Found JSON-like content but failed to parse: ${extractError.message}\nRaw output: ${rawLabels}`,
|
|
);
|
|
return;
|
|
}
|
|
}
|
|
} else {
|
|
core.setFailed(
|
|
`Output is not valid JSON and does not contain extractable JSON.\nRaw output: ${rawLabels}`,
|
|
);
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
core.info(`Parsed labels JSON: ${JSON.stringify(parsedLabels)}`);
|
|
|
|
for (const entry of parsedLabels) {
|
|
const issueNumber = entry.issue_number;
|
|
if (!issueNumber) {
|
|
core.info(
|
|
`Skipping entry with no issue number: ${JSON.stringify(entry)}`,
|
|
);
|
|
continue;
|
|
}
|
|
|
|
const labelsToAdd = entry.labels_to_add || [];
|
|
labelsToAdd.push('status/bot-triaged');
|
|
|
|
let labelsToRemove = entry.labels_to_remove || [];
|
|
labelsToRemove.push('status/need-triage');
|
|
// Deduplicate array
|
|
labelsToRemove = [...new Set(labelsToRemove)];
|
|
|
|
if (labelsToAdd.length > 0) {
|
|
await github.rest.issues.addLabels({
|
|
owner: context.repo.owner,
|
|
repo: context.repo.repo,
|
|
issue_number: issueNumber,
|
|
labels: labelsToAdd,
|
|
});
|
|
|
|
const explanation = entry.explanation ? ` - ${entry.explanation}` : '';
|
|
core.info(
|
|
`Successfully added labels for #${issueNumber}: ${labelsToAdd.join(', ')}${explanation}`,
|
|
);
|
|
}
|
|
|
|
if (labelsToRemove.length > 0) {
|
|
for (const label of labelsToRemove) {
|
|
try {
|
|
await github.rest.issues.removeLabel({
|
|
owner: context.repo.owner,
|
|
repo: context.repo.repo,
|
|
issue_number: issueNumber,
|
|
name: label,
|
|
});
|
|
} catch (e) {
|
|
if (e.status !== 404) {
|
|
core.warning(
|
|
`Failed to remove label ${label} from #${issueNumber}: ${e.message}`,
|
|
);
|
|
}
|
|
}
|
|
}
|
|
core.info(
|
|
`Successfully removed labels for #${issueNumber}: ${labelsToRemove.join(', ')}`,
|
|
);
|
|
}
|
|
|
|
if (entry.explanation || entry.effort_analysis) {
|
|
let commentBody = '';
|
|
if (entry.explanation) {
|
|
commentBody += entry.explanation;
|
|
}
|
|
if (entry.effort_analysis) {
|
|
if (commentBody) commentBody += '\n\n';
|
|
commentBody += `**Effort Analysis:**\n${entry.effort_analysis}`;
|
|
}
|
|
|
|
await github.rest.issues.createComment({
|
|
owner: context.repo.owner,
|
|
repo: context.repo.repo,
|
|
issue_number: issueNumber,
|
|
body: commentBody,
|
|
});
|
|
}
|
|
|
|
if (
|
|
(!entry.labels_to_add || entry.labels_to_add.length === 0) &&
|
|
(!entry.labels_to_remove || entry.labels_to_remove.length === 0)
|
|
) {
|
|
core.info(
|
|
`No labels to add or remove for #${issueNumber}, leaving as is`,
|
|
);
|
|
}
|
|
}
|
|
};
|