@glpkg/cli 0.2.0
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 +42 -0
- package/dist/cli.d.ts +6 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +26 -0
- package/dist/cli.js.map +1 -0
- package/dist/commands/config.d.ts +6 -0
- package/dist/commands/config.d.ts.map +1 -0
- package/dist/commands/config.js +286 -0
- package/dist/commands/config.js.map +1 -0
- package/dist/commands/index.d.ts +6 -0
- package/dist/commands/index.d.ts.map +1 -0
- package/dist/commands/index.js +14 -0
- package/dist/commands/index.js.map +1 -0
- package/dist/commands/install.d.ts +6 -0
- package/dist/commands/install.d.ts.map +1 -0
- package/dist/commands/install.js +378 -0
- package/dist/commands/install.js.map +1 -0
- package/dist/commands/license.d.ts +8 -0
- package/dist/commands/license.d.ts.map +1 -0
- package/dist/commands/license.js +40 -0
- package/dist/commands/license.js.map +1 -0
- package/dist/commands/publish.d.ts +6 -0
- package/dist/commands/publish.d.ts.map +1 -0
- package/dist/commands/publish.js +666 -0
- package/dist/commands/publish.js.map +1 -0
- package/dist/commands/repo.d.ts +12 -0
- package/dist/commands/repo.d.ts.map +1 -0
- package/dist/commands/repo.js +459 -0
- package/dist/commands/repo.js.map +1 -0
- package/dist/index.d.ts +5 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +11 -0
- package/dist/index.js.map +1 -0
- package/package.json +60 -0
|
@@ -0,0 +1,666 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Publish Command - Publish packages to GitLab
|
|
4
|
+
*/
|
|
5
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
6
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
7
|
+
};
|
|
8
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
9
|
+
exports.publishCommand = void 0;
|
|
10
|
+
const commander_1 = require("commander");
|
|
11
|
+
const chalk_1 = __importDefault(require("chalk"));
|
|
12
|
+
const ora_1 = __importDefault(require("ora"));
|
|
13
|
+
const child_process_1 = require("child_process");
|
|
14
|
+
const core_1 = require("@glpkg/core");
|
|
15
|
+
const adapters_npm_1 = require("@glpkg/adapters.npm");
|
|
16
|
+
const adapters_generic_1 = require("@glpkg/adapters.generic");
|
|
17
|
+
const adapters_pypi_1 = require("@glpkg/adapters.pypi");
|
|
18
|
+
const adapters_go_1 = require("@glpkg/adapters.go");
|
|
19
|
+
const adapters_nuget_1 = require("@glpkg/adapters.nuget");
|
|
20
|
+
const fallback_1 = require("@glpkg/fallback");
|
|
21
|
+
exports.publishCommand = new commander_1.Command('publish')
|
|
22
|
+
.alias('pub')
|
|
23
|
+
.argument('[type]', 'Publish type: latest, dev, beta', 'latest')
|
|
24
|
+
.description('Publish package to GitLab registry')
|
|
25
|
+
.option('--bump <type>', 'Version bump: patch, minor, major')
|
|
26
|
+
.option('--dry-run', 'Run without publishing')
|
|
27
|
+
.option('--token <token>', 'Override GitLab token')
|
|
28
|
+
.option('--no-build', 'Skip prepublishOnly script')
|
|
29
|
+
.option('--git-tag <bool>', 'Create git tag (default: true)', 'true')
|
|
30
|
+
.option('--push <bool>', 'Push to remote (default: true)', 'true')
|
|
31
|
+
.option('--force', 'Force publish')
|
|
32
|
+
.option('--generic', 'Publish as generic package')
|
|
33
|
+
.option('--pypi', 'Publish as PyPI package')
|
|
34
|
+
.option('--go', 'Publish as Go module')
|
|
35
|
+
.option('--nuget', 'Publish as NuGet package')
|
|
36
|
+
.option('--manifest <file>', 'Manifest file (generic only)')
|
|
37
|
+
.action(async (type, options) => {
|
|
38
|
+
try {
|
|
39
|
+
if (options.generic) {
|
|
40
|
+
await publishGeneric(options);
|
|
41
|
+
}
|
|
42
|
+
else if (options.pypi) {
|
|
43
|
+
await publishPyPI(type, options);
|
|
44
|
+
}
|
|
45
|
+
else if (options.go) {
|
|
46
|
+
await publishGo(type, options);
|
|
47
|
+
}
|
|
48
|
+
else if (options.nuget) {
|
|
49
|
+
await publishNuGet(type, options);
|
|
50
|
+
}
|
|
51
|
+
else {
|
|
52
|
+
await publishNpm(type, options);
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
catch (error) {
|
|
56
|
+
console.error(chalk_1.default.red('✗'), 'Publish failed:', error.message);
|
|
57
|
+
process.exit(1);
|
|
58
|
+
}
|
|
59
|
+
});
|
|
60
|
+
/**
|
|
61
|
+
* Publish npm package
|
|
62
|
+
*/
|
|
63
|
+
async function publishNpm(type, options) {
|
|
64
|
+
console.log(chalk_1.default.blue.bold('glpkg publish'), chalk_1.default.gray('(npm)'));
|
|
65
|
+
console.log();
|
|
66
|
+
const tokenManager = (0, core_1.createTokenManager)();
|
|
67
|
+
const configManager = (0, core_1.createConfigManager)();
|
|
68
|
+
const token = tokenManager.resolveToken(options.token);
|
|
69
|
+
const pkgManager = (0, adapters_npm_1.createPackageJsonManager)();
|
|
70
|
+
const npmrcManager = (0, adapters_npm_1.createNpmrcManager)();
|
|
71
|
+
// Check git status
|
|
72
|
+
if (!options.dryRun) {
|
|
73
|
+
checkGitClean(options.force);
|
|
74
|
+
}
|
|
75
|
+
// Detect project info
|
|
76
|
+
const spinner = (0, ora_1.default)('Detecting project info...').start();
|
|
77
|
+
let projectInfo;
|
|
78
|
+
try {
|
|
79
|
+
const glabOutput = (0, child_process_1.execSync)('glab api projects/:id -X GET', { encoding: 'utf-8' });
|
|
80
|
+
const project = JSON.parse(glabOutput);
|
|
81
|
+
const client = (0, core_1.createClient)({ token });
|
|
82
|
+
const groupInfo = await client.getGroup(project.namespace.path);
|
|
83
|
+
projectInfo = {
|
|
84
|
+
projectId: project.id,
|
|
85
|
+
groupId: groupInfo.id,
|
|
86
|
+
namespace: project.namespace.path,
|
|
87
|
+
pathWithNamespace: project.path_with_namespace,
|
|
88
|
+
};
|
|
89
|
+
spinner.succeed(`Project: ${projectInfo.pathWithNamespace}`);
|
|
90
|
+
}
|
|
91
|
+
catch (error) {
|
|
92
|
+
spinner.fail('Failed to detect project');
|
|
93
|
+
console.error(chalk_1.default.yellow('→'), 'Run "glab auth login" to authenticate');
|
|
94
|
+
throw error;
|
|
95
|
+
}
|
|
96
|
+
// Setup .npmrc
|
|
97
|
+
const registryUrl = `https://gitlab.com/api/v4/projects/${projectInfo.projectId}/packages/npm/`;
|
|
98
|
+
const scope = pkgManager.getScope();
|
|
99
|
+
npmrcManager.backup();
|
|
100
|
+
try {
|
|
101
|
+
if (scope) {
|
|
102
|
+
npmrcManager.addScopeRegistry(scope, registryUrl);
|
|
103
|
+
}
|
|
104
|
+
npmrcManager.addAuthToken(registryUrl);
|
|
105
|
+
// Handle version bump
|
|
106
|
+
if (options.bump || type === 'dev') {
|
|
107
|
+
await bumpVersion(pkgManager, type, options.bump);
|
|
108
|
+
}
|
|
109
|
+
const version = pkgManager.getVersion();
|
|
110
|
+
const name = pkgManager.getName();
|
|
111
|
+
// Publish
|
|
112
|
+
const publishSpinner = (0, ora_1.default)(`Publishing ${name}@${version}...`).start();
|
|
113
|
+
if (options.dryRun) {
|
|
114
|
+
(0, child_process_1.execSync)('npm publish --dry-run', {
|
|
115
|
+
stdio: 'inherit',
|
|
116
|
+
env: tokenManager.getEnvWithToken(token),
|
|
117
|
+
});
|
|
118
|
+
publishSpinner.succeed('Dry-run complete');
|
|
119
|
+
}
|
|
120
|
+
else {
|
|
121
|
+
const tag = type === 'dev' ? 'dev' : type === 'beta' ? 'beta' : 'latest';
|
|
122
|
+
(0, child_process_1.execSync)(`npm publish --tag ${tag} --registry=${registryUrl}`, {
|
|
123
|
+
stdio: 'inherit',
|
|
124
|
+
env: tokenManager.getEnvWithToken(token),
|
|
125
|
+
});
|
|
126
|
+
publishSpinner.succeed(`Published ${name}@${version}`);
|
|
127
|
+
// Save to local cache for immediate install availability
|
|
128
|
+
try {
|
|
129
|
+
const packOutput = (0, child_process_1.execSync)('npm pack --json', { encoding: 'utf-8' });
|
|
130
|
+
const packResult = JSON.parse(packOutput);
|
|
131
|
+
const tarballName = Array.isArray(packResult) ? packResult[0].filename : packResult.filename;
|
|
132
|
+
if (tarballName) {
|
|
133
|
+
const localCache = new fallback_1.LocalPackageCache();
|
|
134
|
+
const tarballPath = require('path').join(process.cwd(), tarballName);
|
|
135
|
+
await localCache.save(name, version, tarballPath);
|
|
136
|
+
// Clean up the tarball file
|
|
137
|
+
require('fs').unlinkSync(tarballPath);
|
|
138
|
+
console.log(chalk_1.default.gray('○'), 'Saved to local cache');
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
catch {
|
|
142
|
+
// Cache save failure is not critical, continue
|
|
143
|
+
}
|
|
144
|
+
// Save package metadata
|
|
145
|
+
configManager.savePackageInfo({
|
|
146
|
+
packageName: name,
|
|
147
|
+
group: projectInfo.namespace,
|
|
148
|
+
groupId: projectInfo.groupId,
|
|
149
|
+
projectId: projectInfo.projectId,
|
|
150
|
+
projectPath: projectInfo.pathWithNamespace,
|
|
151
|
+
registryType: 'group',
|
|
152
|
+
registryUrl: `https://gitlab.com/api/v4/groups/${projectInfo.groupId}/-/packages/npm/`,
|
|
153
|
+
gitlabHost: 'gitlab.com',
|
|
154
|
+
lastUpdated: new Date().toISOString(),
|
|
155
|
+
source: 'published',
|
|
156
|
+
});
|
|
157
|
+
// Git operations
|
|
158
|
+
if (options.gitTag !== 'false' && type !== 'dev') {
|
|
159
|
+
createGitTag(version);
|
|
160
|
+
}
|
|
161
|
+
if (options.push !== 'false') {
|
|
162
|
+
pushToRemote(options.gitTag !== 'false' && type !== 'dev');
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
console.log();
|
|
166
|
+
console.log(chalk_1.default.green('✓'), 'Publish complete!');
|
|
167
|
+
console.log(chalk_1.default.gray('Package URL:'), `https://gitlab.com/${projectInfo.pathWithNamespace}/-/packages`);
|
|
168
|
+
}
|
|
169
|
+
finally {
|
|
170
|
+
npmrcManager.restore();
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
/**
|
|
174
|
+
* Publish generic package
|
|
175
|
+
*/
|
|
176
|
+
async function publishGeneric(options) {
|
|
177
|
+
console.log(chalk_1.default.blue.bold('glpkg publish'), chalk_1.default.gray('(generic)'));
|
|
178
|
+
console.log();
|
|
179
|
+
const tokenManager = (0, core_1.createTokenManager)();
|
|
180
|
+
const token = tokenManager.resolveToken(options.token);
|
|
181
|
+
const manifestReader = (0, adapters_generic_1.createManifestReader)();
|
|
182
|
+
const tarballCreator = (0, adapters_generic_1.createTarballCreator)();
|
|
183
|
+
const uploader = (0, adapters_generic_1.createUploader)('gitlab.com', token);
|
|
184
|
+
// Read manifest
|
|
185
|
+
const manifest = manifestReader.read(options.manifest);
|
|
186
|
+
console.log(chalk_1.default.gray('○'), `Package: ${manifest.name}@${manifest.version}`);
|
|
187
|
+
// Detect project
|
|
188
|
+
const spinner = (0, ora_1.default)('Detecting project...').start();
|
|
189
|
+
let projectId;
|
|
190
|
+
try {
|
|
191
|
+
const glabOutput = (0, child_process_1.execSync)('glab api projects/:id -X GET', { encoding: 'utf-8' });
|
|
192
|
+
const project = JSON.parse(glabOutput);
|
|
193
|
+
projectId = project.id;
|
|
194
|
+
spinner.succeed(`Project ID: ${projectId}`);
|
|
195
|
+
}
|
|
196
|
+
catch (error) {
|
|
197
|
+
spinner.fail('Failed to detect project');
|
|
198
|
+
throw error;
|
|
199
|
+
}
|
|
200
|
+
// Create tarball
|
|
201
|
+
const tarballSpinner = (0, ora_1.default)('Creating tarball...').start();
|
|
202
|
+
const tarballResult = tarballCreator.create(manifest);
|
|
203
|
+
tarballSpinner.succeed(`Created: ${manifestReader.getOutputName()}`);
|
|
204
|
+
// Upload
|
|
205
|
+
if (options.dryRun) {
|
|
206
|
+
console.log(chalk_1.default.yellow('→'), 'Dry-run: skipping upload');
|
|
207
|
+
}
|
|
208
|
+
else {
|
|
209
|
+
const uploadSpinner = (0, ora_1.default)('Uploading...').start();
|
|
210
|
+
const result = await uploader.upload({
|
|
211
|
+
projectId,
|
|
212
|
+
gitlabHost: 'gitlab.com',
|
|
213
|
+
token,
|
|
214
|
+
packageName: manifest.name,
|
|
215
|
+
packageVersion: manifest.version,
|
|
216
|
+
filename: manifestReader.getOutputName(),
|
|
217
|
+
filePath: tarballResult.tarballPath,
|
|
218
|
+
});
|
|
219
|
+
if (result.success) {
|
|
220
|
+
uploadSpinner.succeed('Upload complete');
|
|
221
|
+
// Save to local cache for immediate install availability
|
|
222
|
+
try {
|
|
223
|
+
const localCache = new fallback_1.LocalPackageCache();
|
|
224
|
+
await localCache.save(manifest.name, manifest.version, tarballResult.tarballPath);
|
|
225
|
+
console.log(chalk_1.default.gray('○'), 'Saved to local cache');
|
|
226
|
+
}
|
|
227
|
+
catch {
|
|
228
|
+
// Cache save failure is not critical
|
|
229
|
+
}
|
|
230
|
+
}
|
|
231
|
+
else {
|
|
232
|
+
uploadSpinner.fail(result.error || 'Upload failed');
|
|
233
|
+
throw new Error(result.error);
|
|
234
|
+
}
|
|
235
|
+
}
|
|
236
|
+
console.log();
|
|
237
|
+
console.log(chalk_1.default.green('✓'), 'Publish complete!');
|
|
238
|
+
}
|
|
239
|
+
/**
|
|
240
|
+
* Publish PyPI package
|
|
241
|
+
*/
|
|
242
|
+
async function publishPyPI(type, options) {
|
|
243
|
+
console.log(chalk_1.default.blue.bold('glpkg publish'), chalk_1.default.gray('(pypi)'));
|
|
244
|
+
console.log();
|
|
245
|
+
const tokenManager = (0, core_1.createTokenManager)();
|
|
246
|
+
const token = tokenManager.resolveToken(options.token);
|
|
247
|
+
const pyprojectManager = (0, adapters_pypi_1.createPyProjectManager)();
|
|
248
|
+
const executor = (0, adapters_pypi_1.createCommandExecutor)();
|
|
249
|
+
// Check tools availability
|
|
250
|
+
if (!executor.hasBuild()) {
|
|
251
|
+
console.error(chalk_1.default.red('✗'), 'python build not found. Install with: pip install build');
|
|
252
|
+
process.exit(1);
|
|
253
|
+
}
|
|
254
|
+
if (!executor.hasTwine()) {
|
|
255
|
+
console.error(chalk_1.default.red('✗'), 'twine not found. Install with: pip install twine');
|
|
256
|
+
process.exit(1);
|
|
257
|
+
}
|
|
258
|
+
// Check pyproject.toml exists
|
|
259
|
+
if (!pyprojectManager.exists()) {
|
|
260
|
+
console.error(chalk_1.default.red('✗'), 'pyproject.toml not found');
|
|
261
|
+
process.exit(1);
|
|
262
|
+
}
|
|
263
|
+
// Check git status
|
|
264
|
+
if (!options.dryRun) {
|
|
265
|
+
checkGitClean(options.force);
|
|
266
|
+
}
|
|
267
|
+
// Detect project
|
|
268
|
+
const spinner = (0, ora_1.default)('Detecting project...').start();
|
|
269
|
+
let projectId;
|
|
270
|
+
let pathWithNamespace;
|
|
271
|
+
try {
|
|
272
|
+
const glabOutput = (0, child_process_1.execSync)('glab api projects/:id -X GET', { encoding: 'utf-8' });
|
|
273
|
+
const project = JSON.parse(glabOutput);
|
|
274
|
+
projectId = project.id;
|
|
275
|
+
pathWithNamespace = project.path_with_namespace;
|
|
276
|
+
spinner.succeed(`Project ID: ${projectId}`);
|
|
277
|
+
}
|
|
278
|
+
catch (error) {
|
|
279
|
+
spinner.fail('Failed to detect project');
|
|
280
|
+
throw error;
|
|
281
|
+
}
|
|
282
|
+
// Handle version bump
|
|
283
|
+
if (options.bump) {
|
|
284
|
+
const currentVersion = pyprojectManager.getVersion();
|
|
285
|
+
const newVersion = (0, core_1.incrementVersion)(currentVersion.replace(/-.*$/, ''), options.bump);
|
|
286
|
+
pyprojectManager.setVersion(newVersion);
|
|
287
|
+
console.log(chalk_1.default.gray('○'), `Version: ${currentVersion} → ${newVersion}`);
|
|
288
|
+
}
|
|
289
|
+
const name = pyprojectManager.getName();
|
|
290
|
+
const version = pyprojectManager.getVersion();
|
|
291
|
+
console.log(chalk_1.default.gray('○'), `Package: ${name}@${version}`);
|
|
292
|
+
// Build
|
|
293
|
+
if (!options.noBuild) {
|
|
294
|
+
const buildSpinner = (0, ora_1.default)('Building package...').start();
|
|
295
|
+
try {
|
|
296
|
+
executor.build();
|
|
297
|
+
buildSpinner.succeed('Build complete');
|
|
298
|
+
}
|
|
299
|
+
catch (error) {
|
|
300
|
+
buildSpinner.fail('Build failed');
|
|
301
|
+
throw error;
|
|
302
|
+
}
|
|
303
|
+
}
|
|
304
|
+
// Upload with twine
|
|
305
|
+
const uploadUrl = (0, adapters_pypi_1.buildProjectUploadUrl)(projectId);
|
|
306
|
+
if (options.dryRun) {
|
|
307
|
+
console.log(chalk_1.default.yellow('→'), 'Dry-run: skipping upload');
|
|
308
|
+
console.log(chalk_1.default.gray(' Would upload to:'), uploadUrl);
|
|
309
|
+
}
|
|
310
|
+
else {
|
|
311
|
+
const uploadSpinner = (0, ora_1.default)('Uploading to GitLab PyPI registry...').start();
|
|
312
|
+
try {
|
|
313
|
+
executor.upload('dist/*', uploadUrl, {
|
|
314
|
+
username: '__token__',
|
|
315
|
+
password: token,
|
|
316
|
+
});
|
|
317
|
+
uploadSpinner.succeed(`Published ${name}@${version}`);
|
|
318
|
+
// Git operations
|
|
319
|
+
if (options.gitTag !== 'false' && type !== 'dev') {
|
|
320
|
+
createGitTag(version, 'pyproject.toml');
|
|
321
|
+
}
|
|
322
|
+
if (options.push !== 'false') {
|
|
323
|
+
pushToRemote(options.gitTag !== 'false' && type !== 'dev');
|
|
324
|
+
}
|
|
325
|
+
}
|
|
326
|
+
catch (error) {
|
|
327
|
+
uploadSpinner.fail('Upload failed');
|
|
328
|
+
throw error;
|
|
329
|
+
}
|
|
330
|
+
}
|
|
331
|
+
console.log();
|
|
332
|
+
console.log(chalk_1.default.green('✓'), 'Publish complete!');
|
|
333
|
+
console.log(chalk_1.default.gray('Package URL:'), `https://gitlab.com/${pathWithNamespace}/-/packages`);
|
|
334
|
+
}
|
|
335
|
+
/**
|
|
336
|
+
* Publish Go module
|
|
337
|
+
* Go modules are published via git tags - GitLab automatically serves them via Go proxy
|
|
338
|
+
*/
|
|
339
|
+
async function publishGo(type, options) {
|
|
340
|
+
console.log(chalk_1.default.blue.bold('glpkg publish'), chalk_1.default.gray('(go)'));
|
|
341
|
+
console.log();
|
|
342
|
+
const goModManager = (0, adapters_go_1.createGoModManager)();
|
|
343
|
+
const executor = (0, adapters_go_1.createCommandExecutor)();
|
|
344
|
+
// Check Go availability
|
|
345
|
+
if (!executor.hasGo()) {
|
|
346
|
+
console.error(chalk_1.default.red('✗'), 'Go not found. Please install Go.');
|
|
347
|
+
process.exit(1);
|
|
348
|
+
}
|
|
349
|
+
// Check go.mod exists
|
|
350
|
+
if (!goModManager.exists()) {
|
|
351
|
+
console.error(chalk_1.default.red('✗'), 'go.mod not found');
|
|
352
|
+
process.exit(1);
|
|
353
|
+
}
|
|
354
|
+
// Check git status
|
|
355
|
+
if (!options.dryRun) {
|
|
356
|
+
checkGitClean(options.force);
|
|
357
|
+
}
|
|
358
|
+
// Read module info
|
|
359
|
+
const goMod = goModManager.read();
|
|
360
|
+
const modulePath = goMod.module;
|
|
361
|
+
console.log(chalk_1.default.gray('○'), `Module: ${modulePath}`);
|
|
362
|
+
// Detect project
|
|
363
|
+
const spinner = (0, ora_1.default)('Detecting project...').start();
|
|
364
|
+
let pathWithNamespace;
|
|
365
|
+
try {
|
|
366
|
+
const glabOutput = (0, child_process_1.execSync)('glab api projects/:id -X GET', { encoding: 'utf-8' });
|
|
367
|
+
const project = JSON.parse(glabOutput);
|
|
368
|
+
pathWithNamespace = project.path_with_namespace;
|
|
369
|
+
spinner.succeed(`Project: ${pathWithNamespace}`);
|
|
370
|
+
}
|
|
371
|
+
catch (error) {
|
|
372
|
+
spinner.fail('Failed to detect project');
|
|
373
|
+
throw error;
|
|
374
|
+
}
|
|
375
|
+
// Determine version
|
|
376
|
+
let version;
|
|
377
|
+
if (options.bump) {
|
|
378
|
+
// Get latest tag and bump
|
|
379
|
+
try {
|
|
380
|
+
const latestTag = (0, child_process_1.execSync)('git describe --tags --abbrev=0 2>/dev/null || echo "v0.0.0"', {
|
|
381
|
+
encoding: 'utf-8',
|
|
382
|
+
}).trim();
|
|
383
|
+
const currentVersion = latestTag.replace(/^v/, '');
|
|
384
|
+
version = (0, adapters_go_1.normalizeVersion)((0, core_1.incrementVersion)(currentVersion, options.bump));
|
|
385
|
+
}
|
|
386
|
+
catch {
|
|
387
|
+
version = 'v0.1.0';
|
|
388
|
+
}
|
|
389
|
+
}
|
|
390
|
+
else {
|
|
391
|
+
// Get version from latest tag or default
|
|
392
|
+
try {
|
|
393
|
+
version = (0, child_process_1.execSync)('git describe --tags --abbrev=0 2>/dev/null', {
|
|
394
|
+
encoding: 'utf-8',
|
|
395
|
+
}).trim();
|
|
396
|
+
// Bump patch for new release
|
|
397
|
+
const currentVersion = version.replace(/^v/, '');
|
|
398
|
+
version = (0, adapters_go_1.normalizeVersion)((0, core_1.incrementVersion)(currentVersion, 'patch'));
|
|
399
|
+
}
|
|
400
|
+
catch {
|
|
401
|
+
version = 'v0.1.0';
|
|
402
|
+
}
|
|
403
|
+
}
|
|
404
|
+
console.log(chalk_1.default.gray('○'), `Version: ${version}`);
|
|
405
|
+
// Validate module
|
|
406
|
+
const validateSpinner = (0, ora_1.default)('Validating module...').start();
|
|
407
|
+
const tidyResult = executor.modTidy();
|
|
408
|
+
if (!tidyResult.success) {
|
|
409
|
+
validateSpinner.fail('Module validation failed');
|
|
410
|
+
if (tidyResult.stderr) {
|
|
411
|
+
console.error(chalk_1.default.gray(' '), tidyResult.stderr.trim());
|
|
412
|
+
}
|
|
413
|
+
throw new Error('go mod tidy failed');
|
|
414
|
+
}
|
|
415
|
+
validateSpinner.succeed('Module validated');
|
|
416
|
+
if (options.dryRun) {
|
|
417
|
+
console.log(chalk_1.default.yellow('→'), 'Dry-run: would create tag', version);
|
|
418
|
+
console.log(chalk_1.default.yellow('→'), 'Dry-run: would push tag to remote');
|
|
419
|
+
}
|
|
420
|
+
else {
|
|
421
|
+
// Create git tag
|
|
422
|
+
const tagSpinner = (0, ora_1.default)(`Creating tag ${version}...`).start();
|
|
423
|
+
try {
|
|
424
|
+
// Commit go.mod/go.sum if changed
|
|
425
|
+
try {
|
|
426
|
+
(0, child_process_1.execSync)('git add go.mod go.sum 2>/dev/null && git commit -m "chore: update go.mod" --allow-empty', {
|
|
427
|
+
stdio: 'pipe',
|
|
428
|
+
});
|
|
429
|
+
}
|
|
430
|
+
catch {
|
|
431
|
+
// No changes to commit
|
|
432
|
+
}
|
|
433
|
+
(0, child_process_1.execSync)(`git tag ${version}`, { stdio: 'pipe' });
|
|
434
|
+
tagSpinner.succeed(`Created tag: ${version}`);
|
|
435
|
+
}
|
|
436
|
+
catch (error) {
|
|
437
|
+
tagSpinner.fail('Failed to create tag');
|
|
438
|
+
throw error;
|
|
439
|
+
}
|
|
440
|
+
// Push tag
|
|
441
|
+
if (options.push !== 'false') {
|
|
442
|
+
const pushSpinner = (0, ora_1.default)('Pushing to remote...').start();
|
|
443
|
+
try {
|
|
444
|
+
(0, child_process_1.execSync)('git push', { stdio: 'pipe' });
|
|
445
|
+
(0, child_process_1.execSync)('git push --tags', { stdio: 'pipe' });
|
|
446
|
+
pushSpinner.succeed('Pushed to remote');
|
|
447
|
+
}
|
|
448
|
+
catch {
|
|
449
|
+
pushSpinner.warn('Failed to push (you can push manually)');
|
|
450
|
+
}
|
|
451
|
+
}
|
|
452
|
+
}
|
|
453
|
+
console.log();
|
|
454
|
+
console.log(chalk_1.default.green('✓'), 'Publish complete!');
|
|
455
|
+
console.log(chalk_1.default.gray('Module URL:'), `https://gitlab.com/${pathWithNamespace}`);
|
|
456
|
+
console.log();
|
|
457
|
+
console.log(chalk_1.default.gray('To install:'));
|
|
458
|
+
console.log(chalk_1.default.cyan(` go get ${modulePath}@${version}`));
|
|
459
|
+
}
|
|
460
|
+
/**
|
|
461
|
+
* Publish NuGet package
|
|
462
|
+
*/
|
|
463
|
+
async function publishNuGet(type, options) {
|
|
464
|
+
console.log(chalk_1.default.blue.bold('glpkg publish'), chalk_1.default.gray('(nuget)'));
|
|
465
|
+
console.log();
|
|
466
|
+
const tokenManager = (0, core_1.createTokenManager)();
|
|
467
|
+
const token = tokenManager.resolveToken(options.token);
|
|
468
|
+
const csprojManager = (0, adapters_nuget_1.createCsProjManager)();
|
|
469
|
+
const executor = (0, adapters_nuget_1.createCommandExecutor)();
|
|
470
|
+
// Check dotnet CLI availability
|
|
471
|
+
if (!executor.hasDotNet()) {
|
|
472
|
+
console.error(chalk_1.default.red('✗'), 'dotnet CLI not found. Please install .NET SDK.');
|
|
473
|
+
process.exit(1);
|
|
474
|
+
}
|
|
475
|
+
// Check .csproj exists
|
|
476
|
+
if (!csprojManager.exists()) {
|
|
477
|
+
console.error(chalk_1.default.red('✗'), '.csproj file not found');
|
|
478
|
+
process.exit(1);
|
|
479
|
+
}
|
|
480
|
+
// Check git status
|
|
481
|
+
if (!options.dryRun) {
|
|
482
|
+
checkGitClean(options.force);
|
|
483
|
+
}
|
|
484
|
+
// Detect project
|
|
485
|
+
const spinner = (0, ora_1.default)('Detecting project...').start();
|
|
486
|
+
let projectId;
|
|
487
|
+
let pathWithNamespace;
|
|
488
|
+
try {
|
|
489
|
+
const glabOutput = (0, child_process_1.execSync)('glab api projects/:id -X GET', { encoding: 'utf-8' });
|
|
490
|
+
const project = JSON.parse(glabOutput);
|
|
491
|
+
projectId = project.id;
|
|
492
|
+
pathWithNamespace = project.path_with_namespace;
|
|
493
|
+
spinner.succeed(`Project ID: ${projectId}`);
|
|
494
|
+
}
|
|
495
|
+
catch (error) {
|
|
496
|
+
spinner.fail('Failed to detect project');
|
|
497
|
+
throw error;
|
|
498
|
+
}
|
|
499
|
+
// Read package info
|
|
500
|
+
const csproj = csprojManager.read();
|
|
501
|
+
const packageId = csprojManager.getPackageId();
|
|
502
|
+
let version = csprojManager.getVersion();
|
|
503
|
+
// Handle version bump
|
|
504
|
+
if (options.bump) {
|
|
505
|
+
const newVersion = (0, core_1.incrementVersion)(version.replace(/-.*$/, ''), options.bump);
|
|
506
|
+
csprojManager.setVersion(newVersion);
|
|
507
|
+
console.log(chalk_1.default.gray('○'), `Version: ${version} → ${newVersion}`);
|
|
508
|
+
version = newVersion;
|
|
509
|
+
}
|
|
510
|
+
console.log(chalk_1.default.gray('○'), `Package: ${packageId}@${version}`);
|
|
511
|
+
// Build and pack
|
|
512
|
+
if (!options.noBuild) {
|
|
513
|
+
const buildSpinner = (0, ora_1.default)('Building and packing...').start();
|
|
514
|
+
const packResult = executor.pack({ configuration: 'Release' });
|
|
515
|
+
if (!packResult.success) {
|
|
516
|
+
buildSpinner.fail('Build failed');
|
|
517
|
+
if (packResult.stderr) {
|
|
518
|
+
console.error(chalk_1.default.gray(' '), packResult.stderr.trim());
|
|
519
|
+
}
|
|
520
|
+
throw new Error('dotnet pack failed');
|
|
521
|
+
}
|
|
522
|
+
buildSpinner.succeed('Build complete');
|
|
523
|
+
}
|
|
524
|
+
// Find the .nupkg file
|
|
525
|
+
const { readdirSync } = require('fs');
|
|
526
|
+
const { join } = require('path');
|
|
527
|
+
const binDir = join(process.cwd(), 'bin', 'Release');
|
|
528
|
+
let nupkgPath = null;
|
|
529
|
+
try {
|
|
530
|
+
const files = readdirSync(binDir);
|
|
531
|
+
const nupkgFile = files.find((f) => f.endsWith('.nupkg') && !f.endsWith('.symbols.nupkg'));
|
|
532
|
+
if (nupkgFile) {
|
|
533
|
+
nupkgPath = join(binDir, nupkgFile);
|
|
534
|
+
}
|
|
535
|
+
}
|
|
536
|
+
catch {
|
|
537
|
+
// Try current directory
|
|
538
|
+
const files = readdirSync(process.cwd());
|
|
539
|
+
const nupkgFile = files.find((f) => f.endsWith('.nupkg') && !f.endsWith('.symbols.nupkg'));
|
|
540
|
+
if (nupkgFile) {
|
|
541
|
+
nupkgPath = join(process.cwd(), nupkgFile);
|
|
542
|
+
}
|
|
543
|
+
}
|
|
544
|
+
if (!nupkgPath) {
|
|
545
|
+
console.error(chalk_1.default.red('✗'), '.nupkg file not found');
|
|
546
|
+
process.exit(1);
|
|
547
|
+
}
|
|
548
|
+
console.log(chalk_1.default.gray('○'), `Package: ${nupkgPath}`);
|
|
549
|
+
// Push to GitLab
|
|
550
|
+
const pushUrl = (0, adapters_nuget_1.buildProjectPushUrl)(projectId);
|
|
551
|
+
if (options.dryRun) {
|
|
552
|
+
console.log(chalk_1.default.yellow('→'), 'Dry-run: skipping push');
|
|
553
|
+
console.log(chalk_1.default.gray(' Would push to:'), pushUrl);
|
|
554
|
+
}
|
|
555
|
+
else {
|
|
556
|
+
const pushSpinner = (0, ora_1.default)('Pushing to GitLab NuGet registry...').start();
|
|
557
|
+
const pushResult = executor.push(nupkgPath, {
|
|
558
|
+
source: pushUrl,
|
|
559
|
+
apiKey: token,
|
|
560
|
+
skipDuplicate: true,
|
|
561
|
+
});
|
|
562
|
+
if (pushResult.success) {
|
|
563
|
+
pushSpinner.succeed(`Published ${packageId}@${version}`);
|
|
564
|
+
// Git operations
|
|
565
|
+
if (options.gitTag !== 'false' && type !== 'dev') {
|
|
566
|
+
createGitTag(version, csprojManager.getFilePath() || '*.csproj');
|
|
567
|
+
}
|
|
568
|
+
if (options.push !== 'false') {
|
|
569
|
+
pushToRemote(options.gitTag !== 'false' && type !== 'dev');
|
|
570
|
+
}
|
|
571
|
+
}
|
|
572
|
+
else {
|
|
573
|
+
pushSpinner.fail('Push failed');
|
|
574
|
+
if (pushResult.stderr) {
|
|
575
|
+
console.error(chalk_1.default.gray(' '), pushResult.stderr.trim());
|
|
576
|
+
}
|
|
577
|
+
throw new Error('dotnet nuget push failed');
|
|
578
|
+
}
|
|
579
|
+
}
|
|
580
|
+
console.log();
|
|
581
|
+
console.log(chalk_1.default.green('✓'), 'Publish complete!');
|
|
582
|
+
console.log(chalk_1.default.gray('Package URL:'), `https://gitlab.com/${pathWithNamespace}/-/packages`);
|
|
583
|
+
}
|
|
584
|
+
/**
|
|
585
|
+
* Bump version in package.json
|
|
586
|
+
*/
|
|
587
|
+
async function bumpVersion(pkgManager, type, bump) {
|
|
588
|
+
const currentVersion = pkgManager.getVersion();
|
|
589
|
+
let newVersion;
|
|
590
|
+
if (type === 'dev') {
|
|
591
|
+
// Dev version: x.y.z-dev.timestamp
|
|
592
|
+
const timestamp = Date.now();
|
|
593
|
+
newVersion = (0, core_1.addPrerelease)(currentVersion.replace(/-.*$/, ''), 'dev', timestamp);
|
|
594
|
+
}
|
|
595
|
+
else if (bump) {
|
|
596
|
+
const baseVersion = currentVersion.replace(/-.*$/, '');
|
|
597
|
+
newVersion = (0, core_1.incrementVersion)(baseVersion, bump);
|
|
598
|
+
if (type === 'beta') {
|
|
599
|
+
newVersion = (0, core_1.addPrerelease)(newVersion, 'beta', 0);
|
|
600
|
+
}
|
|
601
|
+
}
|
|
602
|
+
else {
|
|
603
|
+
return; // No bump needed
|
|
604
|
+
}
|
|
605
|
+
pkgManager.setVersion(newVersion);
|
|
606
|
+
console.log(chalk_1.default.gray('○'), `Version: ${currentVersion} → ${newVersion}`);
|
|
607
|
+
}
|
|
608
|
+
/**
|
|
609
|
+
* Check git working directory is clean
|
|
610
|
+
* Returns true if clean, false if dirty (when force mode)
|
|
611
|
+
*/
|
|
612
|
+
function checkGitClean(force = false) {
|
|
613
|
+
try {
|
|
614
|
+
const status = (0, child_process_1.execSync)('git status --porcelain', { encoding: 'utf-8' });
|
|
615
|
+
if (status.trim()) {
|
|
616
|
+
if (force) {
|
|
617
|
+
console.log(chalk_1.default.yellow('⚠'), 'Git working directory is not clean');
|
|
618
|
+
console.log(chalk_1.default.yellow(' →'), chalk_1.default.bold('It is strongly recommended to commit your changes before publishing'));
|
|
619
|
+
console.log(chalk_1.default.gray(' Continuing with --force...'));
|
|
620
|
+
console.log();
|
|
621
|
+
return false;
|
|
622
|
+
}
|
|
623
|
+
else {
|
|
624
|
+
console.error(chalk_1.default.red('✗'), 'Git working directory is not clean');
|
|
625
|
+
console.error(chalk_1.default.yellow('→'), 'Commit or stash changes, or use --force');
|
|
626
|
+
process.exit(1);
|
|
627
|
+
}
|
|
628
|
+
}
|
|
629
|
+
return true;
|
|
630
|
+
}
|
|
631
|
+
catch {
|
|
632
|
+
// Not a git repo, skip check
|
|
633
|
+
return true;
|
|
634
|
+
}
|
|
635
|
+
}
|
|
636
|
+
/**
|
|
637
|
+
* Create git tag
|
|
638
|
+
*/
|
|
639
|
+
function createGitTag(version, manifestFile = 'package.json') {
|
|
640
|
+
try {
|
|
641
|
+
(0, child_process_1.execSync)(`git add ${manifestFile} && git commit -m "chore: release v${version}" --allow-empty`, {
|
|
642
|
+
stdio: 'pipe',
|
|
643
|
+
});
|
|
644
|
+
(0, child_process_1.execSync)(`git tag v${version}`, { stdio: 'pipe' });
|
|
645
|
+
console.log(chalk_1.default.gray('○'), `Created tag: v${version}`);
|
|
646
|
+
}
|
|
647
|
+
catch {
|
|
648
|
+
// Ignore errors
|
|
649
|
+
}
|
|
650
|
+
}
|
|
651
|
+
/**
|
|
652
|
+
* Push to remote
|
|
653
|
+
*/
|
|
654
|
+
function pushToRemote(includeTags) {
|
|
655
|
+
try {
|
|
656
|
+
(0, child_process_1.execSync)('git push', { stdio: 'pipe' });
|
|
657
|
+
if (includeTags) {
|
|
658
|
+
(0, child_process_1.execSync)('git push --tags', { stdio: 'pipe' });
|
|
659
|
+
}
|
|
660
|
+
console.log(chalk_1.default.gray('○'), 'Pushed to remote');
|
|
661
|
+
}
|
|
662
|
+
catch {
|
|
663
|
+
console.log(chalk_1.default.yellow('⚠'), 'Failed to push (you can push manually)');
|
|
664
|
+
}
|
|
665
|
+
}
|
|
666
|
+
//# sourceMappingURL=publish.js.map
|