diff --git a/docs/project/groups.md b/docs/project/groups.md index 3944789b494c..45e7b7fa3ec0 100644 --- a/docs/project/groups.md +++ b/docs/project/groups.md @@ -22,6 +22,9 @@ We use a mix of: ## All contributors - [GitHub organization](https://github.com/orgs/carbon-language/people) + - [GitHub team: Contributors with label access](https://github.com/orgs/carbon-language/teams/contributors-with-label-access): + Mirrors the GitHub organization for write access. + [Manually updated](/src/scripts/update-label-access.js). - [Discourse Forums account](https://forums.carbon-lang.dev) - [Discord Chat access](https://discord.com/app) - [Google group](https://groups.google.com/g/carbon-lang-contributors): Grants diff --git a/src/scripts/README.md b/src/scripts/README.md new file mode 100644 index 000000000000..1e9d055eb90b --- /dev/null +++ b/src/scripts/README.md @@ -0,0 +1,11 @@ +# Scripts + + + +Self-contained scripts used as part of maintaining Carbon infrastructure. + +See individual scripts for more details. diff --git a/src/scripts/update-label-access.js b/src/scripts/update-label-access.js new file mode 100755 index 000000000000..bd69f3d74979 --- /dev/null +++ b/src/scripts/update-label-access.js @@ -0,0 +1,84 @@ +/* +Part of the Carbon Language project, under the Apache License v2.0 with LLVM +Exceptions. See /LICENSE for license information. +SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +*/ + +/* +Mirrors the carbon-language organization to the contributors-with-label-access +team. + +Set GITHUB_AUTH_KEY in your environment to use this script. e.g.: + GITHUB_AUTH_KEY=abc123 node update-label-access.js + +This team exists because we need a team to manage triage access to repos; +GitHub doesn't allow the org to be set to triage access, only read/write. + +This does not handle removing ex-members from contributors-with-label-access. +*/ + +'use strict'; + +const updateTriageAccess = async () => { + // The org and team to mirror. + const org = 'carbon-language'; + const team = 'contributors-with-label-access'; + // Accounts in the org to skip mirroring. + const ignore = ['CarbonLangInfra', 'google-admin', 'googlebot']; + + // Set up the GitHub API. + const { Octokit } = require('@octokit/rest'); + const key = process.env.GITHUB_AUTH_KEY; + if (!key) { + console.log('Missing GITHUB_AUTH_KEY'); + return; + } + const octokit = new Octokit({ auth: key }); + + // Load org members. + var orgMembers = {}; + try { + const ret = await octokit.orgs.listMembers({ org: org }); + for (var i = 0; i < ret.data.length; ++i) { + orgMembers[ret.data[i].id] = ret.data[i].login; + } + } catch (error) { + console.log(`org.listMembers failed: ${error}`); + return; + } + + // Load team members. + var teamMembers = new Set(); + try { + const ret = await octokit.teams.listMembersInOrg({ + org: org, + team_slug: team, + }); + for (var i = 0; i < ret.data.length; ++i) { + teamMembers[ret.data[i].id] = ret.data[i].login; + } + } catch (error) { + console.log(`teams.listMembersInOrg failed: ${error}`); + return; + } + + // Copy members from the org to the team. + for (const member in orgMembers) { + if ( + teamMembers.hasOwnProperty(member) || + ignore.indexOf(orgMembers[member]) >= 0 + ) { + continue; + } + console.log(`Adding ${orgMembers[member]}`); + octokit.teams.addOrUpdateMembershipForUserInOrg({ + org: org, + team_slug: team, + username: orgMembers[member], + }); + } + + console.log('Done!'); +}; + +updateTriageAccess();