climaybe 1.3.0 → 1.3.1

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "climaybe",
3
- "version": "1.3.0",
3
+ "version": "1.3.1",
4
4
  "description": "Shopify CI/CD CLI — scaffolds workflows, branch strategy, and store config for single-store and multi-store theme repos",
5
5
  "type": "module",
6
6
  "bin": {
@@ -186,13 +186,13 @@ export async function initCommand() {
186
186
  console.log(pc.bold('\n climaybe — Shopify CI/CD Setup\n'));
187
187
 
188
188
  const existing = readConfig();
189
- const alreadyInited = existing?.stores && Object.keys(existing.stores).length > 0;
189
+ const hasConfig = existing != null && typeof existing === 'object';
190
190
 
191
- if (alreadyInited) {
191
+ if (hasConfig) {
192
192
  const { reinit } = await prompts({
193
193
  type: 'confirm',
194
194
  name: 'reinit',
195
- message: 'This repo already has a climaybe config. Reinitialize? This will remove your current stores and workflow settings.',
195
+ message: 'This repo already has a climaybe config. Clear everything and reinitialize from scratch?',
196
196
  initial: false,
197
197
  });
198
198
  if (!reinit) {
package/src/index.js CHANGED
@@ -1,3 +1,6 @@
1
+ import { createRequire } from 'node:module';
2
+ import { dirname, join } from 'node:path';
3
+ import { fileURLToPath } from 'node:url';
1
4
  import { Command } from 'commander';
2
5
  import { initCommand, reinitCommand } from './commands/init.js';
3
6
  import { addStoreCommand } from './commands/add-store.js';
@@ -5,6 +8,10 @@ import { switchCommand } from './commands/switch.js';
5
8
  import { syncCommand } from './commands/sync.js';
6
9
  import { updateWorkflowsCommand } from './commands/update-workflows.js';
7
10
 
11
+ const require = createRequire(import.meta.url);
12
+ const __dirname = dirname(fileURLToPath(import.meta.url));
13
+ const { version } = require(join(__dirname, '..', 'package.json'));
14
+
8
15
  /**
9
16
  * Create the CLI program (for testing and for run).
10
17
  */
@@ -14,7 +21,7 @@ export function createProgram() {
14
21
  program
15
22
  .name('climaybe')
16
23
  .description('Shopify CI/CD CLI — scaffolds workflows, branch strategy, and store config')
17
- .version('1.0.0');
24
+ .version(version);
18
25
 
19
26
  program
20
27
  .command('init')
@@ -1,5 +1,4 @@
1
- import { spawn } from 'node:child_process';
2
- import { execSync } from 'node:child_process';
1
+ import { spawn, spawnSync, execSync } from 'node:child_process';
3
2
  import pc from 'picocolors';
4
3
 
5
4
  /**
@@ -80,12 +79,31 @@ export function hasGitHubRemote(cwd = process.cwd()) {
80
79
  }
81
80
  }
82
81
 
82
+ /**
83
+ * Get GitHub repo as "owner/repo" from origin remote. Returns null if not a GitHub URL or parse fails.
84
+ * Used to pass -R to gh when the repo has multiple remotes.
85
+ */
86
+ export function getGitHubRepoSpec(cwd = process.cwd()) {
87
+ try {
88
+ const url = execSync('git remote get-url origin', { cwd, encoding: 'utf-8', stdio: 'pipe' }).trim();
89
+ // https://github.com/owner/repo[.git] or git@github.com:owner/repo[.git]
90
+ const m = url.match(/github\.com[/:]([^/]+)\/([^/]+?)(?:\.git)?$/i);
91
+ return m ? `${m[1]}/${m[2]}` : null;
92
+ } catch {
93
+ return null;
94
+ }
95
+ }
96
+
83
97
  /**
84
98
  * List repository secret names (GitHub). Returns [] on error or if none.
85
99
  */
86
100
  export function listGitHubSecrets(cwd = process.cwd()) {
87
101
  try {
88
- const out = execSync('gh secret list --json name', { cwd, encoding: 'utf-8', stdio: 'pipe' }).trim();
102
+ const repo = getGitHubRepoSpec(cwd);
103
+ const args = ['secret', 'list', '--json', 'name'];
104
+ if (repo) args.push('-R', repo);
105
+ const result = spawnSync('gh', args, { cwd, encoding: 'utf-8', stdio: ['pipe', 'pipe', 'pipe'] });
106
+ const out = (result.stdout || '').trim();
89
107
  const data = JSON.parse(out || '[]');
90
108
  return Array.isArray(data) ? data.map((s) => s.name).filter(Boolean) : [];
91
109
  } catch {
@@ -109,11 +127,16 @@ export function listGitLabVariables(cwd = process.cwd()) {
109
127
 
110
128
  /**
111
129
  * Set a repository secret via gh CLI. Value is passed via stdin to avoid argv exposure.
130
+ * Uses -R owner/repo from origin when available so gh works with multiple remotes.
112
131
  */
113
- export function setSecret(name, value) {
132
+ export function setSecret(name, value, cwd = process.cwd()) {
114
133
  return new Promise((resolve, reject) => {
115
- const child = spawn('gh', ['secret', 'set', name], {
134
+ const repo = getGitHubRepoSpec(cwd);
135
+ const args = ['secret', 'set', name];
136
+ if (repo) args.push('-R', repo);
137
+ const child = spawn('gh', args, {
116
138
  stdio: ['pipe', 'inherit', 'inherit'],
139
+ cwd,
117
140
  });
118
141
  child.on('error', reject);
119
142
  child.on('close', (code) => (code === 0 ? resolve() : reject(new Error(`gh secret set exited with ${code}`))));