Add ada-marie plugin: a fresh-boot AI partner for the Spartan/AI dynamic #455
Workflow file for this run
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: Label PR Intent | |
| on: | |
| pull_request_target: | |
| types: [opened, synchronize, reopened, edited, ready_for_review] | |
| permissions: | |
| issues: write | |
| pull-requests: write | |
| jobs: | |
| label-pr: | |
| runs-on: ubuntu-latest | |
| if: >- | |
| github.actor != 'dependabot[bot]' && | |
| github.actor != 'github-actions[bot]' | |
| steps: | |
| - name: Apply intent labels | |
| uses: actions/github-script@f28e40c7f34bde8b3046d885e986cb6290c5673b # v7.1.0 | |
| with: | |
| script: | | |
| const managedLabels = { | |
| 'targets-main': { | |
| color: 'B60205', | |
| description: 'PR targets main instead of staged' | |
| }, | |
| 'branched-main': { | |
| color: 'D93F0B', | |
| description: 'PR appears to include plugin files materialized from main' | |
| }, | |
| 'skills': { | |
| color: '1D76DB', | |
| description: 'PR touches skills' | |
| }, | |
| 'plugin': { | |
| color: '5319E7', | |
| description: 'PR touches plugins' | |
| }, | |
| 'agent': { | |
| color: '0E8A16', | |
| description: 'PR touches agents' | |
| }, | |
| 'instructions': { | |
| color: 'FBCA04', | |
| description: 'PR touches instructions' | |
| }, | |
| 'new-submission': { | |
| color: '006B75', | |
| description: 'PR adds at least one new contribution' | |
| }, | |
| 'website-update': { | |
| color: '0052CC', | |
| description: 'PR touches website content or code' | |
| }, | |
| 'external-plugin': { | |
| color: 'FEF2C0', | |
| description: 'PR updates plugins/external.json' | |
| }, | |
| 'hooks': { | |
| color: 'C2E0C6', | |
| description: 'PR touches hooks' | |
| }, | |
| 'workflow': { | |
| color: 'BFD4F2', | |
| description: 'PR touches workflow automation' | |
| } | |
| }; | |
| const matchesAny = (filename, patterns) => patterns.some((pattern) => pattern.test(filename)); | |
| async function listAllFiles() { | |
| const files = []; | |
| let page = 1; | |
| while (true) { | |
| const response = await github.rest.pulls.listFiles({ | |
| owner: context.repo.owner, | |
| repo: context.repo.repo, | |
| pull_number: context.issue.number, | |
| per_page: 100, | |
| page | |
| }); | |
| files.push(...response.data); | |
| if (response.data.length < 100) { | |
| return files; | |
| } | |
| page += 1; | |
| } | |
| } | |
| async function ensureLabel(name, { color, description }) { | |
| try { | |
| await github.rest.issues.createLabel({ | |
| owner: context.repo.owner, | |
| repo: context.repo.repo, | |
| name, | |
| color, | |
| description | |
| }); | |
| } catch (error) { | |
| if (error.status !== 422) { | |
| throw error; | |
| } | |
| } | |
| } | |
| const files = await listAllFiles(); | |
| const filenames = files.map((file) => file.filename); | |
| const patterns = { | |
| branchedMain: [ | |
| /^plugins\/[^/]+\/(?:agents|commands|skills)\// | |
| ], | |
| skills: [ | |
| /^skills\// | |
| ], | |
| plugin: [ | |
| /^plugins\// | |
| ], | |
| agent: [ | |
| /^agents\/.+\.agent\.md$/ | |
| ], | |
| instructions: [ | |
| /^instructions\/.+\.instructions\.md$/ | |
| ], | |
| websiteUpdate: [ | |
| /^website\// | |
| ], | |
| externalPlugin: [ | |
| /^plugins\/external\.json$/ | |
| ], | |
| hooks: [ | |
| /^hooks\// | |
| ], | |
| workflow: [ | |
| /^workflows\/.+\.md$/, | |
| /^\.github\/workflows\/.+\.(?:ya?ml|md)$/ | |
| ], | |
| newSubmission: [ | |
| /^agents\/.+\.agent\.md$/, | |
| /^instructions\/.+\.instructions\.md$/, | |
| /^skills\/[^/]+\/SKILL\.md$/, | |
| /^hooks\/[^/]+\/(?:README\.md|hooks\.json)$/, | |
| /^plugins\/[^/]+\/\.github\/plugin\/plugin\.json$/, | |
| /^workflows\/.+\.md$/, | |
| /^\.github\/workflows\/.+\.(?:ya?ml|md)$/, | |
| /^website\// | |
| ] | |
| }; | |
| const isBranchedMain = filenames.some((filename) => matchesAny(filename, patterns.branchedMain)); | |
| const hasNewSubmission = files.some( | |
| (file) => file.status === 'added' && matchesAny(file.filename, patterns.newSubmission) | |
| ); | |
| const desiredLabels = new Set(); | |
| if (context.payload.pull_request.base.ref === 'main') { | |
| desiredLabels.add('targets-main'); | |
| } | |
| if (filenames.some((filename) => matchesAny(filename, patterns.externalPlugin))) { | |
| desiredLabels.add('external-plugin'); | |
| } | |
| if (isBranchedMain) { | |
| desiredLabels.add('branched-main'); | |
| } else { | |
| if (filenames.some((filename) => matchesAny(filename, patterns.skills))) { | |
| desiredLabels.add('skills'); | |
| } | |
| if (filenames.some((filename) => matchesAny(filename, patterns.plugin))) { | |
| desiredLabels.add('plugin'); | |
| } | |
| if (filenames.some((filename) => matchesAny(filename, patterns.agent))) { | |
| desiredLabels.add('agent'); | |
| } | |
| if (filenames.some((filename) => matchesAny(filename, patterns.instructions))) { | |
| desiredLabels.add('instructions'); | |
| } | |
| if (filenames.some((filename) => matchesAny(filename, patterns.websiteUpdate))) { | |
| desiredLabels.add('website-update'); | |
| } | |
| if (filenames.some((filename) => matchesAny(filename, patterns.hooks))) { | |
| desiredLabels.add('hooks'); | |
| } | |
| if (filenames.some((filename) => matchesAny(filename, patterns.workflow))) { | |
| desiredLabels.add('workflow'); | |
| } | |
| if (hasNewSubmission) { | |
| desiredLabels.add('new-submission'); | |
| } | |
| } | |
| await Promise.all( | |
| Object.entries(managedLabels).map(([name, config]) => ensureLabel(name, config)) | |
| ); | |
| const currentLabels = await github.paginate(github.rest.issues.listLabelsOnIssue, { | |
| owner: context.repo.owner, | |
| repo: context.repo.repo, | |
| issue_number: context.issue.number, | |
| per_page: 100 | |
| }); | |
| const currentManagedLabels = currentLabels | |
| .map((label) => label.name) | |
| .filter((name) => Object.prototype.hasOwnProperty.call(managedLabels, 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: context.issue.number, | |
| labels: labelsToAdd | |
| }); | |
| } | |
| for (const name of labelsToRemove) { | |
| await github.rest.issues.removeLabel({ | |
| owner: context.repo.owner, | |
| repo: context.repo.repo, | |
| issue_number: context.issue.number, | |
| name | |
| }); | |
| } | |
| core.info(`Managed labels: ${[...desiredLabels].sort().join(', ') || 'none'}`); |