Files
gh-anton-abyzov-specweave-p…/commands/specweave-ado-import-projects.md
2025-11-29 17:56:16 +08:00

332 lines
9.5 KiB
Markdown

---
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<string, string[]> = {};
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.