summaryrefslogtreecommitdiff
path: root/.github
diff options
context:
space:
mode:
authorHa Thach <[email protected]>2026-06-04 21:59:59 +0700
committerGitHub <[email protected]>2026-06-04 21:59:59 +0700
commitddc065dc9fd929fcc94b0993c3af4b56877b1cd6 (patch)
tree4b7e0c29f30bb60bc5b57929e5c13e024b87e597 /.github
parent38debe00ba6e23443375107ad84ce50c4f30189d (diff)
Remove Sponsor Triage workflow (migrated to hathach/hathach) (#3675)
This personal automation now lives in the hathach/hathach repo alongside the other personal project-sync workflows; it has no place in the tinyusb library. Co-authored-by: Claude Opus 4.8 (1M context) <[email protected]>
Diffstat (limited to '.github')
-rw-r--r--.github/workflows/sponsor-triage.yml165
1 files changed, 0 insertions, 165 deletions
diff --git a/.github/workflows/sponsor-triage.yml b/.github/workflows/sponsor-triage.yml
deleted file mode 100644
index 48b2ac7cc..000000000
--- a/.github/workflows/sponsor-triage.yml
+++ /dev/null
@@ -1,165 +0,0 @@
-name: Sponsor Triage
-
-# Periodically add open issues and PRs opened by sponsors (public and private) to the private "Sponsor Triage" project board
-# Requires a PAT in secret SPONSOR_TOKEN with scopes:
-# - project (write project items / fields)
-# - read:org (search org issues, check Adafruit membership)
-# - read:user / sponsors (read own sponsorships incl. private)
-
-on:
- schedule:
- - cron: '0 */6 * * *' # every 6 hours
- workflow_dispatch:
-
-concurrency:
- group: sponsor-triage
- cancel-in-progress: false
-
-jobs:
- sync:
- runs-on: ubuntu-latest
- steps:
- - name: Sync sponsor issues to project board
- uses: actions/github-script@v8
- with:
- github-token: ${{ secrets.SPONSOR_TOKEN }}
- script: |
- const PROJECT_OWNER = 'hathach';
- const PROJECT_NUMBER = 3;
- // Where to look for sponsor-authored open issues.
- const SEARCH_SCOPES = ['org:adafruit', 'user:hathach'];
-
- const tierFromMonthly = (m) => {
- if (m >= 512) return 'QWORD';
- if (m >= 128) return 'DWORD';
- if (m >= 32) return 'Word';
- if (m >= 8) return 'Byte';
- if (m >= 2) return 'Bit';
- return null;
- };
-
- // --- 1. Resolve project id + field/option ids (by name, never hardcoded) ---
- const proj = await github.graphql(`
- query($owner: String!, $number: Int!) {
- user(login: $owner) {
- projectV2(number: $number) {
- id
- fields(first: 50) {
- nodes {
- ... on ProjectV2SingleSelectField {
- id name options { id name }
- }
- }
- }
- }
- }
- }`, { owner: PROJECT_OWNER, number: PROJECT_NUMBER });
-
- const project = proj.user.projectV2;
- const fieldByName = {};
- for (const f of project.fields.nodes) {
- if (f && f.name) {
- fieldByName[f.name] = { id: f.id, options: {} };
- for (const o of (f.options || [])) fieldByName[f.name].options[o.name] = o.id;
- }
- }
- const tierField = fieldByName['Tier'];
- const visField = fieldByName['Visibility'];
-
- // --- 2. Build sponsor map: loginLower -> { tier, visibility } ---
- const sponsors = new Map();
-
- // 2a. GitHub Sponsors of the owner, including private ones.
- let after = null;
- for (let page = 0; page < 20; page++) {
- const res = await github.graphql(`
- query($owner: String!, $after: String) {
- user(login: $owner) {
- sponsorshipsAsMaintainer(includePrivate: true, first: 100, after: $after) {
- pageInfo { hasNextPage endCursor }
- nodes {
- privacyLevel
- tier { monthlyPriceInDollars }
- sponsorEntity {
- ... on User { login }
- ... on Organization { login }
- }
- }
- }
- }
- }`, { owner: PROJECT_OWNER, after });
- const conn = res.user.sponsorshipsAsMaintainer;
- for (const n of conn.nodes) {
- const login = n.sponsorEntity && n.sponsorEntity.login;
- if (!login) continue;
- const tier = tierFromMonthly((n.tier && n.tier.monthlyPriceInDollars) || 0);
- const visibility = n.privacyLevel === 'PRIVATE' ? 'Private' : 'Public';
- sponsors.set(login.toLowerCase(), { login, tier, visibility });
- }
- if (!conn.pageInfo.hasNextPage) break;
- after = conn.pageInfo.endCursor;
- }
-
- core.info(`Resolved ${sponsors.size} sponsor account(s).`);
- if (sponsors.size === 0) return;
-
- // 2b. Adafruit org members get the Adafruit tier regardless of $ amount.
- for (const s of sponsors.values()) {
- try {
- const m = await github.rest.orgs.checkMembershipForUser({ org: 'adafruit', username: s.login });
- if (m.status === 204) s.tier = 'Adafruit';
- } catch (e) { /* not an Adafruit member */ }
- }
-
- // --- 3. Find each sponsor's open issues and PRs in the search scopes ---
- // (search type ISSUE returns both issues and pull requests)
- const found = new Map(); // contentId -> { tier, visibility }
- for (const s of sponsors.values()) {
- for (const scope of SEARCH_SCOPES) {
- const q = `${scope} is:open author:${s.login}`;
- try {
- const res = await github.graphql(`
- query($q: String!) {
- search(query: $q, type: ISSUE, first: 100) {
- nodes { ... on Issue { id } ... on PullRequest { id } }
- }
- }`, { q });
- for (const node of res.search.nodes) {
- if (node && node.id && !found.has(node.id)) {
- found.set(node.id, { tier: s.tier, visibility: s.visibility });
- }
- }
- } catch (e) {
- core.warning(`Search failed for one scope: ${e.message}`);
- }
- }
- }
- core.info(`Found ${found.size} open sponsor issue(s) across scopes.`);
-
- // --- 4. Add to board + set Tier / Visibility (idempotent) ---
- const setField = async (itemId, field, optionName) => {
- if (!field || !optionName) return;
- const optId = field.options[optionName];
- if (!optId) return;
- await github.graphql(`
- mutation($p: ID!, $i: ID!, $f: ID!, $o: String!) {
- updateProjectV2ItemFieldValue(input: {
- projectId: $p, itemId: $i, fieldId: $f, value: { singleSelectOptionId: $o }
- }) { projectV2Item { id } }
- }`, { p: project.id, i: itemId, f: field.id, o: optId });
- };
-
- let added = 0;
- for (const [contentId, meta] of found) {
- const res = await github.graphql(`
- mutation($p: ID!, $c: ID!) {
- addProjectV2ItemById(input: { projectId: $p, contentId: $c }) {
- item { id }
- }
- }`, { p: project.id, c: contentId });
- const itemId = res.addProjectV2ItemById.item.id;
- await setField(itemId, tierField, meta.tier);
- await setField(itemId, visField, meta.visibility);
- added++;
- }
- core.info(`Synced ${added} item(s) to the board.`);