mirror of
https://github.com/hathach/tinyusb.git
synced 2026-08-18 11:02:16 +00:00
* ci(labeler): auto-apply Port labels from changed driver files Add path-based labeling so a PR touching a dcd/hcd driver under src/portable/ gets the matching "Port <ip>" label automatically.
183 lines
7.5 KiB
YAML
183 lines
7.5 KiB
YAML
name: Labeler
|
|
|
|
on:
|
|
issues:
|
|
types: [opened]
|
|
pull_request_target:
|
|
types: [opened, synchronize, reopened]
|
|
discussion:
|
|
types: [created]
|
|
|
|
jobs:
|
|
label-priority:
|
|
# Author-based priority labels: only on issue/PR/discussion creation, not on PR updates.
|
|
if: github.event_name != 'pull_request_target' || github.event.action == 'opened'
|
|
runs-on: ubuntu-latest
|
|
permissions:
|
|
issues: write
|
|
pull-requests: write
|
|
discussions: write
|
|
steps:
|
|
- name: Label New Issue, PR or Discussion
|
|
uses: actions/github-script@v8
|
|
with:
|
|
github-token: ${{ secrets.GITHUB_TOKEN }}
|
|
script: |
|
|
let labels = [];
|
|
let username = '';
|
|
let issueOrPrNumber = 0;
|
|
let discussionNodeId = '';
|
|
|
|
if (context.eventName === 'issues') {
|
|
username = context.payload.issue.user.login;
|
|
issueOrPrNumber = context.payload.issue.number;
|
|
} else if (context.eventName === 'pull_request_target') {
|
|
username = context.payload.pull_request.user.login;
|
|
issueOrPrNumber = context.payload.pull_request.number;
|
|
} else if (context.eventName === 'discussion') {
|
|
username = context.payload.discussion.user.login;
|
|
discussionNodeId = context.payload.discussion.node_id;
|
|
}
|
|
|
|
// Maintainer is an Adafruit member; skip the Adafruit perks for their own
|
|
// issues/PRs and treat them as a plain contributor (Prio only).
|
|
const isOwner = username.toLowerCase() === 'hathach';
|
|
|
|
// Check if an Adafruit member: Adafruit + Sponsor + top priority
|
|
if (!isOwner) {
|
|
try {
|
|
const adafruitResponse = await github.rest.orgs.checkMembershipForUser({
|
|
org: 'adafruit',
|
|
username: username
|
|
});
|
|
|
|
if (adafruitResponse.status === 204) {
|
|
console.log('Adafruit Member');
|
|
labels = ['Adafruit 🌸', 'Sponsor 💖', 'Prio Top 🚨'];
|
|
}
|
|
} catch (error) {
|
|
console.log('Not an Adafruit member');
|
|
}
|
|
}
|
|
|
|
// Check if a public GitHub Sponsor of the repo owner.
|
|
// Word ($32) tier and up get triage priority; DWORD/QWORD ($128+) go to the top.
|
|
// Private sponsorships are not visible to GITHUB_TOKEN, so only public sponsors are detected.
|
|
if (labels.length === 0) {
|
|
try {
|
|
const result = await github.graphql(`
|
|
query($sponsorable: String!, $sponsor: String!) {
|
|
user(login: $sponsorable) {
|
|
isSponsoredBy(accountLogin: $sponsor)
|
|
sponsorshipsAsMaintainer(includePrivate: false, first: 100) {
|
|
nodes {
|
|
sponsorEntity {
|
|
... on User { login }
|
|
... on Organization { login }
|
|
}
|
|
tier { monthlyPriceInDollars }
|
|
}
|
|
}
|
|
}
|
|
}`, { sponsorable: context.repo.owner, sponsor: username });
|
|
|
|
const owner = result.user;
|
|
if (owner && owner.isSponsoredBy) {
|
|
let monthly = 0;
|
|
const nodes = (owner.sponsorshipsAsMaintainer && owner.sponsorshipsAsMaintainer.nodes) || [];
|
|
for (const node of nodes) {
|
|
const login = node.sponsorEntity && node.sponsorEntity.login;
|
|
if (login && login.toLowerCase() === username.toLowerCase()) {
|
|
monthly = (node.tier && node.tier.monthlyPriceInDollars) || 0;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (monthly >= 128) {
|
|
console.log('Sponsor (DWORD/QWORD tier)');
|
|
labels = ['Sponsor 💖', 'Prio Top 🚨'];
|
|
} else if (monthly >= 32) {
|
|
console.log('Sponsor (Word tier)');
|
|
labels = ['Sponsor 💖', 'Prio 📌'];
|
|
} else {
|
|
console.log('Sponsor (below Word tier or tier not visible)');
|
|
labels = ['Sponsor 💖'];
|
|
}
|
|
} else {
|
|
console.log('Not a public sponsor');
|
|
}
|
|
} catch (error) {
|
|
console.log('Sponsor lookup failed: ' + error.message);
|
|
}
|
|
}
|
|
|
|
// Check if a contributor: prioritized in triage queue
|
|
if (labels.length === 0) {
|
|
try {
|
|
const collaboratorResponse = await github.rest.repos.checkCollaborator({
|
|
owner: context.repo.owner,
|
|
repo: context.repo.repo,
|
|
username: username
|
|
});
|
|
|
|
if (collaboratorResponse.status === 204) {
|
|
console.log('Contributor');
|
|
labels = ['Prio 📌'];
|
|
}
|
|
} catch (error) {
|
|
console.log('Not a contributor');
|
|
}
|
|
}
|
|
|
|
if (labels.length !== 0) {
|
|
if (context.eventName === 'discussion') {
|
|
// Discussions are not covered by the REST issues API; resolve the label
|
|
// names to node IDs and attach them with the GraphQL labelable mutation.
|
|
const labelIds = [];
|
|
for (const name of labels) {
|
|
const res = await github.graphql(`
|
|
query($owner: String!, $repo: String!, $name: String!) {
|
|
repository(owner: $owner, name: $repo) {
|
|
label(name: $name) { id }
|
|
}
|
|
}`, { owner: context.repo.owner, repo: context.repo.repo, name: name });
|
|
if (res.repository.label) {
|
|
labelIds.push(res.repository.label.id);
|
|
}
|
|
}
|
|
if (labelIds.length !== 0) {
|
|
await github.graphql(`
|
|
mutation($labelableId: ID!, $labelIds: [ID!]!) {
|
|
addLabelsToLabelable(input: { labelableId: $labelableId, labelIds: $labelIds }) {
|
|
clientMutationId
|
|
}
|
|
}`, { labelableId: discussionNodeId, labelIds: labelIds });
|
|
}
|
|
} else {
|
|
await github.rest.issues.addLabels({
|
|
owner: context.repo.owner,
|
|
repo: context.repo.repo,
|
|
issue_number: issueOrPrNumber,
|
|
labels: labels
|
|
});
|
|
}
|
|
}
|
|
|
|
# Path-based Port labels: attach "Port <ip>" when a PR touches the matching
|
|
# dcd/hcd driver under src/portable/. Mapping lives in .github/labeler.yml.
|
|
label-port:
|
|
if: github.event_name == 'pull_request_target'
|
|
runs-on: ubuntu-latest
|
|
permissions:
|
|
contents: read
|
|
pull-requests: write
|
|
issues: write # allow auto-creating a Port label that doesn't exist yet
|
|
steps:
|
|
- uses: actions/labeler@v5
|
|
with:
|
|
configuration-path: .github/labeler.yml
|
|
# sync-labels so a Port label is removed once a PR no longer touches
|
|
# that driver (job reruns on synchronize). Only labels listed in
|
|
# labeler.yml are managed, so author-based Prio/Sponsor labels are untouched.
|
|
sync-labels: true
|