Skip to content

Commit b7570b8

Browse files
authored
chore(repo): Enhance E2E cleanup script (#6870)
1 parent 680da44 commit b7570b8

File tree

1 file changed

+103
-34
lines changed

1 file changed

+103
-34
lines changed

integration/cleanup/cleanup.setup.ts

Lines changed: 103 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -15,20 +15,37 @@ setup('cleanup instances ', async () => {
1515
}
1616
const parsedPk = parsePublishableKey(pk);
1717
const apiUrl = isStaging(parsedPk.frontendApi) ? 'https://api.clerkstage.dev' : 'https://api.clerk.com';
18-
return { secretKey, apiUrl };
18+
return {
19+
secretKey,
20+
apiUrl,
21+
instanceName: parsedPk.instanceId || parsedPk.frontendApi.split('.')[0] || 'unknown',
22+
};
1923
})
2024
.filter(Boolean);
2125

22-
const errors: Array<{ instance: string; error: Error; operation: string }> = [];
26+
const cleanupSummary: Array<{
27+
instanceName: string;
28+
usersDeleted: number;
29+
orgsDeleted: number;
30+
errors: string[];
31+
status: 'success' | 'error' | 'unauthorized';
32+
}> = [];
33+
34+
console.log('🧹 Starting E2E Test Cleanup Process...\n');
2335

