organize-qa-personas.jsโข4.72 kB
#!/usr/bin/env node
/**
* Organize QA Test Personas into QA Subfolder
* Moves all test personas to personas/qa/ in GitHub repository
*/
const GITHUB_TOKEN = process.env.GITHUB_TEST_TOKEN || process.env.GITHUB_TOKEN;
const REPO = 'mickdarling/dollhouse-portfolio';
const API_BASE = 'https://api.github.com';
if (!GITHUB_TOKEN) {
console.error('โ No GitHub token found. Please set GITHUB_TEST_TOKEN or GITHUB_TOKEN');
process.exit(1);
}
async function githubRequest(path, method = 'GET', body = null) {
const url = `${API_BASE}${path}`;
const options = {
method,
headers: {
'Authorization': `Bearer ${GITHUB_TOKEN}`,
'Accept': 'application/vnd.github.v3+json',
'Content-Type': 'application/json',
'User-Agent': 'DollhouseMCP-QA-Organizer'
}
};
if (body) {
options.body = JSON.stringify(body);
}
const response = await fetch(url, options);
if (!response.ok) {
const error = await response.text();
throw new Error(`GitHub API error: ${response.status} - ${error}`);
}
return response.json();
}
async function organizeQAPersonas() {
console.log('\n๐ Organizing QA Test Personas in GitHub Repository\n');
console.log(`Repository: ${REPO}\n`);
try {
// Step 1: Get all personas
console.log('1๏ธโฃ Fetching personas from repository...');
const files = await githubRequest(`/repos/${REPO}/contents/personas`);
// Filter for test personas
const testPersonas = files.filter(file =>
file.name.includes('test-qa-') ||
file.name.startsWith('test-') ||
file.name === 'test.md'
);
console.log(` Found ${testPersonas.length} test personas to organize\n`);
if (testPersonas.length === 0) {
console.log('โ
No test personas to organize!');
return;
}
// Step 2: Create QA README
console.log('2๏ธโฃ Creating QA folder README...');
const readmeContent = `# QA Test Personas
This folder contains test personas created during QA testing of the DollhouseMCP portfolio sync functionality.
## Test Personas
These personas are used for automated testing and should not be used in production.
### Naming Convention
- \`test-qa-*\` - Automated QA test personas
- \`test-manual-*\` - Manual test personas
- \`test-*\` - General test personas
## Cleanup
These files can be safely deleted after testing is complete.
---
*Generated by QA test organization script*`;
const readmeBase64 = Buffer.from(readmeContent).toString('base64');
try {
await githubRequest(`/repos/${REPO}/contents/personas/qa/README.md`, 'PUT', {
message: 'Create QA folder with README',
content: readmeBase64,
branch: 'main'
});
console.log(' โ
Created personas/qa/README.md\n');
} catch (error) {
if (error.message.includes('422')) {
console.log(' โน๏ธ QA folder already exists\n');
} else {
throw error;
}
}
// Step 3: Move each test persona
console.log('3๏ธโฃ Moving test personas to QA folder...\n');
for (const persona of testPersonas) {
console.log(` Moving ${persona.name}...`);
try {
// Get the file content
const fileData = await githubRequest(`/repos/${REPO}/contents/personas/${persona.name}`);
// Create in new location
await githubRequest(`/repos/${REPO}/contents/personas/qa/${persona.name}`, 'PUT', {
message: `Move ${persona.name} to QA folder`,
content: fileData.content,
branch: 'main'
});
console.log(` โ
Created personas/qa/${persona.name}`);
// Delete from old location
await githubRequest(`/repos/${REPO}/contents/personas/${persona.name}`, 'DELETE', {
message: `Remove ${persona.name} from root (moved to QA folder)`,
sha: fileData.sha,
branch: 'main'
});
console.log(` โ
Removed personas/${persona.name}`);
console.log('');
// Rate limit delay
await new Promise(resolve => setTimeout(resolve, 1000));
} catch (error) {
console.error(` โ Error moving ${persona.name}: ${error.message}`);
}
}
// Step 4: Summary
console.log('\n๐ Organization Complete!\n');
console.log(`โ
Moved ${testPersonas.length} test personas to personas/qa/`);
console.log('\nYou can view them at:');
console.log(`https://github.com/${REPO}/tree/main/personas/qa`);
} catch (error) {
console.error('\nโ Error:', error.message);
process.exit(1);
}
}
// Run the script
organizeQAPersonas().catch(console.error);