chrome-ext-ci-cd 1.0.0 → 1.0.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/lib/bump.js CHANGED
@@ -33,6 +33,25 @@ function calculateNewVersion(currentVersion, bumpType) {
33
33
  return bumpType;
34
34
  }
35
35
 
36
+ function detectWxtProject(cwd) {
37
+ return fs.existsSync(path.join(cwd, 'wxt.config.ts'));
38
+ }
39
+
40
+ function readWxtVersion(wxtConfigPath) {
41
+ var contents = fs.readFileSync(wxtConfigPath, 'utf-8');
42
+ var match = contents.match(/version:\s*['"]([\d.]+)['"]/);
43
+ return match ? match[1] : null;
44
+ }
45
+
46
+ function writeWxtVersion(wxtConfigPath, newVersion) {
47
+ var contents = fs.readFileSync(wxtConfigPath, 'utf-8');
48
+ var updated = contents.replace(
49
+ /(version:\s*['"])[\d.]+(['"])/,
50
+ '$1' + newVersion + '$2'
51
+ );
52
+ fs.writeFileSync(wxtConfigPath, updated);
53
+ }
54
+
36
55
  function checkDirtyTree() {
37
56
  try {
38
57
  execFileSync('git', ['diff', '--quiet'], { stdio: 'pipe' });
@@ -46,6 +65,115 @@ function checkDirtyTree() {
46
65
  }
47
66
  }
48
67
 
68
+ // --- WXT Bump Path ---
69
+
70
+ function bumpWxt(bumpType, projectRoot, opts) {
71
+ var wxtConfigPath = path.join(projectRoot, 'wxt.config.ts');
72
+ var packageJsonPath = path.join(projectRoot, 'package.json');
73
+ var builtManifestPath = path.join(projectRoot, '.output', 'chrome-mv3', 'manifest.json');
74
+
75
+ var data = {
76
+ wxt: true,
77
+ wxtConfigPath: wxtConfigPath,
78
+ packageJsonPath: packageJsonPath
79
+ };
80
+
81
+ // Read current version from wxt.config.ts
82
+ var currentVersion = readWxtVersion(wxtConfigPath);
83
+ if (!currentVersion) {
84
+ return {
85
+ success: false,
86
+ errors: ['Could not parse version from ' + wxtConfigPath + '. Expected: version: \'X.Y.Z\' or version: "X.Y.Z"'],
87
+ warnings: [],
88
+ data: data
89
+ };
90
+ }
91
+
92
+ var newVersion = calculateNewVersion(currentVersion, bumpType);
93
+ var tag = 'v' + newVersion;
94
+ data.previousVersion = currentVersion;
95
+ data.newVersion = newVersion;
96
+ data.tag = tag;
97
+
98
+ var warnings = [];
99
+
100
+ // Validation: check built manifest if it exists
101
+ if (fs.existsSync(builtManifestPath)) {
102
+ data.builtManifestPath = builtManifestPath;
103
+ } else {
104
+ warnings.push('No built manifest found at ' + builtManifestPath + '. Run `wxt build` to validate the generated manifest before tagging.');
105
+ }
106
+
107
+ // Dry run -- return early without side effects
108
+ if (opts.dryRun) {
109
+ data.dryRun = true;
110
+ return { success: true, errors: [], warnings: warnings, data: data };
111
+ }
112
+
113
+ // Check dirty tree
114
+ var treeStatus = checkDirtyTree();
115
+ if (!treeStatus.clean) {
116
+ return { success: false, errors: [treeStatus.message], warnings: warnings, data: data };
117
+ }
118
+
119
+ // Update wxt.config.ts
120
+ writeWxtVersion(wxtConfigPath, newVersion);
121
+
122
+ // Update package.json (always present in WXT projects, but guard anyway)
123
+ var updatedPackageJson = false;
124
+ if (fs.existsSync(packageJsonPath)) {
125
+ try {
126
+ var pkg = JSON.parse(fs.readFileSync(packageJsonPath, 'utf-8'));
127
+ pkg.version = newVersion;
128
+ fs.writeFileSync(packageJsonPath, JSON.stringify(pkg, null, 2) + '\n');
129
+ updatedPackageJson = true;
130
+ } catch (e) {
131
+ return {
132
+ success: false,
133
+ errors: ['Failed to update package.json: ' + e.message],
134
+ warnings: warnings,
135
+ data: data
136
+ };
137
+ }
138
+ }
139
+
140
+ // Git operations -- stage wxt.config.ts + package.json (NEVER the gitignored manifest)
141
+ try {
142
+ execFileSync('git', ['add', wxtConfigPath], { stdio: 'pipe' });
143
+ if (updatedPackageJson) {
144
+ execFileSync('git', ['add', packageJsonPath], { stdio: 'pipe' });
145
+ }
146
+ execFileSync('git', ['commit', '-m', 'chore: bump version to ' + newVersion], { stdio: 'pipe' });
147
+ execFileSync('git', ['tag', '-a', tag, '-m', 'Release ' + tag], { stdio: 'pipe' });
148
+ } catch (e) {
149
+ var errMsg = e.stderr ? e.stderr.toString() : e.message;
150
+ return {
151
+ success: false,
152
+ errors: ['Git operations failed: ' + errMsg + '. Commit and tag were not created.'],
153
+ warnings: warnings,
154
+ data: data
155
+ };
156
+ }
157
+
158
+ // Push
159
+ try {
160
+ var branch = execFileSync('git', ['rev-parse', '--abbrev-ref', 'HEAD'], {
161
+ encoding: 'utf-8'
162
+ }).trim();
163
+ execFileSync('git', ['push', 'origin', branch, '--follow-tags'], { stdio: 'inherit' });
164
+ data.branch = branch;
165
+ } catch (e) {
166
+ return {
167
+ success: false,
168
+ errors: ['Push failed. You can push manually: git push origin --follow-tags'],
169
+ warnings: warnings,
170
+ data: data
171
+ };
172
+ }
173
+
174
+ return { success: true, errors: [], warnings: warnings, data: data };
175
+ }
176
+
49
177
  // --- Pure Bump Function ---
50
178
 
51
179
  function bump(bumpType, options) {
@@ -61,9 +189,19 @@ function bump(bumpType, options) {
61
189
  };
62
190
  }
63
191
 
192
+ var projectRoot = opts.cwd || process.cwd();
193
+
194
+ // --- WXT auto-detection ---
195
+ // WXT projects keep the version in wxt.config.ts; manifest.json is generated
196
+ // into .output/ (gitignored) at build time. Bypass the manifest path entirely
197
+ // when wxt.config.ts is present at the project root.
198
+ if (detectWxtProject(projectRoot)) {
199
+ return bumpWxt(bumpType, projectRoot, opts);
200
+ }
201
+
64
202
  // Resolve manifest path
65
203
  var manifestPath = path.resolve(
66
- opts.manifestPath || opts.manifest || process.env.MANIFEST_PATH || path.join(process.cwd(), 'manifest.json')
204
+ opts.manifestPath || opts.manifest || process.env.MANIFEST_PATH || path.join(projectRoot, 'manifest.json')
67
205
  );
68
206
 
69
207
  var data = { manifestPath: manifestPath };
@@ -208,7 +346,8 @@ function bump(bumpType, options) {
208
346
  function printHelp() {
209
347
  console.log('Usage: chrome-ext-ci-cd bump <patch|minor|major|x.y.z> [options]');
210
348
  console.log('');
211
- console.log('Bump version in manifest.json, commit, tag, and push.');
349
+ console.log('Bump version in manifest.json (or wxt.config.ts for WXT projects),');
350
+ console.log('commit, tag, and push.');
212
351
  console.log('');
213
352
  console.log('Arguments:');
214
353
  console.log(' patch Increment patch version (1.0.0 -> 1.0.1)');
@@ -270,6 +409,9 @@ function run(args) {
270
409
  });
271
410
 
272
411
  // Format output
412
+ if (result.data.wxt) {
413
+ console.log('Detected WXT project (using wxt.config.ts)');
414
+ }
273
415
  if (result.data.previousVersion) {
274
416
  console.log('Current version: ' + result.data.previousVersion);
275
417
  }
@@ -277,6 +419,11 @@ function run(args) {
277
419
  console.log('New version: ' + result.data.newVersion);
278
420
  }
279
421
 
422
+ if (result.warnings && result.warnings.length > 0) {
423
+ console.log('');
424
+ result.warnings.forEach(function(w) { console.warn('WARNING: ' + w); });
425
+ }
426
+
280
427
  if (result.data.dryRun) {
281
428
  console.log('');
282
429
  console.log('[DRY RUN] No changes made.');
@@ -296,4 +443,4 @@ function run(args) {
296
443
  return result.success ? 0 : 1;
297
444
  }
298
445
 
299
- module.exports = { bump, run };
446
+ module.exports = { bump, run, detectWxtProject, readWxtVersion, writeWxtVersion, calculateNewVersion };
package/lib/release.js CHANGED
@@ -156,7 +156,7 @@ function run(args) {
156
156
 
157
157
  // Run each step individually with per-step output
158
158
  var manifestPath = values.manifest
159
- ? path.resolve(opts.manifest)
159
+ ? path.resolve(values.manifest)
160
160
  : path.join(process.cwd(), 'manifest.json');
161
161
 
162
162
  var validateResult = validate.validate(manifestPath);
@@ -171,7 +171,7 @@ function run(args) {
171
171
  // Step 2: Bump
172
172
  var bumpResult = bump.bump(bumpType, {
173
173
  manifest: manifestPath,
174
- dryRun: opts.dryRun
174
+ dryRun: values['dry-run']
175
175
  });
176
176
  if (!bumpResult.success) {
177
177
  console.log('[2/3] Bump version... FAILED');
@@ -179,14 +179,14 @@ function run(args) {
179
179
  return 1;
180
180
  }
181
181
  var versionStr = bumpResult.data.previousVersion + ' -> ' + bumpResult.data.newVersion;
182
- if (opts.dryRun) {
182
+ if (values['dry-run']) {
183
183
  console.log('[2/3] Bump version ' + versionStr + '... OK (dry run)');
184
184
  } else {
185
185
  console.log('[2/3] Bump version ' + versionStr + '... OK');
186
186
  }
187
187
 
188
188
  // Step 3: Package
189
- if (opts.dryRun) {
189
+ if (values['dry-run']) {
190
190
  console.log('[3/3] Package extension... SKIPPED (dry run)');
191
191
  console.log('');
192
192
  console.log('Dry run complete. Version would be ' + bumpResult.data.newVersion + '.');
@@ -194,8 +194,8 @@ function run(args) {
194
194
  }
195
195
 
196
196
  var pkgResult = pkg.packageExtension({
197
- source: opts.source ? path.resolve(opts.source) : undefined,
198
- output: opts.output ? path.resolve(opts.output) : undefined
197
+ source: values.source ? path.resolve(values.source) : undefined,
198
+ output: values.output ? path.resolve(values.output) : undefined
199
199
  });
200
200
  if (!pkgResult.success) {
201
201
  console.log('[3/3] Package extension... FAILED');
package/package.json CHANGED
@@ -1,8 +1,9 @@
1
1
  {
2
2
  "name": "chrome-ext-ci-cd",
3
- "version": "1.0.0",
3
+ "version": "1.0.2",
4
4
  "description": "CLI toolkit for Chrome extension CI/CD: validate, version, package, and release",
5
- "license": "MIT",
5
+ "license": "UNLICENSED",
6
+ "private": false,
6
7
  "bin": {
7
8
  "chrome-ext-ci-cd": "./bin/cli.js"
8
9
  },
@@ -16,15 +17,16 @@
16
17
  },
17
18
  "scripts": {
18
19
  "test": "node --test",
19
- "prepublishOnly": "node --test && node -e \"const fs=require('fs');const p=require('./package.json');const bin=p.bin['chrome-ext-ci-cd'];if(!fs.existsSync(bin)){console.error('FAIL: bin entry not found:',bin);process.exit(1)}console.log('OK: bin exists:',bin)\""
20
+ "prepublishOnly": "node --test && node -e \"const fs=require('fs');const p=require('./package.json');const bin=p.bin['chrome-ext-ci-cd'];if(!fs.existsSync(bin)){console.error('FAIL: bin entry not found:',bin);process.exit(1)}console.log('OK: bin exists:',bin)\"",
21
+ "prepare": "husky"
20
22
  },
21
23
  "repository": {
22
24
  "type": "git",
23
- "url": "https://github.com/briangrenier/chrome-ext-ci-cd.git"
25
+ "url": "https://github.com/elfstrob/chrome-ext-ci-cd.git"
24
26
  },
25
- "homepage": "https://github.com/briangrenier/chrome-ext-ci-cd#readme",
27
+ "homepage": "https://github.com/elfstrob/chrome-ext-ci-cd#readme",
26
28
  "bugs": {
27
- "url": "https://github.com/briangrenier/chrome-ext-ci-cd/issues"
29
+ "url": "https://github.com/elfstrob/chrome-ext-ci-cd/issues"
28
30
  },
29
31
  "author": "Brian Grenier",
30
32
  "keywords": [
@@ -33,5 +35,8 @@
33
35
  "manifest-v3",
34
36
  "version-bump",
35
37
  "packaging"
36
- ]
38
+ ],
39
+ "devDependencies": {
40
+ "husky": "^9.1.7"
41
+ }
37
42
  }