mirror of
https://github.com/github/awesome-copilot.git
synced 2026-05-28 09:31:44 +00:00
e66aa80240
* feat: add external plugin submission workflows Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * minor adjustment to contributing guide * fix: address external plugin review feedback Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Reverting some changes to the readme.agents.md file * fix: address follow-up review feedback Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * fix: tighten external plugin workflows Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --------- Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
173 lines
6.1 KiB
YAML
173 lines
6.1 KiB
YAML
name: External Plugin Intake
|
|
|
|
on:
|
|
issues:
|
|
types: [opened, edited, reopened]
|
|
|
|
permissions:
|
|
contents: read
|
|
issues: write
|
|
|
|
jobs:
|
|
validate-submission:
|
|
runs-on: ubuntu-latest
|
|
if: >-
|
|
contains(github.event.issue.labels.*.name, 'external-plugin') ||
|
|
contains(github.event.issue.body, '<!-- external-plugin-submission -->')
|
|
steps:
|
|
- name: Checkout repository
|
|
uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4.3.1
|
|
|
|
- name: Evaluate submission
|
|
id: evaluation
|
|
env:
|
|
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
|
run: |
|
|
result=$(node ./eng/external-plugin-intake.mjs "$GITHUB_EVENT_PATH")
|
|
{
|
|
echo 'result<<EOF'
|
|
echo "$result"
|
|
echo 'EOF'
|
|
} >> "$GITHUB_OUTPUT"
|
|
|
|
- name: Sync labels and comment
|
|
uses: actions/github-script@f28e40c7f34bde8b3046d885e986cb6290c5673b # v7.1.0
|
|
env:
|
|
RESULT_JSON: ${{ steps.evaluation.outputs.result }}
|
|
with:
|
|
script: |
|
|
const managedLabels = {
|
|
'external-plugin': {
|
|
color: 'FEF2C0',
|
|
description: 'Public external plugin submission'
|
|
},
|
|
'awaiting-review': {
|
|
color: 'FBCA04',
|
|
description: 'Submission is waiting for automated intake validation'
|
|
},
|
|
'ready-for-review': {
|
|
color: '0E8A16',
|
|
description: 'Submission passed intake validation and is ready for maintainer review'
|
|
},
|
|
'approved': {
|
|
color: '1D76DB',
|
|
description: 'Submission was approved by a maintainer'
|
|
},
|
|
'rejected': {
|
|
color: 'B60205',
|
|
description: 'Submission was rejected or failed intake validation'
|
|
}
|
|
};
|
|
|
|
async function ensureLabel(name, config) {
|
|
try {
|
|
await github.rest.issues.createLabel({
|
|
owner: context.repo.owner,
|
|
repo: context.repo.repo,
|
|
name,
|
|
color: config.color,
|
|
description: config.description
|
|
});
|
|
} catch (error) {
|
|
if (error.status !== 422) {
|
|
throw error;
|
|
}
|
|
}
|
|
}
|
|
|
|
async function syncManagedLabels(issueNumber, desiredLabels) {
|
|
await Promise.all(Object.entries(managedLabels).map(([name, config]) => ensureLabel(name, config)));
|
|
|
|
const managedForSync = ['external-plugin', 'awaiting-review', 'ready-for-review', 'rejected'];
|
|
const currentLabels = await github.paginate(github.rest.issues.listLabelsOnIssue, {
|
|
owner: context.repo.owner,
|
|
repo: context.repo.repo,
|
|
issue_number: issueNumber,
|
|
per_page: 100
|
|
});
|
|
|
|
const currentManagedLabels = currentLabels
|
|
.map((label) => label.name)
|
|
.filter((name) => managedForSync.includes(name));
|
|
|
|
const labelsToAdd = [...desiredLabels].filter((name) => !currentManagedLabels.includes(name));
|
|
const labelsToRemove = currentManagedLabels.filter((name) => !desiredLabels.has(name));
|
|
|
|
if (labelsToAdd.length > 0) {
|
|
await github.rest.issues.addLabels({
|
|
owner: context.repo.owner,
|
|
repo: context.repo.repo,
|
|
issue_number: issueNumber,
|
|
labels: labelsToAdd
|
|
});
|
|
}
|
|
|
|
for (const name of labelsToRemove) {
|
|
await github.rest.issues.removeLabel({
|
|
owner: context.repo.owner,
|
|
repo: context.repo.repo,
|
|
issue_number: issueNumber,
|
|
name
|
|
});
|
|
}
|
|
}
|
|
|
|
const result = JSON.parse(process.env.RESULT_JSON);
|
|
const issueNumber = context.issue.number;
|
|
const issueState = context.payload.issue.state;
|
|
const action = context.payload.action;
|
|
const existingLabelNames = (context.payload.issue.labels || []).map((label) => label.name);
|
|
|
|
if (existingLabelNames.includes('approved')) {
|
|
core.info('Issue is already approved; skipping intake synchronization.');
|
|
return;
|
|
}
|
|
|
|
if (issueState === 'closed' && action !== 'reopened') {
|
|
core.info('Issue is closed; waiting for reopen before rerunning intake synchronization.');
|
|
return;
|
|
}
|
|
|
|
const desiredLabels = result.valid
|
|
? new Set(['external-plugin', 'ready-for-review'])
|
|
: new Set(['external-plugin', 'rejected']);
|
|
|
|
await syncManagedLabels(issueNumber, desiredLabels);
|
|
|
|
const { data: comments } = await github.rest.issues.listComments({
|
|
owner: context.repo.owner,
|
|
repo: context.repo.repo,
|
|
issue_number: issueNumber,
|
|
per_page: 100
|
|
});
|
|
|
|
const existingComment = comments.find((comment) =>
|
|
comment.user?.login === 'github-actions[bot]' &&
|
|
comment.body?.includes(result.commentMarker)
|
|
);
|
|
|
|
if (existingComment) {
|
|
await github.rest.issues.updateComment({
|
|
owner: context.repo.owner,
|
|
repo: context.repo.repo,
|
|
comment_id: existingComment.id,
|
|
body: result.commentBody
|
|
});
|
|
} else {
|
|
await github.rest.issues.createComment({
|
|
owner: context.repo.owner,
|
|
repo: context.repo.repo,
|
|
issue_number: issueNumber,
|
|
body: result.commentBody
|
|
});
|
|
}
|
|
|
|
if (!result.valid && issueState === 'open') {
|
|
await github.rest.issues.update({
|
|
owner: context.repo.owner,
|
|
repo: context.repo.repo,
|
|
issue_number: issueNumber,
|
|
state: 'closed'
|
|
});
|
|
}
|