Skip to repository content239 lines · 8.1 KB · yaml
tenant.openagents/omega
No repository description is available.
OpenAgents Git authority 2026-07-28T04:25:58.159Z Public web read
NIP-34 coordinate
30617:7649603503856e5148d571eac2766b288a8ff1e9e35d380337a1d2b0015b4f92:omegaMaintainersHidden in public view
References2 branches · 1 tag
Read-only clone
git clone https://openagents.com/git/tenant.openagents/omega.gitBrowse files
pr_issue_labeler.yml
1# Labels pull requests by author:
2# - 'community champion' for community champions
3# - 'bot' for bot accounts
4# - 'staff' for staff team members
5# - 'guild' for guild members
6# - 'first contribution' for first-time external contributors
7# Labels issues by author:
8# - 'community champion' for community champions
9
10name: PR Issue Labeler
11
12on:
13 issues:
14 types: [opened]
15 # zizmor: ignore[dangerous-triggers]
16 # Fork PRs must be labeled, but this workflow only passes GitHub-provided event
17 # metadata to a pinned action; it never checks out or executes PR code.
18 pull_request_target:
19 types: [opened]
20
21permissions:
22 contents: read
23
24jobs:
25 check-authorship-and-label:
26 if: github.repository == 'zed-industries/zed'
27 runs-on: namespace-profile-2x4-ubuntu-2404
28 timeout-minutes: 5
29 steps:
30 - id: get-app-token
31 uses: actions/create-github-app-token@f8d387b68d61c58ab83c6c016672934102569859 # v3.0.0
32 with:
33 app-id: ${{ secrets.ZED_COMMUNITY_BOT_APP_ID }}
34 private-key: ${{ secrets.ZED_COMMUNITY_BOT_PRIVATE_KEY }}
35 owner: zed-industries
36 repositories: zed
37 permission-issues: write
38 permission-members: read
39 permission-pull-requests: write
40
41 - id: apply-authorship-label
42 uses: actions/github-script@60a0d83039c74a4aee543508d2ffcb1c3799cdea # v7.0.1
43 with:
44 github-token: ${{ steps.get-app-token.outputs.token }}
45 script: |
46 const BOT_LABEL = 'bot';
47 const STAFF_LABEL = 'staff';
48 const STAFF_TEAM_SLUG = 'staff';
49 const FIRST_CONTRIBUTION_LABEL = 'first contribution';
50 const GUILD_LABEL = 'guild';
51 // Guild cohort members are outside collaborators holding this custom
52 // repository role, not members of an org team.
53 const GUILD_ROLE_NAME = 'Guild Assign issues/PRs';
54 const COMMUNITY_CHAMPION_LABEL = 'community champion';
55 const COMMUNITY_CHAMPIONS = [
56 '0x2CA',
57 '5brian',
58 '5herlocked',
59 'abdelq',
60 'afgomez',
61 'AidanV',
62 'akbxr',
63 'AlvaroParker',
64 'amtoaer',
65 'artemevsevev',
66 'bajrangCoder',
67 'bcomnes',
68 'Be-ing',
69 'blopker',
70 'bnjjj',
71 'bobbymannino',
72 'CharlesChen0823',
73 'chbk',
74 'davewa',
75 'davidbarsky',
76 'ddoemonn',
77 'djsauble',
78 'errmayank',
79 'fantacell',
80 'fdncred',
81 'findrakecil',
82 'FloppyDisco',
83 'gko',
84 'huacnlee',
85 'imumesh18',
86 'injust',
87 'jacobtread',
88 'jansol',
89 'jeffreyguenther',
90 'jenslys',
91 'jongretar',
92 'KyleBarton',
93 'lemorage',
94 'lingyaochu',
95 'lnay',
96 'marcocondrache',
97 'marius851000',
98 'mikebronner',
99 'ognevny',
100 'PKief',
101 'playdohface',
102 'RemcoSmitsDev',
103 'rgbkrk',
104 'romaninsh',
105 'rxptr',
106 'Simek',
107 'someone13574',
108 'sourcefrog',
109 'suxiaoshao',
110 'Takk8IS',
111 'tartarughina',
112 'thedadams',
113 'tidely',
114 'timvermeulen',
115 'valentinegb',
116 'versecafe',
117 'vitallium',
118 'WhySoBad',
119 'ya7010',
120 'Zertsov',
121 ];
122
123 const pr = context.payload.pull_request;
124 const issue = context.payload.issue;
125 const target = pr || issue;
126 const author = target.user.login;
127
128 const listIncludesAuthor = (members, author) => {
129 const authorLower = author.toLowerCase();
130 return members.some((member) => member.toLowerCase() === authorLower);
131 };
132
133 const isTeamMember = async (teamSlug, author) => {
134 try {
135 const response = await github.rest.teams.getMembershipForUserInOrg({
136 org: 'zed-industries',
137 team_slug: teamSlug,
138 username: author
139 });
140 return response.data.state === 'active';
141 } catch (error) {
142 if (error.status !== 404) {
143 throw error;
144 }
145 return false;
146 }
147 };
148
149 const isStaffMember = (author) => isTeamMember(STAFF_TEAM_SLUG, author);
150
151 const isGuildMember = async (author) => {
152 try {
153 const response = await github.rest.repos.getCollaboratorPermissionLevel({
154 owner: 'zed-industries',
155 repo: 'zed',
156 username: author
157 });
158 // role_name is the effective (highest) role; for cohort outside
159 // collaborators that is the custom role. Built-in roles come back
160 // lowercased and won't match.
161 return (response.data.role_name || '').toLowerCase() === GUILD_ROLE_NAME.toLowerCase();
162 } catch (error) {
163 if (error.status !== 404) {
164 throw error;
165 }
166 return false;
167 }
168 };
169
170 const getIssueLabels = () => {
171 if (listIncludesAuthor(COMMUNITY_CHAMPIONS, author)) {
172 return [COMMUNITY_CHAMPION_LABEL];
173 }
174
175 return [];
176 };
177
178 const getPullRequestLabels = async () => {
179 if (target.user.type === 'Bot') {
180 return [BOT_LABEL];
181 }
182
183 if (await isStaffMember(author)) {
184 return [STAFF_LABEL];
185 }
186
187 // External contributors
188
189 const labelsToAdd = [];
190
191 if (listIncludesAuthor(COMMUNITY_CHAMPIONS, author)) {
192 labelsToAdd.push(COMMUNITY_CHAMPION_LABEL);
193 }
194
195 if (await isGuildMember(author)) {
196 labelsToAdd.push(GUILD_LABEL);
197 }
198
199 // We use inverted logic here due to a suspected GitHub bug where first-time contributors
200 // get 'NONE' instead of 'FIRST_TIME_CONTRIBUTOR' or 'FIRST_TIMER'.
201 // https://github.com/orgs/community/discussions/78038
202 // This will break if GitHub ever adds new associations.
203 const association = pr.author_association;
204 const knownAssociations = ['CONTRIBUTOR', 'COLLABORATOR', 'MEMBER', 'OWNER', 'MANNEQUIN'];
205
206 if (knownAssociations.includes(association)) {
207 console.log(`PR #${pr.number} by ${author}: not a first-time contributor (association: '${association}')`);
208 } else {
209 labelsToAdd.push(FIRST_CONTRIBUTION_LABEL);
210 }
211
212 return labelsToAdd;
213 };
214
215 const labelsToAdd = pr ? await getPullRequestLabels() : getIssueLabels();
216
217 if (labelsToAdd.length === 0) {
218 return;
219 }
220
221 try {
222 await github.rest.issues.addLabels({
223 owner: context.repo.owner,
224 repo: context.repo.repo,
225 issue_number: target.number,
226 labels: labelsToAdd
227 });
228
229 const targetType = pr ? 'PR' : 'issue';
230 const labels = labelsToAdd.map((label) => `'${label}'`).join(', ');
231 console.log(`${targetType} #${target.number} by ${author}: labeled ${labels}`);
232 } catch (error) {
233 if (pr) {
234 throw error;
235 }
236
237 console.error(`Failed to label issue #${target.number}: ${error.message}`);
238 }
239