Initial commit
This commit is contained in:
906
skills/ado-resource-validator/SKILL.md
Normal file
906
skills/ado-resource-validator/SKILL.md
Normal file
@@ -0,0 +1,906 @@
|
||||
---
|
||||
name: ado-resource-validator
|
||||
description: Validates Azure DevOps projects and resources exist, creates missing resources automatically. Smart enough to prompt user to select existing or create new projects. Supports multiple projects for project-per-team strategy, area paths for area-path-based strategy, and teams for team-based strategy. NEW - Per-project configuration support - AZURE_DEVOPS_AREA_PATHS_{ProjectName} and AZURE_DEVOPS_TEAMS_{ProjectName} for hierarchical organization. Activates for ado setup, ado validation, ado configuration, missing ado project, azure devops .env setup, per-project area paths, per-project teams.
|
||||
allowed-tools: Read, Bash, Write, Edit
|
||||
---
|
||||
|
||||
# Azure DevOps Resource Validator Skill
|
||||
|
||||
**Purpose**: Validate and auto-create Azure DevOps projects and resources, ensuring .env configuration is correct.
|
||||
|
||||
**Auto-Activation**: Triggers when Azure DevOps setup or validation is needed.
|
||||
|
||||
## What This Skill Does
|
||||
|
||||
This skill ensures your Azure DevOps configuration in `.env` is valid and all resources exist. It's **smart enough** to:
|
||||
|
||||
1. **Validate Azure DevOps projects** - Check if projects exist (multiple for project-per-team)
|
||||
2. **Prompt for action** - Select existing project or create new one
|
||||
3. **Validate area paths** - Check if area paths exist (for area-path-based strategy)
|
||||
4. **Create missing area paths** - Auto-create area paths if missing
|
||||
5. **Validate teams** - Check if teams exist (for team-based strategy)
|
||||
6. **Update .env with correct values** - Ensure configuration is valid
|
||||
|
||||
## When This Skill Activates
|
||||
|
||||
✅ **Automatically activates when**:
|
||||
- You set up Azure DevOps integration for the first time
|
||||
- You run `/specweave-ado:sync` and resources are missing
|
||||
- Your `.env` has invalid Azure DevOps configuration
|
||||
- You mention "ado setup" or "azure devops validation"
|
||||
|
||||
## Azure DevOps Configuration Structure
|
||||
|
||||
### Required .env Variables
|
||||
|
||||
```bash
|
||||
AZURE_DEVOPS_PAT=your_token_here
|
||||
AZURE_DEVOPS_ORG=yourorganization
|
||||
AZURE_DEVOPS_STRATEGY=project-per-team # or area-path-based, team-based
|
||||
```
|
||||
|
||||
### Strategy-Specific Variables
|
||||
|
||||
**Strategy 1: Project-per-team** (Multiple Projects)
|
||||
```bash
|
||||
AZURE_DEVOPS_STRATEGY=project-per-team
|
||||
AZURE_DEVOPS_PROJECTS=WebApp,MobileApp,Platform
|
||||
```
|
||||
→ Validates that WebApp, MobileApp, and Platform projects exist
|
||||
|
||||
**Strategy 2: Area-path-based** (One Project, Multiple Area Paths)
|
||||
```bash
|
||||
AZURE_DEVOPS_STRATEGY=area-path-based
|
||||
AZURE_DEVOPS_PROJECT=MainProduct
|
||||
AZURE_DEVOPS_AREA_PATHS=Frontend,Backend,Mobile
|
||||
```
|
||||
→ Validates MainProduct project exists
|
||||
→ Creates area paths if missing: MainProduct\Frontend, MainProduct\Backend, MainProduct\Mobile
|
||||
|
||||
**Strategy 3: Team-based** (One Project, Multiple Teams)
|
||||
```bash
|
||||
AZURE_DEVOPS_STRATEGY=team-based
|
||||
AZURE_DEVOPS_PROJECT=MainProduct
|
||||
AZURE_DEVOPS_TEAMS=Alpha Team,Beta Team,Gamma Team
|
||||
```
|
||||
→ Validates MainProduct project exists
|
||||
→ Creates teams if missing: Alpha Team, Beta Team, Gamma Team
|
||||
|
||||
**NEW: Per-Project Configuration** (Advanced - Multiple Projects × Resources)
|
||||
```bash
|
||||
# Multiple projects with their own area paths and teams
|
||||
AZURE_DEVOPS_STRATEGY=project-per-team
|
||||
AZURE_DEVOPS_PROJECTS=Backend,Frontend,Mobile
|
||||
|
||||
# Per-project area paths (hierarchical naming)
|
||||
AZURE_DEVOPS_AREA_PATHS_Backend=API,Database,Cache
|
||||
AZURE_DEVOPS_AREA_PATHS_Frontend=Web,Admin,Public
|
||||
AZURE_DEVOPS_AREA_PATHS_Mobile=iOS,Android,Shared
|
||||
|
||||
# Per-project teams (optional)
|
||||
AZURE_DEVOPS_TEAMS_Backend=Alpha,Beta
|
||||
AZURE_DEVOPS_TEAMS_Frontend=Gamma
|
||||
```
|
||||
→ Validates 3 projects exist: Backend, Frontend, Mobile
|
||||
→ Creates area paths per project:
|
||||
- Backend\API, Backend\Database, Backend\Cache
|
||||
- Frontend\Web, Frontend\Admin, Frontend\Public
|
||||
- Mobile\iOS, Mobile\Android, Mobile\Shared
|
||||
→ Creates teams per project:
|
||||
- Backend: Alpha, Beta
|
||||
- Frontend: Gamma
|
||||
|
||||
**Naming Convention**: `{PROVIDER}_{RESOURCE_TYPE}_{PROJECT_NAME}`
|
||||
|
||||
## Validation Flow
|
||||
|
||||
### Step 1: Strategy Detection
|
||||
|
||||
**Read .env and detect strategy**:
|
||||
```bash
|
||||
AZURE_DEVOPS_STRATEGY=project-per-team
|
||||
```
|
||||
|
||||
**Result**:
|
||||
```
|
||||
🔍 Detected strategy: Project-per-team
|
||||
Projects to validate: WebApp, MobileApp, Platform
|
||||
```
|
||||
|
||||
### Step 2: Project Validation (Project-per-team)
|
||||
|
||||
**Check if projects exist**:
|
||||
```bash
|
||||
# API calls to Azure DevOps
|
||||
GET https://dev.azure.com/{org}/_apis/projects/WebApp
|
||||
GET https://dev.azure.com/{org}/_apis/projects/MobileApp
|
||||
GET https://dev.azure.com/{org}/_apis/projects/Platform
|
||||
```
|
||||
|
||||
**If all projects exist**:
|
||||
```
|
||||
✅ All projects validated:
|
||||
• WebApp (ID: abcd1234)
|
||||
• MobileApp (ID: efgh5678)
|
||||
• Platform (ID: ijkl9012)
|
||||
```
|
||||
|
||||
**If some projects don't exist**:
|
||||
```
|
||||
⚠️ Projects not found:
|
||||
✅ WebApp (exists)
|
||||
❌ MobileApp (not found)
|
||||
❌ Platform (not found)
|
||||
|
||||
What would you like to do?
|
||||
1. Create missing projects
|
||||
2. Select existing projects
|
||||
3. Fix project names manually
|
||||
4. Cancel
|
||||
|
||||
Your choice [1]:
|
||||
```
|
||||
|
||||
**Option 1: Create Missing Projects**:
|
||||
```
|
||||
📦 Creating Azure DevOps projects...
|
||||
|
||||
Creating project: MobileApp...
|
||||
✅ Project created: MobileApp (ID: mnop3456)
|
||||
|
||||
Creating project: Platform...
|
||||
✅ Project created: Platform (ID: qrst7890)
|
||||
|
||||
✅ All projects now exist!
|
||||
```
|
||||
|
||||
**Option 2: Select Existing Projects**:
|
||||
```
|
||||
Available projects in organization:
|
||||
1. WebApp
|
||||
2. ApiGateway
|
||||
3. AuthService
|
||||
4. NotificationService
|
||||
5. DataPipeline
|
||||
|
||||
Select projects (comma-separated numbers) [2,3]:
|
||||
|
||||
✅ Updated .env: AZURE_DEVOPS_PROJECTS=WebApp,ApiGateway,AuthService
|
||||
```
|
||||
|
||||
### Step 3: Area Path Validation (Area-path-based)
|
||||
|
||||
**Scenario**: One project with area paths
|
||||
```bash
|
||||
AZURE_DEVOPS_STRATEGY=area-path-based
|
||||
AZURE_DEVOPS_PROJECT=MainProduct
|
||||
AZURE_DEVOPS_AREA_PATHS=Frontend,Backend,Mobile,QA
|
||||
```
|
||||
|
||||
**Validation**:
|
||||
```
|
||||
Checking project: MainProduct...
|
||||
✅ Project "MainProduct" exists
|
||||
|
||||
Checking area paths...
|
||||
✅ MainProduct\Frontend (exists)
|
||||
✅ MainProduct\Backend (exists)
|
||||
⚠️ MainProduct\Mobile (not found)
|
||||
⚠️ MainProduct\QA (not found)
|
||||
|
||||
📦 Creating missing area paths...
|
||||
✅ Created: MainProduct\Mobile
|
||||
✅ Created: MainProduct\QA
|
||||
|
||||
✅ All area paths validated/created successfully
|
||||
```
|
||||
|
||||
### Step 4: Team Validation (Team-based)
|
||||
|
||||
**Scenario**: One project with multiple teams
|
||||
```bash
|
||||
AZURE_DEVOPS_STRATEGY=team-based
|
||||
AZURE_DEVOPS_PROJECT=MainProduct
|
||||
AZURE_DEVOPS_TEAMS=Alpha Team,Beta Team,Gamma Team
|
||||
```
|
||||
|
||||
**Validation**:
|
||||
```
|
||||
Checking project: MainProduct...
|
||||
✅ Project "MainProduct" exists
|
||||
|
||||
Checking teams...
|
||||
✅ Alpha Team (exists)
|
||||
⚠️ Beta Team (not found)
|
||||
⚠️ Gamma Team (not found)
|
||||
|
||||
📦 Creating missing teams...
|
||||
✅ Created: Beta Team
|
||||
✅ Created: Gamma Team
|
||||
|
||||
✅ All teams validated/created successfully
|
||||
```
|
||||
|
||||
## Usage Examples
|
||||
|
||||
### Example 1: Fresh Azure DevOps Setup (Project-per-team)
|
||||
|
||||
**Scenario**: New setup with multiple projects for different teams
|
||||
|
||||
**Action**: Run `/specweave-ado:sync`
|
||||
|
||||
**What Happens**:
|
||||
```bash
|
||||
🔍 Validating Azure DevOps configuration...
|
||||
|
||||
Strategy: Project-per-team
|
||||
Checking projects: WebApp, MobileApp, Platform...
|
||||
|
||||
⚠️ Projects not found:
|
||||
• WebApp
|
||||
• MobileApp
|
||||
• Platform
|
||||
|
||||
What would you like to do?
|
||||
1. Create new projects
|
||||
2. Select existing projects
|
||||
3. Cancel
|
||||
|
||||
Your choice [1]: 1
|
||||
|
||||
📦 Creating Azure DevOps projects...
|
||||
|
||||
Creating project: WebApp
|
||||
Description: Web application frontend
|
||||
Process template: Agile
|
||||
✅ Created: WebApp (ID: proj-001)
|
||||
|
||||
Creating project: MobileApp
|
||||
Description: Mobile application
|
||||
Process template: Agile
|
||||
✅ Created: MobileApp (ID: proj-002)
|
||||
|
||||
Creating project: Platform
|
||||
Description: Backend platform services
|
||||
Process template: Agile
|
||||
✅ Created: Platform (ID: proj-003)
|
||||
|
||||
🎉 Azure DevOps configuration complete! All resources ready.
|
||||
```
|
||||
|
||||
### Example 2: Migrate from Single to Multi-Project
|
||||
|
||||
**Scenario**: Currently using single project, want to split into multiple
|
||||
|
||||
**Current .env**:
|
||||
```bash
|
||||
AZURE_DEVOPS_PROJECT=MainProduct
|
||||
```
|
||||
|
||||
**New .env**:
|
||||
```bash
|
||||
AZURE_DEVOPS_STRATEGY=project-per-team
|
||||
AZURE_DEVOPS_PROJECTS=MainProduct-Frontend,MainProduct-Backend,MainProduct-Mobile
|
||||
```
|
||||
|
||||
**What Happens**:
|
||||
```bash
|
||||
🔍 Detected strategy change: team-based → project-per-team
|
||||
|
||||
Validating new projects...
|
||||
✅ MainProduct-Frontend (exists from previous split)
|
||||
⚠️ MainProduct-Backend (not found)
|
||||
⚠️ MainProduct-Mobile (not found)
|
||||
|
||||
Would you like to:
|
||||
1. Create missing projects
|
||||
2. Keep single project with area paths instead
|
||||
3. Cancel
|
||||
|
||||
Your choice [1]: 1
|
||||
|
||||
📦 Creating projects...
|
||||
✅ Created: MainProduct-Backend
|
||||
✅ Created: MainProduct-Mobile
|
||||
|
||||
💡 Tip: You can now organize specs by project:
|
||||
.specweave/docs/internal/specs/MainProduct-Frontend/
|
||||
.specweave/docs/internal/specs/MainProduct-Backend/
|
||||
.specweave/docs/internal/specs/MainProduct-Mobile/
|
||||
```
|
||||
|
||||
### Example 3: Area Path Setup
|
||||
|
||||
**Scenario**: Large monolithic project with area-based organization
|
||||
|
||||
**Action**: Setup area paths for team organization
|
||||
|
||||
**What Happens**:
|
||||
```bash
|
||||
🔍 Validating Azure DevOps configuration...
|
||||
|
||||
Strategy: Area-path-based
|
||||
Project: EnterpriseApp
|
||||
Area Paths: Core, UserManagement, Billing, Reports, Analytics
|
||||
|
||||
Checking project: EnterpriseApp...
|
||||
✅ Project exists
|
||||
|
||||
Checking area paths...
|
||||
✅ EnterpriseApp\Core
|
||||
✅ EnterpriseApp\UserManagement
|
||||
⚠️ EnterpriseApp\Billing (not found)
|
||||
⚠️ EnterpriseApp\Reports (not found)
|
||||
⚠️ EnterpriseApp\Analytics (not found)
|
||||
|
||||
📦 Creating area paths...
|
||||
|
||||
Creating: EnterpriseApp\Billing
|
||||
✅ Area path created with default team
|
||||
|
||||
Creating: EnterpriseApp\Reports
|
||||
✅ Area path created with default team
|
||||
|
||||
Creating: EnterpriseApp\Analytics
|
||||
✅ Area path created with default team
|
||||
|
||||
✅ All area paths ready!
|
||||
|
||||
Work items will be organized by area:
|
||||
• Billing features → EnterpriseApp\Billing
|
||||
• Report features → EnterpriseApp\Reports
|
||||
• Analytics features → EnterpriseApp\Analytics
|
||||
```
|
||||
|
||||
## Implementation Details
|
||||
|
||||
**Location**: `src/utils/external-resource-validator.ts`
|
||||
|
||||
**Core Classes**:
|
||||
```typescript
|
||||
// Main validator class
|
||||
export class AzureDevOpsResourceValidator {
|
||||
private pat: string;
|
||||
private organization: string;
|
||||
private envPath: string;
|
||||
|
||||
constructor(envPath: string = '.env') {
|
||||
this.envPath = envPath;
|
||||
const env = this.loadEnv();
|
||||
this.pat = env.AZURE_DEVOPS_PAT || '';
|
||||
this.organization = env.AZURE_DEVOPS_ORG || '';
|
||||
}
|
||||
|
||||
// Main validation entry point
|
||||
async validate(): Promise<AzureDevOpsValidationResult> {
|
||||
const env = this.loadEnv();
|
||||
const strategy = env.AZURE_DEVOPS_STRATEGY || 'project-per-team';
|
||||
|
||||
// Validate based on strategy
|
||||
if (strategy === 'project-per-team') {
|
||||
return this.validateMultipleProjects(projectNames);
|
||||
} else if (strategy === 'area-path-based') {
|
||||
return this.validateAreaPaths(projectName, areaPaths);
|
||||
} else if (strategy === 'team-based') {
|
||||
return this.validateTeams(projectName, teams);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Public API function
|
||||
export async function validateAzureDevOpsResources(
|
||||
envPath: string = '.env'
|
||||
): Promise<AzureDevOpsValidationResult> {
|
||||
const validator = new AzureDevOpsResourceValidator(envPath);
|
||||
return validator.validate();
|
||||
}
|
||||
```
|
||||
|
||||
**Key Implementation Features**:
|
||||
|
||||
1. **Async Project Creation** (ADO-specific):
|
||||
```typescript
|
||||
// ADO creates projects asynchronously - need to poll for completion
|
||||
async createProject(name: string): Promise<AzureDevOpsProject> {
|
||||
const result = await this.callAzureDevOpsApi('projects?api-version=7.0', 'POST', body);
|
||||
|
||||
// Wait for project to be fully created (ADO async behavior)
|
||||
await this.waitForProjectCreation(result.id);
|
||||
|
||||
return { id: result.id, name, description };
|
||||
}
|
||||
|
||||
// Poll until project is in 'wellFormed' state
|
||||
private async waitForProjectCreation(projectId: string): Promise<void> {
|
||||
const maxAttempts = 30; // 30 seconds max wait
|
||||
for (let i = 0; i < maxAttempts; i++) {
|
||||
const project = await this.getProject(projectId);
|
||||
if (project.state === 'wellFormed') {
|
||||
return; // Project is ready!
|
||||
}
|
||||
await new Promise(resolve => setTimeout(resolve, 1000)); // Wait 1 second
|
||||
}
|
||||
throw new Error('Project creation timeout');
|
||||
}
|
||||
```
|
||||
|
||||
2. **Interactive Prompts** (when resources missing):
|
||||
```typescript
|
||||
const { action } = await inquirer.prompt([
|
||||
{
|
||||
type: 'select',
|
||||
name: 'action',
|
||||
message: `Project "${projectName}" not found. What would you like to do?`,
|
||||
choices: [
|
||||
{ name: 'Create new project', value: 'create' },
|
||||
{ name: 'Select existing project', value: 'select' },
|
||||
{ name: 'Skip this project', value: 'skip' },
|
||||
{ name: 'Cancel', value: 'cancel' }
|
||||
]
|
||||
}
|
||||
]);
|
||||
```
|
||||
|
||||
3. **Automatic .env Updates**:
|
||||
```typescript
|
||||
// After creating projects, update .env
|
||||
updateEnv(key: string, value: string): void {
|
||||
const envContent = fs.readFileSync(this.envPath, 'utf-8');
|
||||
const updated = envContent.replace(
|
||||
new RegExp(`^${key}=.*$`, 'm'),
|
||||
`${key}=${value}`
|
||||
);
|
||||
fs.writeFileSync(this.envPath, updated);
|
||||
}
|
||||
```
|
||||
|
||||
## CLI Command
|
||||
|
||||
**Automatic validation** (during setup):
|
||||
```bash
|
||||
# Runs automatically during specweave init
|
||||
npx specweave init
|
||||
|
||||
# Also runs automatically before sync
|
||||
/specweave-ado:sync 0014
|
||||
```
|
||||
|
||||
**Manual validation**:
|
||||
```bash
|
||||
# Via skill activation
|
||||
"Can you validate my Azure DevOps configuration?"
|
||||
|
||||
# Via TypeScript directly
|
||||
npx tsx -e "import { validateAzureDevOpsResources } from './dist/utils/external-resource-validator.js'; await validateAzureDevOpsResources();"
|
||||
|
||||
# Via CLI (future command - planned)
|
||||
specweave validate-ado
|
||||
```
|
||||
|
||||
**Validation output**:
|
||||
```typescript
|
||||
interface AzureDevOpsValidationResult {
|
||||
valid: boolean;
|
||||
strategy: 'project-per-team' | 'area-path-based' | 'team-based';
|
||||
projects: Array<{
|
||||
name: string;
|
||||
id: string;
|
||||
exists: boolean;
|
||||
}>;
|
||||
created: string[]; // Names of newly created resources
|
||||
envUpdated: boolean; // Whether .env was modified
|
||||
}
|
||||
|
||||
// Example output:
|
||||
{
|
||||
valid: true,
|
||||
strategy: 'project-per-team',
|
||||
projects: [
|
||||
{ name: 'WebApp', id: 'proj-001', exists: true },
|
||||
{ name: 'MobileApp', id: 'proj-002', exists: true, created: true },
|
||||
{ name: 'Platform', id: 'proj-003', exists: true, created: true }
|
||||
],
|
||||
created: ['MobileApp', 'Platform'],
|
||||
envUpdated: false
|
||||
}
|
||||
```
|
||||
|
||||
## Smart Project Detection
|
||||
|
||||
### Auto-detect Based on Work Item Patterns
|
||||
|
||||
The skill can intelligently suggest project organization based on your existing work items:
|
||||
|
||||
```typescript
|
||||
// Analyze existing work items
|
||||
const workItems = await analyzeWorkItems(org, project);
|
||||
|
||||
// Detect patterns
|
||||
const patterns = {
|
||||
byArea: workItems.groupBy('areaPath'), // Area-based organization
|
||||
byTeam: workItems.groupBy('assignedTeam'), // Team-based organization
|
||||
byType: workItems.groupBy('workItemType') // Type-based organization
|
||||
};
|
||||
|
||||
// Suggest strategy
|
||||
if (patterns.byArea.length > 3) {
|
||||
console.log('💡 Detected area-based organization');
|
||||
console.log(' Suggested strategy: area-path-based');
|
||||
} else if (patterns.byTeam.length > 2) {
|
||||
console.log('💡 Detected team-based organization');
|
||||
console.log(' Suggested strategy: team-based or project-per-team');
|
||||
}
|
||||
```
|
||||
|
||||
## Project Creation API
|
||||
|
||||
**Azure DevOps REST API** (v7.0):
|
||||
|
||||
### Create Project
|
||||
```bash
|
||||
POST https://dev.azure.com/{org}/_apis/projects?api-version=7.0
|
||||
Content-Type: application/json
|
||||
Authorization: Basic {base64(":PAT")}
|
||||
|
||||
{
|
||||
"name": "MobileApp",
|
||||
"description": "Mobile application project",
|
||||
"capabilities": {
|
||||
"versioncontrol": {
|
||||
"sourceControlType": "Git"
|
||||
},
|
||||
"processTemplate": {
|
||||
"templateTypeId": "adcc42ab-9882-485e-a3ed-7678f01f66bc" # Agile
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Response:
|
||||
{
|
||||
"id": "proj-002",
|
||||
"name": "MobileApp",
|
||||
"state": "wellFormed"
|
||||
}
|
||||
```
|
||||
|
||||
### Create Area Path
|
||||
```bash
|
||||
POST https://dev.azure.com/{org}/{project}/_apis/wit/classificationnodes/areas?api-version=7.0
|
||||
Content-Type: application/json
|
||||
|
||||
{
|
||||
"name": "Frontend",
|
||||
"attributes": {
|
||||
"startDate": null,
|
||||
"finishDate": null
|
||||
}
|
||||
}
|
||||
|
||||
Response:
|
||||
{
|
||||
"id": 123,
|
||||
"name": "Frontend",
|
||||
"path": "\\MainProduct\\Area\\Frontend"
|
||||
}
|
||||
```
|
||||
|
||||
### Create Team
|
||||
```bash
|
||||
POST https://dev.azure.com/{org}/_apis/projects/{projectId}/teams?api-version=7.0
|
||||
Content-Type: application/json
|
||||
|
||||
{
|
||||
"name": "Alpha Team",
|
||||
"description": "Alpha development team"
|
||||
}
|
||||
|
||||
Response:
|
||||
{
|
||||
"id": "team-001",
|
||||
"name": "Alpha Team",
|
||||
"projectName": "MainProduct"
|
||||
}
|
||||
```
|
||||
|
||||
## Configuration Examples
|
||||
|
||||
### Example 1: Microservices Architecture (Project-per-team)
|
||||
|
||||
**Before** (`.env`):
|
||||
```bash
|
||||
AZURE_DEVOPS_ORG=mycompany
|
||||
AZURE_DEVOPS_PAT=xxx
|
||||
```
|
||||
|
||||
**After validation**:
|
||||
```bash
|
||||
AZURE_DEVOPS_ORG=mycompany
|
||||
AZURE_DEVOPS_PAT=xxx
|
||||
AZURE_DEVOPS_STRATEGY=project-per-team
|
||||
AZURE_DEVOPS_PROJECTS=AuthService,UserService,PaymentService,NotificationService
|
||||
```
|
||||
|
||||
**Folder structure created**:
|
||||
```
|
||||
.specweave/docs/internal/specs/
|
||||
├── AuthService/
|
||||
│ └── spec-001-oauth-implementation.md
|
||||
├── UserService/
|
||||
│ └── spec-001-user-management.md
|
||||
├── PaymentService/
|
||||
│ └── spec-001-stripe-integration.md
|
||||
└── NotificationService/
|
||||
└── spec-001-email-notifications.md
|
||||
```
|
||||
|
||||
### Example 2: Monolithic Application (Area-path-based)
|
||||
|
||||
**Before** (`.env`):
|
||||
```bash
|
||||
AZURE_DEVOPS_PROJECT=ERP
|
||||
```
|
||||
|
||||
**After validation**:
|
||||
```bash
|
||||
AZURE_DEVOPS_ORG=enterprise
|
||||
AZURE_DEVOPS_PAT=xxx
|
||||
AZURE_DEVOPS_STRATEGY=area-path-based
|
||||
AZURE_DEVOPS_PROJECT=ERP
|
||||
AZURE_DEVOPS_AREA_PATHS=Finance,HR,Inventory,Sales,Reports
|
||||
```
|
||||
|
||||
**Work item organization**:
|
||||
```
|
||||
ERP
|
||||
├── Finance/ → Finance module features
|
||||
├── HR/ → HR module features
|
||||
├── Inventory/ → Inventory management
|
||||
├── Sales/ → Sales module features
|
||||
└── Reports/ → Reporting features
|
||||
```
|
||||
|
||||
### Example 3: Platform Teams (Team-based)
|
||||
|
||||
**Before** (`.env`):
|
||||
```bash
|
||||
AZURE_DEVOPS_PROJECT=Platform
|
||||
```
|
||||
|
||||
**After validation**:
|
||||
```bash
|
||||
AZURE_DEVOPS_ORG=techcorp
|
||||
AZURE_DEVOPS_PAT=xxx
|
||||
AZURE_DEVOPS_STRATEGY=team-based
|
||||
AZURE_DEVOPS_PROJECT=Platform
|
||||
AZURE_DEVOPS_TEAMS=Infrastructure,Security,Data,DevOps
|
||||
```
|
||||
|
||||
**Team assignments**:
|
||||
- Infrastructure Team → Cloud resources, networking
|
||||
- Security Team → Auth, compliance, auditing
|
||||
- Data Team → Databases, analytics, ML
|
||||
- DevOps Team → CI/CD, monitoring, tooling
|
||||
|
||||
## Error Handling
|
||||
|
||||
### Error 1: Invalid Credentials
|
||||
|
||||
**Symptom**: API calls fail with 401 Unauthorized
|
||||
|
||||
**Solution**:
|
||||
```
|
||||
❌ Azure DevOps API authentication failed
|
||||
|
||||
Please check:
|
||||
1. AZURE_DEVOPS_PAT is correct
|
||||
2. Token has not expired
|
||||
3. AZURE_DEVOPS_ORG is correct
|
||||
|
||||
Generate new token at:
|
||||
https://dev.azure.com/{org}/_usersSettings/tokens
|
||||
```
|
||||
|
||||
### Error 2: Insufficient Permissions
|
||||
|
||||
**Symptom**: Cannot create projects (403 Forbidden)
|
||||
|
||||
**Solution**:
|
||||
```
|
||||
❌ Insufficient permissions to create projects
|
||||
|
||||
You need:
|
||||
- Project Collection Administrator role (for creating projects)
|
||||
- Project Administrator role (for area paths and teams)
|
||||
|
||||
Contact your Azure DevOps administrator to request permissions.
|
||||
```
|
||||
|
||||
### Error 3: Project Name Conflicts
|
||||
|
||||
**Symptom**: Project creation fails (name exists)
|
||||
|
||||
**Solution**:
|
||||
```
|
||||
❌ Project name "WebApp" already exists
|
||||
|
||||
Options:
|
||||
1. Use a different project name
|
||||
2. Select the existing project
|
||||
3. Add a suffix (e.g., WebApp-v2)
|
||||
|
||||
Your choice [2]:
|
||||
```
|
||||
|
||||
### Error 4: Organization Limits
|
||||
|
||||
**Symptom**: Cannot create more projects
|
||||
|
||||
**Solution**:
|
||||
```
|
||||
❌ Organization project limit reached (250 projects)
|
||||
|
||||
Consider:
|
||||
1. Using area-path-based strategy (one project)
|
||||
2. Archiving old projects
|
||||
3. Upgrading organization plan
|
||||
|
||||
Contact Azure DevOps support for limit increases.
|
||||
```
|
||||
|
||||
## Integration with SpecWeave Workflow
|
||||
|
||||
### Automatic Validation
|
||||
|
||||
When using `/specweave-ado:sync`, validation runs automatically:
|
||||
|
||||
```bash
|
||||
/specweave-ado:sync 0014
|
||||
|
||||
# Internally calls:
|
||||
1. validateAzureDevOpsResources()
|
||||
2. Fix missing projects/area paths/teams
|
||||
3. Create folder structure for specs
|
||||
4. Proceed with sync
|
||||
```
|
||||
|
||||
### Manual Validation
|
||||
|
||||
Run validation independently:
|
||||
|
||||
```bash
|
||||
# Via skill
|
||||
"Validate my Azure DevOps configuration"
|
||||
|
||||
# Via TypeScript
|
||||
npx tsx src/utils/external-resource-validator.ts --provider=ado
|
||||
|
||||
# Via CLI (future)
|
||||
specweave validate-ado
|
||||
```
|
||||
|
||||
## Best Practices
|
||||
|
||||
✅ **Choose the right strategy**:
|
||||
- **Project-per-team**: Best for autonomous teams, microservices
|
||||
- **Area-path-based**: Best for monolithic apps, shared codebase
|
||||
- **Team-based**: Best for small organizations, simple structure
|
||||
|
||||
✅ **Use descriptive names**:
|
||||
```bash
|
||||
# Good
|
||||
AZURE_DEVOPS_PROJECTS=UserManagement,PaymentProcessing,NotificationEngine
|
||||
|
||||
# Bad
|
||||
AZURE_DEVOPS_PROJECTS=Proj1,Proj2,Proj3
|
||||
```
|
||||
|
||||
✅ **Document project mapping** (in README):
|
||||
```markdown
|
||||
## Azure DevOps Projects
|
||||
|
||||
- UserManagement: User authentication and profile management
|
||||
- PaymentProcessing: Payment gateway integrations
|
||||
- NotificationEngine: Email, SMS, and push notifications
|
||||
```
|
||||
|
||||
✅ **Keep .env in version control** (gitignored tokens):
|
||||
```bash
|
||||
# Commit project structure
|
||||
AZURE_DEVOPS_STRATEGY=project-per-team
|
||||
AZURE_DEVOPS_PROJECTS=WebApp,MobileApp,Platform
|
||||
|
||||
# Don't commit sensitive data
|
||||
AZURE_DEVOPS_PAT=<redacted>
|
||||
```
|
||||
|
||||
## Folder Organization
|
||||
|
||||
Based on strategy, the skill creates appropriate folder structure:
|
||||
|
||||
### Project-per-team Structure
|
||||
```
|
||||
.specweave/docs/internal/specs/
|
||||
├── WebApp/
|
||||
│ ├── spec-001-user-interface.md
|
||||
│ └── spec-002-responsive-design.md
|
||||
├── MobileApp/
|
||||
│ ├── spec-001-ios-features.md
|
||||
│ └── spec-002-android-features.md
|
||||
└── Platform/
|
||||
├── spec-001-api-design.md
|
||||
└── spec-002-database-schema.md
|
||||
```
|
||||
|
||||
### Area-path-based Structure
|
||||
```
|
||||
.specweave/docs/internal/specs/MainProduct/
|
||||
├── Frontend/
|
||||
│ └── spec-001-ui-components.md
|
||||
├── Backend/
|
||||
│ └── spec-001-api-endpoints.md
|
||||
└── Mobile/
|
||||
└── spec-001-mobile-sync.md
|
||||
```
|
||||
|
||||
### Team-based Structure
|
||||
```
|
||||
.specweave/docs/internal/specs/MainProduct/
|
||||
├── AlphaTeam/
|
||||
│ └── spec-001-feature-a.md
|
||||
├── BetaTeam/
|
||||
│ └── spec-001-feature-b.md
|
||||
└── GammaTeam/
|
||||
└── spec-001-feature-c.md
|
||||
```
|
||||
|
||||
## Key Differences from JIRA
|
||||
|
||||
**Azure DevOps vs JIRA Resource Creation**:
|
||||
|
||||
| Aspect | Azure DevOps | JIRA |
|
||||
|--------|-------------|------|
|
||||
| **Project Creation** | Asynchronous (polling required) | Synchronous (immediate) |
|
||||
| **Creation Time** | 5-30 seconds | <1 second |
|
||||
| **Status Tracking** | Poll `state` field ('wellFormed') | No polling needed |
|
||||
| **API Complexity** | Higher (async handling) | Lower (sync operations) |
|
||||
| **Board Creation** | Auto-created with project | Requires separate API call |
|
||||
| **Process Templates** | Required (Agile, Scrum, CMMI) | Not applicable |
|
||||
|
||||
**Why Async Matters**:
|
||||
|
||||
When you create an ADO project, the API returns immediately with `state: 'new'`, but the project isn't usable yet. The validator polls every 1 second (max 30 attempts) until `state: 'wellFormed'`:
|
||||
|
||||
```typescript
|
||||
// Create project (returns immediately)
|
||||
const project = await createProject('MobileApp'); // state: 'new'
|
||||
|
||||
// Poll until ready
|
||||
await waitForProjectCreation(project.id); // Polls until state: 'wellFormed'
|
||||
|
||||
// Now safe to use!
|
||||
console.log('✅ Project ready for work items');
|
||||
```
|
||||
|
||||
**Impact on UX**:
|
||||
- JIRA: "✅ Project created" (instant)
|
||||
- ADO: "📦 Creating project... ⏳ Waiting for Azure DevOps to complete setup... ✅ Project ready!" (5-30s)
|
||||
|
||||
## Summary
|
||||
|
||||
This skill ensures your Azure DevOps configuration is **always valid** by:
|
||||
|
||||
1. ✅ **Validating projects** - Check if projects exist, prompt to select or create
|
||||
2. ✅ **Supporting multiple strategies** - Project-per-team, area-path-based, team-based
|
||||
3. ✅ **Auto-creating resources** - Projects, area paths, teams (with async handling)
|
||||
4. ✅ **Organizing specs** - Create folder structure based on projects
|
||||
5. ✅ **Clear error messages** - Actionable guidance for all failures
|
||||
6. ✅ **Handles ADO async behavior** - Polls for project creation completion
|
||||
|
||||
**Result**: Zero manual Azure DevOps setup - system handles everything, including ADO's async project creation!
|
||||
|
||||
---
|
||||
|
||||
**Skill Version**: 1.1.0
|
||||
**Introduced**: SpecWeave v0.17.0
|
||||
**Last Updated**: 2025-11-11
|
||||
**Key Changes v1.1.0**: Added implementation details, async project creation handling, JIRA comparison
|
||||
Reference in New Issue
Block a user