--- name: specweave-ado:import-projects description: Import additional Azure DevOps projects post-init with area path mapping, filtering, and dry-run preview --- # Import Azure DevOps Projects Command You are an Azure DevOps project import expert. Help users add additional ADO projects to their SpecWeave workspace after initial setup. ## Purpose This command allows users to import additional Azure DevOps projects **after** initial SpecWeave setup (`specweave init`), with area path mapping, filtering, and dry-run preview. **Use Cases**: - Adding new ADO projects to existing workspace - Importing projects from different organizations - Selective import with area path granularity - Multi-project organization (Backend, Frontend, Mobile, Infrastructure) ## Command Syntax ```bash # Basic import (interactive) /specweave-ado:import-projects # With area path granularity /specweave-ado:import-projects --granularity two-level # Dry-run (preview) /specweave-ado:import-projects --dry-run # Resume interrupted import /specweave-ado:import-projects --resume # Combined /specweave-ado:import-projects --granularity top-level --dry-run ``` ## Your Task When the user runs this command: ### Step 1: Validate Prerequisites ```typescript import { readEnvFile, parseEnvFile } from '../../../src/utils/env-file.js'; // 1. Check if ADO credentials exist const envContent = readEnvFile(process.cwd()); const parsed = parseEnvFile(envContent); if (!parsed.AZURE_DEVOPS_PAT || !parsed.AZURE_DEVOPS_ORG) { console.log('āŒ Missing Azure DevOps credentials. Run `specweave init` first.'); return; } // 2. Get existing configuration const org = parsed.AZURE_DEVOPS_ORG; const existingProject = parsed.AZURE_DEVOPS_PROJECT; console.log(`\nšŸ“‹ Organization: ${org}`); console.log(` Current project: ${existingProject || 'None'}\n`); ``` ### Step 2: Fetch Available Projects ```typescript import { getProjectCount } from '../../../src/cli/helpers/project-count-fetcher.js'; import { AsyncProjectLoader } from '../../../src/cli/helpers/async-project-loader.js'; // Count check (< 1 second) const countResult = await getProjectCount({ provider: 'ado', credentials: { organization: org, pat: parsed.AZURE_DEVOPS_PAT } }); console.log(`āœ“ Found ${countResult.accessible} accessible project(s)`); // Fetch all projects (with smart pagination) const loader = new AsyncProjectLoader( { organization: org, pat: parsed.AZURE_DEVOPS_PAT }, 'ado', { batchSize: 50, updateFrequency: 5, showEta: true } ); const result = await loader.fetchAllProjects(countResult.accessible); const allProjects = result.projects; ``` ### Step 3: Area Path Mapping (Multi-Project Organization) ```typescript import { AreaPathMapper } from '../../../src/integrations/ado/area-path-mapper.js'; const { selectedProject } = await inquirer.prompt([{ type: 'select', name: 'selectedProject', message: 'Select ADO project to import area paths from:', choices: allProjects.map(p => ({ name: p.name, value: p.name })) }]); const mapper = new AreaPathMapper({ credentials: { organization: org, pat: parsed.AZURE_DEVOPS_PAT }, project: selectedProject }); // Fetch area path tree const areaPathTree = await mapper.fetchAreaPaths(); // Get granularity suggestion const suggestion = mapper.suggestGranularity(areaPathTree); console.log(`\nšŸ’” Suggestion: ${suggestion.suggested}`); console.log(` ${suggestion.reasoning}\n`); // Prompt for granularity (if not provided via CLI) const granularity = args.granularity || await mapper.promptAreaPathGranularity(areaPathTree); // Flatten area paths with selected granularity const areaPaths = mapper.flattenAreaPaths(areaPathTree, granularity); console.log(`\nšŸ“Š ${areaPaths.length} project(s) will be created from area paths:\n`); areaPaths.forEach(ap => { const projectId = mapper.mapToProjectId(ap.path); console.log(` ✨ ${ap.path} → ${projectId}`); }); ``` ### Step 4: Dry-Run or Execute ```typescript if (args.dryRun) { console.log('\nšŸ”Ž DRY RUN: No changes will be made.\n'); console.log('The following projects would be configured:'); areaPaths.forEach(ap => { const projectId = mapper.mapToProjectId(ap.path); console.log(` ✨ ${projectId} (${ap.path})`); }); console.log(`\nTotal: ${areaPaths.length} projects would be configured\n`); return; } // Confirm import const { confirmed } = await inquirer.prompt([{ type: 'confirm', name: 'confirmed', message: `Configure ${areaPaths.length} project(s) from area paths?`, default: true }]); if (!confirmed) { console.log('ā­ļø Import cancelled.'); return; } ``` ### Step 5: Update Configuration ```typescript import { getConfigManager } from '../../../src/core/config/index.js'; const configManager = getConfigManager(process.cwd()); // Build area path configuration const areaPathConfig: Record = {}; for (const ap of areaPaths) { const projectId = mapper.mapToProjectId(ap.path); areaPathConfig[projectId] = [ap.path]; } // Update configuration await configManager.update({ issueTracker: { provider: 'ado', ado: { organization: org, project: selectedProject, areaPathMapping: areaPathConfig, granularity } } }); // Update .env file import { updateEnvFile } from '../../../src/utils/env-manager.js'; await updateEnvFile('AZURE_DEVOPS_PROJECT', selectedProject); // Write area paths to .env (comma-separated) const areaPathList = areaPaths.map(ap => ap.path).join(','); await updateEnvFile('AZURE_DEVOPS_AREA_PATHS', areaPathList); console.log('\nāœ… Projects configured successfully!\n'); console.log(`Organization: ${org}`); console.log(`Project: ${selectedProject}`); console.log(`Granularity: ${granularity}`); console.log(`\nArea paths configured:\n ${areaPathList.split(',').join('\n ')}\n`); ``` ### Step 6: Resume Support ```typescript if (args.resume) { const { CacheManager } = await import('../../../src/core/cache/cache-manager.js'); const cacheManager = new CacheManager(process.cwd()); const importState = await cacheManager.get('ado-import-state'); if (!importState) { console.log('āš ļø No import state found. Use without --resume to start fresh.'); return; } console.log(`\nšŸ“‚ Resuming from: ${importState.lastAreaPath} (${importState.completed}/${importState.total})`); // Skip already-processed area paths const remainingPaths = areaPaths.filter(ap => !importState.processed.includes(ap.path)); // Continue import with remaining paths // (use same logic as Step 5) } ``` ## Examples ### Example 1: Basic Import with Area Paths **User**: `/specweave-ado:import-projects` **Output**: ``` šŸ“‹ Organization: mycompany Current project: Platform āœ“ Found 5 accessible project(s) Select ADO project to import area paths from: > Platform šŸ’” Suggestion: two-level Balanced hierarchy (8 two-level areas). Recommended granularity. Select area path granularity for project organization: > Two-level (8 projects) - e.g., Backend-API, Backend-Database šŸ“Š 8 project(s) will be created from area paths: ✨ Platform/Backend/API → backend-api ✨ Platform/Backend/Database → backend-database ✨ Platform/Frontend/Web → frontend-web ✨ Platform/Frontend/Admin → frontend-admin ✨ Platform/Mobile/iOS → mobile-ios ✨ Platform/Mobile/Android → mobile-android ✨ Platform/Infrastructure/Cloud → infrastructure-cloud ✨ Platform/Infrastructure/Network → infrastructure-network Configure 8 project(s) from area paths? (Y/n) āœ… Projects configured successfully! Organization: mycompany Project: Platform Granularity: two-level Area paths configured: Platform/Backend/API Platform/Backend/Database Platform/Frontend/Web Platform/Frontend/Admin Platform/Mobile/iOS Platform/Mobile/Android Platform/Infrastructure/Cloud Platform/Infrastructure/Network ``` ### Example 2: Top-Level Only **User**: `/specweave-ado:import-projects --granularity top-level` **Output**: ``` Select area path granularity: top-level (forced via CLI) šŸ“Š 3 project(s) will be created from area paths: ✨ Platform/Backend → backend ✨ Platform/Frontend → frontend ✨ Platform/Mobile → mobile ``` ### Example 3: Dry-Run **User**: `/specweave-ado:import-projects --dry-run` **Output**: ``` šŸ”Ž DRY RUN: No changes will be made. The following projects would be configured: ✨ backend-api (Platform/Backend/API) ✨ backend-database (Platform/Backend/Database) ✨ frontend-web (Platform/Frontend/Web) Total: 8 projects would be configured ``` ## Important Notes - **Multi-Project Organization**: Uses area paths to create logical project separation - **Granularity Control**: Top-level, two-level, or full-tree based on hierarchy complexity - **Atomic Updates**: Uses temp file + rename to prevent corruption - **Progress Tracking**: Shows progress bar for large hierarchies (> 50 area paths) - **Resume Support**: Interrupted imports can be resumed with `--resume` ## Related Commands - `/specweave:init` - Initial SpecWeave setup - `/specweave-ado:sync` - Sync increments with ADO work items - `/specweave-ado:refresh-cache` - Clear cached ADO data ## Error Handling - **Missing Credentials**: Prompt user to run `specweave init` first - **API Errors**: Show clear error message with suggestion - **No Area Paths**: Fallback to single-project mode - **Permission Errors**: Check ADO PAT scopes --- **Multi-Project Excellence**: This command enables sophisticated multi-project organization in Azure DevOps using area paths, perfect for large teams with complex hierarchies.