@eve-horizon/cli 0.2.5 → 0.2.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.
@@ -4,6 +4,7 @@ exports.handleBuild = handleBuild;
4
4
  const args_1 = require("../lib/args");
5
5
  const client_1 = require("../lib/client");
6
6
  const output_1 = require("../lib/output");
7
+ const node_child_process_1 = require("node:child_process");
7
8
  // ---------------------------------------------------------------------------
8
9
  // Entry point
9
10
  // ---------------------------------------------------------------------------
@@ -52,7 +53,22 @@ async function handleCreate(flags, context, json) {
52
53
  if (!projectId || !ref || !manifestHash) {
53
54
  throw new Error('Usage: eve build create --project <id> --ref <sha> --manifest-hash <hash> [--services <s1,s2>]');
54
55
  }
55
- const body = { git_sha: ref, manifest_hash: manifestHash };
56
+ // Resolve git ref to actual 40-char SHA
57
+ let gitSha;
58
+ try {
59
+ gitSha = (0, node_child_process_1.execSync)(`git rev-parse ${ref}`, {
60
+ encoding: 'utf-8',
61
+ stdio: ['pipe', 'pipe', 'pipe'],
62
+ }).trim();
63
+ if (!json) {
64
+ console.log(`Resolved ref '${ref}' → ${gitSha.substring(0, 8)}...`);
65
+ }
66
+ }
67
+ catch (error) {
68
+ throw new Error(`Failed to resolve git ref '${ref}': ${error instanceof Error ? error.message : String(error)}\n` +
69
+ 'Make sure you are in a git repository and the ref exists.');
70
+ }
71
+ const body = { git_sha: gitSha, manifest_hash: manifestHash };
56
72
  if (services) {
57
73
  body.services = services.split(',').map(s => s.trim());
58
74
  }
@@ -197,10 +197,25 @@ async function handleDeploy(positionals, flags, context, json) {
197
197
  throw new Error('Usage: eve env deploy <env> --ref <sha> [--direct] [--inputs <json>] [--image-tag <tag>] [--project=<id>]');
198
198
  }
199
199
  // --ref flag is now required
200
- const gitSha = (0, args_1.getStringFlag)(flags, ['ref']);
201
- if (!gitSha) {
200
+ const ref = (0, args_1.getStringFlag)(flags, ['ref']);
201
+ if (!ref) {
202
202
  throw new Error('Usage: eve env deploy <env> --ref <sha> [options]\n\nThe --ref flag is required (git SHA or commit reference)');
203
203
  }
204
+ // Resolve git ref to actual 40-char SHA
205
+ let gitSha;
206
+ try {
207
+ gitSha = (0, child_process_1.execSync)(`git rev-parse ${ref}`, {
208
+ encoding: 'utf-8',
209
+ stdio: ['pipe', 'pipe', 'pipe'],
210
+ }).trim();
211
+ if (!json) {
212
+ console.log(`Resolved ref '${ref}' → ${gitSha.substring(0, 8)}...`);
213
+ }
214
+ }
215
+ catch (error) {
216
+ throw new Error(`Failed to resolve git ref '${ref}': ${error instanceof Error ? error.message : String(error)}\n` +
217
+ 'Make sure you are in a git repository and the ref exists.');
218
+ }
204
219
  if (!json) {
205
220
  console.log(`Deploying commit ${gitSha.substring(0, 8)} to ${envName}...`);
206
221
  }
@@ -1012,6 +1012,22 @@ function formatJobDetails(job) {
1012
1012
  console.log(` Key: ${job.workspace.key}`);
1013
1013
  }
1014
1014
  }
1015
+ // Resolved Git
1016
+ if (job.resolved_git) {
1017
+ const rg = job.resolved_git;
1018
+ console.log('');
1019
+ console.log(' Resolved Git:');
1020
+ if (rg.resolved_sha)
1021
+ console.log(` SHA: ${rg.resolved_sha}`);
1022
+ if (rg.resolved_branch)
1023
+ console.log(` Branch: ${rg.resolved_branch}`);
1024
+ if (rg.ref_source)
1025
+ console.log(` Source: ${rg.ref_source}`);
1026
+ if (rg.pushed !== undefined)
1027
+ console.log(` Pushed: ${rg.pushed}`);
1028
+ if (rg.commits?.length)
1029
+ console.log(` Commits: ${rg.commits.join(', ')}`);
1030
+ }
1015
1031
  console.log('');
1016
1032
  console.log(` Created: ${formatDate(job.created_at)}`);
1017
1033
  console.log(` Updated: ${formatDate(job.updated_at)}`);
@@ -1795,6 +1811,22 @@ function formatResultFull(response) {
1795
1811
  if (pipelineOutput?.deploy?.preview_url) {
1796
1812
  console.log(`Preview: ${pipelineOutput.deploy.preview_url}`);
1797
1813
  }
1814
+ // Display git metadata if present in result_json
1815
+ const resolvedGit = response.resultJson.resolved_git;
1816
+ if (resolvedGit) {
1817
+ console.log('');
1818
+ console.log('Git:');
1819
+ if (resolvedGit.resolved_sha)
1820
+ console.log(` SHA: ${resolvedGit.resolved_sha}`);
1821
+ if (resolvedGit.resolved_branch)
1822
+ console.log(` Branch: ${resolvedGit.resolved_branch}`);
1823
+ if (resolvedGit.ref_source)
1824
+ console.log(` Source: ${resolvedGit.ref_source}`);
1825
+ if (resolvedGit.pushed !== undefined)
1826
+ console.log(` Pushed: ${resolvedGit.pushed}`);
1827
+ if (resolvedGit.commits?.length)
1828
+ console.log(` Commits: ${resolvedGit.commits.join(', ')}`);
1829
+ }
1798
1830
  }
1799
1831
  console.log('');
1800
1832
  console.log('Result:');
@@ -4,6 +4,7 @@ exports.handlePipeline = handlePipeline;
4
4
  const args_1 = require("../lib/args");
5
5
  const client_1 = require("../lib/client");
6
6
  const output_1 = require("../lib/output");
7
+ const node_child_process_1 = require("node:child_process");
7
8
  async function handlePipeline(subcommand, positionals, flags, context) {
8
9
  const json = Boolean(flags.json);
9
10
  switch (subcommand) {
@@ -165,6 +166,21 @@ async function handleRun(positionals, flags, context, json) {
165
166
  if (!pipelineName || !projectId || !ref) {
166
167
  throw new Error('Usage: eve pipeline run <name> --ref <sha> [--env <env>] [--project <id>] [--wait] [--inputs <json>] [--only <step>]');
167
168
  }
169
+ // Resolve git ref to actual 40-char SHA
170
+ let gitSha;
171
+ try {
172
+ gitSha = (0, node_child_process_1.execSync)(`git rev-parse ${ref}`, {
173
+ encoding: 'utf-8',
174
+ stdio: ['pipe', 'pipe', 'pipe'],
175
+ }).trim();
176
+ if (!json) {
177
+ console.log(`Resolved ref '${ref}' → ${gitSha.substring(0, 8)}...`);
178
+ }
179
+ }
180
+ catch (error) {
181
+ throw new Error(`Failed to resolve git ref '${ref}': ${error instanceof Error ? error.message : String(error)}\n` +
182
+ 'Make sure you are in a git repository and the ref exists.');
183
+ }
168
184
  let inputs;
169
185
  if (inputsRaw) {
170
186
  try {
@@ -175,11 +191,11 @@ async function handleRun(positionals, flags, context, json) {
175
191
  }
176
192
  }
177
193
  // Emit event before creating the pipeline run
178
- await emitPipelineRunEvent(context, projectId, pipelineName, { env, ref, inputs });
194
+ await emitPipelineRunEvent(context, projectId, pipelineName, { env, ref: gitSha, inputs });
179
195
  if (only) {
180
196
  const response = await (0, client_1.requestJson)(context, `/projects/${projectId}/pipelines/${pipelineName}/runs`, {
181
197
  method: 'POST',
182
- body: { git_sha: ref, env_name: env, inputs, only },
198
+ body: { git_sha: gitSha, env_name: env, inputs, only },
183
199
  });
184
200
  if (json) {
185
201
  (0, output_1.outputJson)(response, json);
@@ -203,7 +219,7 @@ async function handleRun(positionals, flags, context, json) {
203
219
  const url = `/projects/${projectId}/pipelines/${pipelineName}/run${queryString ? `?${queryString}` : ''}`;
204
220
  const response = await (0, client_1.requestJson)(context, url, {
205
221
  method: 'POST',
206
- body: { ref, env, inputs },
222
+ body: { ref: gitSha, env, inputs },
207
223
  });
208
224
  if (json) {
209
225
  (0, output_1.outputJson)(response, json);
@@ -64,10 +64,10 @@ function handleProfile(subcommand, positionals, flags, config) {
64
64
  return;
65
65
  }
66
66
  case 'use': {
67
- const isLocal = Boolean(flags.local);
67
+ const isGlobal = Boolean(flags.global);
68
68
  const isClear = Boolean(flags.clear);
69
- // Handle --local --clear: remove local profile
70
- if (isLocal && isClear) {
69
+ // Handle --clear: remove local profile
70
+ if (isClear) {
71
71
  const removed = (0, context_1.removeRepoProfile)();
72
72
  if (removed) {
73
73
  (0, output_1.outputJson)({ cleared: true, path: (0, context_1.getRepoProfilePath)() }, json, `✓ Removed local profile`);
@@ -79,15 +79,21 @@ function handleProfile(subcommand, positionals, flags, config) {
79
79
  }
80
80
  const name = positionals[0];
81
81
  if (!name) {
82
- throw new Error('Usage: eve profile use <name> [--local]');
82
+ throw new Error('Usage: eve profile use <name> [--global]');
83
83
  }
84
- // Validate profile exists in global config
84
+ // Validate profile exists in global config (auto-create if needed)
85
85
  if (!config.profiles[name]) {
86
86
  config.profiles[name] = {};
87
87
  (0, config_1.saveConfig)(config);
88
88
  }
89
- if (isLocal) {
90
- // Write to .eve/profile.yaml
89
+ if (isGlobal) {
90
+ // Explicit: set global active profile in ~/.eve/config.json
91
+ config.active_profile = name;
92
+ (0, config_1.saveConfig)(config);
93
+ (0, output_1.outputJson)({ active_profile: name }, json, `✓ Active profile: ${name} (global)`);
94
+ }
95
+ else {
96
+ // Default: write to .eve/profile.yaml (local project mode)
91
97
  const repoProfile = { profile: name };
92
98
  // Apply any override flags
93
99
  if (typeof flags['api-url'] === 'string')
@@ -99,12 +105,6 @@ function handleProfile(subcommand, positionals, flags, config) {
99
105
  (0, context_1.saveRepoProfile)(repoProfile);
100
106
  (0, output_1.outputJson)({ profile: name, local: true, path: (0, context_1.getRepoProfilePath)(), ...repoProfile }, json, `✓ Local profile set: ${name} (${(0, context_1.getRepoProfilePath)()})`);
101
107
  }
102
- else {
103
- // Set global active profile
104
- config.active_profile = name;
105
- (0, config_1.saveConfig)(config);
106
- (0, output_1.outputJson)({ active_profile: name }, json, `✓ Active profile: ${name}`);
107
- }
108
108
  return;
109
109
  }
110
110
  case 'create': {
@@ -121,14 +121,42 @@ function handleProfile(subcommand, positionals, flags, config) {
121
121
  return;
122
122
  }
123
123
  case 'set': {
124
- const name = positionals[0] ?? config.active_profile;
125
- if (!config.profiles[name]) {
126
- config.profiles[name] = {};
124
+ const isGlobal = Boolean(flags.global);
125
+ if (isGlobal) {
126
+ // Explicit: write to global ~/.eve/config.json
127
+ const name = positionals[0] ?? config.active_profile;
128
+ if (!config.profiles[name]) {
129
+ config.profiles[name] = {};
130
+ }
131
+ config.profiles[name] = applyProfileFlags(config.profiles[name], flags);
132
+ config.active_profile = name;
133
+ (0, config_1.saveConfig)(config);
134
+ (0, output_1.outputJson)({ active_profile: name, ...config.profiles[name] }, json, `✓ Profile set: ${name} (global)`);
135
+ }
136
+ else {
137
+ // Default: write to local .eve/profile.yaml
138
+ const globalOnlyFields = ['supabase-url', 'supabase-anon-key', 'default-email', 'default-ssh-key'];
139
+ const usedGlobalFields = globalOnlyFields.filter(f => typeof flags[f] === 'string');
140
+ if (usedGlobalFields.length > 0) {
141
+ throw new Error(`${usedGlobalFields.map(f => `--${f}`).join(', ')} are user-level settings.\n` +
142
+ `Use --global to write them to ~/.eve/config.json`);
143
+ }
144
+ const existing = (0, context_1.loadRepoProfile)() ?? {};
145
+ const repoProfile = { ...existing };
146
+ const name = positionals[0];
147
+ if (name)
148
+ repoProfile.profile = name;
149
+ if (typeof flags['api-url'] === 'string')
150
+ repoProfile.api_url = flags['api-url'];
151
+ if (typeof flags.org === 'string')
152
+ repoProfile.org_id = flags.org;
153
+ if (typeof flags.project === 'string')
154
+ repoProfile.project_id = flags.project;
155
+ if (typeof flags.harness === 'string')
156
+ repoProfile.default_harness = flags.harness;
157
+ (0, context_1.saveRepoProfile)(repoProfile);
158
+ (0, output_1.outputJson)({ ...repoProfile, path: (0, context_1.getRepoProfilePath)() }, json, `✓ Profile set: ${repoProfile.profile ?? 'local'} (${(0, context_1.getRepoProfilePath)()})`);
127
159
  }
128
- config.profiles[name] = applyProfileFlags(config.profiles[name], flags);
129
- config.active_profile = name;
130
- (0, config_1.saveConfig)(config);
131
- (0, output_1.outputJson)({ active_profile: name, ...config.profiles[name] }, json, `✓ Profile set: ${name}`);
132
160
  return;
133
161
  }
134
162
  case 'remove': {
package/dist/lib/help.js CHANGED
@@ -530,7 +530,11 @@ Jobs default to 'ready' phase, making them immediately schedulable.`,
530
530
  },
531
531
  profile: {
532
532
  description: `Manage CLI profiles. Profiles store defaults (API URL, org, project) so you don't
533
- have to specify them on every command. Useful when working with multiple environments.`,
533
+ have to specify them on every command.
534
+
535
+ By default, set and use write to .eve/profile.yaml (project-local). Use --global to
536
+ write to ~/.eve/config.json instead. This lets you work on multiple projects without
537
+ clobbering your global config.`,
534
538
  usage: 'eve profile <subcommand> [options]',
535
539
  subcommands: {
536
540
  list: {
@@ -538,17 +542,28 @@ have to specify them on every command. Useful when working with multiple environ
538
542
  usage: 'eve profile list',
539
543
  },
540
544
  show: {
541
- description: 'Show profile details',
545
+ description: 'Show profile details (local overrides applied)',
542
546
  usage: 'eve profile show [name]',
543
547
  examples: ['eve profile show', 'eve profile show prod'],
544
548
  },
545
549
  use: {
546
- description: 'Switch active profile',
547
- usage: 'eve profile use <name>',
548
- examples: ['eve profile use prod'],
550
+ description: 'Switch active profile (defaults to local .eve/profile.yaml)',
551
+ usage: 'eve profile use <name> [--global] [--org <id>] [--project <id>]',
552
+ options: [
553
+ '--global Write to ~/.eve/config.json instead of local project',
554
+ '--org <id> Set org override',
555
+ '--project <id> Set project override',
556
+ '--api-url <url> Set API URL override',
557
+ '--clear Remove local .eve/profile.yaml',
558
+ ],
559
+ examples: [
560
+ 'eve profile use staging --org org_xxx --project proj_yyy',
561
+ 'eve profile use staging --global',
562
+ 'eve profile use --clear',
563
+ ],
549
564
  },
550
565
  create: {
551
- description: 'Create a new profile',
566
+ description: 'Create a new named profile (always global)',
552
567
  usage: 'eve profile create <name> [--api-url <url>] [--org <id>] [--project <id>]',
553
568
  options: [
554
569
  '--api-url <url> API base URL',
@@ -566,13 +581,16 @@ have to specify them on every command. Useful when working with multiple environ
566
581
  ],
567
582
  },
568
583
  set: {
569
- description: 'Update profile settings',
570
- usage: 'eve profile set [name] [--api-url <url>] [--org <id>] [--project <id>]',
584
+ description: 'Update profile settings (defaults to local .eve/profile.yaml)',
585
+ usage: 'eve profile set [name] [--org <id>] [--project <id>] [--global]',
571
586
  options: [
572
- '--api-url <url> API base URL',
573
587
  '--org <id> Default organization ID',
574
588
  '--project <id> Default project ID',
589
+ '--api-url <url> API base URL',
575
590
  '--harness <name> Default harness',
591
+ '--global Write to ~/.eve/config.json instead of local project',
592
+ '',
593
+ 'Global-only (require --global):',
576
594
  '--supabase-url <url> Supabase URL',
577
595
  '--supabase-anon-key <key> Supabase anon key',
578
596
  '--default-email <email> Default email for auth login',
@@ -580,19 +598,19 @@ have to specify them on every command. Useful when working with multiple environ
580
598
  ],
581
599
  examples: [
582
600
  'eve profile set --org org_xxx --project proj_yyy',
583
- 'eve profile set prod --api-url https://new-api.example.com',
584
- 'eve profile set --default-email user@example.com --default-ssh-key ~/.ssh/id_rsa',
601
+ 'eve profile set staging --org org_xxx --project proj_yyy',
602
+ 'eve profile set --global --default-email user@example.com',
585
603
  ],
586
604
  },
587
605
  remove: {
588
- description: 'Remove a profile',
606
+ description: 'Remove a named profile (global)',
589
607
  usage: 'eve profile remove <name>',
590
608
  },
591
609
  },
592
610
  examples: [
593
- 'eve profile create local --api-url http://localhost:4701',
594
- 'eve profile use local',
595
- 'eve profile set --org org_xxx',
611
+ 'eve profile set --org org_xxx --project proj_yyy # writes .eve/profile.yaml',
612
+ 'eve profile use staging --org org_xxx # writes .eve/profile.yaml',
613
+ 'eve profile set --global --default-email me@dev.com # writes ~/.eve/config.json',
596
614
  ],
597
615
  },
598
616
  auth: {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@eve-horizon/cli",
3
- "version": "0.2.5",
3
+ "version": "0.2.7",
4
4
  "description": "Eve Horizon CLI",
5
5
  "license": "MIT",
6
6
  "repository": {