specweave 0.32.6 → 0.32.7
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 +3 -0
- package/dist/src/cli/commands/init.d.ts.map +1 -1
- package/dist/src/cli/commands/init.js +16 -0
- package/dist/src/cli/commands/init.js.map +1 -1
- package/dist/src/cli/helpers/init/bitbucket-repo-cloning.d.ts +42 -0
- package/dist/src/cli/helpers/init/bitbucket-repo-cloning.d.ts.map +1 -0
- package/dist/src/cli/helpers/init/bitbucket-repo-cloning.js +256 -0
- package/dist/src/cli/helpers/init/bitbucket-repo-cloning.js.map +1 -0
- package/dist/src/cli/helpers/init/github-repo-cloning.d.ts +40 -0
- package/dist/src/cli/helpers/init/github-repo-cloning.d.ts.map +1 -0
- package/dist/src/cli/helpers/init/github-repo-cloning.js +284 -0
- package/dist/src/cli/helpers/init/github-repo-cloning.js.map +1 -0
- package/dist/src/cli/helpers/init/repository-setup.d.ts +24 -0
- package/dist/src/cli/helpers/init/repository-setup.d.ts.map +1 -1
- package/dist/src/cli/helpers/init/repository-setup.js +196 -2
- package/dist/src/cli/helpers/init/repository-setup.js.map +1 -1
- package/dist/src/cli/helpers/issue-tracker/github.d.ts +35 -0
- package/dist/src/cli/helpers/issue-tracker/github.d.ts.map +1 -1
- package/dist/src/cli/helpers/issue-tracker/github.js +203 -0
- package/dist/src/cli/helpers/issue-tracker/github.js.map +1 -1
- package/dist/src/cli/helpers/issue-tracker/index.d.ts.map +1 -1
- package/dist/src/cli/helpers/issue-tracker/index.js +120 -12
- package/dist/src/cli/helpers/issue-tracker/index.js.map +1 -1
- package/dist/src/cli/helpers/issue-tracker/jira.d.ts.map +1 -1
- package/dist/src/cli/helpers/issue-tracker/jira.js +6 -7
- package/dist/src/cli/helpers/issue-tracker/jira.js.map +1 -1
- package/dist/src/utils/validators/jira-validator.d.ts +12 -0
- package/dist/src/utils/validators/jira-validator.d.ts.map +1 -1
- package/dist/src/utils/validators/jira-validator.js +35 -11
- package/dist/src/utils/validators/jira-validator.js.map +1 -1
- package/package.json +3 -3
- package/plugins/specweave/commands/specweave-done.md +34 -0
- package/plugins/specweave/commands/specweave-increment.md +13 -5
- package/plugins/specweave/hooks/v2/detectors/lifecycle-detector.sh +3 -1
- package/plugins/specweave/hooks/docs-changed.sh.backup +0 -79
- package/plugins/specweave/hooks/human-input-required.sh.backup +0 -75
- package/plugins/specweave/hooks/post-first-increment.sh.backup +0 -61
- package/plugins/specweave/hooks/post-increment-change.sh.backup +0 -98
- package/plugins/specweave/hooks/post-increment-completion.sh.backup +0 -231
- package/plugins/specweave/hooks/post-increment-planning.sh.backup +0 -1048
- package/plugins/specweave/hooks/post-increment-status-change.sh.backup +0 -147
- package/plugins/specweave/hooks/post-spec-update.sh.backup +0 -158
- package/plugins/specweave/hooks/post-user-story-complete.sh.backup +0 -179
- package/plugins/specweave/hooks/pre-command-deduplication.sh.backup +0 -83
- package/plugins/specweave/hooks/pre-implementation.sh.backup +0 -67
- package/plugins/specweave/hooks/pre-task-completion.sh.backup +0 -194
- package/plugins/specweave/hooks/pre-tool-use.sh.backup +0 -133
- package/plugins/specweave/hooks/user-prompt-submit.sh.backup +0 -386
- package/plugins/specweave-ado/hooks/post-living-docs-update.sh.backup +0 -353
- package/plugins/specweave-ado/hooks/post-task-completion.sh.backup +0 -172
- package/plugins/specweave-ado/lib/enhanced-ado-sync.js +0 -170
- package/plugins/specweave-github/hooks/.specweave/logs/hooks-debug.log +0 -1262
- package/plugins/specweave-github/hooks/post-task-completion.sh.backup +0 -258
- package/plugins/specweave-github/lib/enhanced-github-sync.js +0 -220
- package/plugins/specweave-jira/hooks/post-task-completion.sh.backup +0 -172
- package/plugins/specweave-jira/lib/enhanced-jira-sync.js +0 -134
- package/plugins/specweave-release/hooks/.specweave/logs/dora-tracking.log +0 -1254
- package/plugins/specweave-release/hooks/post-task-completion.sh.backup +0 -110
|
@@ -0,0 +1,284 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* GitHub Repository Cloning
|
|
3
|
+
*
|
|
4
|
+
* Handles fetching and cloning GitHub repositories during init.
|
|
5
|
+
* Cloning runs in background (non-blocking) via job manager.
|
|
6
|
+
*
|
|
7
|
+
* Provides parity with ADO multi-repo cloning:
|
|
8
|
+
* - Fetches repos from GitHub org via API
|
|
9
|
+
* - Filters by user-selected pattern (all/glob/regex)
|
|
10
|
+
* - Creates background clone jobs
|
|
11
|
+
* - Tracks progress via /specweave:jobs
|
|
12
|
+
*
|
|
13
|
+
* @module cli/helpers/init/github-repo-cloning
|
|
14
|
+
*/
|
|
15
|
+
import chalk from 'chalk';
|
|
16
|
+
import { filterRepositoriesByPattern } from '../selection-strategy.js';
|
|
17
|
+
import { launchCloneJob } from '../../../core/background/job-launcher.js';
|
|
18
|
+
/**
|
|
19
|
+
* Parse rate limit headers from GitHub API response
|
|
20
|
+
*/
|
|
21
|
+
function parseRateLimitHeaders(headers) {
|
|
22
|
+
const remaining = headers.get('x-ratelimit-remaining');
|
|
23
|
+
const limit = headers.get('x-ratelimit-limit');
|
|
24
|
+
const reset = headers.get('x-ratelimit-reset');
|
|
25
|
+
if (remaining && limit && reset) {
|
|
26
|
+
return {
|
|
27
|
+
remaining: parseInt(remaining, 10),
|
|
28
|
+
limit: parseInt(limit, 10),
|
|
29
|
+
reset: new Date(parseInt(reset, 10) * 1000)
|
|
30
|
+
};
|
|
31
|
+
}
|
|
32
|
+
return undefined;
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* Sleep for specified milliseconds
|
|
36
|
+
*/
|
|
37
|
+
function sleep(ms) {
|
|
38
|
+
return new Promise(resolve => setTimeout(resolve, ms));
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* Fetch repositories from GitHub organization with pagination and rate limit handling
|
|
42
|
+
*
|
|
43
|
+
* @param org - GitHub organization or owner
|
|
44
|
+
* @param pat - Personal Access Token
|
|
45
|
+
* @param maxRepos - Maximum repos to fetch (default 500)
|
|
46
|
+
* @returns Fetch result with repos and metadata
|
|
47
|
+
*/
|
|
48
|
+
async function fetchGitHubRepos(org, pat, maxRepos = 500) {
|
|
49
|
+
const repos = [];
|
|
50
|
+
let page = 1;
|
|
51
|
+
const perPage = 100;
|
|
52
|
+
let rateLimit;
|
|
53
|
+
let partial = false;
|
|
54
|
+
console.log(chalk.gray(` Fetching repositories from ${org}...`));
|
|
55
|
+
while (repos.length < maxRepos) {
|
|
56
|
+
// Retry logic with exponential backoff
|
|
57
|
+
let retries = 0;
|
|
58
|
+
const maxRetries = 3;
|
|
59
|
+
let response;
|
|
60
|
+
while (retries < maxRetries) {
|
|
61
|
+
try {
|
|
62
|
+
response = await fetch(`https://api.github.com/orgs/${encodeURIComponent(org)}/repos?per_page=${perPage}&page=${page}`, {
|
|
63
|
+
headers: {
|
|
64
|
+
'Authorization': `Bearer ${pat}`,
|
|
65
|
+
'Accept': 'application/vnd.github+json',
|
|
66
|
+
'X-GitHub-Api-Version': '2022-11-28'
|
|
67
|
+
}
|
|
68
|
+
});
|
|
69
|
+
// Parse rate limit from every response
|
|
70
|
+
rateLimit = parseRateLimitHeaders(response.headers);
|
|
71
|
+
// Warn if rate limit is low
|
|
72
|
+
if (rateLimit && rateLimit.remaining < 100) {
|
|
73
|
+
console.log(chalk.yellow(` ⚠️ GitHub API rate limit low: ${rateLimit.remaining}/${rateLimit.limit} remaining`));
|
|
74
|
+
}
|
|
75
|
+
if (response.ok) {
|
|
76
|
+
break; // Success, exit retry loop
|
|
77
|
+
}
|
|
78
|
+
// Handle rate limit (403)
|
|
79
|
+
if (response.status === 403) {
|
|
80
|
+
const errorBody = await response.text();
|
|
81
|
+
if (errorBody.includes('rate limit') || errorBody.includes('secondary rate limit')) {
|
|
82
|
+
const backoffMs = Math.pow(2, retries + 1) * 1000; // 2s, 4s, 8s
|
|
83
|
+
console.log(chalk.yellow(` ⚠️ Rate limit hit, retrying in ${backoffMs / 1000}s (attempt ${retries + 1}/${maxRetries})`));
|
|
84
|
+
await sleep(backoffMs);
|
|
85
|
+
retries++;
|
|
86
|
+
continue;
|
|
87
|
+
}
|
|
88
|
+
// Other 403 error - not rate limit
|
|
89
|
+
break;
|
|
90
|
+
}
|
|
91
|
+
// Handle 401 (invalid PAT)
|
|
92
|
+
if (response.status === 401) {
|
|
93
|
+
return {
|
|
94
|
+
repos: [],
|
|
95
|
+
rateLimit,
|
|
96
|
+
partial: false,
|
|
97
|
+
error: 'Invalid GitHub PAT. Please check your token has repo:read access.'
|
|
98
|
+
};
|
|
99
|
+
}
|
|
100
|
+
// Handle 404 (org not found) - try user repos instead
|
|
101
|
+
if (response.status === 404) {
|
|
102
|
+
// Try as user instead of org
|
|
103
|
+
const userResponse = await fetch(`https://api.github.com/users/${encodeURIComponent(org)}/repos?per_page=${perPage}&page=${page}`, {
|
|
104
|
+
headers: {
|
|
105
|
+
'Authorization': `Bearer ${pat}`,
|
|
106
|
+
'Accept': 'application/vnd.github+json',
|
|
107
|
+
'X-GitHub-Api-Version': '2022-11-28'
|
|
108
|
+
}
|
|
109
|
+
});
|
|
110
|
+
if (userResponse.ok) {
|
|
111
|
+
response = userResponse;
|
|
112
|
+
break;
|
|
113
|
+
}
|
|
114
|
+
return {
|
|
115
|
+
repos: [],
|
|
116
|
+
rateLimit,
|
|
117
|
+
partial: false,
|
|
118
|
+
error: `Organization or user "${org}" not found on GitHub.`
|
|
119
|
+
};
|
|
120
|
+
}
|
|
121
|
+
// Other error - don't retry
|
|
122
|
+
break;
|
|
123
|
+
}
|
|
124
|
+
catch (networkError) {
|
|
125
|
+
retries++;
|
|
126
|
+
if (retries >= maxRetries) {
|
|
127
|
+
return {
|
|
128
|
+
repos,
|
|
129
|
+
rateLimit,
|
|
130
|
+
partial: repos.length > 0,
|
|
131
|
+
error: `Network error after ${maxRetries} retries: ${networkError instanceof Error ? networkError.message : 'Unknown error'}`
|
|
132
|
+
};
|
|
133
|
+
}
|
|
134
|
+
const backoffMs = Math.pow(2, retries) * 1000;
|
|
135
|
+
console.log(chalk.yellow(` ⚠️ Network error, retrying in ${backoffMs / 1000}s (attempt ${retries}/${maxRetries})`));
|
|
136
|
+
await sleep(backoffMs);
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
// Check if we exhausted retries without success
|
|
140
|
+
if (!response || !response.ok) {
|
|
141
|
+
if (repos.length > 0) {
|
|
142
|
+
// Continue with partial results
|
|
143
|
+
console.log(chalk.yellow(` ⚠️ Rate limit reached, continuing with ${repos.length} repos fetched`));
|
|
144
|
+
partial = true;
|
|
145
|
+
break;
|
|
146
|
+
}
|
|
147
|
+
return {
|
|
148
|
+
repos: [],
|
|
149
|
+
rateLimit,
|
|
150
|
+
partial: false,
|
|
151
|
+
error: `GitHub API error: ${response?.status || 'No response'}`
|
|
152
|
+
};
|
|
153
|
+
}
|
|
154
|
+
const batch = await response.json();
|
|
155
|
+
// Empty batch means no more repos
|
|
156
|
+
if (batch.length === 0) {
|
|
157
|
+
break;
|
|
158
|
+
}
|
|
159
|
+
repos.push(...batch);
|
|
160
|
+
// Show progress for large orgs
|
|
161
|
+
if (repos.length >= 100 && repos.length % 100 === 0) {
|
|
162
|
+
console.log(chalk.gray(` Fetched ${repos.length} repos...`));
|
|
163
|
+
}
|
|
164
|
+
// Last page if we got fewer than perPage
|
|
165
|
+
if (batch.length < perPage) {
|
|
166
|
+
break;
|
|
167
|
+
}
|
|
168
|
+
page++;
|
|
169
|
+
}
|
|
170
|
+
return {
|
|
171
|
+
repos,
|
|
172
|
+
rateLimit,
|
|
173
|
+
partial
|
|
174
|
+
};
|
|
175
|
+
}
|
|
176
|
+
/**
|
|
177
|
+
* Build HTTPS clone URL with PAT authentication
|
|
178
|
+
*
|
|
179
|
+
* @param owner - Repository owner (org or user)
|
|
180
|
+
* @param repo - Repository name
|
|
181
|
+
* @param pat - Personal Access Token
|
|
182
|
+
* @returns Clone URL with embedded authentication
|
|
183
|
+
*/
|
|
184
|
+
function buildGitHubCloneUrl(owner, repo, pat) {
|
|
185
|
+
// Format: https://{pat}@github.com/{owner}/{repo}.git
|
|
186
|
+
// URL-encode to handle special characters
|
|
187
|
+
const encodedOwner = encodeURIComponent(owner);
|
|
188
|
+
const encodedRepo = encodeURIComponent(repo);
|
|
189
|
+
return `https://${pat}@github.com/${encodedOwner}/${encodedRepo}.git`;
|
|
190
|
+
}
|
|
191
|
+
/**
|
|
192
|
+
* Trigger GitHub repository cloning during init
|
|
193
|
+
*
|
|
194
|
+
* This function:
|
|
195
|
+
* 1. Fetches repository list from GitHub organization
|
|
196
|
+
* 2. Filters repositories by clone pattern (glob/regex)
|
|
197
|
+
* 3. Creates a background job for cloning
|
|
198
|
+
* 4. Starts cloning asynchronously (non-blocking)
|
|
199
|
+
*
|
|
200
|
+
* @param projectPath - Target directory for cloning
|
|
201
|
+
* @param githubRepoSelection - GitHub org and PAT
|
|
202
|
+
* @param clonePattern - Clone pattern configuration
|
|
203
|
+
* @returns Job ID for dependency tracking, or undefined if skipped/failed
|
|
204
|
+
*/
|
|
205
|
+
export async function triggerGitHubRepoCloning(projectPath, githubRepoSelection, clonePattern) {
|
|
206
|
+
// Skip if user chose to skip cloning
|
|
207
|
+
if (clonePattern.strategy === 'skip') {
|
|
208
|
+
console.log(chalk.gray('\n Skipping repository cloning (can configure later with /specweave-github:clone-repos)\n'));
|
|
209
|
+
return undefined;
|
|
210
|
+
}
|
|
211
|
+
const { org, pat } = githubRepoSelection;
|
|
212
|
+
if (!org) {
|
|
213
|
+
console.log(chalk.yellow('\n No GitHub organization specified for cloning.\n'));
|
|
214
|
+
return undefined;
|
|
215
|
+
}
|
|
216
|
+
if (!pat) {
|
|
217
|
+
console.log(chalk.yellow('\n No GitHub PAT provided. Cannot clone repositories.\n'));
|
|
218
|
+
return undefined;
|
|
219
|
+
}
|
|
220
|
+
// Security warning about token visibility
|
|
221
|
+
console.log(chalk.yellow('\n ⚠️ Note: PAT will be visible in process list during clone (Git limitation)'));
|
|
222
|
+
console.log(chalk.gray(' 💡 Tip: Use PAT with minimal scope (repo:read) for cloning\n'));
|
|
223
|
+
console.log(chalk.blue('\n📦 Fetching GitHub Repositories\n'));
|
|
224
|
+
// Fetch repos from GitHub API
|
|
225
|
+
const fetchResult = await fetchGitHubRepos(org, pat);
|
|
226
|
+
if (fetchResult.error) {
|
|
227
|
+
console.log(chalk.red(` ❌ ${fetchResult.error}\n`));
|
|
228
|
+
return undefined;
|
|
229
|
+
}
|
|
230
|
+
if (fetchResult.partial) {
|
|
231
|
+
console.log(chalk.yellow(` ⚠️ Partial fetch: Got ${fetchResult.repos.length} repos before rate limit\n`));
|
|
232
|
+
}
|
|
233
|
+
const allRepos = fetchResult.repos;
|
|
234
|
+
if (allRepos.length === 0) {
|
|
235
|
+
console.log(chalk.yellow('\n No repositories found in organization.\n'));
|
|
236
|
+
return undefined;
|
|
237
|
+
}
|
|
238
|
+
console.log(chalk.green(` ✓ Found ${allRepos.length} repositories in ${org}`));
|
|
239
|
+
// Filter by pattern
|
|
240
|
+
const filteredRepos = filterRepositoriesByPattern(allRepos, clonePattern);
|
|
241
|
+
if (filteredRepos.length === 0) {
|
|
242
|
+
const patternDesc = clonePattern.pattern ? ` matching "${clonePattern.pattern}"` : '';
|
|
243
|
+
console.log(chalk.yellow(`\n No repositories${patternDesc} to clone.\n`));
|
|
244
|
+
return undefined;
|
|
245
|
+
}
|
|
246
|
+
console.log(chalk.blue(`\n🔄 Starting background clone for ${filteredRepos.length} repositories...\n`));
|
|
247
|
+
// Show repos to be cloned
|
|
248
|
+
const previewCount = Math.min(filteredRepos.length, 10);
|
|
249
|
+
for (let i = 0; i < previewCount; i++) {
|
|
250
|
+
console.log(chalk.gray(` 📁 ${filteredRepos[i].name}`));
|
|
251
|
+
}
|
|
252
|
+
if (filteredRepos.length > 10) {
|
|
253
|
+
console.log(chalk.gray(` ... and ${filteredRepos.length - 10} more`));
|
|
254
|
+
}
|
|
255
|
+
console.log('');
|
|
256
|
+
// Prepare repositories with clone URLs
|
|
257
|
+
const reposWithUrls = filteredRepos.map(r => ({
|
|
258
|
+
owner: org,
|
|
259
|
+
name: r.name,
|
|
260
|
+
path: r.name, // Clone directly into project path
|
|
261
|
+
cloneUrl: buildGitHubCloneUrl(org, r.name, pat)
|
|
262
|
+
}));
|
|
263
|
+
// Launch background clone job
|
|
264
|
+
const result = await launchCloneJob({
|
|
265
|
+
projectPath,
|
|
266
|
+
repositories: reposWithUrls
|
|
267
|
+
});
|
|
268
|
+
// Show progress info
|
|
269
|
+
console.log(chalk.gray(` Repositories will be cloned to: ${projectPath}/`));
|
|
270
|
+
console.log(chalk.gray(` Job ID: ${result.job.id}`));
|
|
271
|
+
if (result.isBackground) {
|
|
272
|
+
console.log(chalk.green(` ✓ Clone job started in background (PID: ${result.pid})`));
|
|
273
|
+
console.log(chalk.cyan('\n Check progress: /specweave:jobs'));
|
|
274
|
+
console.log(chalk.cyan(` Kill if needed: /specweave:jobs --kill ${result.job.id}`));
|
|
275
|
+
console.log(chalk.gray('\n Init will continue - cloning runs independently.\n'));
|
|
276
|
+
}
|
|
277
|
+
else {
|
|
278
|
+
console.log(chalk.yellow(' ⚠️ Running in foreground (clone worker not found)'));
|
|
279
|
+
console.log(chalk.gray(' Init will block until cloning completes.\n'));
|
|
280
|
+
}
|
|
281
|
+
// Return job ID for dependency tracking
|
|
282
|
+
return result.job.id;
|
|
283
|
+
}
|
|
284
|
+
//# sourceMappingURL=github-repo-cloning.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"github-repo-cloning.js","sourceRoot":"","sources":["../../../../../src/cli/helpers/init/github-repo-cloning.ts"],"names":[],"mappings":"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"}
|
|
@@ -27,6 +27,26 @@ export interface AdoClonePatternResult {
|
|
|
27
27
|
}
|
|
28
28
|
import type { AdoProjectSelection } from '../issue-tracker/types.js';
|
|
29
29
|
export type { AdoProjectSelection };
|
|
30
|
+
/**
|
|
31
|
+
* GitHub repository selection (for multi-repo cloning)
|
|
32
|
+
*/
|
|
33
|
+
export interface GitHubRepoSelection {
|
|
34
|
+
/** GitHub organization or owner */
|
|
35
|
+
org: string;
|
|
36
|
+
/** Personal Access Token */
|
|
37
|
+
pat: string;
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* Bitbucket repository selection (for multi-repo cloning)
|
|
41
|
+
*/
|
|
42
|
+
export interface BitbucketRepoSelection {
|
|
43
|
+
/** Bitbucket workspace slug */
|
|
44
|
+
workspace: string;
|
|
45
|
+
/** Bitbucket username */
|
|
46
|
+
username: string;
|
|
47
|
+
/** Bitbucket App Password */
|
|
48
|
+
appPassword: string;
|
|
49
|
+
}
|
|
30
50
|
/**
|
|
31
51
|
* Result of repository setup
|
|
32
52
|
*/
|
|
@@ -39,6 +59,10 @@ export interface RepositorySetupResult {
|
|
|
39
59
|
adoClonePatternResult?: AdoClonePatternResult;
|
|
40
60
|
/** ADO project(s) to clone repositories from */
|
|
41
61
|
adoProjectSelection?: AdoProjectSelection;
|
|
62
|
+
/** GitHub repo selection for multi-repo cloning (v0.32.7+) */
|
|
63
|
+
githubRepoSelection?: GitHubRepoSelection;
|
|
64
|
+
/** Bitbucket repo selection for multi-repo cloning (v0.32.7+) */
|
|
65
|
+
bitbucketRepoSelection?: BitbucketRepoSelection;
|
|
42
66
|
}
|
|
43
67
|
/**
|
|
44
68
|
* Generic multi-repo pattern selection strategy type
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"repository-setup.d.ts","sourceRoot":"","sources":["../../../../../src/cli/helpers/init/repository-setup.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAKH,OAAO,KAAK,EAAE,iBAAiB,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAClE,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,6BAA6B,CAAC;AA6DrE;;GAEG;AACH,MAAM,WAAW,sBAAsB;IACrC,SAAS,EAAE,MAAM,CAAC;IAClB,IAAI,EAAE,OAAO,CAAC;IACd,YAAY,EAAE,YAAY,GAAG,IAAI,CAAC;IAClC,QAAQ,CAAC,EAAE,iBAAiB,CAAC;CAC9B;AAED;;GAEG;AACH,MAAM,MAAM,gBAAgB,GAAG,KAAK,GAAG,cAAc,GAAG,eAAe,GAAG,MAAM,CAAC;AAEjF;;GAEG;AACH,MAAM,WAAW,qBAAqB;IACpC,QAAQ,EAAE,gBAAgB,CAAC;IAC3B,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,OAAO,CAAC,EAAE,OAAO,CAAC;CACnB;AAGD,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,2BAA2B,CAAC;AACrE,YAAY,EAAE,mBAAmB,EAAE,CAAC;AAEpC;;GAEG;AACH,MAAM,WAAW,qBAAqB;IACpC,OAAO,EAAE,iBAAiB,CAAC;IAC3B,WAAW,EAAE,OAAO,CAAC;IACrB,0FAA0F;IAC1F,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,4BAA4B;IAC5B,qBAAqB,CAAC,EAAE,qBAAqB,CAAC;IAC9C,gDAAgD;IAChD,mBAAmB,CAAC,EAAE,mBAAmB,CAAC;
|
|
1
|
+
{"version":3,"file":"repository-setup.d.ts","sourceRoot":"","sources":["../../../../../src/cli/helpers/init/repository-setup.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAKH,OAAO,KAAK,EAAE,iBAAiB,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAClE,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,6BAA6B,CAAC;AA6DrE;;GAEG;AACH,MAAM,WAAW,sBAAsB;IACrC,SAAS,EAAE,MAAM,CAAC;IAClB,IAAI,EAAE,OAAO,CAAC;IACd,YAAY,EAAE,YAAY,GAAG,IAAI,CAAC;IAClC,QAAQ,CAAC,EAAE,iBAAiB,CAAC;CAC9B;AAED;;GAEG;AACH,MAAM,MAAM,gBAAgB,GAAG,KAAK,GAAG,cAAc,GAAG,eAAe,GAAG,MAAM,CAAC;AAEjF;;GAEG;AACH,MAAM,WAAW,qBAAqB;IACpC,QAAQ,EAAE,gBAAgB,CAAC;IAC3B,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,OAAO,CAAC,EAAE,OAAO,CAAC;CACnB;AAGD,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,2BAA2B,CAAC;AACrE,YAAY,EAAE,mBAAmB,EAAE,CAAC;AAEpC;;GAEG;AACH,MAAM,WAAW,mBAAmB;IAClC,mCAAmC;IACnC,GAAG,EAAE,MAAM,CAAC;IACZ,4BAA4B;IAC5B,GAAG,EAAE,MAAM,CAAC;CACb;AAED;;GAEG;AACH,MAAM,WAAW,sBAAsB;IACrC,+BAA+B;IAC/B,SAAS,EAAE,MAAM,CAAC;IAClB,yBAAyB;IACzB,QAAQ,EAAE,MAAM,CAAC;IACjB,6BAA6B;IAC7B,WAAW,EAAE,MAAM,CAAC;CACrB;AAED;;GAEG;AACH,MAAM,WAAW,qBAAqB;IACpC,OAAO,EAAE,iBAAiB,CAAC;IAC3B,WAAW,EAAE,OAAO,CAAC;IACrB,0FAA0F;IAC1F,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,4BAA4B;IAC5B,qBAAqB,CAAC,EAAE,qBAAqB,CAAC;IAC9C,gDAAgD;IAChD,mBAAmB,CAAC,EAAE,mBAAmB,CAAC;IAC1C,8DAA8D;IAC9D,mBAAmB,CAAC,EAAE,mBAAmB,CAAC;IAC1C,iEAAiE;IACjE,sBAAsB,CAAC,EAAE,sBAAsB,CAAC;CACjD;AAo1BD;;GAEG;AACH,MAAM,MAAM,sBAAsB,GAAG,KAAK,GAAG,cAAc,GAAG,eAAe,GAAG,MAAM,CAAC;AAEvF;;GAEG;AACH,MAAM,WAAW,sBAAsB;IACrC,QAAQ,EAAE,sBAAsB,CAAC;IACjC,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,OAAO,CAAC,EAAE,OAAO,CAAC;CACnB;AA6GD;;;;;GAKG;AACH,wBAAsB,sBAAsB,CAAC,OAAO,EAAE,sBAAsB,GAAG,OAAO,CAAC,qBAAqB,CAAC,CA2I5G"}
|
|
@@ -160,6 +160,108 @@ async function promptAdoProjectSelection(targetDir, strings) {
|
|
|
160
160
|
projects: selectedProjects
|
|
161
161
|
};
|
|
162
162
|
}
|
|
163
|
+
/**
|
|
164
|
+
* Prompt user for GitHub organization and PAT for multi-repo cloning
|
|
165
|
+
*
|
|
166
|
+
* @param targetDir - Target directory (for reading existing .env)
|
|
167
|
+
* @param gitHubRemote - Detected GitHub remote (provides default org)
|
|
168
|
+
* @param strings - Translated strings
|
|
169
|
+
* @returns GitHub selection or null if cancelled
|
|
170
|
+
*/
|
|
171
|
+
async function promptGitHubRepoSelection(targetDir, gitHubRemote, strings) {
|
|
172
|
+
// Check for existing credentials in .env or environment
|
|
173
|
+
let existingOrg;
|
|
174
|
+
let existingPat;
|
|
175
|
+
const envContent = readEnvFile(targetDir);
|
|
176
|
+
if (envContent) {
|
|
177
|
+
const parsed = parseEnvFile(envContent);
|
|
178
|
+
existingOrg = parsed.GITHUB_ORG;
|
|
179
|
+
existingPat = parsed.GITHUB_PAT || parsed.GITHUB_TOKEN;
|
|
180
|
+
}
|
|
181
|
+
// Fall back to environment variables
|
|
182
|
+
existingOrg = existingOrg || process.env.GITHUB_ORG;
|
|
183
|
+
existingPat = existingPat || process.env.GITHUB_PAT || process.env.GITHUB_TOKEN;
|
|
184
|
+
// Use detected remote owner as default
|
|
185
|
+
const defaultOrg = existingOrg || gitHubRemote?.owner;
|
|
186
|
+
// Prompt for organization
|
|
187
|
+
const org = await input({
|
|
188
|
+
message: strings.githubOrgPrompt,
|
|
189
|
+
default: defaultOrg,
|
|
190
|
+
validate: (value) => {
|
|
191
|
+
if (!value.trim())
|
|
192
|
+
return 'Organization or username is required';
|
|
193
|
+
return true;
|
|
194
|
+
}
|
|
195
|
+
});
|
|
196
|
+
// Prompt for PAT
|
|
197
|
+
const pat = await password({
|
|
198
|
+
message: strings.githubPatPrompt,
|
|
199
|
+
mask: true,
|
|
200
|
+
validate: (value) => {
|
|
201
|
+
if (!value.trim())
|
|
202
|
+
return 'Personal Access Token is required';
|
|
203
|
+
return true;
|
|
204
|
+
}
|
|
205
|
+
});
|
|
206
|
+
console.log(chalk.green(` ✓ ${strings.githubSelected.replace('{org}', org)}`));
|
|
207
|
+
return { org, pat };
|
|
208
|
+
}
|
|
209
|
+
/**
|
|
210
|
+
* Prompt user for Bitbucket workspace and credentials for multi-repo cloning
|
|
211
|
+
*
|
|
212
|
+
* @param targetDir - Target directory (for reading existing .env)
|
|
213
|
+
* @param strings - Translated strings
|
|
214
|
+
* @returns Bitbucket selection or null if cancelled
|
|
215
|
+
*/
|
|
216
|
+
async function promptBitbucketRepoSelection(targetDir, strings) {
|
|
217
|
+
// Check for existing credentials in .env or environment
|
|
218
|
+
let existingWorkspace;
|
|
219
|
+
let existingUsername;
|
|
220
|
+
let existingAppPassword;
|
|
221
|
+
const envContent = readEnvFile(targetDir);
|
|
222
|
+
if (envContent) {
|
|
223
|
+
const parsed = parseEnvFile(envContent);
|
|
224
|
+
existingWorkspace = parsed.BITBUCKET_WORKSPACE;
|
|
225
|
+
existingUsername = parsed.BITBUCKET_USERNAME;
|
|
226
|
+
existingAppPassword = parsed.BITBUCKET_APP_PASSWORD;
|
|
227
|
+
}
|
|
228
|
+
// Fall back to environment variables
|
|
229
|
+
existingWorkspace = existingWorkspace || process.env.BITBUCKET_WORKSPACE;
|
|
230
|
+
existingUsername = existingUsername || process.env.BITBUCKET_USERNAME;
|
|
231
|
+
existingAppPassword = existingAppPassword || process.env.BITBUCKET_APP_PASSWORD;
|
|
232
|
+
// Prompt for workspace
|
|
233
|
+
const workspace = await input({
|
|
234
|
+
message: strings.bitbucketWorkspacePrompt,
|
|
235
|
+
default: existingWorkspace,
|
|
236
|
+
validate: (value) => {
|
|
237
|
+
if (!value.trim())
|
|
238
|
+
return 'Workspace slug is required';
|
|
239
|
+
return true;
|
|
240
|
+
}
|
|
241
|
+
});
|
|
242
|
+
// Prompt for username
|
|
243
|
+
const username = await input({
|
|
244
|
+
message: strings.bitbucketUsernamePrompt,
|
|
245
|
+
default: existingUsername,
|
|
246
|
+
validate: (value) => {
|
|
247
|
+
if (!value.trim())
|
|
248
|
+
return 'Username is required';
|
|
249
|
+
return true;
|
|
250
|
+
}
|
|
251
|
+
});
|
|
252
|
+
// Prompt for app password
|
|
253
|
+
const appPassword = await password({
|
|
254
|
+
message: strings.bitbucketAppPasswordPrompt,
|
|
255
|
+
mask: true,
|
|
256
|
+
validate: (value) => {
|
|
257
|
+
if (!value.trim())
|
|
258
|
+
return 'App Password is required';
|
|
259
|
+
return true;
|
|
260
|
+
}
|
|
261
|
+
});
|
|
262
|
+
console.log(chalk.green(` ✓ ${strings.bitbucketSelected.replace('{workspace}', workspace)}`));
|
|
263
|
+
return { workspace, username, appPassword };
|
|
264
|
+
}
|
|
163
265
|
/**
|
|
164
266
|
* Get translated strings for repository setup
|
|
165
267
|
*/
|
|
@@ -216,6 +318,14 @@ function getRepoStrings(language) {
|
|
|
216
318
|
bitbucketMultiRepoHeader: '📁 Bitbucket Multi-Repository Selection',
|
|
217
319
|
bitbucketMultiRepoDesc: 'Select which repositories to work with from your Bitbucket workspace.',
|
|
218
320
|
bitbucketSelectStrategy: 'How do you want to select Bitbucket repositories?',
|
|
321
|
+
// GitHub/Bitbucket credential prompts (v0.32.7+)
|
|
322
|
+
githubOrgPrompt: 'GitHub organization or username:',
|
|
323
|
+
githubPatPrompt: 'GitHub Personal Access Token (PAT):',
|
|
324
|
+
githubSelected: 'GitHub organization "{org}" configured for cloning',
|
|
325
|
+
bitbucketWorkspacePrompt: 'Bitbucket workspace slug:',
|
|
326
|
+
bitbucketUsernamePrompt: 'Bitbucket username:',
|
|
327
|
+
bitbucketAppPasswordPrompt: 'Bitbucket App Password:',
|
|
328
|
+
bitbucketSelected: 'Bitbucket workspace "{workspace}" configured for cloning',
|
|
219
329
|
},
|
|
220
330
|
ru: {
|
|
221
331
|
header: '📦 Хостинг репозитория',
|
|
@@ -268,6 +378,13 @@ function getRepoStrings(language) {
|
|
|
268
378
|
bitbucketMultiRepoHeader: '📁 Выбор репозиториев Bitbucket',
|
|
269
379
|
bitbucketMultiRepoDesc: 'Выберите репозитории для работы из вашего рабочего пространства Bitbucket.',
|
|
270
380
|
bitbucketSelectStrategy: 'Как вы хотите выбрать репозитории Bitbucket?',
|
|
381
|
+
githubOrgPrompt: 'Организация или имя пользователя GitHub:',
|
|
382
|
+
githubPatPrompt: 'Personal Access Token (PAT) GitHub:',
|
|
383
|
+
githubSelected: 'Организация GitHub "{org}" настроена для клонирования',
|
|
384
|
+
bitbucketWorkspacePrompt: 'Workspace Bitbucket:',
|
|
385
|
+
bitbucketUsernamePrompt: 'Имя пользователя Bitbucket:',
|
|
386
|
+
bitbucketAppPasswordPrompt: 'App Password Bitbucket:',
|
|
387
|
+
bitbucketSelected: 'Workspace Bitbucket "{workspace}" настроен для клонирования',
|
|
271
388
|
},
|
|
272
389
|
es: {
|
|
273
390
|
header: '📦 Alojamiento del repositorio',
|
|
@@ -320,6 +437,13 @@ function getRepoStrings(language) {
|
|
|
320
437
|
bitbucketMultiRepoHeader: '📁 Selección de repositorios Bitbucket',
|
|
321
438
|
bitbucketMultiRepoDesc: 'Seleccione los repositorios de su espacio de trabajo Bitbucket.',
|
|
322
439
|
bitbucketSelectStrategy: '¿Cómo desea seleccionar los repositorios de Bitbucket?',
|
|
440
|
+
githubOrgPrompt: 'Organización o nombre de usuario de GitHub:',
|
|
441
|
+
githubPatPrompt: 'Token de acceso personal (PAT) de GitHub:',
|
|
442
|
+
githubSelected: 'Organización de GitHub "{org}" configurada para clonar',
|
|
443
|
+
bitbucketWorkspacePrompt: 'Workspace de Bitbucket:',
|
|
444
|
+
bitbucketUsernamePrompt: 'Nombre de usuario de Bitbucket:',
|
|
445
|
+
bitbucketAppPasswordPrompt: 'Contraseña de aplicación de Bitbucket:',
|
|
446
|
+
bitbucketSelected: 'Workspace de Bitbucket "{workspace}" configurado para clonar',
|
|
323
447
|
},
|
|
324
448
|
zh: {
|
|
325
449
|
header: '📦 仓库托管',
|
|
@@ -372,6 +496,13 @@ function getRepoStrings(language) {
|
|
|
372
496
|
bitbucketMultiRepoHeader: '📁 Bitbucket 多仓库选择',
|
|
373
497
|
bitbucketMultiRepoDesc: '从您的 Bitbucket 工作区中选择要使用的仓库。',
|
|
374
498
|
bitbucketSelectStrategy: '您想如何选择 Bitbucket 仓库?',
|
|
499
|
+
githubOrgPrompt: 'GitHub 组织或用户名:',
|
|
500
|
+
githubPatPrompt: 'GitHub 个人访问令牌 (PAT):',
|
|
501
|
+
githubSelected: 'GitHub 组织 "{org}" 已配置用于克隆',
|
|
502
|
+
bitbucketWorkspacePrompt: 'Bitbucket 工作区:',
|
|
503
|
+
bitbucketUsernamePrompt: 'Bitbucket 用户名:',
|
|
504
|
+
bitbucketAppPasswordPrompt: 'Bitbucket 应用密码:',
|
|
505
|
+
bitbucketSelected: 'Bitbucket 工作区 "{workspace}" 已配置用于克隆',
|
|
375
506
|
},
|
|
376
507
|
de: {
|
|
377
508
|
header: '📦 Repository-Hosting',
|
|
@@ -424,6 +555,13 @@ function getRepoStrings(language) {
|
|
|
424
555
|
bitbucketMultiRepoHeader: '📁 Bitbucket Multi-Repository Auswahl',
|
|
425
556
|
bitbucketMultiRepoDesc: 'Wählen Sie die Repositories aus Ihrem Bitbucket-Workspace.',
|
|
426
557
|
bitbucketSelectStrategy: 'Wie möchten Sie Bitbucket-Repositories auswählen?',
|
|
558
|
+
githubOrgPrompt: 'GitHub-Organisation oder Benutzername:',
|
|
559
|
+
githubPatPrompt: 'GitHub Personal Access Token (PAT):',
|
|
560
|
+
githubSelected: 'GitHub-Organisation "{org}" für Klonen konfiguriert',
|
|
561
|
+
bitbucketWorkspacePrompt: 'Bitbucket-Workspace:',
|
|
562
|
+
bitbucketUsernamePrompt: 'Bitbucket-Benutzername:',
|
|
563
|
+
bitbucketAppPasswordPrompt: 'Bitbucket-App-Passwort:',
|
|
564
|
+
bitbucketSelected: 'Bitbucket-Workspace "{workspace}" für Klonen konfiguriert',
|
|
427
565
|
},
|
|
428
566
|
fr: {
|
|
429
567
|
header: '📦 Hébergement du dépôt',
|
|
@@ -476,6 +614,13 @@ function getRepoStrings(language) {
|
|
|
476
614
|
bitbucketMultiRepoHeader: '📁 Sélection multi-dépôt Bitbucket',
|
|
477
615
|
bitbucketMultiRepoDesc: 'Sélectionnez les dépôts de votre espace de travail Bitbucket.',
|
|
478
616
|
bitbucketSelectStrategy: 'Comment voulez-vous sélectionner les dépôts Bitbucket?',
|
|
617
|
+
githubOrgPrompt: 'Organisation ou nom d\'utilisateur GitHub :',
|
|
618
|
+
githubPatPrompt: 'Token d\'accès personnel GitHub (PAT) :',
|
|
619
|
+
githubSelected: 'Organisation GitHub "{org}" configurée pour le clonage',
|
|
620
|
+
bitbucketWorkspacePrompt: 'Workspace Bitbucket :',
|
|
621
|
+
bitbucketUsernamePrompt: 'Nom d\'utilisateur Bitbucket :',
|
|
622
|
+
bitbucketAppPasswordPrompt: 'Mot de passe d\'application Bitbucket :',
|
|
623
|
+
bitbucketSelected: 'Workspace Bitbucket "{workspace}" configuré pour le clonage',
|
|
479
624
|
},
|
|
480
625
|
ja: {
|
|
481
626
|
header: '📦 リポジトリホスティング',
|
|
@@ -528,6 +673,13 @@ function getRepoStrings(language) {
|
|
|
528
673
|
bitbucketMultiRepoHeader: '📁 Bitbucket マルチリポジトリ選択',
|
|
529
674
|
bitbucketMultiRepoDesc: 'Bitbucketワークスペースからリポジトリを選択してください。',
|
|
530
675
|
bitbucketSelectStrategy: 'Bitbucketリポジトリをどのように選択しますか?',
|
|
676
|
+
githubOrgPrompt: 'GitHub組織またはユーザー名:',
|
|
677
|
+
githubPatPrompt: 'GitHub Personal Access Token (PAT):',
|
|
678
|
+
githubSelected: 'GitHub組織 "{org}" がクローン用に設定されました',
|
|
679
|
+
bitbucketWorkspacePrompt: 'Bitbucketワークスペース:',
|
|
680
|
+
bitbucketUsernamePrompt: 'Bitbucketユーザー名:',
|
|
681
|
+
bitbucketAppPasswordPrompt: 'Bitbucketアプリパスワード:',
|
|
682
|
+
bitbucketSelected: 'Bitbucketワークスペース "{workspace}" がクローン用に設定されました',
|
|
531
683
|
},
|
|
532
684
|
ko: {
|
|
533
685
|
header: '📦 저장소 호스팅',
|
|
@@ -580,6 +732,13 @@ function getRepoStrings(language) {
|
|
|
580
732
|
bitbucketMultiRepoHeader: '📁 Bitbucket 다중 저장소 선택',
|
|
581
733
|
bitbucketMultiRepoDesc: 'Bitbucket 워크스페이스에서 저장소를 선택하세요.',
|
|
582
734
|
bitbucketSelectStrategy: 'Bitbucket 저장소를 어떻게 선택하시겠습니까?',
|
|
735
|
+
githubOrgPrompt: 'GitHub 조직 또는 사용자 이름:',
|
|
736
|
+
githubPatPrompt: 'GitHub Personal Access Token (PAT):',
|
|
737
|
+
githubSelected: 'GitHub 조직 "{org}"이(가) 복제용으로 구성되었습니다',
|
|
738
|
+
bitbucketWorkspacePrompt: 'Bitbucket 워크스페이스:',
|
|
739
|
+
bitbucketUsernamePrompt: 'Bitbucket 사용자 이름:',
|
|
740
|
+
bitbucketAppPasswordPrompt: 'Bitbucket 앱 비밀번호:',
|
|
741
|
+
bitbucketSelected: 'Bitbucket 워크스페이스 "{workspace}"이(가) 복제용으로 구성되었습니다',
|
|
583
742
|
},
|
|
584
743
|
pt: {
|
|
585
744
|
header: '📦 Hospedagem do repositório',
|
|
@@ -632,6 +791,13 @@ function getRepoStrings(language) {
|
|
|
632
791
|
bitbucketMultiRepoHeader: '📁 Seleção de múltiplos repositórios Bitbucket',
|
|
633
792
|
bitbucketMultiRepoDesc: 'Selecione os repositórios do seu workspace Bitbucket.',
|
|
634
793
|
bitbucketSelectStrategy: 'Como você quer selecionar os repositórios do Bitbucket?',
|
|
794
|
+
githubOrgPrompt: 'Organização ou nome de usuário do GitHub:',
|
|
795
|
+
githubPatPrompt: 'Token de acesso pessoal do GitHub (PAT):',
|
|
796
|
+
githubSelected: 'Organização do GitHub "{org}" configurada para clonagem',
|
|
797
|
+
bitbucketWorkspacePrompt: 'Workspace do Bitbucket:',
|
|
798
|
+
bitbucketUsernamePrompt: 'Nome de usuário do Bitbucket:',
|
|
799
|
+
bitbucketAppPasswordPrompt: 'Senha de aplicativo do Bitbucket:',
|
|
800
|
+
bitbucketSelected: 'Workspace do Bitbucket "{workspace}" configurado para clonagem',
|
|
635
801
|
},
|
|
636
802
|
};
|
|
637
803
|
return strings[language] || strings.en;
|
|
@@ -807,8 +973,10 @@ export async function setupRepositoryHosting(options) {
|
|
|
807
973
|
let adoClonePattern;
|
|
808
974
|
let adoClonePatternResult;
|
|
809
975
|
let adoProjectSelection;
|
|
976
|
+
let githubRepoSelection;
|
|
977
|
+
let bitbucketRepoSelection;
|
|
810
978
|
if (isMultiRepo && (provider === 'ado' || provider === 'github' || provider === 'bitbucket')) {
|
|
811
|
-
// Step 3a:
|
|
979
|
+
// Step 3a: Provider-specific credential prompts
|
|
812
980
|
if (provider === 'ado') {
|
|
813
981
|
console.log(chalk.blue('\n📁 Azure DevOps Project Selection\n'));
|
|
814
982
|
console.log(chalk.gray(' Select which project(s) to clone repositories from.\n'));
|
|
@@ -817,6 +985,24 @@ export async function setupRepositoryHosting(options) {
|
|
|
817
985
|
adoProjectSelection = projectSelection;
|
|
818
986
|
}
|
|
819
987
|
}
|
|
988
|
+
else if (provider === 'github') {
|
|
989
|
+
// GitHub multi-repo credential prompt (v0.32.7+)
|
|
990
|
+
console.log(chalk.blue(`\n${strings.githubMultiRepoHeader}\n`));
|
|
991
|
+
console.log(chalk.gray(` ${strings.githubMultiRepoDesc}\n`));
|
|
992
|
+
const githubSelection = await promptGitHubRepoSelection(options.targetDir, gitHubRemote, strings);
|
|
993
|
+
if (githubSelection) {
|
|
994
|
+
githubRepoSelection = githubSelection;
|
|
995
|
+
}
|
|
996
|
+
}
|
|
997
|
+
else if (provider === 'bitbucket') {
|
|
998
|
+
// Bitbucket multi-repo credential prompt (v0.32.7+)
|
|
999
|
+
console.log(chalk.blue(`\n${strings.bitbucketMultiRepoHeader}\n`));
|
|
1000
|
+
console.log(chalk.gray(` ${strings.bitbucketMultiRepoDesc}\n`));
|
|
1001
|
+
const bitbucketSelection = await promptBitbucketRepoSelection(options.targetDir, strings);
|
|
1002
|
+
if (bitbucketSelection) {
|
|
1003
|
+
bitbucketRepoSelection = bitbucketSelection;
|
|
1004
|
+
}
|
|
1005
|
+
}
|
|
820
1006
|
// Step 3b: Show unified strategy selection (ALL providers)
|
|
821
1007
|
const patternResult = await promptMultiRepoPatternSelection(provider, strings);
|
|
822
1008
|
// Map to ADO-style result for backward compatibility
|
|
@@ -837,6 +1023,14 @@ export async function setupRepositoryHosting(options) {
|
|
|
837
1023
|
}
|
|
838
1024
|
// For 'skip', adoClonePattern remains undefined
|
|
839
1025
|
}
|
|
840
|
-
return {
|
|
1026
|
+
return {
|
|
1027
|
+
hosting: repositoryHosting,
|
|
1028
|
+
isMultiRepo,
|
|
1029
|
+
adoClonePattern,
|
|
1030
|
+
adoClonePatternResult,
|
|
1031
|
+
adoProjectSelection,
|
|
1032
|
+
githubRepoSelection,
|
|
1033
|
+
bitbucketRepoSelection
|
|
1034
|
+
};
|
|
841
1035
|
}
|
|
842
1036
|
//# sourceMappingURL=repository-setup.js.map
|