2436
for (const entry of entries) {
25-
const instanceKey = entry.secretKey.replace(/(sk_(test|live)_)(.+)(...)/, '$1***$4');
26-
console.log(`Cleanup for ${instanceKey}`);
37+
const instanceSummary = {
38+
instanceName: entry.instanceName,
39+
usersDeleted: 0,
40+
orgsDeleted: 0,
41+
errors: [] as string[],
42+
status: 'success' as 'success' | 'error' | 'unauthorized',
43+
};
2744

2845
try {
2946
const clerkClient = createClerkClient({ secretKey: entry.secretKey, apiUrl: entry.apiUrl });
3047

31-
// Get users
48+
// Get users with error handling
3249
let users: any[] = [];
3350
try {
3451
const { data: usersWithEmail } = await clerkClient.users.getUserList({
@@ -43,14 +60,19 @@ setup('cleanup instances ', async () => {
4360
limit: 150,
4461
});
4562

46-
users = [...usersWithEmail, ...usersWithPhoneNumber];
63+
// Deduplicate users by ID
64+
const allUsersMap = new Map();
65+
[...usersWithEmail, ...usersWithPhoneNumber].forEach(user => {
66+
allUsersMap.set(user.id, user);
67+
});
68+
users = Array.from(allUsersMap.values());
4769
} catch (error) {
48-
errors.push({ instance: instanceKey, error: error as Error, operation: 'getUserList' });
49-
console.error(`Error getting users for ${instanceKey}:`, error);
70+
instanceSummary.errors.push(`Failed to get users: ${error.message}`);
71+
console.error(`Error getting users for ${entry.instanceName}:`, error);
5072
users = []; // Continue with empty users list
5173
}
5274

53-
// Get organizations
75+
// Get organizations with error handling
5476
let orgs: any[] = [];
5577
try {
5678
const { data: orgsData } = await clerkClient.organizations.getOrganizationList({
@@ -63,16 +85,16 @@ setup('cleanup instances ', async () => {
6385
if (isClerkAPIResponseError(error) && (error.status === 404 || error.status === 403)) {
6486
orgs = [];
6587
} else {
66-
errors.push({ instance: instanceKey, error: error as Error, operation: 'getOrganizationList' });
67-
console.error(`Error getting organizations for ${instanceKey}:`, error);
88+
instanceSummary.errors.push(`Failed to get organizations: ${error.message}`);
89+
console.error(`Error getting organizations for ${entry.instanceName}:`, error);
6890
orgs = []; // Continue with empty orgs list
6991
}
7092
}
7193

7294
const usersToDelete = batchElements(skipObjectsThatWereCreatedWithinTheLast10Minutes(users), 5);
7395
const orgsToDelete = batchElements(skipObjectsThatWereCreatedWithinTheLast10Minutes(orgs), 5);
7496

75-
// Delete users
97+
// Delete users with tracking
7698
for (const batch of usersToDelete) {
7799
console.log(`Starting user deletion batch...`);
78100
await Promise.all(
@@ -82,47 +104,94 @@ setup('cleanup instances ', async () => {
82104
user.createdAt,
83105
).toISOString()})`,
84106
);
85-
return clerkClient.users.deleteUser(user.id).catch(error => {
86-
console.error(`Error deleting user ${user.id}:`, error);
87-
});
107+
return clerkClient.users
108+
.deleteUser(user.id)
109+
.then(() => {
110+
instanceSummary.usersDeleted++;
111+
})
112+
.catch(error => {
113+
if (error.status !== 404) {
114+
instanceSummary.errors.push(`User ${user.id}: ${error.message}`);
115+
console.error(`Error deleting user ${user.id}:`, error);
116+
}
117+
});
88118
}),
89119
);
90120
await new Promise(r => setTimeout(r, 1000));
91121
}
92122

93-
// Delete organizations
123+
// Delete organizations with tracking
94124
for (const batch of orgsToDelete) {
95125
console.log(`Starting organization deletion batch...`);
96126
await Promise.all(
97127
batch.map(org => {
98128
console.log(`Cleaning up org ${org.id} (${org.name}) (${new Date(org.createdAt).toISOString()})`);
99-
return clerkClient.organizations.deleteOrganization(org.id).catch(error => {
100-
console.error(`Error deleting org ${org.id}:`, error);
101-
});
129+
return clerkClient.organizations
130+
.deleteOrganization(org.id)
131+
.then(() => {
132+
instanceSummary.orgsDeleted++;
133+
})
134+
.catch(error => {
135+
if (error.status !== 404) {
136+
instanceSummary.errors.push(`Org ${org.id}: ${error.message}`);
137+
console.error(`Error deleting org ${org.id}:`, error);
138+
}
139+
});
102140
}),
103141
);
104142
await new Promise(r => setTimeout(r, 1000));
105143
}
144+
145+
// Report instance results
146+
const maskedKey = entry.secretKey.replace(/(sk_(test|live)_)(.+)(...)/, '$1***$4');
147+
if (instanceSummary.usersDeleted > 0 || instanceSummary.orgsDeleted > 0) {
148+
console.log(
149+
`✅ ${entry.instanceName} (${maskedKey}): ${instanceSummary.usersDeleted} users, ${instanceSummary.orgsDeleted} orgs deleted`,
150+
);
151+
} else {
152+
console.log(`✅ ${entry.instanceName} (${maskedKey}): clean`);
153+
}
154+
155+
if (instanceSummary.errors.length > 0) {
156+
instanceSummary.status = 'error';
157+
}
106158
} catch (error) {
107-
errors.push({ instance: instanceKey, error: error as Error, operation: 'general' });
108-
console.error(`General error during cleanup for ${instanceKey}:`, error);
159+
const maskedKey = entry.secretKey.replace(/(sk_(test|live)_)(.+)(...)/, '$1***$4');
160+
if (isClerkAPIResponseError(error) && (error.status === 401 || error.status === 403)) {
161+
console.log(`🔒 ${entry.instanceName} (${maskedKey}): Unauthorized access`);
162+
instanceSummary.status = 'unauthorized';
163+
} else {
164+
console.log(`❌ ${entry.instanceName} (${maskedKey}): ${error.message}`);
165+
instanceSummary.errors.push(error.message);
166+
instanceSummary.status = 'error';
167+
}
109168
}
169+
170+
cleanupSummary.push(instanceSummary);
110171
}
111172

112-
// Report all errors at the end
113-
if (errors.length > 0) {
114-
console.log('\n=== CLEANUP ERRORS SUMMARY ===');
115-
errors.forEach(({ instance, error, operation }) => {
116-
console.log(`Instance: ${instance}`);
117-
console.log(`Operation: ${operation}`);
118-
console.log(`Error: ${error.message}`);
119-
if (isClerkAPIResponseError(error)) {
120-
console.log(`Status: ${error.status}`);
121-
}
122-
console.log('---');
173+
// Final summary
174+
const totalUsersDeleted = cleanupSummary.reduce((sum, instance) => sum + instance.usersDeleted, 0);
175+
const totalOrgsDeleted = cleanupSummary.reduce((sum, instance) => sum + instance.orgsDeleted, 0);
176+
const errorInstances = cleanupSummary.filter(instance => instance.status === 'error').length;
177+
const unauthorizedInstances = cleanupSummary.filter(instance => instance.status === 'unauthorized').length;
178+
179+
console.log(`\n📊 Summary: ${totalUsersDeleted} users, ${totalOrgsDeleted} orgs deleted`);
180+
if (errorInstances > 0 || unauthorizedInstances > 0) {
181+
console.log(` ${errorInstances} errors, ${unauthorizedInstances} unauthorized`);
182+
}
183+
184+
// Detailed error report
185+
const instancesWithErrors = cleanupSummary.filter(instance => instance.errors.length > 0);
186+
if (instancesWithErrors.length > 0) {
187+
console.log('\n=== DETAILED ERROR REPORT ===');
188+
instancesWithErrors.forEach(instance => {
189+
console.log(`\n${instance.instanceName}:`);
190+
instance.errors.forEach(error => console.log(` - ${error}`));
123191
});
124-
console.log(`Total errors: ${errors.length}`);
125-
} else {
192+
}
193+
194+
if (errorInstances === 0 && unauthorizedInstances === 0) {
126195
console.log('\n✅ Cleanup completed successfully with no errors');
127196
}
128197
});

0 commit comments

Comments
 (0)