diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index c1ff399..bcbd3db 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -33,4 +33,10 @@ jobs: run: npm ci - name: Build - run: npm run build \ No newline at end of file + run: npm run build + + - name: Validate config + run: npm run validate + + - name: Check formatting + run: npm run format:check \ No newline at end of file diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 770ad7e..7962d99 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -22,3 +22,10 @@ repos: language: system pass_filenames: false files: ^src/config/ + + - id: prettier + name: Prettier formatting + entry: npx prettier --write --ignore-unknown + language: system + types: [text] + files: \.(ts|tsx|js|jsx|json|md)$ diff --git a/.prettierignore b/.prettierignore new file mode 100644 index 0000000..8e8e1fe --- /dev/null +++ b/.prettierignore @@ -0,0 +1,5 @@ +node_modules/ +sdks/ +*.yaml +*.yml +package-lock.json diff --git a/.prettierrc b/.prettierrc new file mode 100644 index 0000000..a95cb05 --- /dev/null +++ b/.prettierrc @@ -0,0 +1,7 @@ +{ + "semi": true, + "singleQuote": true, + "trailingComma": "es5", + "printWidth": 100, + "tabWidth": 2 +} diff --git a/README.md b/README.md index 57a50af..e07859b 100644 --- a/README.md +++ b/README.md @@ -21,6 +21,7 @@ Infrastructure as Code for managing access to MCP community resources using Pulu ### Manual Deployment Pre-requisites: + - [Pulumi CLI installed](https://www.pulumi.com/docs/iac/download-install/) - [Google Cloud SDK installed](https://cloud.google.com/sdk/docs/install) - Access to GCP project and GCS bucket @@ -79,6 +80,7 @@ gsutil mb gs://mcp-access-prod-pulumi-state ``` Then: + 1. In Google Workspace Admin Console, go to **Account** → **Admin roles** 2. Select **Groups Admin** role (or create a custom role with these privileges): - Read, create, update, and delete groups @@ -104,5 +106,6 @@ pulumi config set --secret github:token "ghp_your_github_token_here" ### 3. Configure GitHub Actions Secrets Add the CI/CD secrets to GitHub Actions (repository settings → Secrets and variables → Actions): + - `GCP_PROD_SERVICE_ACCOUNT_KEY`: Content of `sa-key.json` - `PULUMI_PROD_PASSPHRASE`: The passphrase you set above diff --git a/package-lock.json b/package-lock.json index c914992..84cac9a 100644 --- a/package-lock.json +++ b/package-lock.json @@ -15,6 +15,7 @@ }, "devDependencies": { "@types/node": "^22.18.6", + "prettier": "^3.7.2", "typescript": "^5.9.2" } }, @@ -2513,6 +2514,22 @@ "node": ">=4" } }, + "node_modules/prettier": { + "version": "3.7.2", + "resolved": "https://artifactory.infra.ant.dev:443/artifactory/api/npm/npm-all/prettier/-/prettier-3.7.2.tgz", + "integrity": "sha512-n3HV2J6QhItCXndGa3oMWvWFAgN1ibnS7R9mt6iokScBOC0Ul9/iZORmU2IWUMcyAQaMPjTlY3uT34TqocUxMA==", + "dev": true, + "license": "MIT", + "bin": { + "prettier": "bin/prettier.cjs" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/prettier/prettier?sponsor=1" + } + }, "node_modules/proc-log": { "version": "4.2.0", "resolved": "https://registry.npmjs.org/proc-log/-/proc-log-4.2.0.tgz", diff --git a/package.json b/package.json index 42d2018..59c9dd7 100644 --- a/package.json +++ b/package.json @@ -5,7 +5,9 @@ "main": "src/index.ts", "scripts": { "build": "tsc", - "validate": "npx ts-node scripts/validate-config.ts" + "validate": "npx ts-node scripts/validate-config.ts", + "format": "prettier --write .", + "format:check": "prettier --check ." }, "license": "MIT", "dependencies": { @@ -15,6 +17,7 @@ }, "devDependencies": { "@types/node": "^22.18.6", + "prettier": "^3.7.2", "typescript": "^5.9.2" } } diff --git a/src/config/groups.ts b/src/config/groups.ts index 73291b4..72c1552 100644 --- a/src/config/groups.ts +++ b/src/config/groups.ts @@ -184,4 +184,4 @@ export const GROUPS = defineGroups([ isEmailGroup: true, onlyOnPlatforms: ['google'], }, -] as const); \ No newline at end of file +] as const); diff --git a/src/config/repoAccess.ts b/src/config/repoAccess.ts index e05b59f..937a0f3 100644 --- a/src/config/repoAccess.ts +++ b/src/config/repoAccess.ts @@ -16,9 +16,7 @@ export interface RepositoryAccess { export const REPOSITORY_ACCESS: RepositoryAccess[] = [ { repository: 'docs', - users: [ - { username: 'jspahrsummers', permission: 'admin' }, - ], + users: [{ username: 'jspahrsummers', permission: 'admin' }], teams: [ { team: 'auth-wg', permission: 'push' }, { team: 'core-maintainers', permission: 'maintain' }, @@ -48,9 +46,7 @@ export const REPOSITORY_ACCESS: RepositoryAccess[] = [ }, { repository: '.github', - users: [ - { username: 'jspahrsummers', permission: 'admin' }, - ], + users: [{ username: 'jspahrsummers', permission: 'admin' }], teams: [ { team: 'auth-wg', permission: 'triage' }, { team: 'core-maintainers', permission: 'maintain' }, @@ -116,9 +112,7 @@ export const REPOSITORY_ACCESS: RepositoryAccess[] = [ }, { repository: 'modelcontextprotocol', - users: [ - { username: 'jspahrsummers', permission: 'admin' }, - ], + users: [{ username: 'jspahrsummers', permission: 'admin' }], teams: [ { team: 'auth-wg', permission: 'push' }, { team: 'core-maintainers', permission: 'maintain' }, @@ -251,9 +245,7 @@ export const REPOSITORY_ACCESS: RepositoryAccess[] = [ { team: 'python-sdk', permission: 'admin' }, { team: 'python-sdk-auth', permission: 'admin' }, ], - users: [ - { username: 'jspahrsummers', permission: 'admin' }, - ], + users: [{ username: 'jspahrsummers', permission: 'admin' }], }, { repository: 'ruby-sdk', @@ -280,9 +272,7 @@ export const REPOSITORY_ACCESS: RepositoryAccess[] = [ { team: 'typescript-sdk', permission: 'admin' }, { team: 'typescript-sdk-auth', permission: 'admin' }, ], - users: [ - { username: 'jspahrsummers', permission: 'admin' }, - ], + users: [{ username: 'jspahrsummers', permission: 'admin' }], }, { repository: 'create-python-server', @@ -301,9 +291,7 @@ export const REPOSITORY_ACCESS: RepositoryAccess[] = [ { repository: 'registry', teams: [{ team: 'registry-wg', permission: 'admin' }], - users: [ - { username: 'rdimitrov', permission: 'admin' }, - ], + users: [{ username: 'rdimitrov', permission: 'admin' }], }, { repository: 'static', @@ -322,9 +310,7 @@ export const REPOSITORY_ACCESS: RepositoryAccess[] = [ }, { repository: 'ext-auth', - teams: [ - { team: 'auth-wg', permission: 'admin' }, - ], + teams: [{ team: 'auth-wg', permission: 'admin' }], }, ]; diff --git a/src/config/users.ts b/src/config/users.ts index b0e6ae9..da7a07c 100644 --- a/src/config/users.ts +++ b/src/config/users.ts @@ -97,7 +97,19 @@ export const MEMBERS: readonly Member[] = [ { github: 'dsp-ant', email: 'david@modelcontextprotocol.io', - memberOf: ['auth-wg', 'core-maintainers', 'docs-maintaners', 'go-sdk', 'ig-financial-services', 'moderators', 'php-sdk', 'python-sdk', 'security-wg', 'transport-wg', 'typescript-sdk'], + memberOf: [ + 'auth-wg', + 'core-maintainers', + 'docs-maintaners', + 'go-sdk', + 'ig-financial-services', + 'moderators', + 'php-sdk', + 'python-sdk', + 'security-wg', + 'transport-wg', + 'typescript-sdk', + ], }, { github: 'e5l', @@ -242,7 +254,14 @@ export const MEMBERS: readonly Member[] = [ }, { github: 'pcarleton', - memberOf: ['core-maintainers', 'python-sdk', 'python-sdk-auth', 'typescript-sdk', 'typescript-sdk-auth', 'auth-wg'], + memberOf: [ + 'core-maintainers', + 'python-sdk', + 'python-sdk-auth', + 'typescript-sdk', + 'typescript-sdk-auth', + 'auth-wg', + ], }, { github: 'pederhp', diff --git a/src/config/utils.ts b/src/config/utils.ts index 241b86f..fd0112a 100644 --- a/src/config/utils.ts +++ b/src/config/utils.ts @@ -10,10 +10,10 @@ export function defineGroups< const T extends readonly { name: Lowercase; description: string; - memberOf?: readonly (T[number]['name'])[]; + memberOf?: readonly T[number]['name'][]; isEmailGroup?: boolean; onlyOnPlatforms?: readonly Platform[]; - }[] + }[], >(groups: T) { for (const group of groups) { if (!isValidGroupName(group.name)) { @@ -40,4 +40,4 @@ export interface Member { github?: string; email?: string; memberOf: readonly GroupKey[]; -} \ No newline at end of file +} diff --git a/src/google.ts b/src/google.ts index 503ded0..96c7d7c 100644 --- a/src/google.ts +++ b/src/google.ts @@ -29,16 +29,17 @@ GROUPS.forEach((group: Group) => { // Email groups allow anyone (including externals) to post // Non-email groups are not intended as mailing lists, so use the most restrictive settings // whoCanViewGroup is badly named, but actually means 'Permissions to view group messages'. See https://developers.google.com/workspace/admin/groups-settings/v1/reference/groups - ...(group.isEmailGroup ? { - whoCanPostMessage: 'ANYONE_CAN_POST', - whoCanContactOwner: 'ALL_OWNERS_CAN_CONTACT', - whoCanViewGroup: 'ALL_MEMBERS_CAN_VIEW', - } : { - whoCanPostMessage: 'ALL_OWNERS_CAN_POST', - whoCanContactOwner: 'ALL_OWNERS_CAN_CONTACT', - whoCanViewGroup: 'ALL_OWNERS_CAN_VIEW', - }), - + ...(group.isEmailGroup + ? { + whoCanPostMessage: 'ANYONE_CAN_POST', + whoCanContactOwner: 'ALL_OWNERS_CAN_CONTACT', + whoCanViewGroup: 'ALL_MEMBERS_CAN_VIEW', + } + : { + whoCanPostMessage: 'ALL_OWNERS_CAN_POST', + whoCanContactOwner: 'ALL_OWNERS_CAN_CONTACT', + whoCanViewGroup: 'ALL_OWNERS_CAN_VIEW', + }), }); group.memberOf?.forEach((parentGroupKey) => { diff --git a/tsconfig.json b/tsconfig.json index 4b8e53f..09e8d66 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -13,4 +13,4 @@ }, "include": ["src/**/*"], "exclude": ["node_modules"] -} \ No newline at end of file +}