Initial commit
This commit is contained in:
commit
e3f0af2f94
6 changed files with 3857 additions and 0 deletions
15
src/config/groups.ts
Normal file
15
src/config/groups.ts
Normal file
|
|
@ -0,0 +1,15 @@
|
|||
import { defineGroups } from './utils';
|
||||
|
||||
// NOTE: For GitHub teams, only the first memberOf will be used as the parent team.
|
||||
// GitHub only supports one parent team per team.
|
||||
export const GROUPS = defineGroups([
|
||||
{
|
||||
name: 'test-parent',
|
||||
description: 'All maintainers. Users should not be added directly to this group.',
|
||||
},
|
||||
{
|
||||
name: 'test-child',
|
||||
description: 'Registry maintainers',
|
||||
memberOf: ['test-parent'],
|
||||
},
|
||||
] as const);
|
||||
9
src/config/users.ts
Normal file
9
src/config/users.ts
Normal file
|
|
@ -0,0 +1,9 @@
|
|||
import type { Member } from './utils';
|
||||
|
||||
export const MEMBERS: readonly Member[] = [
|
||||
{
|
||||
github: 'domdomegg',
|
||||
email: 'adam@modelcontextprotocol.io',
|
||||
memberOf: ['test-child'],
|
||||
},
|
||||
] as const;
|
||||
37
src/config/utils.ts
Normal file
37
src/config/utils.ts
Normal file
|
|
@ -0,0 +1,37 @@
|
|||
import type { GROUPS } from './groups';
|
||||
|
||||
function isValidGroupName(name: string): boolean {
|
||||
return /^[a-z][a-z0-9-]*[a-z]$/.test(name);
|
||||
}
|
||||
|
||||
export function defineGroups<
|
||||
const T extends readonly {
|
||||
name: Lowercase<string>;
|
||||
description: string;
|
||||
memberOf?: readonly (T[number]['name'])[];
|
||||
}[]
|
||||
>(groups: T) {
|
||||
for (const group of groups) {
|
||||
if (!isValidGroupName(group.name)) {
|
||||
throw new Error(
|
||||
`Invalid group name: ${group.name}. Must be lowercase alphanumeric with dashes, starting with a letter.`
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
return groups;
|
||||
}
|
||||
|
||||
export type GroupKey = (typeof GROUPS)[number]['name'];
|
||||
|
||||
export interface Group {
|
||||
name: GroupKey;
|
||||
description: string;
|
||||
memberOf?: readonly GroupKey[];
|
||||
}
|
||||
|
||||
export interface Member {
|
||||
github?: string;
|
||||
email?: `${string}@modelcontextprotocol.io`;
|
||||
memberOf: readonly GroupKey[];
|
||||
}
|
||||
27
src/github.ts
Normal file
27
src/github.ts
Normal file
|
|
@ -0,0 +1,27 @@
|
|||
import * as github from '@pulumi/github';
|
||||
import { GROUPS } from './config/groups';
|
||||
import type { Group } from './config/utils';
|
||||
import { MEMBERS } from './config/users';
|
||||
|
||||
const teams: Record<string, github.Team> = {};
|
||||
|
||||
GROUPS.forEach((group: Group) => {
|
||||
teams[group.name] = new github.Team(group.name, {
|
||||
name: group.name,
|
||||
description: group.description + ' \n(Managed by github.com/modelcontextprotocol/access)',
|
||||
privacy: 'closed',
|
||||
parentTeamId: group.memberOf?.[0] ? teams[group.memberOf[0]].id : undefined,
|
||||
});
|
||||
});
|
||||
|
||||
MEMBERS.forEach((member) => {
|
||||
if (!member.github) return;
|
||||
|
||||
member.memberOf.forEach((teamKey) => {
|
||||
new github.TeamMembership(`${member.github}-${teamKey}`, {
|
||||
teamId: teams[teamKey].id,
|
||||
username: member.github!,
|
||||
role: 'member',
|
||||
});
|
||||
});
|
||||
});
|
||||
45
src/google.ts
Normal file
45
src/google.ts
Normal file
|
|
@ -0,0 +1,45 @@
|
|||
import * as gworkspace from '@pulumi/googleworkspace';
|
||||
import { GROUPS } from './config/groups';
|
||||
import type { Group } from './config/utils';
|
||||
import { MEMBERS } from './config/users';
|
||||
|
||||
const groups: Record<string, gworkspace.Group> = {};
|
||||
|
||||
GROUPS.forEach((group: Group) => {
|
||||
groups[group.name] = new gworkspace.Group(group.name, {
|
||||
email: `${group.name}@modelcontextprotocol.io`,
|
||||
name: group.name,
|
||||
description: group.description + ' \n(Managed by github.com/modelcontextprotocol/access)',
|
||||
});
|
||||
|
||||
new gworkspace.GroupSettings(group.name, {
|
||||
email: groups[group.name].email,
|
||||
whoCanContactOwner: 'ALL_OWNERS_CAN_CONTACT',
|
||||
whoCanJoin: 'INVITED_CAN_JOIN',
|
||||
whoCanLeaveGroup: 'NONE_CAN_LEAVE',
|
||||
whoCanModerateMembers: 'OWNERS_ONLY',
|
||||
whoCanPostMessage: 'ALL_OWNERS_CAN_POST',
|
||||
whoCanViewGroup: 'ALL_MEMBERS_CAN_VIEW',
|
||||
whoCanViewMembership: 'ALL_IN_DOMAIN_CAN_VIEW',
|
||||
});
|
||||
|
||||
group.memberOf?.forEach((parentGroupKey) => {
|
||||
new gworkspace.GroupMember(`${group.name}-in-${parentGroupKey}`, {
|
||||
groupId: groups[parentGroupKey].id,
|
||||
email: groups[group.name].email,
|
||||
role: 'MEMBER',
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
MEMBERS.forEach((member) => {
|
||||
if (!member.email) return;
|
||||
|
||||
member.memberOf.forEach((teamKey) => {
|
||||
new gworkspace.GroupMember(`${member.email}-${teamKey}`, {
|
||||
groupId: groups[teamKey].id,
|
||||
email: member.email!,
|
||||
role: 'MEMBER',
|
||||
});
|
||||
});
|
||||
});
|
||||
2
src/index.ts
Normal file
2
src/index.ts
Normal file
|
|
@ -0,0 +1,2 @@
|
|||
export * from './github';
|
||||
export * from './google';
|
||||
Loading…
Reference in a new issue