@uns-kit/cli 0.0.12 → 0.0.13
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/dist/index.js +119 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -1,14 +1,17 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
+
import { execFile } from "node:child_process";
|
|
2
3
|
import { access, cp, mkdir, readFile, readdir, stat, writeFile } from "node:fs/promises";
|
|
3
4
|
import path from "node:path";
|
|
4
5
|
import { fileURLToPath } from "node:url";
|
|
5
6
|
import { createRequire } from "node:module";
|
|
6
7
|
import process from "node:process";
|
|
7
8
|
import readline from "node:readline/promises";
|
|
9
|
+
import { promisify } from "node:util";
|
|
8
10
|
const __filename = fileURLToPath(import.meta.url);
|
|
9
11
|
const __dirname = path.dirname(__filename);
|
|
10
12
|
const require = createRequire(import.meta.url);
|
|
11
13
|
const coreVersion = resolveCoreVersion();
|
|
14
|
+
const execFileAsync = promisify(execFile);
|
|
12
15
|
async function main() {
|
|
13
16
|
const args = process.argv.slice(2);
|
|
14
17
|
const command = args[0];
|
|
@@ -91,7 +94,21 @@ async function configureDevops(targetPath) {
|
|
|
91
94
|
}
|
|
92
95
|
const pkg = JSON.parse(pkgRaw);
|
|
93
96
|
const config = JSON.parse(configRaw);
|
|
94
|
-
|
|
97
|
+
await ensureGitRepository(targetDir);
|
|
98
|
+
const remoteUrl = await getGitRemoteUrl(targetDir, "origin");
|
|
99
|
+
let gitRemoteMessage;
|
|
100
|
+
let ensuredRemoteUrl = remoteUrl;
|
|
101
|
+
if (!ensuredRemoteUrl) {
|
|
102
|
+
const remoteAnswer = (await promptQuestion("Azure DevOps repository URL (e.g. https://dev.azure.com/sijit/industry40/_git/my-repo): ")).trim();
|
|
103
|
+
if (!remoteAnswer) {
|
|
104
|
+
throw new Error("A repository URL is required to set the git remote origin.");
|
|
105
|
+
}
|
|
106
|
+
await addGitRemote(targetDir, "origin", remoteAnswer);
|
|
107
|
+
ensuredRemoteUrl = remoteAnswer;
|
|
108
|
+
gitRemoteMessage = ` Added git remote origin -> ${remoteAnswer}`;
|
|
109
|
+
}
|
|
110
|
+
const inferredOrganization = ensuredRemoteUrl ? inferAzureOrganization(ensuredRemoteUrl) : undefined;
|
|
111
|
+
const defaultOrg = config.devops?.organization?.trim() || inferredOrganization || "sijit";
|
|
95
112
|
const answer = (await promptQuestion(`Azure DevOps organization [${defaultOrg}]: `)).trim();
|
|
96
113
|
const organization = answer || defaultOrg;
|
|
97
114
|
if (!config.devops || typeof config.devops !== "object") {
|
|
@@ -124,6 +141,9 @@ async function configureDevops(targetPath) {
|
|
|
124
141
|
}
|
|
125
142
|
console.log(`\nDevOps tooling configured.`);
|
|
126
143
|
console.log(` Azure organization: ${organization}`);
|
|
144
|
+
if (gitRemoteMessage) {
|
|
145
|
+
console.log(gitRemoteMessage);
|
|
146
|
+
}
|
|
127
147
|
if (pkgChanged) {
|
|
128
148
|
console.log(" Updated package.json scripts/devDependencies. Run pnpm install to fetch new packages.");
|
|
129
149
|
}
|
|
@@ -131,6 +151,104 @@ async function configureDevops(targetPath) {
|
|
|
131
151
|
console.log(" Existing package.json already contained required entries.");
|
|
132
152
|
}
|
|
133
153
|
}
|
|
154
|
+
async function ensureGitRepository(dir) {
|
|
155
|
+
try {
|
|
156
|
+
const { stdout } = await execFileAsync("git", ["rev-parse", "--is-inside-work-tree"], {
|
|
157
|
+
cwd: dir,
|
|
158
|
+
encoding: "utf8",
|
|
159
|
+
});
|
|
160
|
+
if (stdout.trim() !== "true") {
|
|
161
|
+
throw new Error(`Directory ${dir} is not a git repository.`);
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
catch (error) {
|
|
165
|
+
if (isGitCommandNotFoundError(error)) {
|
|
166
|
+
throw new Error("Git is required to run configure-devops but was not found in PATH.");
|
|
167
|
+
}
|
|
168
|
+
const execError = error;
|
|
169
|
+
const stderr = typeof execError.stderr === "string" ? execError.stderr : "";
|
|
170
|
+
if (stderr.includes("not a git repository")) {
|
|
171
|
+
throw new Error(`Directory ${dir} is not a git repository.`);
|
|
172
|
+
}
|
|
173
|
+
throw error;
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
async function getGitRemoteUrl(dir, remoteName) {
|
|
177
|
+
try {
|
|
178
|
+
const { stdout } = await execFileAsync("git", ["remote", "get-url", remoteName], {
|
|
179
|
+
cwd: dir,
|
|
180
|
+
encoding: "utf8",
|
|
181
|
+
});
|
|
182
|
+
return stdout.trim();
|
|
183
|
+
}
|
|
184
|
+
catch (error) {
|
|
185
|
+
if (isGitCommandNotFoundError(error)) {
|
|
186
|
+
throw new Error("Git is required to run configure-devops but was not found in PATH.");
|
|
187
|
+
}
|
|
188
|
+
if (isGitRemoteMissingError(error)) {
|
|
189
|
+
return null;
|
|
190
|
+
}
|
|
191
|
+
throw error;
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
async function addGitRemote(dir, remoteName, remoteUrl) {
|
|
195
|
+
try {
|
|
196
|
+
await execFileAsync("git", ["remote", "add", remoteName, remoteUrl], {
|
|
197
|
+
cwd: dir,
|
|
198
|
+
encoding: "utf8",
|
|
199
|
+
});
|
|
200
|
+
}
|
|
201
|
+
catch (error) {
|
|
202
|
+
if (isGitCommandNotFoundError(error)) {
|
|
203
|
+
throw new Error("Git is required to run configure-devops but was not found in PATH.");
|
|
204
|
+
}
|
|
205
|
+
const execError = error;
|
|
206
|
+
const stderr = typeof execError.stderr === "string" ? execError.stderr.trim() : "";
|
|
207
|
+
if (stderr) {
|
|
208
|
+
throw new Error(`Failed to add git remote origin: ${stderr}`);
|
|
209
|
+
}
|
|
210
|
+
throw new Error(`Failed to add git remote origin: ${error.message}`);
|
|
211
|
+
}
|
|
212
|
+
}
|
|
213
|
+
function inferAzureOrganization(remoteUrl) {
|
|
214
|
+
try {
|
|
215
|
+
const url = new URL(remoteUrl);
|
|
216
|
+
const hostname = url.hostname.toLowerCase();
|
|
217
|
+
if (hostname === "dev.azure.com" || hostname.endsWith(".visualstudio.com")) {
|
|
218
|
+
const segments = url.pathname.split("/").filter(Boolean);
|
|
219
|
+
if (segments.length >= 1) {
|
|
220
|
+
return segments[0];
|
|
221
|
+
}
|
|
222
|
+
}
|
|
223
|
+
}
|
|
224
|
+
catch (error) {
|
|
225
|
+
// ignore parse errors for non-HTTP(S) remotes
|
|
226
|
+
}
|
|
227
|
+
if (remoteUrl.startsWith("git@ssh.dev.azure.com:")) {
|
|
228
|
+
const [, pathPart] = remoteUrl.split(":", 2);
|
|
229
|
+
if (pathPart) {
|
|
230
|
+
const segments = pathPart.split("/").filter(Boolean);
|
|
231
|
+
// Format: v3/{organization}/{project}/{repo}
|
|
232
|
+
if (segments.length >= 2) {
|
|
233
|
+
return segments[1];
|
|
234
|
+
}
|
|
235
|
+
}
|
|
236
|
+
}
|
|
237
|
+
return undefined;
|
|
238
|
+
}
|
|
239
|
+
function isGitRemoteMissingError(error) {
|
|
240
|
+
if (!error || typeof error !== "object") {
|
|
241
|
+
return false;
|
|
242
|
+
}
|
|
243
|
+
const execError = error;
|
|
244
|
+
if (typeof execError.stderr === "string") {
|
|
245
|
+
return execError.stderr.includes("No such remote");
|
|
246
|
+
}
|
|
247
|
+
return false;
|
|
248
|
+
}
|
|
249
|
+
function isGitCommandNotFoundError(error) {
|
|
250
|
+
return Boolean(error && typeof error === "object" && error.code === "ENOENT");
|
|
251
|
+
}
|
|
134
252
|
async function promptQuestion(message) {
|
|
135
253
|
const rl = readline.createInterface({ input: process.stdin, output: process.stdout });
|
|
136
254
|
try {
|