From 9fe97a1d2af397ea21272f7baed479ff37718cdd Mon Sep 17 00:00:00 2001 From: David Soria Parra Date: Thu, 19 Feb 2026 23:41:53 +0000 Subject: [PATCH] fix: create OrgUnit resource before provisioning GWS users The orgUnitPath '/Model Context Protocol' was hardcoded but the OU didn't exist in Pulumi state, causing INVALID_OU_ID errors for all user creates/updates. Create it as a Pulumi resource and wire up dependsOn so users are provisioned after the OU exists. Co-Authored-By: Claude Opus 4.6 --- src/google.ts | 31 +++++++++++++++++++++---------- 1 file changed, 21 insertions(+), 10 deletions(-) diff --git a/src/google.ts b/src/google.ts index 43cce9a..c133c84 100644 --- a/src/google.ts +++ b/src/google.ts @@ -48,6 +48,13 @@ ROLES.forEach((role: Role) => { }); }); +// Create the organizational unit for MCP users +const mcpOrgUnit = new gworkspace.OrgUnit('mcp-org-unit', { + name: 'Model Context Protocol', + parentOrgUnitPath: '/', + description: 'Organizational unit for MCP team members (Managed by github.com/modelcontextprotocol/access)', +}); + // Provision Google Workspace user accounts for members in roles with provisionUser const provisionedUsersByEmail: Record = {}; const newUserPasswords: Record> = {}; @@ -76,9 +83,9 @@ MEMBERS.forEach((member) => { { primaryEmail, name: { familyName: member.lastName!, givenName: member.firstName! }, - orgUnitPath: '/Model Context Protocol', + orgUnitPath: mcpOrgUnit.orgUnitPath, }, - { import: primaryEmail } + { import: primaryEmail, dependsOn: [mcpOrgUnit] } ); provisionedUsersByEmail[primaryEmail] = user; } else { @@ -91,14 +98,18 @@ MEMBERS.forEach((member) => { crypto.createHash('sha1').update(plaintext).digest('hex') ); - const user = new gworkspace.User(`gws-user-${member.googleEmailPrefix}`, { - primaryEmail, - name: { familyName: member.lastName!, givenName: member.firstName! }, - password: hashedPassword, - hashFunction: 'SHA-1', - changePasswordAtNextLogin: true, - orgUnitPath: '/Model Context Protocol', - }); + const user = new gworkspace.User( + `gws-user-${member.googleEmailPrefix}`, + { + primaryEmail, + name: { familyName: member.lastName!, givenName: member.firstName! }, + password: hashedPassword, + hashFunction: 'SHA-1', + changePasswordAtNextLogin: true, + orgUnitPath: mcpOrgUnit.orgUnitPath, + }, + { dependsOn: [mcpOrgUnit] } + ); provisionedUsersByEmail[primaryEmail] = user; // Track password for export so an admin can retrieve it