hereya-cli 0.87.0 → 0.89.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 +111 -163
- package/dist/backend/cloud/cloud-backend.d.ts +2 -1
- package/dist/backend/cloud/cloud-backend.js +36 -0
- package/dist/backend/common.d.ts +17 -0
- package/dist/backend/index.js +0 -24
- package/dist/commands/app/deploy/index.d.ts +0 -2
- package/dist/commands/app/deploy/index.js +0 -17
- package/dist/commands/app/deployments/index.d.ts +0 -4
- package/dist/commands/app/deployments/index.js +1 -20
- package/dist/commands/app/destroy/index.d.ts +0 -2
- package/dist/commands/app/destroy/index.js +0 -17
- package/dist/commands/app/env/index.d.ts +0 -2
- package/dist/commands/app/env/index.js +0 -17
- package/dist/commands/app/list/index.d.ts +0 -4
- package/dist/commands/app/list/index.js +1 -20
- package/dist/commands/app/status/index.d.ts +0 -2
- package/dist/commands/app/status/index.js +0 -17
- package/dist/commands/clone/index.js +2 -2
- package/dist/commands/deploy/index.d.ts +0 -2
- package/dist/commands/deploy/index.js +56 -69
- package/dist/commands/import-repo/index.d.ts +15 -0
- package/dist/commands/import-repo/index.js +111 -0
- package/dist/commands/init/index.d.ts +0 -2
- package/dist/commands/init/index.js +10 -70
- package/dist/commands/login/index.js +0 -5
- package/dist/commands/publish/index.d.ts +0 -2
- package/dist/commands/publish/index.js +0 -17
- package/dist/commands/run/index.d.ts +0 -2
- package/dist/commands/run/index.js +0 -17
- package/dist/commands/search/index.d.ts +0 -2
- package/dist/commands/search/index.js +21 -38
- package/dist/commands/undeploy/index.d.ts +0 -2
- package/dist/commands/undeploy/index.js +14 -27
- package/dist/commands/up/index.d.ts +0 -2
- package/dist/commands/up/index.js +1 -17
- package/dist/commands/workspace/executor/install/index.d.ts +0 -2
- package/dist/commands/workspace/executor/install/index.js +1 -17
- package/dist/commands/workspace/executor/token/index.d.ts +0 -2
- package/dist/commands/workspace/executor/token/index.js +0 -17
- package/dist/commands/workspace/executor/uninstall/index.d.ts +0 -2
- package/dist/commands/workspace/executor/uninstall/index.js +1 -17
- package/dist/executor/context.js +15 -12
- package/dist/lib/clone-and-configure.d.ts +43 -0
- package/dist/lib/clone-and-configure.js +77 -0
- package/dist/lib/hereya-token.js +11 -10
- package/dist/lib/package/index.js +24 -20
- package/oclif.manifest.json +145 -254
- package/package.json +1 -1
- package/dist/commands/git/index.d.ts +0 -12
- package/dist/commands/git/index.js +0 -116
- package/dist/lib/active-cloud.d.ts +0 -31
- package/dist/lib/active-cloud.js +0 -55
- package/dist/lib/ephemeral-token.d.ts +0 -45
- package/dist/lib/ephemeral-token.js +0 -89
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { Config } from '../../lib/config/common.js';
|
|
2
2
|
import { IParameterSpec } from '../../lib/package/index.js';
|
|
3
|
-
import { AddPackageToWorkspaceInput, AddPackageToWorkspaceOutput, Backend, CreateWorkspaceInput, CreateWorkspaceOutput, DeleteStateInput, DeleteStateOutput, DeleteWorkspaceInput, DeleteWorkspaceOutput, ExportBackendOutput, GetPackageOutput, GetProjectMetadataInput, GetProjectMetadataOutput, GetProvisioningIdInput, GetProvisioningIdOutput, GetStateInput, GetStateOutput, GetWorkspaceEnvInput, GetWorkspaceEnvOutput, GetWorkspaceOutput, ImportBackendInput, ImportBackendOutput, InitProjectInput, InitProjectOutput, ListPackageVersionsOutput, ListProjectsOutput, ListWorkspacesInput, PublishPackageInput, PublishPackageOutput, RemovePackageFromWorkspaceInput, RemovePackageFromWorkspaceOutput, SaveProjectMetadataInput, SaveProjectMetadataOutput, SearchPackagesInput, SearchPackagesOutput, SetEnvVarInput, SetEnvVarOutput, UnsetEnvVarInput, UnsetEnvVarOutput, UpdateWorkspaceInput, UpdateWorkspaceOutput } from '../common.js';
|
|
3
|
+
import { AddPackageToWorkspaceInput, AddPackageToWorkspaceOutput, Backend, CreateWorkspaceInput, CreateWorkspaceOutput, DeleteStateInput, DeleteStateOutput, DeleteWorkspaceInput, DeleteWorkspaceOutput, ExportBackendOutput, GetPackageOutput, GetProjectMetadataInput, GetProjectMetadataOutput, GetProvisioningIdInput, GetProvisioningIdOutput, GetStateInput, GetStateOutput, GetWorkspaceEnvInput, GetWorkspaceEnvOutput, GetWorkspaceOutput, ImportBackendInput, ImportBackendOutput, ImportProjectInput, ImportProjectOutput, InitProjectInput, InitProjectOutput, ListPackageVersionsOutput, ListProjectsOutput, ListWorkspacesInput, PublishPackageInput, PublishPackageOutput, RemovePackageFromWorkspaceInput, RemovePackageFromWorkspaceOutput, SaveProjectMetadataInput, SaveProjectMetadataOutput, SearchPackagesInput, SearchPackagesOutput, SetEnvVarInput, SetEnvVarOutput, UnsetEnvVarInput, UnsetEnvVarOutput, UpdateWorkspaceInput, UpdateWorkspaceOutput } from '../common.js';
|
|
4
4
|
interface CloudBackendConfig {
|
|
5
5
|
accessToken: string;
|
|
6
6
|
clientId: string;
|
|
@@ -158,6 +158,7 @@ export declare class CloudBackend implements Backend {
|
|
|
158
158
|
getWorkspace(name: string): Promise<GetWorkspaceOutput>;
|
|
159
159
|
getWorkspaceEnv(input: GetWorkspaceEnvInput): Promise<GetWorkspaceEnvOutput>;
|
|
160
160
|
importBackend(input: ImportBackendInput): Promise<ImportBackendOutput>;
|
|
161
|
+
importProject(input: ImportProjectInput): Promise<ImportProjectOutput>;
|
|
161
162
|
init(input: InitProjectInput): Promise<InitProjectOutput>;
|
|
162
163
|
listAppDeployments(name: string): Promise<{
|
|
163
164
|
deployments: AppDeploymentSummary[];
|
|
@@ -488,6 +488,42 @@ export class CloudBackend {
|
|
|
488
488
|
success: true,
|
|
489
489
|
};
|
|
490
490
|
}
|
|
491
|
+
async importProject(input) {
|
|
492
|
+
const response = await fetch(`${this.config.url}/api/projects/${encodeURIComponent(input.project)}/import`, {
|
|
493
|
+
body: JSON.stringify({ repoUrl: input.repoUrl, workspace: input.workspace }),
|
|
494
|
+
headers: {
|
|
495
|
+
'Authorization': `Bearer ${this.config.accessToken}`,
|
|
496
|
+
'Content-Type': 'application/json',
|
|
497
|
+
},
|
|
498
|
+
method: 'POST',
|
|
499
|
+
});
|
|
500
|
+
const result = await this.safeResponseJson(response);
|
|
501
|
+
if (!response.ok) {
|
|
502
|
+
const reason = typeof result?.error === 'string'
|
|
503
|
+
? result.error
|
|
504
|
+
: (result?.errors && typeof result.errors === 'object'
|
|
505
|
+
? JSON.stringify(result.errors)
|
|
506
|
+
: JSON.stringify(result));
|
|
507
|
+
return {
|
|
508
|
+
...(typeof result?.code === 'string' ? { code: result.code } : {}),
|
|
509
|
+
reason,
|
|
510
|
+
success: false,
|
|
511
|
+
};
|
|
512
|
+
}
|
|
513
|
+
if (!result?.success || !result?.project) {
|
|
514
|
+
return {
|
|
515
|
+
reason: typeof result?.error === 'string' ? result.error : 'Unexpected response from server',
|
|
516
|
+
success: false,
|
|
517
|
+
};
|
|
518
|
+
}
|
|
519
|
+
return {
|
|
520
|
+
project: {
|
|
521
|
+
defaultWorkspace: result.project.defaultWorkspace,
|
|
522
|
+
name: result.project.name,
|
|
523
|
+
},
|
|
524
|
+
success: true,
|
|
525
|
+
};
|
|
526
|
+
}
|
|
491
527
|
async init(input) {
|
|
492
528
|
const formData = new FormData();
|
|
493
529
|
formData.append('name', input.project);
|
package/dist/backend/common.d.ts
CHANGED
|
@@ -15,6 +15,7 @@ export interface Backend {
|
|
|
15
15
|
getWorkspace(workspace: string): Promise<GetWorkspaceOutput>;
|
|
16
16
|
getWorkspaceEnv(input: GetWorkspaceEnvInput): Promise<GetWorkspaceEnvOutput>;
|
|
17
17
|
importBackend(input: ImportBackendInput): Promise<ImportBackendOutput>;
|
|
18
|
+
importProject?(input: ImportProjectInput): Promise<ImportProjectOutput>;
|
|
18
19
|
init(options: InitProjectInput): Promise<InitProjectOutput>;
|
|
19
20
|
listPackageVersions?(name: string): Promise<ListPackageVersionsOutput>;
|
|
20
21
|
listProjects?(): Promise<ListProjectsOutput>;
|
|
@@ -363,6 +364,22 @@ export type SaveProjectMetadataOutput = {
|
|
|
363
364
|
} | {
|
|
364
365
|
success: true;
|
|
365
366
|
};
|
|
367
|
+
export interface ImportProjectInput {
|
|
368
|
+
project: string;
|
|
369
|
+
repoUrl: string;
|
|
370
|
+
workspace: string;
|
|
371
|
+
}
|
|
372
|
+
export type ImportProjectOutput = {
|
|
373
|
+
code?: string;
|
|
374
|
+
reason: string;
|
|
375
|
+
success: false;
|
|
376
|
+
} | {
|
|
377
|
+
project: {
|
|
378
|
+
defaultWorkspace: string;
|
|
379
|
+
name: string;
|
|
380
|
+
};
|
|
381
|
+
success: true;
|
|
382
|
+
};
|
|
366
383
|
export type ProjectSummary = {
|
|
367
384
|
defaultWorkspace: string;
|
|
368
385
|
name: string;
|
package/dist/backend/index.js
CHANGED
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import { getAwsConfig } from '../infrastructure/aws-config.js';
|
|
2
|
-
import { getEphemeralToken } from '../lib/ephemeral-token.js';
|
|
3
2
|
import { CloudBackend } from './cloud/cloud-backend.js';
|
|
4
3
|
import { loginWithToken, refreshToken } from './cloud/login.js';
|
|
5
4
|
import { getCloudCredentials, loadBackendConfig, saveCloudCredentials } from './config.js';
|
|
@@ -67,29 +66,6 @@ export async function getBackend(typeOrOptions) {
|
|
|
67
66
|
if (backend) {
|
|
68
67
|
return backend;
|
|
69
68
|
}
|
|
70
|
-
// Ephemeral, in-memory-only token (typically set via the --token flag or by
|
|
71
|
-
// an embedding integration). We use the supplied token directly as the
|
|
72
|
-
// bearer for cloud API calls and explicitly do NOT exchange it via
|
|
73
|
-
// `loginWithToken` — that would mint a long-lived refresh token and we
|
|
74
|
-
// want this code path to never persist anything to disk or the keychain.
|
|
75
|
-
const ephemeral = getEphemeralToken();
|
|
76
|
-
if (ephemeral) {
|
|
77
|
-
const url = ephemeral.cloudUrl
|
|
78
|
-
?? process.env.HEREYA_CLOUD_URL
|
|
79
|
-
?? (await loadBackendConfig()).cloud?.url
|
|
80
|
-
?? 'https://cloud.hereya.dev';
|
|
81
|
-
backend = new CloudBackend({
|
|
82
|
-
accessToken: ephemeral.token,
|
|
83
|
-
// We have no client/refresh identity for an ephemeral token. Use empty
|
|
84
|
-
// strings — the CloudBackend never uses these for the request bearer
|
|
85
|
-
// (it only uses accessToken), and we never call refreshToken() in this
|
|
86
|
-
// mode.
|
|
87
|
-
clientId: '',
|
|
88
|
-
refreshToken: '',
|
|
89
|
-
url,
|
|
90
|
-
});
|
|
91
|
-
return backend;
|
|
92
|
-
}
|
|
93
69
|
// Handle token-based auth
|
|
94
70
|
if (typeOrOptions && typeof typeOrOptions === 'object' && typeOrOptions.token) {
|
|
95
71
|
const url = typeOrOptions.url || 'https://cloud.hereya.dev';
|
|
@@ -9,12 +9,10 @@ export default class AppDeploy extends Command {
|
|
|
9
9
|
chdir: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
10
10
|
local: import("@oclif/core/interfaces").BooleanFlag<boolean>;
|
|
11
11
|
parameter: import("@oclif/core/interfaces").OptionFlag<string[], import("@oclif/core/interfaces").CustomOptions>;
|
|
12
|
-
token: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
13
12
|
version: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
14
13
|
workspace: import("@oclif/core/interfaces").OptionFlag<string, import("@oclif/core/interfaces").CustomOptions>;
|
|
15
14
|
};
|
|
16
15
|
run(): Promise<void>;
|
|
17
|
-
private runInner;
|
|
18
16
|
private runLocal;
|
|
19
17
|
private runRemote;
|
|
20
18
|
}
|
|
@@ -8,8 +8,6 @@ import { getBackend } from '../../../backend/index.js';
|
|
|
8
8
|
import { LocalExecutor } from '../../../executor/local.js';
|
|
9
9
|
import { resolveAndSubstituteAppParams, resolveAppParameters } from '../../../lib/app-parameters.js';
|
|
10
10
|
import { getEnvManager } from '../../../lib/env/index.js';
|
|
11
|
-
import { withEphemeralToken } from '../../../lib/ephemeral-token.js';
|
|
12
|
-
import { getDefaultLogger } from '../../../lib/log.js';
|
|
13
11
|
import { arrayOfStringToObject } from '../../../lib/object-utils.js';
|
|
14
12
|
import { stripOrgPrefix } from '../../../lib/org-utils.js';
|
|
15
13
|
import { getProfileFromWorkspace } from '../../../lib/profile-utils.js';
|
|
@@ -90,10 +88,6 @@ export default class AppDeploy extends Command {
|
|
|
90
88
|
description: 'parameter for the app deployment, in the form of key=value (repeatable)',
|
|
91
89
|
multiple: true,
|
|
92
90
|
}),
|
|
93
|
-
token: Flags.string({
|
|
94
|
-
description: 'Ephemeral cloud access token used for this invocation only. Held in memory; never written to the keychain or `~/.hereya/secrets/`. Takes precedence over the HEREYA_TOKEN environment variable.',
|
|
95
|
-
required: false,
|
|
96
|
-
}),
|
|
97
91
|
version: Flags.string({
|
|
98
92
|
description: 'specific app version to deploy (defaults to latest)',
|
|
99
93
|
}),
|
|
@@ -104,17 +98,6 @@ export default class AppDeploy extends Command {
|
|
|
104
98
|
}),
|
|
105
99
|
};
|
|
106
100
|
async run() {
|
|
107
|
-
const { flags } = await this.parse(AppDeploy);
|
|
108
|
-
// Precedence: --token flag > HEREYA_TOKEN env var > keychain.
|
|
109
|
-
if (flags.token) {
|
|
110
|
-
if (process.env.HEREYA_TOKEN) {
|
|
111
|
-
getDefaultLogger().debug('[app deploy] --token flag overrides HEREYA_TOKEN environment variable.');
|
|
112
|
-
}
|
|
113
|
-
return withEphemeralToken(flags.token, () => this.runInner());
|
|
114
|
-
}
|
|
115
|
-
return this.runInner();
|
|
116
|
-
}
|
|
117
|
-
async runInner() {
|
|
118
101
|
const { args, flags } = await this.parse(AppDeploy);
|
|
119
102
|
const forceLocal = flags.local || process.env.HEREYA_LOCAL_EXECUTION === 'true';
|
|
120
103
|
if (forceLocal) {
|
|
@@ -5,9 +5,5 @@ export default class AppDeployments extends Command {
|
|
|
5
5
|
};
|
|
6
6
|
static description: string;
|
|
7
7
|
static examples: string[];
|
|
8
|
-
static flags: {
|
|
9
|
-
token: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
10
|
-
};
|
|
11
8
|
run(): Promise<void>;
|
|
12
|
-
private runInner;
|
|
13
9
|
}
|
|
@@ -1,32 +1,13 @@
|
|
|
1
|
-
import { Args, Command
|
|
1
|
+
import { Args, Command } from '@oclif/core';
|
|
2
2
|
import { CloudBackend } from '../../../backend/cloud/cloud-backend.js';
|
|
3
3
|
import { getBackend } from '../../../backend/index.js';
|
|
4
|
-
import { withEphemeralToken } from '../../../lib/ephemeral-token.js';
|
|
5
|
-
import { getDefaultLogger } from '../../../lib/log.js';
|
|
6
4
|
export default class AppDeployments extends Command {
|
|
7
5
|
static args = {
|
|
8
6
|
name: Args.string({ description: 'app name in org/name format', required: true }),
|
|
9
7
|
};
|
|
10
8
|
static description = 'List workspaces a hereya-app has been deployed to.';
|
|
11
9
|
static examples = ['<%= config.bin %> <%= command.id %> my-org/my-app'];
|
|
12
|
-
static flags = {
|
|
13
|
-
token: Flags.string({
|
|
14
|
-
description: 'Ephemeral cloud access token used for this invocation only. Held in memory; never written to the keychain or `~/.hereya/secrets/`. Takes precedence over the HEREYA_TOKEN environment variable.',
|
|
15
|
-
required: false,
|
|
16
|
-
}),
|
|
17
|
-
};
|
|
18
10
|
async run() {
|
|
19
|
-
const { flags } = await this.parse(AppDeployments);
|
|
20
|
-
// Precedence: --token flag > HEREYA_TOKEN env var > keychain.
|
|
21
|
-
if (flags.token) {
|
|
22
|
-
if (process.env.HEREYA_TOKEN) {
|
|
23
|
-
getDefaultLogger().debug('[app deployments] --token flag overrides HEREYA_TOKEN environment variable.');
|
|
24
|
-
}
|
|
25
|
-
return withEphemeralToken(flags.token, () => this.runInner());
|
|
26
|
-
}
|
|
27
|
-
return this.runInner();
|
|
28
|
-
}
|
|
29
|
-
async runInner() {
|
|
30
11
|
const { args } = await this.parse(AppDeployments);
|
|
31
12
|
const backend = await getBackend();
|
|
32
13
|
if (!(backend instanceof CloudBackend)) {
|
|
@@ -9,11 +9,9 @@ export default class AppDestroy extends Command {
|
|
|
9
9
|
chdir: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
10
10
|
local: import("@oclif/core/interfaces").BooleanFlag<boolean>;
|
|
11
11
|
parameter: import("@oclif/core/interfaces").OptionFlag<string[], import("@oclif/core/interfaces").CustomOptions>;
|
|
12
|
-
token: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
13
12
|
workspace: import("@oclif/core/interfaces").OptionFlag<string, import("@oclif/core/interfaces").CustomOptions>;
|
|
14
13
|
};
|
|
15
14
|
run(): Promise<void>;
|
|
16
|
-
private runInner;
|
|
17
15
|
private runLocal;
|
|
18
16
|
private runRemote;
|
|
19
17
|
}
|
|
@@ -8,8 +8,6 @@ import { getBackend } from '../../../backend/index.js';
|
|
|
8
8
|
import { LocalExecutor } from '../../../executor/local.js';
|
|
9
9
|
import { resolveAndSubstituteAppParams } from '../../../lib/app-parameters.js';
|
|
10
10
|
import { getEnvManager } from '../../../lib/env/index.js';
|
|
11
|
-
import { withEphemeralToken } from '../../../lib/ephemeral-token.js';
|
|
12
|
-
import { getDefaultLogger } from '../../../lib/log.js';
|
|
13
11
|
import { arrayOfStringToObject } from '../../../lib/object-utils.js';
|
|
14
12
|
import { stripOrgPrefix } from '../../../lib/org-utils.js';
|
|
15
13
|
import { getProfileFromWorkspace } from '../../../lib/profile-utils.js';
|
|
@@ -78,10 +76,6 @@ export default class AppDestroy extends Command {
|
|
|
78
76
|
description: 'parameter for the app deployment, in the form of key=value (repeatable)',
|
|
79
77
|
multiple: true,
|
|
80
78
|
}),
|
|
81
|
-
token: Flags.string({
|
|
82
|
-
description: 'Ephemeral cloud access token used for this invocation only. Held in memory; never written to the keychain or `~/.hereya/secrets/`. Takes precedence over the HEREYA_TOKEN environment variable.',
|
|
83
|
-
required: false,
|
|
84
|
-
}),
|
|
85
79
|
workspace: Flags.string({
|
|
86
80
|
char: 'w',
|
|
87
81
|
description: 'workspace where the app is currently deployed',
|
|
@@ -89,17 +83,6 @@ export default class AppDestroy extends Command {
|
|
|
89
83
|
}),
|
|
90
84
|
};
|
|
91
85
|
async run() {
|
|
92
|
-
const { flags } = await this.parse(AppDestroy);
|
|
93
|
-
// Precedence: --token flag > HEREYA_TOKEN env var > keychain.
|
|
94
|
-
if (flags.token) {
|
|
95
|
-
if (process.env.HEREYA_TOKEN) {
|
|
96
|
-
getDefaultLogger().debug('[app destroy] --token flag overrides HEREYA_TOKEN environment variable.');
|
|
97
|
-
}
|
|
98
|
-
return withEphemeralToken(flags.token, () => this.runInner());
|
|
99
|
-
}
|
|
100
|
-
return this.runInner();
|
|
101
|
-
}
|
|
102
|
-
async runInner() {
|
|
103
86
|
const { args, flags } = await this.parse(AppDestroy);
|
|
104
87
|
const forceLocal = flags.local || process.env.HEREYA_LOCAL_EXECUTION === 'true';
|
|
105
88
|
if (forceLocal) {
|
|
@@ -7,9 +7,7 @@ export default class AppEnv extends Command {
|
|
|
7
7
|
static description: string;
|
|
8
8
|
static examples: string[];
|
|
9
9
|
static flags: {
|
|
10
|
-
token: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
11
10
|
workspace: import("@oclif/core/interfaces").OptionFlag<string, import("@oclif/core/interfaces").CustomOptions>;
|
|
12
11
|
};
|
|
13
12
|
run(): Promise<void>;
|
|
14
|
-
private runInner;
|
|
15
13
|
}
|
|
@@ -1,8 +1,6 @@
|
|
|
1
1
|
import { Args, Command, Flags } from '@oclif/core';
|
|
2
2
|
import { CloudBackend } from '../../../backend/cloud/cloud-backend.js';
|
|
3
3
|
import { getBackend } from '../../../backend/index.js';
|
|
4
|
-
import { withEphemeralToken } from '../../../lib/ephemeral-token.js';
|
|
5
|
-
import { getDefaultLogger } from '../../../lib/log.js';
|
|
6
4
|
export default class AppEnv extends Command {
|
|
7
5
|
static args = {
|
|
8
6
|
name: Args.string({ description: 'app name in org/name format', required: true }),
|
|
@@ -15,10 +13,6 @@ export default class AppEnv extends Command {
|
|
|
15
13
|
'<%= config.bin %> <%= command.id %> my-org/my-app -w my-workspace DATABASE_URL',
|
|
16
14
|
];
|
|
17
15
|
static flags = {
|
|
18
|
-
token: Flags.string({
|
|
19
|
-
description: 'Ephemeral cloud access token used for this invocation only. Held in memory; never written to the keychain or `~/.hereya/secrets/`. Takes precedence over the HEREYA_TOKEN environment variable.',
|
|
20
|
-
required: false,
|
|
21
|
-
}),
|
|
22
16
|
workspace: Flags.string({
|
|
23
17
|
char: 'w',
|
|
24
18
|
description: 'workspace to read env outputs from',
|
|
@@ -26,17 +20,6 @@ export default class AppEnv extends Command {
|
|
|
26
20
|
}),
|
|
27
21
|
};
|
|
28
22
|
async run() {
|
|
29
|
-
const { flags } = await this.parse(AppEnv);
|
|
30
|
-
// Precedence: --token flag > HEREYA_TOKEN env var > keychain.
|
|
31
|
-
if (flags.token) {
|
|
32
|
-
if (process.env.HEREYA_TOKEN) {
|
|
33
|
-
getDefaultLogger().debug('[app env] --token flag overrides HEREYA_TOKEN environment variable.');
|
|
34
|
-
}
|
|
35
|
-
return withEphemeralToken(flags.token, () => this.runInner());
|
|
36
|
-
}
|
|
37
|
-
return this.runInner();
|
|
38
|
-
}
|
|
39
|
-
async runInner() {
|
|
40
23
|
const { args, flags } = await this.parse(AppEnv);
|
|
41
24
|
const backend = await getBackend();
|
|
42
25
|
if (!(backend instanceof CloudBackend)) {
|
|
@@ -2,9 +2,5 @@ import { Command } from '@oclif/core';
|
|
|
2
2
|
export default class AppList extends Command {
|
|
3
3
|
static description: string;
|
|
4
4
|
static examples: string[];
|
|
5
|
-
static flags: {
|
|
6
|
-
token: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
7
|
-
};
|
|
8
5
|
run(): Promise<void>;
|
|
9
|
-
private runInner;
|
|
10
6
|
}
|
|
@@ -1,29 +1,10 @@
|
|
|
1
|
-
import { Command
|
|
1
|
+
import { Command } from '@oclif/core';
|
|
2
2
|
import { CloudBackend } from '../../../backend/cloud/cloud-backend.js';
|
|
3
3
|
import { getBackend } from '../../../backend/index.js';
|
|
4
|
-
import { withEphemeralToken } from '../../../lib/ephemeral-token.js';
|
|
5
|
-
import { getDefaultLogger } from '../../../lib/log.js';
|
|
6
4
|
export default class AppList extends Command {
|
|
7
5
|
static description = 'List hereya-apps available to your account.';
|
|
8
6
|
static examples = ['<%= config.bin %> <%= command.id %>'];
|
|
9
|
-
static flags = {
|
|
10
|
-
token: Flags.string({
|
|
11
|
-
description: 'Ephemeral cloud access token used for this invocation only. Held in memory; never written to the keychain or `~/.hereya/secrets/`. Takes precedence over the HEREYA_TOKEN environment variable.',
|
|
12
|
-
required: false,
|
|
13
|
-
}),
|
|
14
|
-
};
|
|
15
7
|
async run() {
|
|
16
|
-
const { flags } = await this.parse(AppList);
|
|
17
|
-
// Precedence: --token flag > HEREYA_TOKEN env var > keychain.
|
|
18
|
-
if (flags.token) {
|
|
19
|
-
if (process.env.HEREYA_TOKEN) {
|
|
20
|
-
getDefaultLogger().debug('[app list] --token flag overrides HEREYA_TOKEN environment variable.');
|
|
21
|
-
}
|
|
22
|
-
return withEphemeralToken(flags.token, () => this.runInner());
|
|
23
|
-
}
|
|
24
|
-
return this.runInner();
|
|
25
|
-
}
|
|
26
|
-
async runInner() {
|
|
27
8
|
const backend = await getBackend();
|
|
28
9
|
if (!(backend instanceof CloudBackend)) {
|
|
29
10
|
this.error('Listing apps requires the cloud backend. Run `hereya login` first.');
|
|
@@ -6,9 +6,7 @@ export default class AppStatus extends Command {
|
|
|
6
6
|
static description: string;
|
|
7
7
|
static examples: string[];
|
|
8
8
|
static flags: {
|
|
9
|
-
token: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
10
9
|
workspace: import("@oclif/core/interfaces").OptionFlag<string, import("@oclif/core/interfaces").CustomOptions>;
|
|
11
10
|
};
|
|
12
11
|
run(): Promise<void>;
|
|
13
|
-
private runInner;
|
|
14
12
|
}
|
|
@@ -1,8 +1,6 @@
|
|
|
1
1
|
import { Args, Command, Flags } from '@oclif/core';
|
|
2
2
|
import { CloudBackend } from '../../../backend/cloud/cloud-backend.js';
|
|
3
3
|
import { getBackend } from '../../../backend/index.js';
|
|
4
|
-
import { withEphemeralToken } from '../../../lib/ephemeral-token.js';
|
|
5
|
-
import { getDefaultLogger } from '../../../lib/log.js';
|
|
6
4
|
export default class AppStatus extends Command {
|
|
7
5
|
static args = {
|
|
8
6
|
name: Args.string({ description: 'app name in org/name format', required: true }),
|
|
@@ -10,10 +8,6 @@ export default class AppStatus extends Command {
|
|
|
10
8
|
static description = 'Show the deployment status of a hereya-app on a workspace.';
|
|
11
9
|
static examples = ['<%= config.bin %> <%= command.id %> my-org/my-app -w my-workspace'];
|
|
12
10
|
static flags = {
|
|
13
|
-
token: Flags.string({
|
|
14
|
-
description: 'Ephemeral cloud access token used for this invocation only. Held in memory; never written to the keychain or `~/.hereya/secrets/`. Takes precedence over the HEREYA_TOKEN environment variable.',
|
|
15
|
-
required: false,
|
|
16
|
-
}),
|
|
17
11
|
workspace: Flags.string({
|
|
18
12
|
char: 'w',
|
|
19
13
|
description: 'workspace to read deployment status from',
|
|
@@ -21,17 +15,6 @@ export default class AppStatus extends Command {
|
|
|
21
15
|
}),
|
|
22
16
|
};
|
|
23
17
|
async run() {
|
|
24
|
-
const { flags } = await this.parse(AppStatus);
|
|
25
|
-
// Precedence: --token flag > HEREYA_TOKEN env var > keychain.
|
|
26
|
-
if (flags.token) {
|
|
27
|
-
if (process.env.HEREYA_TOKEN) {
|
|
28
|
-
getDefaultLogger().debug('[app status] --token flag overrides HEREYA_TOKEN environment variable.');
|
|
29
|
-
}
|
|
30
|
-
return withEphemeralToken(flags.token, () => this.runInner());
|
|
31
|
-
}
|
|
32
|
-
return this.runInner();
|
|
33
|
-
}
|
|
34
|
-
async runInner() {
|
|
35
18
|
const { args, flags } = await this.parse(AppStatus);
|
|
36
19
|
const backend = await getBackend();
|
|
37
20
|
if (!(backend instanceof CloudBackend)) {
|
|
@@ -36,7 +36,7 @@ export default class Clone extends Command {
|
|
|
36
36
|
}
|
|
37
37
|
const metadata$ = await backend.getProjectMetadata({ project: args.project });
|
|
38
38
|
if (!metadata$.found) {
|
|
39
|
-
throw new Error(`Project metadata not found for ${args.project}. Was it initialized
|
|
39
|
+
throw new Error(`Project metadata not found for ${args.project}. Was it initialized or imported?`);
|
|
40
40
|
}
|
|
41
41
|
ctx.metadata = metadata$.metadata;
|
|
42
42
|
ctx.defaultWorkspace = metadata$.defaultWorkspace;
|
|
@@ -59,7 +59,7 @@ export default class Clone extends Command {
|
|
|
59
59
|
workspace: ctx.defaultWorkspace,
|
|
60
60
|
});
|
|
61
61
|
if (!ctx.resolvedGitEnv.hereyaGitRemoteUrl) {
|
|
62
|
-
throw new Error(
|
|
62
|
+
throw new Error(`Project metadata does not contain hereyaGitRemoteUrl for ${args.project}. Was it initialized or imported?`);
|
|
63
63
|
}
|
|
64
64
|
},
|
|
65
65
|
title: 'Resolving git credentials',
|
|
@@ -6,10 +6,8 @@ export default class Deploy extends Command {
|
|
|
6
6
|
chdir: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
7
7
|
debug: import("@oclif/core/interfaces").BooleanFlag<boolean>;
|
|
8
8
|
local: import("@oclif/core/interfaces").BooleanFlag<boolean>;
|
|
9
|
-
token: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
10
9
|
workspace: import("@oclif/core/interfaces").OptionFlag<string, import("@oclif/core/interfaces").CustomOptions>;
|
|
11
10
|
};
|
|
12
11
|
run(): Promise<void>;
|
|
13
12
|
private deployRemotely;
|
|
14
|
-
private runInner;
|
|
15
13
|
}
|
|
@@ -2,14 +2,13 @@ import { Command, Flags } from '@oclif/core';
|
|
|
2
2
|
import { getRendererClass, Listr, ListrLogger, ListrLogLevels } from 'listr2';
|
|
3
3
|
import path from 'node:path';
|
|
4
4
|
import { CloudBackend } from '../../backend/cloud/cloud-backend.js';
|
|
5
|
+
import { getCloudCredentials, loadBackendConfig } from '../../backend/config.js';
|
|
5
6
|
import { getBackend } from '../../backend/index.js';
|
|
6
7
|
import { getExecutor } from '../../executor/index.js';
|
|
7
|
-
import { getActiveCloudAuth } from '../../lib/active-cloud.js';
|
|
8
8
|
import { getConfigManager } from '../../lib/config/index.js';
|
|
9
9
|
import { getEnvManager } from '../../lib/env/index.js';
|
|
10
|
-
import { withEphemeralToken } from '../../lib/ephemeral-token.js';
|
|
11
10
|
import { gitUtils } from '../../lib/git-utils.js';
|
|
12
|
-
import {
|
|
11
|
+
import { getLogger, getLogPath, isDebug, setDebug } from '../../lib/log.js';
|
|
13
12
|
import { getParameterManager } from '../../lib/parameter/index.js';
|
|
14
13
|
import { getProfileFromWorkspace } from '../../lib/profile-utils.js';
|
|
15
14
|
import { pollExecutorJob } from '../../lib/remote-job-utils.js';
|
|
@@ -36,10 +35,6 @@ export default class Deploy extends Command {
|
|
|
36
35
|
default: false,
|
|
37
36
|
description: 'force local execution (skip remote executor)',
|
|
38
37
|
}),
|
|
39
|
-
token: Flags.string({
|
|
40
|
-
description: 'Ephemeral cloud access token used for this invocation only. Held in memory; never written to the keychain or `~/.hereya/secrets/`. Takes precedence over the HEREYA_TOKEN environment variable.',
|
|
41
|
-
required: false,
|
|
42
|
-
}),
|
|
43
38
|
workspace: Flags.string({
|
|
44
39
|
char: 'w',
|
|
45
40
|
description: 'name of the workspace to deploy the packages for',
|
|
@@ -47,68 +42,6 @@ export default class Deploy extends Command {
|
|
|
47
42
|
}),
|
|
48
43
|
};
|
|
49
44
|
async run() {
|
|
50
|
-
const { flags } = await this.parse(Deploy);
|
|
51
|
-
// Precedence: --token flag > HEREYA_TOKEN env var > keychain.
|
|
52
|
-
if (flags.token) {
|
|
53
|
-
if (process.env.HEREYA_TOKEN) {
|
|
54
|
-
getDefaultLogger().debug('[deploy] --token flag overrides HEREYA_TOKEN environment variable.');
|
|
55
|
-
}
|
|
56
|
-
return withEphemeralToken(flags.token, () => this.runInner());
|
|
57
|
-
}
|
|
58
|
-
return this.runInner();
|
|
59
|
-
}
|
|
60
|
-
async deployRemotely(input) {
|
|
61
|
-
const myLogger = new ListrLogger({ useIcons: false });
|
|
62
|
-
// 1. Ensure clean working tree
|
|
63
|
-
const cleanCheck = await gitUtils.ensureCleanAndPushed({ cwd: input.projectRootDir });
|
|
64
|
-
if (!cleanCheck.clean) {
|
|
65
|
-
this.error(cleanCheck.reason);
|
|
66
|
-
}
|
|
67
|
-
myLogger.log(ListrLogLevels.STARTED, `Deploying to ${input.workspace} via remote executor (branch: ${input.gitBranch})`);
|
|
68
|
-
// 2. Resolve cloud auth (ephemeral --token first, then persisted creds)
|
|
69
|
-
// and build a CloudBackend for job submission + polling.
|
|
70
|
-
const auth = await getActiveCloudAuth();
|
|
71
|
-
if (!auth) {
|
|
72
|
-
this.error('Remote deployment requires cloud backend. Run `hereya login` or pass `--token <token>`.');
|
|
73
|
-
}
|
|
74
|
-
const resolvedWorkspaceName = resolveWorkspaceName(input.workspace, input.project);
|
|
75
|
-
const cloudBackend = new CloudBackend({
|
|
76
|
-
accessToken: auth.accessToken,
|
|
77
|
-
clientId: auth.clientId ?? '',
|
|
78
|
-
refreshToken: auth.refreshToken ?? '',
|
|
79
|
-
url: auth.cloudUrl,
|
|
80
|
-
});
|
|
81
|
-
// 3. Submit deploy job
|
|
82
|
-
const submitResult = await cloudBackend.submitExecutorJob({
|
|
83
|
-
payload: {
|
|
84
|
-
gitBranch: input.gitBranch,
|
|
85
|
-
project: input.project,
|
|
86
|
-
workspace: input.workspace,
|
|
87
|
-
},
|
|
88
|
-
type: 'deploy',
|
|
89
|
-
workspace: resolvedWorkspaceName,
|
|
90
|
-
});
|
|
91
|
-
if (!submitResult.success) {
|
|
92
|
-
this.error(`Failed to submit remote deploy job: ${submitResult.reason}`);
|
|
93
|
-
}
|
|
94
|
-
// 4. Poll for results
|
|
95
|
-
const logger = {
|
|
96
|
-
debug: (msg) => myLogger.log(ListrLogLevels.OUTPUT, msg),
|
|
97
|
-
error: (msg) => myLogger.log(ListrLogLevels.OUTPUT, msg),
|
|
98
|
-
info: (msg) => myLogger.log(ListrLogLevels.OUTPUT, msg),
|
|
99
|
-
};
|
|
100
|
-
const pollResult = await pollExecutorJob({
|
|
101
|
-
cloudBackend,
|
|
102
|
-
jobId: submitResult.jobId,
|
|
103
|
-
logger,
|
|
104
|
-
workspace: resolvedWorkspaceName,
|
|
105
|
-
});
|
|
106
|
-
if (!pollResult.success) {
|
|
107
|
-
this.error(pollResult.reason);
|
|
108
|
-
}
|
|
109
|
-
myLogger.log(ListrLogLevels.COMPLETED, 'Remote deployment completed successfully');
|
|
110
|
-
}
|
|
111
|
-
async runInner() {
|
|
112
45
|
const { flags } = await this.parse(Deploy);
|
|
113
46
|
setDebug(flags.debug);
|
|
114
47
|
const projectRootDir = path.resolve(flags.chdir || process.env.HEREYA_PROJECT_ROOT_DIR || process.cwd());
|
|
@@ -521,4 +454,58 @@ export default class Deploy extends Command {
|
|
|
521
454
|
See ${getLogPath()} for more details`);
|
|
522
455
|
}
|
|
523
456
|
}
|
|
457
|
+
async deployRemotely(input) {
|
|
458
|
+
const myLogger = new ListrLogger({ useIcons: false });
|
|
459
|
+
// 1. Ensure clean working tree
|
|
460
|
+
const cleanCheck = await gitUtils.ensureCleanAndPushed({ cwd: input.projectRootDir });
|
|
461
|
+
if (!cleanCheck.clean) {
|
|
462
|
+
this.error(cleanCheck.reason);
|
|
463
|
+
}
|
|
464
|
+
myLogger.log(ListrLogLevels.STARTED, `Deploying to ${input.workspace} via remote executor (branch: ${input.gitBranch})`);
|
|
465
|
+
// 2. Build CloudBackend for job submission + polling
|
|
466
|
+
const backendConfig = await loadBackendConfig();
|
|
467
|
+
if (!backendConfig.cloud) {
|
|
468
|
+
this.error('Remote deployment requires cloud backend. Run `hereya login` first.');
|
|
469
|
+
}
|
|
470
|
+
const credentials = await getCloudCredentials(backendConfig.cloud.clientId);
|
|
471
|
+
if (!credentials) {
|
|
472
|
+
this.error('Cloud credentials not found. Run `hereya login` first.');
|
|
473
|
+
}
|
|
474
|
+
const resolvedWorkspaceName = resolveWorkspaceName(input.workspace, input.project);
|
|
475
|
+
const cloudBackend = new CloudBackend({
|
|
476
|
+
accessToken: credentials.accessToken,
|
|
477
|
+
clientId: backendConfig.cloud.clientId,
|
|
478
|
+
refreshToken: credentials.refreshToken,
|
|
479
|
+
url: backendConfig.cloud.url,
|
|
480
|
+
});
|
|
481
|
+
// 3. Submit deploy job
|
|
482
|
+
const submitResult = await cloudBackend.submitExecutorJob({
|
|
483
|
+
payload: {
|
|
484
|
+
gitBranch: input.gitBranch,
|
|
485
|
+
project: input.project,
|
|
486
|
+
workspace: input.workspace,
|
|
487
|
+
},
|
|
488
|
+
type: 'deploy',
|
|
489
|
+
workspace: resolvedWorkspaceName,
|
|
490
|
+
});
|
|
491
|
+
if (!submitResult.success) {
|
|
492
|
+
this.error(`Failed to submit remote deploy job: ${submitResult.reason}`);
|
|
493
|
+
}
|
|
494
|
+
// 4. Poll for results
|
|
495
|
+
const logger = {
|
|
496
|
+
debug: (msg) => myLogger.log(ListrLogLevels.OUTPUT, msg),
|
|
497
|
+
error: (msg) => myLogger.log(ListrLogLevels.OUTPUT, msg),
|
|
498
|
+
info: (msg) => myLogger.log(ListrLogLevels.OUTPUT, msg),
|
|
499
|
+
};
|
|
500
|
+
const pollResult = await pollExecutorJob({
|
|
501
|
+
cloudBackend,
|
|
502
|
+
jobId: submitResult.jobId,
|
|
503
|
+
logger,
|
|
504
|
+
workspace: resolvedWorkspaceName,
|
|
505
|
+
});
|
|
506
|
+
if (!pollResult.success) {
|
|
507
|
+
this.error(pollResult.reason);
|
|
508
|
+
}
|
|
509
|
+
myLogger.log(ListrLogLevels.COMPLETED, 'Remote deployment completed successfully');
|
|
510
|
+
}
|
|
524
511
|
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { Command } from '@oclif/core';
|
|
2
|
+
export default class ImportRepo extends Command {
|
|
3
|
+
static args: {
|
|
4
|
+
project: import("@oclif/core/interfaces").Arg<string, Record<string, unknown>>;
|
|
5
|
+
};
|
|
6
|
+
static description: string;
|
|
7
|
+
static examples: string[];
|
|
8
|
+
static flags: {
|
|
9
|
+
chdir: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
10
|
+
clone: import("@oclif/core/interfaces").BooleanFlag<boolean>;
|
|
11
|
+
'repo-url': import("@oclif/core/interfaces").OptionFlag<string, import("@oclif/core/interfaces").CustomOptions>;
|
|
12
|
+
workspace: import("@oclif/core/interfaces").OptionFlag<string, import("@oclif/core/interfaces").CustomOptions>;
|
|
13
|
+
};
|
|
14
|
+
run(): Promise<void>;
|
|
15
|
+
}
|