claude-autopm 2.7.0 → 2.8.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +307 -56
- package/autopm/.claude/.env +158 -0
- package/autopm/.claude/settings.local.json +9 -0
- package/bin/autopm.js +11 -2
- package/bin/commands/epic.js +23 -3
- package/bin/commands/plugin.js +395 -0
- package/bin/commands/team.js +184 -10
- package/install/install.js +223 -4
- package/lib/cli/commands/issue.js +360 -20
- package/lib/plugins/PluginManager.js +1328 -0
- package/lib/plugins/PluginManager.old.js +400 -0
- package/lib/providers/AzureDevOpsProvider.js +575 -0
- package/lib/providers/GitHubProvider.js +475 -0
- package/lib/services/EpicService.js +1092 -3
- package/lib/services/IssueService.js +991 -0
- package/package.json +9 -1
- package/scripts/publish-plugins.sh +166 -0
- package/autopm/.claude/agents/cloud/README.md +0 -55
- package/autopm/.claude/agents/cloud/aws-cloud-architect.md +0 -521
- package/autopm/.claude/agents/cloud/azure-cloud-architect.md +0 -436
- package/autopm/.claude/agents/cloud/gcp-cloud-architect.md +0 -385
- package/autopm/.claude/agents/cloud/gcp-cloud-functions-engineer.md +0 -306
- package/autopm/.claude/agents/cloud/gemini-api-expert.md +0 -880
- package/autopm/.claude/agents/cloud/kubernetes-orchestrator.md +0 -566
- package/autopm/.claude/agents/cloud/openai-python-expert.md +0 -1087
- package/autopm/.claude/agents/cloud/terraform-infrastructure-expert.md +0 -454
- package/autopm/.claude/agents/core/agent-manager.md +0 -296
- package/autopm/.claude/agents/core/code-analyzer.md +0 -131
- package/autopm/.claude/agents/core/file-analyzer.md +0 -162
- package/autopm/.claude/agents/core/test-runner.md +0 -200
- package/autopm/.claude/agents/data/airflow-orchestration-expert.md +0 -52
- package/autopm/.claude/agents/data/kedro-pipeline-expert.md +0 -50
- package/autopm/.claude/agents/data/langgraph-workflow-expert.md +0 -520
- package/autopm/.claude/agents/databases/README.md +0 -50
- package/autopm/.claude/agents/databases/bigquery-expert.md +0 -392
- package/autopm/.claude/agents/databases/cosmosdb-expert.md +0 -368
- package/autopm/.claude/agents/databases/mongodb-expert.md +0 -398
- package/autopm/.claude/agents/databases/postgresql-expert.md +0 -321
- package/autopm/.claude/agents/databases/redis-expert.md +0 -52
- package/autopm/.claude/agents/devops/README.md +0 -52
- package/autopm/.claude/agents/devops/azure-devops-specialist.md +0 -308
- package/autopm/.claude/agents/devops/docker-containerization-expert.md +0 -298
- package/autopm/.claude/agents/devops/github-operations-specialist.md +0 -335
- package/autopm/.claude/agents/devops/mcp-context-manager.md +0 -319
- package/autopm/.claude/agents/devops/observability-engineer.md +0 -574
- package/autopm/.claude/agents/devops/ssh-operations-expert.md +0 -1093
- package/autopm/.claude/agents/devops/traefik-proxy-expert.md +0 -444
- package/autopm/.claude/agents/frameworks/README.md +0 -64
- package/autopm/.claude/agents/frameworks/e2e-test-engineer.md +0 -360
- package/autopm/.claude/agents/frameworks/nats-messaging-expert.md +0 -254
- package/autopm/.claude/agents/frameworks/react-frontend-engineer.md +0 -217
- package/autopm/.claude/agents/frameworks/react-ui-expert.md +0 -226
- package/autopm/.claude/agents/frameworks/tailwindcss-expert.md +0 -770
- package/autopm/.claude/agents/frameworks/ux-design-expert.md +0 -244
- package/autopm/.claude/agents/integration/message-queue-engineer.md +0 -794
- package/autopm/.claude/agents/languages/README.md +0 -50
- package/autopm/.claude/agents/languages/bash-scripting-expert.md +0 -541
- package/autopm/.claude/agents/languages/javascript-frontend-engineer.md +0 -197
- package/autopm/.claude/agents/languages/nodejs-backend-engineer.md +0 -226
- package/autopm/.claude/agents/languages/python-backend-engineer.md +0 -214
- package/autopm/.claude/agents/languages/python-backend-expert.md +0 -289
- package/autopm/.claude/agents/testing/frontend-testing-engineer.md +0 -395
- package/autopm/.claude/commands/ai/langgraph-workflow.md +0 -65
- package/autopm/.claude/commands/ai/openai-chat.md +0 -65
- package/autopm/.claude/commands/azure/COMMANDS.md +0 -107
- package/autopm/.claude/commands/azure/COMMAND_MAPPING.md +0 -252
- package/autopm/.claude/commands/azure/INTEGRATION_FIX.md +0 -103
- package/autopm/.claude/commands/azure/README.md +0 -246
- package/autopm/.claude/commands/azure/active-work.md +0 -198
- package/autopm/.claude/commands/azure/aliases.md +0 -143
- package/autopm/.claude/commands/azure/blocked-items.md +0 -287
- package/autopm/.claude/commands/azure/clean.md +0 -93
- package/autopm/.claude/commands/azure/docs-query.md +0 -48
- package/autopm/.claude/commands/azure/feature-decompose.md +0 -380
- package/autopm/.claude/commands/azure/feature-list.md +0 -61
- package/autopm/.claude/commands/azure/feature-new.md +0 -115
- package/autopm/.claude/commands/azure/feature-show.md +0 -205
- package/autopm/.claude/commands/azure/feature-start.md +0 -130
- package/autopm/.claude/commands/azure/fix-integration-example.md +0 -93
- package/autopm/.claude/commands/azure/help.md +0 -150
- package/autopm/.claude/commands/azure/import-us.md +0 -269
- package/autopm/.claude/commands/azure/init.md +0 -211
- package/autopm/.claude/commands/azure/next-task.md +0 -262
- package/autopm/.claude/commands/azure/search.md +0 -160
- package/autopm/.claude/commands/azure/sprint-status.md +0 -235
- package/autopm/.claude/commands/azure/standup.md +0 -260
- package/autopm/.claude/commands/azure/sync-all.md +0 -99
- package/autopm/.claude/commands/azure/task-analyze.md +0 -186
- package/autopm/.claude/commands/azure/task-close.md +0 -329
- package/autopm/.claude/commands/azure/task-edit.md +0 -145
- package/autopm/.claude/commands/azure/task-list.md +0 -263
- package/autopm/.claude/commands/azure/task-new.md +0 -84
- package/autopm/.claude/commands/azure/task-reopen.md +0 -79
- package/autopm/.claude/commands/azure/task-show.md +0 -126
- package/autopm/.claude/commands/azure/task-start.md +0 -301
- package/autopm/.claude/commands/azure/task-status.md +0 -65
- package/autopm/.claude/commands/azure/task-sync.md +0 -67
- package/autopm/.claude/commands/azure/us-edit.md +0 -164
- package/autopm/.claude/commands/azure/us-list.md +0 -202
- package/autopm/.claude/commands/azure/us-new.md +0 -265
- package/autopm/.claude/commands/azure/us-parse.md +0 -253
- package/autopm/.claude/commands/azure/us-show.md +0 -188
- package/autopm/.claude/commands/azure/us-status.md +0 -320
- package/autopm/.claude/commands/azure/validate.md +0 -86
- package/autopm/.claude/commands/azure/work-item-sync.md +0 -47
- package/autopm/.claude/commands/cloud/infra-deploy.md +0 -38
- package/autopm/.claude/commands/github/workflow-create.md +0 -42
- package/autopm/.claude/commands/infrastructure/ssh-security.md +0 -65
- package/autopm/.claude/commands/infrastructure/traefik-setup.md +0 -65
- package/autopm/.claude/commands/kubernetes/deploy.md +0 -37
- package/autopm/.claude/commands/playwright/test-scaffold.md +0 -38
- package/autopm/.claude/commands/pm/blocked.md +0 -28
- package/autopm/.claude/commands/pm/clean.md +0 -119
- package/autopm/.claude/commands/pm/context-create.md +0 -136
- package/autopm/.claude/commands/pm/context-prime.md +0 -170
- package/autopm/.claude/commands/pm/context-update.md +0 -292
- package/autopm/.claude/commands/pm/context.md +0 -28
- package/autopm/.claude/commands/pm/epic-close.md +0 -86
- package/autopm/.claude/commands/pm/epic-decompose.md +0 -370
- package/autopm/.claude/commands/pm/epic-edit.md +0 -83
- package/autopm/.claude/commands/pm/epic-list.md +0 -30
- package/autopm/.claude/commands/pm/epic-merge.md +0 -222
- package/autopm/.claude/commands/pm/epic-oneshot.md +0 -119
- package/autopm/.claude/commands/pm/epic-refresh.md +0 -119
- package/autopm/.claude/commands/pm/epic-show.md +0 -28
- package/autopm/.claude/commands/pm/epic-split.md +0 -120
- package/autopm/.claude/commands/pm/epic-start.md +0 -195
- package/autopm/.claude/commands/pm/epic-status.md +0 -28
- package/autopm/.claude/commands/pm/epic-sync-modular.md +0 -338
- package/autopm/.claude/commands/pm/epic-sync-original.md +0 -473
- package/autopm/.claude/commands/pm/epic-sync.md +0 -486
- package/autopm/.claude/commands/pm/help.md +0 -28
- package/autopm/.claude/commands/pm/import.md +0 -115
- package/autopm/.claude/commands/pm/in-progress.md +0 -28
- package/autopm/.claude/commands/pm/init.md +0 -28
- package/autopm/.claude/commands/pm/issue-analyze.md +0 -202
- package/autopm/.claude/commands/pm/issue-close.md +0 -119
- package/autopm/.claude/commands/pm/issue-edit.md +0 -93
- package/autopm/.claude/commands/pm/issue-reopen.md +0 -87
- package/autopm/.claude/commands/pm/issue-show.md +0 -41
- package/autopm/.claude/commands/pm/issue-start.md +0 -234
- package/autopm/.claude/commands/pm/issue-status.md +0 -95
- package/autopm/.claude/commands/pm/issue-sync.md +0 -411
- package/autopm/.claude/commands/pm/next.md +0 -28
- package/autopm/.claude/commands/pm/prd-edit.md +0 -82
- package/autopm/.claude/commands/pm/prd-list.md +0 -28
- package/autopm/.claude/commands/pm/prd-new.md +0 -55
- package/autopm/.claude/commands/pm/prd-parse.md +0 -42
- package/autopm/.claude/commands/pm/prd-status.md +0 -28
- package/autopm/.claude/commands/pm/search.md +0 -28
- package/autopm/.claude/commands/pm/standup.md +0 -28
- package/autopm/.claude/commands/pm/status.md +0 -28
- package/autopm/.claude/commands/pm/sync.md +0 -99
- package/autopm/.claude/commands/pm/test-reference-update.md +0 -151
- package/autopm/.claude/commands/pm/validate.md +0 -28
- package/autopm/.claude/commands/pm/what-next.md +0 -28
- package/autopm/.claude/commands/python/api-scaffold.md +0 -50
- package/autopm/.claude/commands/python/docs-query.md +0 -48
- package/autopm/.claude/commands/react/app-scaffold.md +0 -50
- package/autopm/.claude/commands/testing/prime.md +0 -314
- package/autopm/.claude/commands/testing/run.md +0 -125
- package/autopm/.claude/commands/ui/bootstrap-scaffold.md +0 -65
- package/autopm/.claude/commands/ui/tailwind-system.md +0 -64
- package/autopm/.claude/rules/ai-integration-patterns.md +0 -219
- package/autopm/.claude/rules/ci-cd-kubernetes-strategy.md +0 -25
- package/autopm/.claude/rules/database-management-strategy.md +0 -17
- package/autopm/.claude/rules/database-pipeline.md +0 -94
- package/autopm/.claude/rules/devops-troubleshooting-playbook.md +0 -450
- package/autopm/.claude/rules/docker-first-development.md +0 -404
- package/autopm/.claude/rules/infrastructure-pipeline.md +0 -128
- package/autopm/.claude/rules/performance-guidelines.md +0 -403
- package/autopm/.claude/rules/ui-development-standards.md +0 -281
- package/autopm/.claude/rules/ui-framework-rules.md +0 -151
- package/autopm/.claude/rules/ux-design-rules.md +0 -209
- package/autopm/.claude/rules/visual-testing.md +0 -223
- package/autopm/.claude/scripts/azure/README.md +0 -192
- package/autopm/.claude/scripts/azure/active-work.js +0 -524
- package/autopm/.claude/scripts/azure/active-work.sh +0 -20
- package/autopm/.claude/scripts/azure/blocked.js +0 -520
- package/autopm/.claude/scripts/azure/blocked.sh +0 -20
- package/autopm/.claude/scripts/azure/daily.js +0 -533
- package/autopm/.claude/scripts/azure/daily.sh +0 -20
- package/autopm/.claude/scripts/azure/dashboard.js +0 -970
- package/autopm/.claude/scripts/azure/dashboard.sh +0 -20
- package/autopm/.claude/scripts/azure/feature-list.js +0 -254
- package/autopm/.claude/scripts/azure/feature-list.sh +0 -20
- package/autopm/.claude/scripts/azure/feature-show.js +0 -7
- package/autopm/.claude/scripts/azure/feature-show.sh +0 -20
- package/autopm/.claude/scripts/azure/feature-status.js +0 -604
- package/autopm/.claude/scripts/azure/feature-status.sh +0 -20
- package/autopm/.claude/scripts/azure/help.js +0 -342
- package/autopm/.claude/scripts/azure/help.sh +0 -20
- package/autopm/.claude/scripts/azure/next-task.js +0 -508
- package/autopm/.claude/scripts/azure/next-task.sh +0 -20
- package/autopm/.claude/scripts/azure/search.js +0 -469
- package/autopm/.claude/scripts/azure/search.sh +0 -20
- package/autopm/.claude/scripts/azure/setup.js +0 -745
- package/autopm/.claude/scripts/azure/setup.sh +0 -20
- package/autopm/.claude/scripts/azure/sprint-report.js +0 -1012
- package/autopm/.claude/scripts/azure/sprint-report.sh +0 -20
- package/autopm/.claude/scripts/azure/sync.js +0 -563
- package/autopm/.claude/scripts/azure/sync.sh +0 -20
- package/autopm/.claude/scripts/azure/us-list.js +0 -210
- package/autopm/.claude/scripts/azure/us-list.sh +0 -20
- package/autopm/.claude/scripts/azure/us-status.js +0 -238
- package/autopm/.claude/scripts/azure/us-status.sh +0 -20
- package/autopm/.claude/scripts/azure/validate.js +0 -626
- package/autopm/.claude/scripts/azure/validate.sh +0 -20
- package/autopm/.claude/scripts/azure/wrapper-template.sh +0 -20
- package/autopm/.claude/scripts/github/dependency-tracker.js +0 -554
- package/autopm/.claude/scripts/github/dependency-validator.js +0 -545
- package/autopm/.claude/scripts/github/dependency-visualizer.js +0 -477
- package/autopm/.claude/scripts/pm/analytics.js +0 -425
- package/autopm/.claude/scripts/pm/blocked.js +0 -164
- package/autopm/.claude/scripts/pm/blocked.sh +0 -78
- package/autopm/.claude/scripts/pm/clean.js +0 -464
- package/autopm/.claude/scripts/pm/context-create.js +0 -216
- package/autopm/.claude/scripts/pm/context-prime.js +0 -335
- package/autopm/.claude/scripts/pm/context-update.js +0 -344
- package/autopm/.claude/scripts/pm/context.js +0 -338
- package/autopm/.claude/scripts/pm/epic-close.js +0 -347
- package/autopm/.claude/scripts/pm/epic-edit.js +0 -382
- package/autopm/.claude/scripts/pm/epic-list.js +0 -273
- package/autopm/.claude/scripts/pm/epic-list.sh +0 -109
- package/autopm/.claude/scripts/pm/epic-show.js +0 -291
- package/autopm/.claude/scripts/pm/epic-show.sh +0 -105
- package/autopm/.claude/scripts/pm/epic-split.js +0 -522
- package/autopm/.claude/scripts/pm/epic-start/epic-start.js +0 -183
- package/autopm/.claude/scripts/pm/epic-start/epic-start.sh +0 -94
- package/autopm/.claude/scripts/pm/epic-status.js +0 -291
- package/autopm/.claude/scripts/pm/epic-status.sh +0 -104
- package/autopm/.claude/scripts/pm/epic-sync/README.md +0 -208
- package/autopm/.claude/scripts/pm/epic-sync/create-epic-issue.sh +0 -77
- package/autopm/.claude/scripts/pm/epic-sync/create-task-issues.sh +0 -86
- package/autopm/.claude/scripts/pm/epic-sync/update-epic-file.sh +0 -79
- package/autopm/.claude/scripts/pm/epic-sync/update-references.sh +0 -89
- package/autopm/.claude/scripts/pm/epic-sync.sh +0 -137
- package/autopm/.claude/scripts/pm/help.js +0 -92
- package/autopm/.claude/scripts/pm/help.sh +0 -90
- package/autopm/.claude/scripts/pm/in-progress.js +0 -178
- package/autopm/.claude/scripts/pm/in-progress.sh +0 -93
- package/autopm/.claude/scripts/pm/init.js +0 -321
- package/autopm/.claude/scripts/pm/init.sh +0 -178
- package/autopm/.claude/scripts/pm/issue-close.js +0 -232
- package/autopm/.claude/scripts/pm/issue-edit.js +0 -310
- package/autopm/.claude/scripts/pm/issue-show.js +0 -272
- package/autopm/.claude/scripts/pm/issue-start.js +0 -181
- package/autopm/.claude/scripts/pm/issue-sync/format-comment.sh +0 -468
- package/autopm/.claude/scripts/pm/issue-sync/gather-updates.sh +0 -460
- package/autopm/.claude/scripts/pm/issue-sync/post-comment.sh +0 -330
- package/autopm/.claude/scripts/pm/issue-sync/preflight-validation.sh +0 -348
- package/autopm/.claude/scripts/pm/issue-sync/update-frontmatter.sh +0 -387
- package/autopm/.claude/scripts/pm/lib/README.md +0 -85
- package/autopm/.claude/scripts/pm/lib/epic-discovery.js +0 -119
- package/autopm/.claude/scripts/pm/lib/logger.js +0 -78
- package/autopm/.claude/scripts/pm/next.js +0 -189
- package/autopm/.claude/scripts/pm/next.sh +0 -72
- package/autopm/.claude/scripts/pm/optimize.js +0 -407
- package/autopm/.claude/scripts/pm/pr-create.js +0 -337
- package/autopm/.claude/scripts/pm/pr-list.js +0 -257
- package/autopm/.claude/scripts/pm/prd-list.js +0 -242
- package/autopm/.claude/scripts/pm/prd-list.sh +0 -103
- package/autopm/.claude/scripts/pm/prd-new.js +0 -684
- package/autopm/.claude/scripts/pm/prd-parse.js +0 -547
- package/autopm/.claude/scripts/pm/prd-status.js +0 -152
- package/autopm/.claude/scripts/pm/prd-status.sh +0 -63
- package/autopm/.claude/scripts/pm/release.js +0 -460
- package/autopm/.claude/scripts/pm/search.js +0 -192
- package/autopm/.claude/scripts/pm/search.sh +0 -89
- package/autopm/.claude/scripts/pm/standup.js +0 -362
- package/autopm/.claude/scripts/pm/standup.sh +0 -95
- package/autopm/.claude/scripts/pm/status.js +0 -148
- package/autopm/.claude/scripts/pm/status.sh +0 -59
- package/autopm/.claude/scripts/pm/sync-batch.js +0 -337
- package/autopm/.claude/scripts/pm/sync.js +0 -343
- package/autopm/.claude/scripts/pm/template-list.js +0 -141
- package/autopm/.claude/scripts/pm/template-new.js +0 -366
- package/autopm/.claude/scripts/pm/validate.js +0 -274
- package/autopm/.claude/scripts/pm/validate.sh +0 -106
- package/autopm/.claude/scripts/pm/what-next.js +0 -660
- package/bin/node/azure-feature-show.js +0 -7
|
@@ -1,745 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* Azure DevOps Setup Script
|
|
5
|
-
* Migrated from autopm/.claude/scripts/azure/setup.sh to Node.js
|
|
6
|
-
*
|
|
7
|
-
* Features:
|
|
8
|
-
* - Azure DevOps credential collection and validation
|
|
9
|
-
* - Connection testing via Azure DevOps REST API
|
|
10
|
-
* - Directory structure creation
|
|
11
|
-
* - YAML configuration generation
|
|
12
|
-
* - Script permissions management
|
|
13
|
-
* - Initial sync attempt
|
|
14
|
-
* - Cross-platform compatibility
|
|
15
|
-
*/
|
|
16
|
-
|
|
17
|
-
const path = require('path');
|
|
18
|
-
const fs = require('fs').promises;
|
|
19
|
-
const https = require('https');
|
|
20
|
-
const { spawn } = require('child_process');
|
|
21
|
-
const yargs = require('yargs/yargs');
|
|
22
|
-
const { hideBin } = require('yargs/helpers');
|
|
23
|
-
const yaml = require('js-yaml');
|
|
24
|
-
|
|
25
|
-
// TODO: Implement utility modules before using this script
|
|
26
|
-
// const Logger = require('../../lib/utils/logger');
|
|
27
|
-
// const FileSystem = require('../../lib/utils/filesystem');
|
|
28
|
-
// const Prompts = require('../../lib/utils/prompts');
|
|
29
|
-
// const Config = require('../../lib/utils/config');
|
|
30
|
-
|
|
31
|
-
class AzureSetup {
|
|
32
|
-
constructor(options = {}) {
|
|
33
|
-
// Initialize utilities (commented out until utils are implemented)
|
|
34
|
-
// const loggerOptions = {
|
|
35
|
-
// verbose: options.verbose || false,
|
|
36
|
-
// silent: options.silent || false
|
|
37
|
-
// };
|
|
38
|
-
|
|
39
|
-
// this.logger = new Logger(loggerOptions);
|
|
40
|
-
// this.fs = new FileSystem(this.logger);
|
|
41
|
-
// this.prompts = new Prompts(this.logger);
|
|
42
|
-
// this.config = new Config(this.logger);
|
|
43
|
-
|
|
44
|
-
// Set options
|
|
45
|
-
this.options = {
|
|
46
|
-
projectPath: options.projectPath || process.cwd(),
|
|
47
|
-
interactive: !options.nonInteractive,
|
|
48
|
-
verbose: options.verbose || false,
|
|
49
|
-
silent: options.silent || false
|
|
50
|
-
};
|
|
51
|
-
|
|
52
|
-
// Set paths
|
|
53
|
-
this.envPath = path.join(this.options.projectPath, '.claude', '.env');
|
|
54
|
-
this.configPath = path.join(this.options.projectPath, '.claude', 'azure', 'config.yml');
|
|
55
|
-
this.scriptsPath = path.join(this.options.projectPath, '.claude', 'scripts', 'azure');
|
|
56
|
-
|
|
57
|
-
// Environment variables to collect
|
|
58
|
-
this.envVars = {};
|
|
59
|
-
|
|
60
|
-
// Colors (disabled in silent mode)
|
|
61
|
-
this.colors = this.options.silent ? {
|
|
62
|
-
green: '',
|
|
63
|
-
yellow: '',
|
|
64
|
-
red: '',
|
|
65
|
-
blue: '',
|
|
66
|
-
cyan: '',
|
|
67
|
-
reset: ''
|
|
68
|
-
} : {
|
|
69
|
-
green: '\x1b[32m',
|
|
70
|
-
yellow: '\x1b[33m',
|
|
71
|
-
red: '\x1b[31m',
|
|
72
|
-
blue: '\x1b[34m',
|
|
73
|
-
cyan: '\x1b[36m',
|
|
74
|
-
reset: '\x1b[0m'
|
|
75
|
-
};
|
|
76
|
-
|
|
77
|
-
// Directory structure to create
|
|
78
|
-
this.directories = [
|
|
79
|
-
'.claude/azure/cache/features',
|
|
80
|
-
'.claude/azure/cache/stories',
|
|
81
|
-
'.claude/azure/cache/tasks',
|
|
82
|
-
'.claude/azure/user-stories',
|
|
83
|
-
'.claude/azure/tasks',
|
|
84
|
-
'.claude/azure/features',
|
|
85
|
-
'.claude/azure/reports',
|
|
86
|
-
'.claude/azure/imports',
|
|
87
|
-
'.claude/azure/sync',
|
|
88
|
-
'.claude/azure/archive'
|
|
89
|
-
];
|
|
90
|
-
|
|
91
|
-
// For testing - allow dependency injection
|
|
92
|
-
this.spawn = options.spawn || spawn;
|
|
93
|
-
this.prompt = options.prompt || this.prompts.askQuestions.bind(this.prompts);
|
|
94
|
-
}
|
|
95
|
-
|
|
96
|
-
/**
|
|
97
|
-
* Main setup process
|
|
98
|
-
*/
|
|
99
|
-
async run() {
|
|
100
|
-
try {
|
|
101
|
-
if (!this.options.silent) {
|
|
102
|
-
this.logger.info('🔧 Azure DevOps Integration Setup');
|
|
103
|
-
this.logger.info('==================================');
|
|
104
|
-
}
|
|
105
|
-
|
|
106
|
-
// Check/create .env file
|
|
107
|
-
await this.initializeEnvFile();
|
|
108
|
-
|
|
109
|
-
// Load existing environment variables
|
|
110
|
-
await this.loadExistingEnv();
|
|
111
|
-
|
|
112
|
-
// Collect Azure DevOps credentials
|
|
113
|
-
if (this.options.interactive) {
|
|
114
|
-
await this.collectCredentials();
|
|
115
|
-
}
|
|
116
|
-
|
|
117
|
-
// Test connection
|
|
118
|
-
const connectionResult = await this.testConnection();
|
|
119
|
-
if (!connectionResult.success) {
|
|
120
|
-
return {
|
|
121
|
-
success: false,
|
|
122
|
-
error: `Connection test failed: ${connectionResult.error || connectionResult.statusCode}`
|
|
123
|
-
};
|
|
124
|
-
}
|
|
125
|
-
|
|
126
|
-
// Create directory structure
|
|
127
|
-
await this.createDirectoryStructure();
|
|
128
|
-
|
|
129
|
-
// Generate configuration file
|
|
130
|
-
await this.generateConfig();
|
|
131
|
-
|
|
132
|
-
// Set script permissions
|
|
133
|
-
await this.setScriptPermissions();
|
|
134
|
-
|
|
135
|
-
// Save environment variables
|
|
136
|
-
await this.saveEnvironment();
|
|
137
|
-
|
|
138
|
-
// Perform initial sync
|
|
139
|
-
await this.performInitialSync();
|
|
140
|
-
|
|
141
|
-
// Show completion message
|
|
142
|
-
if (!this.options.silent) {
|
|
143
|
-
await this.showCompletionMessage();
|
|
144
|
-
}
|
|
145
|
-
|
|
146
|
-
return {
|
|
147
|
-
success: true,
|
|
148
|
-
projectName: connectionResult.projectName
|
|
149
|
-
};
|
|
150
|
-
|
|
151
|
-
} catch (error) {
|
|
152
|
-
this.logger.error('Azure DevOps setup failed', error);
|
|
153
|
-
return {
|
|
154
|
-
success: false,
|
|
155
|
-
error: error.message
|
|
156
|
-
};
|
|
157
|
-
}
|
|
158
|
-
}
|
|
159
|
-
|
|
160
|
-
/**
|
|
161
|
-
* Check if .env file exists
|
|
162
|
-
*/
|
|
163
|
-
async envFileExists() {
|
|
164
|
-
return await this.fs.exists(this.envPath);
|
|
165
|
-
}
|
|
166
|
-
|
|
167
|
-
/**
|
|
168
|
-
* Initialize .env file
|
|
169
|
-
*/
|
|
170
|
-
async initializeEnvFile() {
|
|
171
|
-
const envExists = await this.envFileExists();
|
|
172
|
-
|
|
173
|
-
if (!envExists) {
|
|
174
|
-
// Ensure .claude directory exists
|
|
175
|
-
await fs.mkdir(path.dirname(this.envPath), { recursive: true });
|
|
176
|
-
|
|
177
|
-
// Try to copy from .env.example
|
|
178
|
-
const examplePath = path.join(path.dirname(this.envPath), '.env.example');
|
|
179
|
-
if (await this.fs.exists(examplePath)) {
|
|
180
|
-
await this.createEnvFromExample();
|
|
181
|
-
} else {
|
|
182
|
-
// Create empty .env file
|
|
183
|
-
await fs.writeFile(this.envPath, '');
|
|
184
|
-
}
|
|
185
|
-
|
|
186
|
-
if (!this.options.silent) {
|
|
187
|
-
this.logger.info('Created .env file');
|
|
188
|
-
}
|
|
189
|
-
}
|
|
190
|
-
}
|
|
191
|
-
|
|
192
|
-
/**
|
|
193
|
-
* Create .env from .env.example
|
|
194
|
-
*/
|
|
195
|
-
async createEnvFromExample() {
|
|
196
|
-
const examplePath = path.join(path.dirname(this.envPath), '.env.example');
|
|
197
|
-
const content = await fs.readFile(examplePath, 'utf8');
|
|
198
|
-
await fs.writeFile(this.envPath, content);
|
|
199
|
-
}
|
|
200
|
-
|
|
201
|
-
/**
|
|
202
|
-
* Load existing environment variables
|
|
203
|
-
*/
|
|
204
|
-
async loadExistingEnv() {
|
|
205
|
-
try {
|
|
206
|
-
const content = await fs.readFile(this.envPath, 'utf8');
|
|
207
|
-
const lines = content.split('\n');
|
|
208
|
-
|
|
209
|
-
for (const line of lines) {
|
|
210
|
-
const trimmed = line.trim();
|
|
211
|
-
if (trimmed && !trimmed.startsWith('#') && trimmed.includes('=')) {
|
|
212
|
-
const [key, ...valueParts] = trimmed.split('=');
|
|
213
|
-
const value = valueParts.join('=').replace(/^["']|["']$/g, '');
|
|
214
|
-
if (key && value) {
|
|
215
|
-
this.envVars[key] = value;
|
|
216
|
-
}
|
|
217
|
-
}
|
|
218
|
-
}
|
|
219
|
-
} catch (error) {
|
|
220
|
-
// File doesn't exist or is empty, that's okay
|
|
221
|
-
}
|
|
222
|
-
}
|
|
223
|
-
|
|
224
|
-
/**
|
|
225
|
-
* Collect Azure DevOps credentials interactively
|
|
226
|
-
*/
|
|
227
|
-
async collectCredentials() {
|
|
228
|
-
if (!this.options.silent) {
|
|
229
|
-
this.logger.info('📋 Azure DevOps Configuration');
|
|
230
|
-
this.logger.info('-----------------------------');
|
|
231
|
-
this.logger.info('Please provide your Azure DevOps details:');
|
|
232
|
-
}
|
|
233
|
-
|
|
234
|
-
const questions = [];
|
|
235
|
-
|
|
236
|
-
// PAT Token
|
|
237
|
-
if (!this.envVars.AZURE_DEVOPS_PAT) {
|
|
238
|
-
questions.push({
|
|
239
|
-
type: 'password',
|
|
240
|
-
name: 'AZURE_DEVOPS_PAT',
|
|
241
|
-
message: 'Personal Access Token (PAT)',
|
|
242
|
-
mask: '*',
|
|
243
|
-
validate: (input) => {
|
|
244
|
-
if (!input || input.length < 10) {
|
|
245
|
-
return 'Please enter a valid Personal Access Token';
|
|
246
|
-
}
|
|
247
|
-
return true;
|
|
248
|
-
}
|
|
249
|
-
});
|
|
250
|
-
} else {
|
|
251
|
-
if (!this.options.silent) {
|
|
252
|
-
this.logger.info(`${this.colors.green}✓${this.colors.reset} PAT already configured`);
|
|
253
|
-
}
|
|
254
|
-
}
|
|
255
|
-
|
|
256
|
-
// Organization
|
|
257
|
-
if (!this.envVars.AZURE_DEVOPS_ORG) {
|
|
258
|
-
questions.push({
|
|
259
|
-
type: 'input',
|
|
260
|
-
name: 'AZURE_DEVOPS_ORG',
|
|
261
|
-
message: 'Organization name',
|
|
262
|
-
validate: (input) => {
|
|
263
|
-
if (!input || input.length < 1) {
|
|
264
|
-
return 'Please enter your Azure DevOps organization name';
|
|
265
|
-
}
|
|
266
|
-
return true;
|
|
267
|
-
}
|
|
268
|
-
});
|
|
269
|
-
} else {
|
|
270
|
-
if (!this.options.silent) {
|
|
271
|
-
this.logger.info(`${this.colors.green}✓${this.colors.reset} Organization: ${this.envVars.AZURE_DEVOPS_ORG}`);
|
|
272
|
-
}
|
|
273
|
-
}
|
|
274
|
-
|
|
275
|
-
// Project
|
|
276
|
-
if (!this.envVars.AZURE_DEVOPS_PROJECT) {
|
|
277
|
-
questions.push({
|
|
278
|
-
type: 'input',
|
|
279
|
-
name: 'AZURE_DEVOPS_PROJECT',
|
|
280
|
-
message: 'Project name',
|
|
281
|
-
validate: (input) => {
|
|
282
|
-
if (!input || input.length < 1) {
|
|
283
|
-
return 'Please enter your Azure DevOps project name';
|
|
284
|
-
}
|
|
285
|
-
return true;
|
|
286
|
-
}
|
|
287
|
-
});
|
|
288
|
-
} else {
|
|
289
|
-
if (!this.options.silent) {
|
|
290
|
-
this.logger.info(`${this.colors.green}✓${this.colors.reset} Project: ${this.envVars.AZURE_DEVOPS_PROJECT}`);
|
|
291
|
-
}
|
|
292
|
-
}
|
|
293
|
-
|
|
294
|
-
if (questions.length > 0) {
|
|
295
|
-
const answers = await this.prompt(questions);
|
|
296
|
-
Object.assign(this.envVars, answers);
|
|
297
|
-
}
|
|
298
|
-
}
|
|
299
|
-
|
|
300
|
-
/**
|
|
301
|
-
* Test Azure DevOps API connection
|
|
302
|
-
*/
|
|
303
|
-
async testConnection() {
|
|
304
|
-
if (!this.options.silent) {
|
|
305
|
-
this.logger.info('');
|
|
306
|
-
this.logger.info('🔌 Testing Azure DevOps Connection');
|
|
307
|
-
this.logger.info('-----------------------------------');
|
|
308
|
-
}
|
|
309
|
-
|
|
310
|
-
return new Promise((resolve) => {
|
|
311
|
-
const { AZURE_DEVOPS_PAT, AZURE_DEVOPS_ORG, AZURE_DEVOPS_PROJECT } = this.envVars;
|
|
312
|
-
|
|
313
|
-
if (!AZURE_DEVOPS_PAT || !AZURE_DEVOPS_ORG || !AZURE_DEVOPS_PROJECT) {
|
|
314
|
-
resolve({
|
|
315
|
-
success: false,
|
|
316
|
-
error: 'Missing required Azure DevOps credentials'
|
|
317
|
-
});
|
|
318
|
-
return;
|
|
319
|
-
}
|
|
320
|
-
|
|
321
|
-
const auth = Buffer.from(`:${AZURE_DEVOPS_PAT}`).toString('base64');
|
|
322
|
-
const options = {
|
|
323
|
-
hostname: 'dev.azure.com',
|
|
324
|
-
port: 443,
|
|
325
|
-
path: `/${AZURE_DEVOPS_ORG}/_apis/projects/${AZURE_DEVOPS_PROJECT}?api-version=7.0`,
|
|
326
|
-
method: 'GET',
|
|
327
|
-
headers: {
|
|
328
|
-
'Authorization': `Basic ${auth}`,
|
|
329
|
-
'User-Agent': 'ClaudeAutoPM/1.0'
|
|
330
|
-
}
|
|
331
|
-
};
|
|
332
|
-
|
|
333
|
-
const req = https.request(options, (res) => {
|
|
334
|
-
let data = '';
|
|
335
|
-
|
|
336
|
-
res.on('data', (chunk) => {
|
|
337
|
-
data += chunk;
|
|
338
|
-
});
|
|
339
|
-
|
|
340
|
-
res.on('end', () => {
|
|
341
|
-
if (res.statusCode === 200) {
|
|
342
|
-
try {
|
|
343
|
-
const project = JSON.parse(data);
|
|
344
|
-
if (!this.options.silent) {
|
|
345
|
-
this.logger.info(`${this.colors.green}✅ Connection successful!${this.colors.reset}`);
|
|
346
|
-
this.logger.info(`Connected to project: ${project.name}`);
|
|
347
|
-
}
|
|
348
|
-
resolve({
|
|
349
|
-
success: true,
|
|
350
|
-
projectName: project.name,
|
|
351
|
-
statusCode: 200
|
|
352
|
-
});
|
|
353
|
-
} catch (error) {
|
|
354
|
-
resolve({
|
|
355
|
-
success: false,
|
|
356
|
-
error: 'Invalid response from Azure DevOps API',
|
|
357
|
-
statusCode: res.statusCode
|
|
358
|
-
});
|
|
359
|
-
}
|
|
360
|
-
} else {
|
|
361
|
-
if (!this.options.silent) {
|
|
362
|
-
this.logger.error(`${this.colors.red}❌ Connection failed (HTTP ${res.statusCode})${this.colors.reset}`);
|
|
363
|
-
this.logger.error('Please check your credentials and try again');
|
|
364
|
-
}
|
|
365
|
-
resolve({
|
|
366
|
-
success: false,
|
|
367
|
-
statusCode: res.statusCode,
|
|
368
|
-
error: `HTTP ${res.statusCode}`
|
|
369
|
-
});
|
|
370
|
-
}
|
|
371
|
-
});
|
|
372
|
-
});
|
|
373
|
-
|
|
374
|
-
req.on('error', (error) => {
|
|
375
|
-
if (!this.options.silent) {
|
|
376
|
-
this.logger.error(`${this.colors.red}❌ Connection failed${this.colors.reset}`);
|
|
377
|
-
this.logger.error(`Network error: ${error.message}`);
|
|
378
|
-
}
|
|
379
|
-
resolve({
|
|
380
|
-
success: false,
|
|
381
|
-
error: `Network error: ${error.message}`
|
|
382
|
-
});
|
|
383
|
-
});
|
|
384
|
-
|
|
385
|
-
req.end();
|
|
386
|
-
});
|
|
387
|
-
}
|
|
388
|
-
|
|
389
|
-
/**
|
|
390
|
-
* Create Azure directory structure
|
|
391
|
-
*/
|
|
392
|
-
async createDirectoryStructure() {
|
|
393
|
-
if (!this.options.silent) {
|
|
394
|
-
this.logger.info('');
|
|
395
|
-
this.logger.info('📁 Creating Directory Structure');
|
|
396
|
-
this.logger.info('-------------------------------');
|
|
397
|
-
}
|
|
398
|
-
|
|
399
|
-
for (const dir of this.directories) {
|
|
400
|
-
const dirPath = path.join(this.options.projectPath, dir);
|
|
401
|
-
let exists;
|
|
402
|
-
try {
|
|
403
|
-
await fs.access(dirPath);
|
|
404
|
-
exists = true;
|
|
405
|
-
} catch {
|
|
406
|
-
exists = false;
|
|
407
|
-
}
|
|
408
|
-
|
|
409
|
-
if (!exists) {
|
|
410
|
-
await fs.mkdir(dirPath, { recursive: true });
|
|
411
|
-
if (!this.options.silent) {
|
|
412
|
-
this.logger.info(` ✓ Created ${dir}`);
|
|
413
|
-
}
|
|
414
|
-
} else {
|
|
415
|
-
if (!this.options.silent) {
|
|
416
|
-
this.logger.info(` • ${dir} exists`);
|
|
417
|
-
}
|
|
418
|
-
}
|
|
419
|
-
}
|
|
420
|
-
}
|
|
421
|
-
|
|
422
|
-
/**
|
|
423
|
-
* Generate Azure configuration file
|
|
424
|
-
*/
|
|
425
|
-
async generateConfig() {
|
|
426
|
-
if (!this.options.silent) {
|
|
427
|
-
this.logger.info('');
|
|
428
|
-
this.logger.info('⚙️ Creating Configuration');
|
|
429
|
-
this.logger.info('-------------------------');
|
|
430
|
-
}
|
|
431
|
-
|
|
432
|
-
const configData = {
|
|
433
|
-
'# Azure DevOps Configuration': null,
|
|
434
|
-
'# Generated': new Date().toISOString(),
|
|
435
|
-
azure_devops: {
|
|
436
|
-
organization: this.envVars.AZURE_DEVOPS_ORG,
|
|
437
|
-
project: this.envVars.AZURE_DEVOPS_PROJECT,
|
|
438
|
-
api_version: '7.0'
|
|
439
|
-
},
|
|
440
|
-
defaults: {
|
|
441
|
-
area_path: this.envVars.AZURE_DEVOPS_PROJECT,
|
|
442
|
-
iteration_path: this.envVars.AZURE_DEVOPS_PROJECT,
|
|
443
|
-
work_item_types: ['Feature', 'User Story', 'Task', 'Bug']
|
|
444
|
-
},
|
|
445
|
-
sync: {
|
|
446
|
-
enabled: true,
|
|
447
|
-
interval_minutes: 15,
|
|
448
|
-
cache_ttl_days: 30
|
|
449
|
-
},
|
|
450
|
-
git: {
|
|
451
|
-
auto_branch: true,
|
|
452
|
-
branch_prefix: 'azure',
|
|
453
|
-
link_commits: true,
|
|
454
|
-
pr_template: true
|
|
455
|
-
},
|
|
456
|
-
features: {
|
|
457
|
-
time_tracking: true,
|
|
458
|
-
auto_assign: false,
|
|
459
|
-
notifications: true,
|
|
460
|
-
burndown_charts: true
|
|
461
|
-
},
|
|
462
|
-
team: {
|
|
463
|
-
default_capacity_hours: 6,
|
|
464
|
-
sprint_days: 10
|
|
465
|
-
},
|
|
466
|
-
aliases: {
|
|
467
|
-
enabled: true,
|
|
468
|
-
prefix: 'az'
|
|
469
|
-
}
|
|
470
|
-
};
|
|
471
|
-
|
|
472
|
-
// Ensure config directory exists
|
|
473
|
-
await fs.mkdir(path.dirname(this.configPath), { recursive: true });
|
|
474
|
-
|
|
475
|
-
// Generate YAML content
|
|
476
|
-
let yamlContent = `# Azure DevOps Configuration\n# Generated: ${new Date().toISOString()}\n\n`;
|
|
477
|
-
yamlContent += yaml.dump({
|
|
478
|
-
azure_devops: configData.azure_devops,
|
|
479
|
-
defaults: configData.defaults,
|
|
480
|
-
sync: configData.sync,
|
|
481
|
-
git: configData.git,
|
|
482
|
-
features: configData.features,
|
|
483
|
-
team: configData.team,
|
|
484
|
-
aliases: configData.aliases
|
|
485
|
-
}, {
|
|
486
|
-
indent: 2,
|
|
487
|
-
lineWidth: 80
|
|
488
|
-
});
|
|
489
|
-
|
|
490
|
-
await fs.writeFile(this.configPath, yamlContent);
|
|
491
|
-
|
|
492
|
-
if (!this.options.silent) {
|
|
493
|
-
this.logger.info(`${this.colors.green}✓${this.colors.reset} Configuration created`);
|
|
494
|
-
}
|
|
495
|
-
}
|
|
496
|
-
|
|
497
|
-
/**
|
|
498
|
-
* Set executable permissions on Azure scripts
|
|
499
|
-
*/
|
|
500
|
-
async setScriptPermissions() {
|
|
501
|
-
if (!this.options.silent) {
|
|
502
|
-
this.logger.info('');
|
|
503
|
-
this.logger.info('🔐 Setting Script Permissions');
|
|
504
|
-
this.logger.info('-----------------------------');
|
|
505
|
-
}
|
|
506
|
-
|
|
507
|
-
try {
|
|
508
|
-
// Check if scripts directory exists
|
|
509
|
-
let scriptsPathExists;
|
|
510
|
-
try {
|
|
511
|
-
await fs.access(this.scriptsPath);
|
|
512
|
-
scriptsPathExists = true;
|
|
513
|
-
} catch {
|
|
514
|
-
scriptsPathExists = false;
|
|
515
|
-
}
|
|
516
|
-
if (scriptsPathExists) {
|
|
517
|
-
const files = await fs.readdir(this.scriptsPath);
|
|
518
|
-
const scriptFiles = files.filter(file => file.endsWith('.sh'));
|
|
519
|
-
|
|
520
|
-
for (const file of scriptFiles) {
|
|
521
|
-
const filePath = path.join(this.scriptsPath, file);
|
|
522
|
-
try {
|
|
523
|
-
// Set executable permissions (owner read/write/execute)
|
|
524
|
-
await fs.chmod(filePath, 0o755);
|
|
525
|
-
} catch (error) {
|
|
526
|
-
// Ignore permission errors on Windows
|
|
527
|
-
if (process.platform !== 'win32') {
|
|
528
|
-
this.logger.warn(`Could not set permissions for ${file}: ${error.message}`);
|
|
529
|
-
}
|
|
530
|
-
}
|
|
531
|
-
}
|
|
532
|
-
}
|
|
533
|
-
|
|
534
|
-
if (!this.options.silent) {
|
|
535
|
-
this.logger.info(`${this.colors.green}✓${this.colors.reset} Scripts are executable`);
|
|
536
|
-
}
|
|
537
|
-
} catch (error) {
|
|
538
|
-
// Non-critical error, continue
|
|
539
|
-
this.logger.warn(`Could not set script permissions: ${error.message}`);
|
|
540
|
-
}
|
|
541
|
-
}
|
|
542
|
-
|
|
543
|
-
/**
|
|
544
|
-
* Save environment variables to .env file
|
|
545
|
-
*/
|
|
546
|
-
async saveEnvironment() {
|
|
547
|
-
try {
|
|
548
|
-
// Ensure .claude directory exists
|
|
549
|
-
await fs.mkdir(path.dirname(this.envPath), { recursive: true });
|
|
550
|
-
|
|
551
|
-
// Read existing content
|
|
552
|
-
let existingContent = '';
|
|
553
|
-
try {
|
|
554
|
-
existingContent = await fs.readFile(this.envPath, 'utf8');
|
|
555
|
-
} catch (error) {
|
|
556
|
-
// File doesn't exist, that's okay
|
|
557
|
-
}
|
|
558
|
-
|
|
559
|
-
// Parse existing variables to avoid duplicates
|
|
560
|
-
const existingVars = new Set();
|
|
561
|
-
const lines = existingContent.split('\n');
|
|
562
|
-
for (const line of lines) {
|
|
563
|
-
const trimmed = line.trim();
|
|
564
|
-
if (trimmed && !trimmed.startsWith('#') && trimmed.includes('=')) {
|
|
565
|
-
const [key] = trimmed.split('=');
|
|
566
|
-
if (key) {
|
|
567
|
-
existingVars.add(key);
|
|
568
|
-
}
|
|
569
|
-
}
|
|
570
|
-
}
|
|
571
|
-
|
|
572
|
-
// Append new variables
|
|
573
|
-
let newContent = existingContent.trim();
|
|
574
|
-
if (newContent && !newContent.endsWith('\n')) {
|
|
575
|
-
newContent += '\n';
|
|
576
|
-
}
|
|
577
|
-
|
|
578
|
-
const azureVars = ['AZURE_DEVOPS_PAT', 'AZURE_DEVOPS_ORG', 'AZURE_DEVOPS_PROJECT'];
|
|
579
|
-
const newVars = azureVars.filter(key =>
|
|
580
|
-
this.envVars[key] && !existingVars.has(key)
|
|
581
|
-
);
|
|
582
|
-
|
|
583
|
-
if (newVars.length > 0) {
|
|
584
|
-
if (newContent) {
|
|
585
|
-
newContent += '\n';
|
|
586
|
-
}
|
|
587
|
-
newContent += '# Azure DevOps Configuration\n';
|
|
588
|
-
for (const key of newVars) {
|
|
589
|
-
newContent += `${key}=${this.envVars[key]}\n`;
|
|
590
|
-
}
|
|
591
|
-
}
|
|
592
|
-
|
|
593
|
-
// Write to file
|
|
594
|
-
await fs.writeFile(this.envPath, newContent);
|
|
595
|
-
|
|
596
|
-
// Set secure permissions (owner read/write only)
|
|
597
|
-
if (process.platform !== 'win32') {
|
|
598
|
-
await fs.chmod(this.envPath, 0o600);
|
|
599
|
-
}
|
|
600
|
-
|
|
601
|
-
} catch (error) {
|
|
602
|
-
throw new Error(`Failed to save environment variables: ${error.message}`);
|
|
603
|
-
}
|
|
604
|
-
}
|
|
605
|
-
|
|
606
|
-
/**
|
|
607
|
-
* Perform initial sync with Azure DevOps
|
|
608
|
-
*/
|
|
609
|
-
async performInitialSync() {
|
|
610
|
-
if (!this.options.silent) {
|
|
611
|
-
this.logger.info('');
|
|
612
|
-
this.logger.info('🔄 Performing Initial Sync');
|
|
613
|
-
this.logger.info('--------------------------');
|
|
614
|
-
}
|
|
615
|
-
|
|
616
|
-
try {
|
|
617
|
-
const syncScript = path.join(this.scriptsPath, 'sync.sh');
|
|
618
|
-
|
|
619
|
-
let syncScriptExists;
|
|
620
|
-
try {
|
|
621
|
-
await fs.access(syncScript);
|
|
622
|
-
syncScriptExists = true;
|
|
623
|
-
} catch {
|
|
624
|
-
syncScriptExists = false;
|
|
625
|
-
}
|
|
626
|
-
if (syncScriptExists) {
|
|
627
|
-
if (!this.options.silent) {
|
|
628
|
-
this.logger.info('Fetching recent work items...');
|
|
629
|
-
}
|
|
630
|
-
|
|
631
|
-
return new Promise((resolve) => {
|
|
632
|
-
const child = this.spawn(syncScript, ['--quick'], {
|
|
633
|
-
cwd: this.options.projectPath,
|
|
634
|
-
stdio: this.options.silent ? 'ignore' : 'inherit'
|
|
635
|
-
});
|
|
636
|
-
|
|
637
|
-
child.on('close', (code) => {
|
|
638
|
-
if (code === 0) {
|
|
639
|
-
if (!this.options.silent) {
|
|
640
|
-
this.logger.info('Initial sync completed');
|
|
641
|
-
}
|
|
642
|
-
} else {
|
|
643
|
-
if (!this.options.silent) {
|
|
644
|
-
this.logger.warn('Sync will be available after first command run');
|
|
645
|
-
}
|
|
646
|
-
}
|
|
647
|
-
resolve();
|
|
648
|
-
});
|
|
649
|
-
|
|
650
|
-
child.on('error', () => {
|
|
651
|
-
if (!this.options.silent) {
|
|
652
|
-
this.logger.warn('Sync will be available after first command run');
|
|
653
|
-
}
|
|
654
|
-
resolve();
|
|
655
|
-
});
|
|
656
|
-
});
|
|
657
|
-
} else {
|
|
658
|
-
if (!this.options.silent) {
|
|
659
|
-
this.logger.warn('Sync script not found, skipping initial sync');
|
|
660
|
-
}
|
|
661
|
-
}
|
|
662
|
-
} catch (error) {
|
|
663
|
-
// Non-critical error
|
|
664
|
-
if (!this.options.silent) {
|
|
665
|
-
this.logger.warn('Sync will be available after first command run');
|
|
666
|
-
}
|
|
667
|
-
}
|
|
668
|
-
}
|
|
669
|
-
|
|
670
|
-
/**
|
|
671
|
-
* Show completion message
|
|
672
|
-
*/
|
|
673
|
-
async showCompletionMessage() {
|
|
674
|
-
this.logger.info('');
|
|
675
|
-
this.logger.info('==================================');
|
|
676
|
-
this.logger.info(`${this.colors.green}✅ Azure DevOps Setup Complete!${this.colors.reset}`);
|
|
677
|
-
this.logger.info('==================================');
|
|
678
|
-
this.logger.info('');
|
|
679
|
-
this.logger.info('📋 Quick Start Guide:');
|
|
680
|
-
this.logger.info('--------------------');
|
|
681
|
-
this.logger.info('1. Initialize in Claude: /azure:init');
|
|
682
|
-
this.logger.info('2. View commands: /azure:help');
|
|
683
|
-
this.logger.info('3. Start daily workflow: /azure:standup');
|
|
684
|
-
this.logger.info('4. Get next task: /azure:next-task');
|
|
685
|
-
this.logger.info('');
|
|
686
|
-
this.logger.info('📚 Documentation:');
|
|
687
|
-
this.logger.info(' • Commands: .claude/commands/azure/README.md');
|
|
688
|
-
this.logger.info(' • Aliases: .claude/commands/azure/aliases.md');
|
|
689
|
-
this.logger.info(' • Config: .claude/azure/config.yml');
|
|
690
|
-
this.logger.info('');
|
|
691
|
-
this.logger.info('🚀 Ready to use Azure DevOps integration!');
|
|
692
|
-
}
|
|
693
|
-
}
|
|
694
|
-
|
|
695
|
-
// CLI interface
|
|
696
|
-
if (require.main === module) {
|
|
697
|
-
const argv = yargs(hideBin(process.argv))
|
|
698
|
-
.option('path', {
|
|
699
|
-
alias: 'p',
|
|
700
|
-
describe: 'Project path',
|
|
701
|
-
type: 'string',
|
|
702
|
-
default: process.cwd()
|
|
703
|
-
})
|
|
704
|
-
.option('non-interactive', {
|
|
705
|
-
alias: 'n',
|
|
706
|
-
describe: 'Run in non-interactive mode',
|
|
707
|
-
type: 'boolean',
|
|
708
|
-
default: false
|
|
709
|
-
})
|
|
710
|
-
.option('verbose', {
|
|
711
|
-
alias: 'v',
|
|
712
|
-
describe: 'Verbose output',
|
|
713
|
-
type: 'boolean',
|
|
714
|
-
default: false
|
|
715
|
-
})
|
|
716
|
-
.option('silent', {
|
|
717
|
-
alias: 's',
|
|
718
|
-
describe: 'Silent mode',
|
|
719
|
-
type: 'boolean',
|
|
720
|
-
default: false
|
|
721
|
-
})
|
|
722
|
-
.help()
|
|
723
|
-
.argv;
|
|
724
|
-
|
|
725
|
-
const setup = new AzureSetup({
|
|
726
|
-
projectPath: argv.path,
|
|
727
|
-
nonInteractive: argv.nonInteractive,
|
|
728
|
-
verbose: argv.verbose,
|
|
729
|
-
silent: argv.silent
|
|
730
|
-
});
|
|
731
|
-
|
|
732
|
-
setup.run()
|
|
733
|
-
.then((result) => {
|
|
734
|
-
if (!result.success) {
|
|
735
|
-
console.error('Azure DevOps setup failed:', result.error);
|
|
736
|
-
process.exit(1);
|
|
737
|
-
}
|
|
738
|
-
})
|
|
739
|
-
.catch((error) => {
|
|
740
|
-
console.error('Azure DevOps setup failed:', error.message);
|
|
741
|
-
process.exit(1);
|
|
742
|
-
});
|
|
743
|
-
}
|
|
744
|
-
|
|
745
|
-
module.exports = AzureSetup;
|