hereya-cli 0.18.0 → 0.20.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 +24 -24
- package/bin/dev.js +1 -1
- package/dist/backend/common.d.ts +4 -4
- package/dist/backend/local.js +10 -2
- package/dist/commands/add/index.d.ts +4 -4
- package/dist/commands/add/index.js +12 -21
- package/dist/commands/bootstrap/index.d.ts +2 -2
- package/dist/commands/deploy/index.d.ts +3 -3
- package/dist/commands/deploy/index.js +45 -36
- package/dist/commands/down/index.d.ts +4 -4
- package/dist/commands/down/index.js +10 -21
- package/dist/commands/env/index.d.ts +4 -4
- package/dist/commands/env/index.js +6 -2
- package/dist/commands/env/set/index.d.ts +4 -4
- package/dist/commands/init/index.d.ts +3 -3
- package/dist/commands/remove/index.d.ts +3 -3
- package/dist/commands/remove/index.js +9 -19
- package/dist/commands/run/index.d.ts +3 -3
- package/dist/commands/run/index.js +7 -3
- package/dist/commands/unbootstrap/index.d.ts +2 -2
- package/dist/commands/undeploy/index.d.ts +3 -3
- package/dist/commands/undeploy/index.js +21 -24
- package/dist/commands/up/index.d.ts +4 -4
- package/dist/commands/up/index.js +24 -32
- package/dist/commands/workspace/create/index.d.ts +1 -1
- package/dist/commands/workspace/delete/index.d.ts +1 -1
- package/dist/commands/workspace/env/index.d.ts +3 -3
- package/dist/commands/workspace/env/set/index.d.ts +5 -5
- package/dist/commands/workspace/env/unset/index.d.ts +2 -2
- package/dist/commands/workspace/install/index.d.ts +5 -5
- package/dist/commands/workspace/install/index.js +8 -3
- package/dist/commands/workspace/uninstall/index.d.ts +5 -5
- package/dist/commands/workspace/uninstall/index.js +8 -3
- package/dist/executor/index.d.ts +11 -0
- package/dist/executor/index.js +8 -0
- package/dist/executor/interface.d.ts +41 -0
- package/dist/executor/interface.js +1 -0
- package/dist/executor/local.d.ts +7 -0
- package/dist/executor/local.js +56 -0
- package/dist/iac/cdk.js +5 -5
- package/dist/iac/index.js +5 -5
- package/dist/iac/terraform.js +7 -7
- package/dist/infrastructure/aws.js +1 -1
- package/dist/infrastructure/common.d.ts +2 -2
- package/dist/infrastructure/index.d.ts +3 -3
- package/dist/infrastructure/index.js +6 -6
- package/dist/infrastructure/local.js +1 -1
- package/dist/lib/env/index.d.ts +4 -0
- package/dist/lib/env/index.js +11 -3
- package/dist/lib/env-utils.d.ts +0 -7
- package/dist/lib/env-utils.js +0 -18
- package/dist/lib/log.js +1 -1
- package/dist/lib/package/common.d.ts +1 -0
- package/dist/lib/package/index.d.ts +1 -0
- package/dist/lib/package/index.js +3 -3
- package/dist/lib/package/local.d.ts +1 -1
- package/dist/lib/package/local.js +17 -4
- package/dist/lib/shell.d.ts +17 -7
- package/dist/lib/shell.js +73 -14
- package/dist/lib/yaml-utils.js +1 -1
- package/oclif.manifest.json +72 -72
- package/package.json +37 -37
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import { IPackageMetadata } from '../lib/package/index.js';
|
|
2
|
+
export type ExecutorProvisionInput = {
|
|
3
|
+
isDeploying?: boolean;
|
|
4
|
+
package: string;
|
|
5
|
+
parameters?: {
|
|
6
|
+
[key: string]: string;
|
|
7
|
+
};
|
|
8
|
+
project?: string;
|
|
9
|
+
projectEnv?: {
|
|
10
|
+
[key: string]: string;
|
|
11
|
+
};
|
|
12
|
+
projectRootDir?: string;
|
|
13
|
+
skipDeploy?: boolean;
|
|
14
|
+
workspace?: string;
|
|
15
|
+
};
|
|
16
|
+
export type ExecutorProvisionOutput = {
|
|
17
|
+
env: {
|
|
18
|
+
[key: string]: string;
|
|
19
|
+
};
|
|
20
|
+
metadata: IPackageMetadata;
|
|
21
|
+
success: true;
|
|
22
|
+
} | {
|
|
23
|
+
reason: string;
|
|
24
|
+
success: false;
|
|
25
|
+
};
|
|
26
|
+
export type ExecutorDestroyInput = ExecutorProvisionInput;
|
|
27
|
+
export type ExecutorDestroyOutput = ExecutorProvisionOutput;
|
|
28
|
+
export type ExecutorResolveEnvValuesInput = {
|
|
29
|
+
env: {
|
|
30
|
+
[key: string]: string;
|
|
31
|
+
};
|
|
32
|
+
markSecret?: boolean;
|
|
33
|
+
};
|
|
34
|
+
export type ExecutorResolveEnvValuesOutput = {
|
|
35
|
+
[key: string]: string;
|
|
36
|
+
};
|
|
37
|
+
export interface Executor {
|
|
38
|
+
destroy(input: ExecutorDestroyInput): Promise<ExecutorDestroyOutput>;
|
|
39
|
+
provision(input: ExecutorProvisionInput): Promise<ExecutorProvisionOutput>;
|
|
40
|
+
resolveEnvValues(input: ExecutorResolveEnvValuesInput): Promise<ExecutorResolveEnvValuesOutput>;
|
|
41
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import { Executor, ExecutorDestroyInput, ExecutorDestroyOutput, ExecutorProvisionInput, ExecutorProvisionOutput, ExecutorResolveEnvValuesInput, ExecutorResolveEnvValuesOutput } from './interface.js';
|
|
2
|
+
export declare class LocalExecutor implements Executor {
|
|
3
|
+
destroy(input: ExecutorDestroyInput): Promise<ExecutorDestroyOutput>;
|
|
4
|
+
provision(input: ExecutorProvisionInput): Promise<ExecutorProvisionOutput>;
|
|
5
|
+
resolveEnvValues(input: ExecutorResolveEnvValuesInput): Promise<ExecutorResolveEnvValuesOutput>;
|
|
6
|
+
private getWorkspaceEnv;
|
|
7
|
+
}
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
import { getBackend } from '../backend/index.js';
|
|
2
|
+
import { destroyPackage, getInfrastructure, provisionPackage } from '../infrastructure/index.js';
|
|
3
|
+
export class LocalExecutor {
|
|
4
|
+
async destroy(input) {
|
|
5
|
+
const getWorkspaceEnvOutput = await this.getWorkspaceEnv({
|
|
6
|
+
project: input.project,
|
|
7
|
+
workspace: input.workspace,
|
|
8
|
+
});
|
|
9
|
+
if (!getWorkspaceEnvOutput.success) {
|
|
10
|
+
return { reason: getWorkspaceEnvOutput.reason, success: false };
|
|
11
|
+
}
|
|
12
|
+
return destroyPackage({
|
|
13
|
+
...input,
|
|
14
|
+
env: getWorkspaceEnvOutput.env,
|
|
15
|
+
});
|
|
16
|
+
}
|
|
17
|
+
async provision(input) {
|
|
18
|
+
const getWorkspaceEnvOutput = await this.getWorkspaceEnv({
|
|
19
|
+
project: input.project,
|
|
20
|
+
workspace: input.workspace,
|
|
21
|
+
});
|
|
22
|
+
if (!getWorkspaceEnvOutput.success) {
|
|
23
|
+
return { reason: getWorkspaceEnvOutput.reason, success: false };
|
|
24
|
+
}
|
|
25
|
+
return provisionPackage({
|
|
26
|
+
...input,
|
|
27
|
+
env: getWorkspaceEnvOutput.env,
|
|
28
|
+
});
|
|
29
|
+
}
|
|
30
|
+
async resolveEnvValues(input) {
|
|
31
|
+
return Object.fromEntries(await Promise.all(Object.entries(input.env).map(async ([key, value]) => {
|
|
32
|
+
const infraType = value.split(':')[0];
|
|
33
|
+
const infra$ = getInfrastructure({ type: infraType });
|
|
34
|
+
if (!infra$.supported) {
|
|
35
|
+
throw new Error(infra$.reason);
|
|
36
|
+
}
|
|
37
|
+
const { infrastructure } = infra$;
|
|
38
|
+
const valueWithoutInfra = value.split(':').slice(1).join(':');
|
|
39
|
+
const { isSecret, value: resolvedValue } = await infrastructure.resolveEnv({
|
|
40
|
+
value: valueWithoutInfra,
|
|
41
|
+
});
|
|
42
|
+
const finalValue = input.markSecret && isSecret ? `secret://${resolvedValue}` : resolvedValue;
|
|
43
|
+
return [key, finalValue];
|
|
44
|
+
})));
|
|
45
|
+
}
|
|
46
|
+
async getWorkspaceEnv({ project, workspace, }) {
|
|
47
|
+
if (!workspace || !project) {
|
|
48
|
+
return { env: {}, success: true };
|
|
49
|
+
}
|
|
50
|
+
const backend = await getBackend();
|
|
51
|
+
return backend.getWorkspaceEnv({
|
|
52
|
+
project,
|
|
53
|
+
workspace,
|
|
54
|
+
});
|
|
55
|
+
}
|
|
56
|
+
}
|
package/dist/iac/cdk.js
CHANGED
|
@@ -7,7 +7,7 @@ export class Cdk {
|
|
|
7
7
|
async apply(input) {
|
|
8
8
|
try {
|
|
9
9
|
const { remainingEnv, serializedParameters, serializedWorkspaceEnv } = await this.serializedParametersAndContext(input);
|
|
10
|
-
runShell('npx', [
|
|
10
|
+
await runShell('npx', [
|
|
11
11
|
'aws-cdk', 'deploy', '--require-approval', 'never', ...serializedWorkspaceEnv, ...serializedParameters,
|
|
12
12
|
], {
|
|
13
13
|
directory: input.pkgPath,
|
|
@@ -27,7 +27,7 @@ export class Cdk {
|
|
|
27
27
|
try {
|
|
28
28
|
const env = await this.getEnv(input.id);
|
|
29
29
|
const { remainingEnv, serializedParameters, serializedWorkspaceEnv } = await this.serializedParametersAndContext(input);
|
|
30
|
-
runShell('npx', [
|
|
30
|
+
await runShell('npx', [
|
|
31
31
|
'aws-cdk', 'destroy', '--force', ...serializedWorkspaceEnv, ...serializedParameters
|
|
32
32
|
], {
|
|
33
33
|
directory: input.pkgPath,
|
|
@@ -52,14 +52,14 @@ export class Cdk {
|
|
|
52
52
|
}
|
|
53
53
|
async getParameterNames(input) {
|
|
54
54
|
const workDir = input.pkgPath;
|
|
55
|
-
runShell('npm', ['install'], { directory: workDir });
|
|
56
|
-
runShell('npx', [
|
|
55
|
+
await runShell('npm', ['install'], { directory: workDir });
|
|
56
|
+
await runShell('npx', [
|
|
57
57
|
'aws-cdk', 'synth',
|
|
58
58
|
], {
|
|
59
59
|
directory: workDir,
|
|
60
60
|
env: { ...input.env, ...input.parameters },
|
|
61
61
|
});
|
|
62
|
-
const result = runShell('npx', [
|
|
62
|
+
const result = await runShell('npx', [
|
|
63
63
|
'aws-cdk', 'synth',
|
|
64
64
|
], {
|
|
65
65
|
directory: workDir,
|
package/dist/iac/index.js
CHANGED
|
@@ -5,21 +5,21 @@ export const terraform = new Terraform();
|
|
|
5
5
|
export const cdk = new Cdk();
|
|
6
6
|
export function getIac({ type }) {
|
|
7
7
|
switch (type) {
|
|
8
|
-
case IacType.
|
|
8
|
+
case IacType.cdk: {
|
|
9
|
+
return { iac: cdk, supported: true };
|
|
10
|
+
}
|
|
11
|
+
case IacType.opentf: {
|
|
9
12
|
return { iac: terraform, supported: true };
|
|
10
13
|
}
|
|
11
14
|
case IacType.opentofu: {
|
|
12
15
|
return { iac: terraform, supported: true };
|
|
13
16
|
}
|
|
14
|
-
case IacType.
|
|
17
|
+
case IacType.terraform: {
|
|
15
18
|
return { iac: terraform, supported: true };
|
|
16
19
|
}
|
|
17
20
|
case IacType.tofu: {
|
|
18
21
|
return { iac: terraform, supported: true };
|
|
19
22
|
}
|
|
20
|
-
case IacType.cdk: {
|
|
21
|
-
return { iac: cdk, supported: true };
|
|
22
|
-
}
|
|
23
23
|
default: {
|
|
24
24
|
return { reason: `Iac type ${type} is not supported yet!`, supported: false };
|
|
25
25
|
}
|
package/dist/iac/terraform.js
CHANGED
|
@@ -27,7 +27,7 @@ export class Terraform {
|
|
|
27
27
|
}
|
|
28
28
|
try {
|
|
29
29
|
const terraform = await this.getTerraformBinary();
|
|
30
|
-
runShell(terraform, ['init'], {
|
|
30
|
+
await runShell(terraform, ['init'], {
|
|
31
31
|
directory: input.pkgPath,
|
|
32
32
|
env: {
|
|
33
33
|
...mapObject(input.env ?? {}, (key, value) => [
|
|
@@ -41,7 +41,7 @@ export class Terraform {
|
|
|
41
41
|
]),
|
|
42
42
|
},
|
|
43
43
|
});
|
|
44
|
-
runShell(terraform, ['apply', '-auto-approve'], {
|
|
44
|
+
await runShell(terraform, ['apply', '-auto-approve'], {
|
|
45
45
|
directory: input.pkgPath,
|
|
46
46
|
env: {
|
|
47
47
|
...mapObject(input.env ?? {}, (key, value) => [
|
|
@@ -71,7 +71,7 @@ export class Terraform {
|
|
|
71
71
|
async destroy(input) {
|
|
72
72
|
const terraform = await this.getTerraformBinary();
|
|
73
73
|
try {
|
|
74
|
-
runShell(terraform, ['init'], {
|
|
74
|
+
await runShell(terraform, ['init'], {
|
|
75
75
|
directory: input.pkgPath,
|
|
76
76
|
env: {
|
|
77
77
|
...mapObject(input.env ?? {}, (key, value) => [
|
|
@@ -86,7 +86,7 @@ export class Terraform {
|
|
|
86
86
|
},
|
|
87
87
|
});
|
|
88
88
|
const env = await this.getEnv(input.pkgPath);
|
|
89
|
-
runShell(terraform, ['destroy', '-auto-approve'], {
|
|
89
|
+
await runShell(terraform, ['destroy', '-auto-approve'], {
|
|
90
90
|
directory: input.pkgPath,
|
|
91
91
|
env: {
|
|
92
92
|
...mapObject(input.env ?? {}, (key, value) => [
|
|
@@ -119,8 +119,8 @@ export class Terraform {
|
|
|
119
119
|
['freebsd_arm', 'https://github.com/opentofu/opentofu/releases/download/v1.9.0/tofu_1.9.0_freebsd_arm.zip'],
|
|
120
120
|
['freebsd_ia32', 'https://github.com/opentofu/opentofu/releases/download/v1.9.0/tofu_1.9.0_freebsd_386.zip'],
|
|
121
121
|
['freebsd_x64', 'https://github.com/opentofu/opentofu/releases/download/v1.9.0/tofu_1.9.0_freebsd_amd64.zip'],
|
|
122
|
-
['linux_arm', 'https://github.com/opentofu/opentofu/releases/download/v1.9.0/tofu_1.9.0_linux_arm.zip'],
|
|
123
122
|
['linux_arm64', 'https://github.com/opentofu/opentofu/releases/download/v1.9.0/tofu_1.9.0_linux_arm64.zip'],
|
|
123
|
+
['linux_arm', 'https://github.com/opentofu/opentofu/releases/download/v1.9.0/tofu_1.9.0_linux_arm.zip'],
|
|
124
124
|
['linux_ia32', 'https://github.com/opentofu/opentofu/releases/download/v1.9.0/tofu_1.9.0_linux_386.zip'],
|
|
125
125
|
['linux_x64', 'https://github.com/opentofu/opentofu/releases/download/v1.9.0/tofu_1.9.0_linux_amd64.zip'],
|
|
126
126
|
['openbsd_ia32', 'https://github.com/opentofu/opentofu/releases/download/v1.9.0/tofu_1.9.0_openbsd_386.zip'],
|
|
@@ -170,11 +170,11 @@ export class Terraform {
|
|
|
170
170
|
}
|
|
171
171
|
async getEnv(pkgPath) {
|
|
172
172
|
const terraform = await this.getTerraformBinary();
|
|
173
|
-
const resourceOut = runShell(terraform, ['output', '--json'], {
|
|
173
|
+
const resourceOut = await runShell(terraform, ['output', '--json'], {
|
|
174
174
|
directory: pkgPath,
|
|
175
175
|
stdio: 'pipe',
|
|
176
176
|
});
|
|
177
|
-
let outStr = resourceOut.
|
|
177
|
+
let outStr = resourceOut.stdout.toString().trim();
|
|
178
178
|
const start = outStr.indexOf('{');
|
|
179
179
|
const end = outStr.lastIndexOf('}');
|
|
180
180
|
outStr = outStr.slice(start, end + 1);
|
|
@@ -15,7 +15,7 @@ export class AwsInfrastructure {
|
|
|
15
15
|
const stsClient = new STSClient({});
|
|
16
16
|
const { Account: accountId } = await stsClient.send(new GetCallerIdentityCommand({}));
|
|
17
17
|
const region = process.env.AWS_REGION || process.env.AWS_DEFAULT_REGION;
|
|
18
|
-
runShell('npx', ['cdk', 'bootstrap', `aws://${accountId}/${region}`]);
|
|
18
|
+
await runShell('npx', ['cdk', 'bootstrap', `aws://${accountId}/${region}`]);
|
|
19
19
|
const bootstrapPackage = 'hereya/bootstrap-aws-stack';
|
|
20
20
|
const output = await provisionPackage({ package: bootstrapPackage });
|
|
21
21
|
if (!output.success) {
|
|
@@ -44,12 +44,12 @@ export type ProvisionOutput = {
|
|
|
44
44
|
};
|
|
45
45
|
export type DestroyInput = ProvisionInput;
|
|
46
46
|
export type DestroyOutput = ProvisionOutput;
|
|
47
|
-
export type DeployInput = {
|
|
47
|
+
export type DeployInput = ProvisionInput & {
|
|
48
48
|
projectEnv: {
|
|
49
49
|
[key: string]: string;
|
|
50
50
|
};
|
|
51
51
|
projectRootDir: string;
|
|
52
|
-
}
|
|
52
|
+
};
|
|
53
53
|
export type DeployOutput = ProvisionOutput;
|
|
54
54
|
export type UndeployInput = DeployInput;
|
|
55
55
|
export type UndeployOutput = DeployOutput;
|
|
@@ -41,10 +41,10 @@ export type GetInfrastructureInput = {
|
|
|
41
41
|
type: InfrastructureType;
|
|
42
42
|
};
|
|
43
43
|
export type GetInfrastructureOutput = {
|
|
44
|
-
reason: string;
|
|
45
|
-
supported: false;
|
|
46
|
-
} | {
|
|
47
44
|
infrastructure: Infrastructure;
|
|
48
45
|
supported: true;
|
|
46
|
+
} | {
|
|
47
|
+
reason: string;
|
|
48
|
+
supported: false;
|
|
49
49
|
};
|
|
50
50
|
export type PackageMetadata = z.infer<typeof PackageMetadata>;
|
|
@@ -7,15 +7,15 @@ export const localInfrastructure = new LocalInfrastructure();
|
|
|
7
7
|
export const awsInfrastructure = new AwsInfrastructure();
|
|
8
8
|
export function getInfrastructure(input) {
|
|
9
9
|
switch (input.type) {
|
|
10
|
-
case InfrastructureType.
|
|
10
|
+
case InfrastructureType.aws: {
|
|
11
11
|
return {
|
|
12
|
-
infrastructure:
|
|
12
|
+
infrastructure: awsInfrastructure,
|
|
13
13
|
supported: true,
|
|
14
14
|
};
|
|
15
15
|
}
|
|
16
|
-
case InfrastructureType.
|
|
16
|
+
case InfrastructureType.local: {
|
|
17
17
|
return {
|
|
18
|
-
infrastructure:
|
|
18
|
+
infrastructure: localInfrastructure,
|
|
19
19
|
supported: true,
|
|
20
20
|
};
|
|
21
21
|
}
|
|
@@ -28,7 +28,7 @@ export function getInfrastructure(input) {
|
|
|
28
28
|
}
|
|
29
29
|
}
|
|
30
30
|
export async function destroyPackage(input) {
|
|
31
|
-
const resolvePackageOutput = await resolvePackage({ isDeploying: input.isDeploying, package: input.package });
|
|
31
|
+
const resolvePackageOutput = await resolvePackage({ isDeploying: input.isDeploying, package: input.package, projectRootDir: input.projectRootDir });
|
|
32
32
|
if (!resolvePackageOutput.found) {
|
|
33
33
|
return { reason: resolvePackageOutput.reason, success: false };
|
|
34
34
|
}
|
|
@@ -91,7 +91,7 @@ export async function destroyPackage(input) {
|
|
|
91
91
|
return { env: destroyOutput.env, metadata, success: true };
|
|
92
92
|
}
|
|
93
93
|
export async function provisionPackage(input) {
|
|
94
|
-
const resolvePackageOutput = await resolvePackage({ isDeploying: input.isDeploying, package: input.package });
|
|
94
|
+
const resolvePackageOutput = await resolvePackage({ isDeploying: input.isDeploying, package: input.package, projectRootDir: input.projectRootDir });
|
|
95
95
|
if (!resolvePackageOutput.found) {
|
|
96
96
|
return { reason: resolvePackageOutput.reason, success: false };
|
|
97
97
|
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import * as fs from 'node:fs/promises';
|
|
2
2
|
import * as os from 'node:os';
|
|
3
|
-
import
|
|
3
|
+
import path from 'node:path';
|
|
4
4
|
import { getIac } from '../iac/index.js';
|
|
5
5
|
import { downloadPackage } from '../lib/package/index.js';
|
|
6
6
|
export class LocalInfrastructure {
|
package/dist/lib/env/index.d.ts
CHANGED
package/dist/lib/env/index.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import path from 'node:path';
|
|
2
|
-
import {
|
|
2
|
+
import { getExecutor } from '../../executor/index.js';
|
|
3
3
|
import { getAnyPath } from '../filesystem.js';
|
|
4
4
|
import { load, save } from '../yaml-utils.js';
|
|
5
5
|
export class EnvManager {
|
|
@@ -14,8 +14,16 @@ export class EnvManager {
|
|
|
14
14
|
const envPath = await this.getEnvPath(input);
|
|
15
15
|
const { data: env, found } = await load(envPath);
|
|
16
16
|
let resolvedEnv = {};
|
|
17
|
+
const executor$ = getExecutor();
|
|
18
|
+
if (!executor$.success) {
|
|
19
|
+
return {
|
|
20
|
+
reason: executor$.reason,
|
|
21
|
+
success: false,
|
|
22
|
+
};
|
|
23
|
+
}
|
|
24
|
+
const { executor } = executor$;
|
|
17
25
|
if (found) {
|
|
18
|
-
resolvedEnv = await resolveEnvValues(env,
|
|
26
|
+
resolvedEnv = await executor.resolveEnvValues({ env, markSecret: input.markSecret });
|
|
19
27
|
}
|
|
20
28
|
const userEnvs = await this.getUserEnvPaths(input).then((paths) => Promise.all(paths.map((path) => load(path))));
|
|
21
29
|
let userMergedEnv = {};
|
|
@@ -23,7 +31,7 @@ export class EnvManager {
|
|
|
23
31
|
userMergedEnv = { ...userMergedEnv, ...data };
|
|
24
32
|
}
|
|
25
33
|
const finalEnv = { ...resolvedEnv, ...userMergedEnv };
|
|
26
|
-
return { env: finalEnv };
|
|
34
|
+
return { env: finalEnv, success: true };
|
|
27
35
|
}
|
|
28
36
|
async removeProjectEnv(input) {
|
|
29
37
|
const envPath = await this.getEnvPath(input);
|
package/dist/lib/env-utils.d.ts
CHANGED
|
@@ -1,10 +1,3 @@
|
|
|
1
1
|
export declare function logEnv(env: {
|
|
2
2
|
[key: string]: string;
|
|
3
3
|
}, logFn?: (_: string) => void): void;
|
|
4
|
-
export declare function resolveEnvValues(env: {
|
|
5
|
-
[key: string]: string;
|
|
6
|
-
}, options?: {
|
|
7
|
-
markSecret?: boolean;
|
|
8
|
-
}): Promise<{
|
|
9
|
-
[key: string]: string;
|
|
10
|
-
}>;
|
package/dist/lib/env-utils.js
CHANGED
|
@@ -1,23 +1,5 @@
|
|
|
1
|
-
import { getInfrastructure } from '../infrastructure/index.js';
|
|
2
1
|
export function logEnv(env, logFn = console.log) {
|
|
3
2
|
for (const [key, value] of Object.entries(env)) {
|
|
4
3
|
logFn(`${key}=${value}`);
|
|
5
4
|
}
|
|
6
5
|
}
|
|
7
|
-
export async function resolveEnvValues(env, options = {}) {
|
|
8
|
-
return Object.fromEntries(await Promise.all(Object.entries(env)
|
|
9
|
-
.map(async ([key, value]) => {
|
|
10
|
-
const infraType = value.split(':')[0];
|
|
11
|
-
const infra$ = getInfrastructure({ type: infraType });
|
|
12
|
-
if (!infra$.supported) {
|
|
13
|
-
throw new Error(infra$.reason);
|
|
14
|
-
}
|
|
15
|
-
const { infrastructure } = infra$;
|
|
16
|
-
const valueWithoutInfra = value.split(':').slice(1).join(':');
|
|
17
|
-
const { isSecret, value: resolvedValue } = await infrastructure.resolveEnv({
|
|
18
|
-
value: valueWithoutInfra
|
|
19
|
-
});
|
|
20
|
-
const finalValue = options.markSecret && isSecret ? `secret://${resolvedValue}` : resolvedValue;
|
|
21
|
-
return [key, finalValue];
|
|
22
|
-
})));
|
|
23
|
-
}
|
package/dist/lib/log.js
CHANGED
|
@@ -12,6 +12,7 @@ export declare function downloadPackage(pkgUrl: string, destPath: string): Promi
|
|
|
12
12
|
export type ResolvePackageInput = {
|
|
13
13
|
isDeploying?: boolean;
|
|
14
14
|
package: string;
|
|
15
|
+
projectRootDir?: string;
|
|
15
16
|
};
|
|
16
17
|
export type ResolvePackageOutput = {
|
|
17
18
|
canonicalName: string;
|
|
@@ -29,8 +29,8 @@ export async function resolvePackage(input) {
|
|
|
29
29
|
}
|
|
30
30
|
const packageManager = getPackageManager(isLocal ? 'local' : '');
|
|
31
31
|
const metadataContentCandidates = (await Promise.all([
|
|
32
|
-
packageManager.getRepoContent({ owner, path: 'hereyarc.yaml', repo }),
|
|
33
|
-
packageManager.getRepoContent({ owner, path: 'hereyarc.yml', repo }),
|
|
32
|
+
packageManager.getRepoContent({ owner, path: 'hereyarc.yaml', projectRootDir: input.projectRootDir, repo }),
|
|
33
|
+
packageManager.getRepoContent({ owner, path: 'hereyarc.yml', projectRootDir: input.projectRootDir, repo }),
|
|
34
34
|
])).filter((content$) => content$.found);
|
|
35
35
|
if (metadataContentCandidates.length === 0) {
|
|
36
36
|
return { found: false, reason: `No hereya metadata file found in ${input.package}` };
|
|
@@ -42,7 +42,7 @@ export async function resolvePackage(input) {
|
|
|
42
42
|
return { found: false, reason: 'Package has dependencies but is not a deploy package' };
|
|
43
43
|
}
|
|
44
44
|
if (input.isDeploying && metadata.onDeploy) {
|
|
45
|
-
return resolvePackage({ package: metadata.onDeploy.pkg });
|
|
45
|
+
return resolvePackage({ package: metadata.onDeploy.pkg, projectRootDir: input.projectRootDir });
|
|
46
46
|
}
|
|
47
47
|
return {
|
|
48
48
|
canonicalName: getPackageCanonicalName(input.package),
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { GetRepoContentInput, GetRepoContentOutput, PackageManager } from './common.js';
|
|
2
2
|
export declare class LocalPackageManager implements PackageManager {
|
|
3
3
|
downloadPackage(pkgUrl: string, destPath: string): Promise<string>;
|
|
4
|
-
getRepoContent({ path: filePath, repo }: GetRepoContentInput): Promise<GetRepoContentOutput>;
|
|
4
|
+
getRepoContent({ path: filePath, projectRootDir, repo }: GetRepoContentInput): Promise<GetRepoContentOutput>;
|
|
5
5
|
}
|
|
@@ -3,18 +3,19 @@ import path from 'node:path';
|
|
|
3
3
|
export class LocalPackageManager {
|
|
4
4
|
async downloadPackage(pkgUrl, destPath) {
|
|
5
5
|
const [, source] = pkgUrl.split('://');
|
|
6
|
-
await
|
|
6
|
+
await copyRecursive(source, destPath);
|
|
7
7
|
return destPath;
|
|
8
8
|
}
|
|
9
|
-
async getRepoContent({ path: filePath, repo }) {
|
|
9
|
+
async getRepoContent({ path: filePath, projectRootDir, repo }) {
|
|
10
10
|
try {
|
|
11
|
-
const
|
|
11
|
+
const pkgRootDir = path.join(projectRootDir ?? process.cwd(), repo);
|
|
12
|
+
const resolvedPath = path.join(pkgRootDir, filePath);
|
|
12
13
|
if (await fs.stat(resolvedPath)) {
|
|
13
14
|
const content = await fs.readFile(resolvedPath, 'utf8');
|
|
14
15
|
return {
|
|
15
16
|
content,
|
|
16
17
|
found: true,
|
|
17
|
-
pkgUrl: `local://${
|
|
18
|
+
pkgUrl: `local://${pkgRootDir}`,
|
|
18
19
|
};
|
|
19
20
|
}
|
|
20
21
|
return {
|
|
@@ -30,3 +31,15 @@ export class LocalPackageManager {
|
|
|
30
31
|
}
|
|
31
32
|
}
|
|
32
33
|
}
|
|
34
|
+
async function copyRecursive(src, dest) {
|
|
35
|
+
// Ensure the destination directory exists.
|
|
36
|
+
await fs.mkdir(dest, { recursive: true });
|
|
37
|
+
// Read the contents of the source directory.
|
|
38
|
+
const entries = await fs.readdir(src, { withFileTypes: true });
|
|
39
|
+
// Loop through each entry in the directory.
|
|
40
|
+
await Promise.all(entries.map(async (entry) => {
|
|
41
|
+
const srcPath = path.join(src, entry.name);
|
|
42
|
+
const destPath = path.join(dest, entry.name);
|
|
43
|
+
return entry.isDirectory() ? copyRecursive(srcPath, destPath) : fs.copyFile(srcPath, destPath);
|
|
44
|
+
}));
|
|
45
|
+
}
|
package/dist/lib/shell.d.ts
CHANGED
|
@@ -1,12 +1,22 @@
|
|
|
1
|
-
|
|
2
|
-
/// <reference types="node" resolution-mode="require"/>
|
|
3
|
-
import { StdioOptions, spawnSync } from 'node:child_process';
|
|
1
|
+
import { SpawnOptions } from 'node:child_process';
|
|
4
2
|
export declare function setDebug(value: boolean): void;
|
|
5
3
|
export declare function isDebug(): boolean;
|
|
6
|
-
export
|
|
4
|
+
export interface RunShellOptions {
|
|
7
5
|
directory?: string;
|
|
8
6
|
env?: NodeJS.ProcessEnv;
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
7
|
+
logger?: typeof defaultLogger;
|
|
8
|
+
stdio?: SpawnOptions['stdio'];
|
|
9
|
+
}
|
|
10
|
+
export declare function runShell(cmd: string, args: string[], options?: RunShellOptions): Promise<{
|
|
11
|
+
pid: number;
|
|
12
|
+
signal: NodeJS.Signals | null;
|
|
13
|
+
status: null | number;
|
|
14
|
+
stderr: string;
|
|
15
|
+
stdout: string;
|
|
16
|
+
}>;
|
|
12
17
|
export declare function delay(ms: number): Promise<unknown> | undefined;
|
|
18
|
+
export declare const defaultLogger: {
|
|
19
|
+
debug(message: string): void;
|
|
20
|
+
error(message: string): void;
|
|
21
|
+
info(message: string): void;
|
|
22
|
+
};
|
package/dist/lib/shell.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { spawn } from 'node:child_process';
|
|
2
2
|
let debug = false;
|
|
3
3
|
export function setDebug(value) {
|
|
4
4
|
debug = value;
|
|
@@ -6,20 +6,62 @@ export function setDebug(value) {
|
|
|
6
6
|
export function isDebug() {
|
|
7
7
|
return debug;
|
|
8
8
|
}
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
9
|
+
// Asynchronous runShell that logs output using the provided logger.
|
|
10
|
+
export async function runShell(cmd, args, options = {}) {
|
|
11
|
+
return new Promise((resolve, reject) => {
|
|
12
|
+
// Use the provided logger or default to console.log
|
|
13
|
+
const logger = options.logger ?? defaultLogger;
|
|
14
|
+
const spawnOptions = {
|
|
15
|
+
cwd: options.directory ?? process.cwd(),
|
|
16
|
+
env: { ...process.env, ...options.env },
|
|
17
|
+
shell: true,
|
|
18
|
+
// If not explicitly set, use 'inherit' when debugging, or 'pipe' otherwise
|
|
19
|
+
stdio: options.stdio ?? (isDebug() ? 'inherit' : 'pipe'),
|
|
20
|
+
};
|
|
21
|
+
logger.debug(`Executing: ${cmd} ${args.join(' ')}`);
|
|
22
|
+
const child = spawn(cmd, args, spawnOptions);
|
|
23
|
+
// Buffers to accumulate output from the process.
|
|
24
|
+
let stdout = '';
|
|
25
|
+
let stderr = '';
|
|
26
|
+
if (child.stdout) {
|
|
27
|
+
child.stdout.on('data', (data) => {
|
|
28
|
+
const chunk = data.toString();
|
|
29
|
+
stdout += chunk;
|
|
30
|
+
logger.info(chunk);
|
|
31
|
+
});
|
|
32
|
+
}
|
|
33
|
+
if (child.stderr) {
|
|
34
|
+
child.stderr.on('data', (data) => {
|
|
35
|
+
const chunk = data.toString();
|
|
36
|
+
stderr += chunk;
|
|
37
|
+
logger.info(chunk);
|
|
38
|
+
});
|
|
39
|
+
}
|
|
40
|
+
child.on('error', (err) => {
|
|
41
|
+
logger.error(`Error: ${err.message}`);
|
|
42
|
+
reject(err);
|
|
43
|
+
});
|
|
44
|
+
let exitCode = null;
|
|
45
|
+
let exitSignal = null;
|
|
46
|
+
child.on('exit', (code, signal) => {
|
|
47
|
+
exitCode = code;
|
|
48
|
+
exitSignal = signal;
|
|
49
|
+
});
|
|
50
|
+
child.on('close', () => {
|
|
51
|
+
if (exitCode !== 0) {
|
|
52
|
+
const errorMsg = `Command "${cmd} ${args.join(' ')}" failed with exit code "${exitCode}"`;
|
|
53
|
+
logger.error(errorMsg);
|
|
54
|
+
return reject(new Error(errorMsg));
|
|
55
|
+
}
|
|
56
|
+
resolve({
|
|
57
|
+
pid: child.pid,
|
|
58
|
+
signal: exitSignal,
|
|
59
|
+
status: exitCode,
|
|
60
|
+
stderr,
|
|
61
|
+
stdout,
|
|
62
|
+
});
|
|
63
|
+
});
|
|
17
64
|
});
|
|
18
|
-
// Throw an error if the command failed
|
|
19
|
-
if (result.status !== 0) {
|
|
20
|
-
throw new Error(`Command "${cmd} ${args.join(' ')}" failed with exit code "${result.status}"`);
|
|
21
|
-
}
|
|
22
|
-
return result;
|
|
23
65
|
}
|
|
24
66
|
export function delay(ms) {
|
|
25
67
|
if (process.env.NODE_ENV === 'test') {
|
|
@@ -29,3 +71,20 @@ export function delay(ms) {
|
|
|
29
71
|
setTimeout(resolve, ms);
|
|
30
72
|
});
|
|
31
73
|
}
|
|
74
|
+
export const defaultLogger = {
|
|
75
|
+
debug(message) {
|
|
76
|
+
if (isDebug()) {
|
|
77
|
+
console.debug(message);
|
|
78
|
+
}
|
|
79
|
+
},
|
|
80
|
+
error(message) {
|
|
81
|
+
if (isDebug()) {
|
|
82
|
+
console.error(message);
|
|
83
|
+
}
|
|
84
|
+
},
|
|
85
|
+
info(message) {
|
|
86
|
+
if (isDebug()) {
|
|
87
|
+
console.info(message);
|
|
88
|
+
}
|
|
89
|
+
},
|
|
90
|
+
};
|
package/dist/lib/yaml-utils.js
CHANGED