hereya-cli 0.45.0 → 0.47.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 +135 -36
- package/dist/backend/cloud/cloud-backend.d.ts +2 -1
- package/dist/backend/cloud/cloud-backend.js +18 -0
- package/dist/backend/common.d.ts +12 -0
- package/dist/backend/file-storage/local.js +10 -2
- package/dist/backend/file.d.ts +2 -1
- package/dist/backend/file.js +17 -0
- package/dist/commands/add/index.d.ts +1 -0
- package/dist/commands/add/index.js +12 -5
- package/dist/commands/delete-state/index.d.ts +10 -0
- package/dist/commands/delete-state/index.js +49 -0
- package/dist/commands/env/set/index.js +4 -2
- package/dist/commands/flow/down/index.d.ts +14 -0
- package/dist/commands/flow/down/index.js +110 -0
- package/dist/commands/flow/up/index.d.ts +14 -0
- package/dist/commands/flow/up/index.js +99 -0
- package/dist/commands/remove/index.d.ts +1 -0
- package/dist/commands/remove/index.js +12 -5
- package/dist/lib/env/index.js +3 -1
- package/dist/lib/git-utils.d.ts +29 -0
- package/dist/lib/git-utils.js +62 -0
- package/oclif.manifest.json +210 -1
- package/package.json +1 -1
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import { Command, Flags } from '@oclif/core';
|
|
2
|
+
import { getBackend } from '../../backend/index.js';
|
|
3
|
+
import { getConfigManager } from '../../lib/config/index.js';
|
|
4
|
+
export default class DeleteState extends Command {
|
|
5
|
+
static description = 'Delete the remote state of a project for a given workspace';
|
|
6
|
+
static examples = [
|
|
7
|
+
'<%= config.bin %> <%= command.id %> -w dev',
|
|
8
|
+
'<%= config.bin %> <%= command.id %> --workspace staging',
|
|
9
|
+
];
|
|
10
|
+
static flags = {
|
|
11
|
+
chdir: Flags.string({
|
|
12
|
+
description: `
|
|
13
|
+
Directory where the command will be executed.
|
|
14
|
+
If not specified, it defaults to the current working directory.
|
|
15
|
+
Alternatively, you can define the project root by setting the HEREYA_PROJECT_ROOT_DIR environment variable.
|
|
16
|
+
`,
|
|
17
|
+
required: false,
|
|
18
|
+
}),
|
|
19
|
+
workspace: Flags.string({
|
|
20
|
+
char: 'w',
|
|
21
|
+
description: 'workspace name',
|
|
22
|
+
required: true,
|
|
23
|
+
}),
|
|
24
|
+
};
|
|
25
|
+
async run() {
|
|
26
|
+
const { flags } = await this.parse(DeleteState);
|
|
27
|
+
const projectRootDir = flags.chdir || process.env.HEREYA_PROJECT_ROOT_DIR;
|
|
28
|
+
const configManager = getConfigManager();
|
|
29
|
+
const loadConfigOutput = await configManager.loadConfig({ projectRootDir });
|
|
30
|
+
if (!loadConfigOutput.found) {
|
|
31
|
+
this.error("Project not initialized. Run 'hereya init' first.");
|
|
32
|
+
}
|
|
33
|
+
const { config } = loadConfigOutput;
|
|
34
|
+
const backend = await getBackend();
|
|
35
|
+
const output = await backend.deleteState({
|
|
36
|
+
project: config.project,
|
|
37
|
+
workspace: flags.workspace,
|
|
38
|
+
});
|
|
39
|
+
if (!output.success) {
|
|
40
|
+
this.error(`Failed to delete state: ${output.reason}`);
|
|
41
|
+
}
|
|
42
|
+
if (output.message) {
|
|
43
|
+
this.log(output.message);
|
|
44
|
+
}
|
|
45
|
+
else {
|
|
46
|
+
this.log(`State for project ${config.project} in workspace ${flags.workspace} deleted successfully`);
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
}
|
|
@@ -3,6 +3,7 @@ import path from 'node:path';
|
|
|
3
3
|
import { getConfigManager } from '../../../lib/config/index.js';
|
|
4
4
|
import { getEnvManager } from '../../../lib/env/index.js';
|
|
5
5
|
import { getAnyPath } from '../../../lib/filesystem.js';
|
|
6
|
+
import { stripOrgPrefix } from '../../../lib/org-utils.js';
|
|
6
7
|
import { load, save } from '../../../lib/yaml-utils.js';
|
|
7
8
|
export default class EnvSet extends Command {
|
|
8
9
|
static args = {
|
|
@@ -43,8 +44,9 @@ export default class EnvSet extends Command {
|
|
|
43
44
|
}
|
|
44
45
|
const envManager = getEnvManager();
|
|
45
46
|
const envDir = await envManager.getStaticEnvDir(projectRootDir);
|
|
46
|
-
const
|
|
47
|
-
|
|
47
|
+
const workspaceName = flags.workspace ? stripOrgPrefix(flags.workspace) : null;
|
|
48
|
+
const candidates = workspaceName
|
|
49
|
+
? [path.join(envDir, `env.${workspaceName}.yaml`), path.join(envDir, `env.${workspaceName}.yml`)]
|
|
48
50
|
: [path.join(envDir, `env.yaml`), path.join(envDir, `env.yml`)];
|
|
49
51
|
const envFile = await getAnyPath(...candidates);
|
|
50
52
|
const { data: env } = await load(envFile);
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { Command } from '@oclif/core';
|
|
2
|
+
export default class FlowDown extends Command {
|
|
3
|
+
static description: string;
|
|
4
|
+
static examples: string[];
|
|
5
|
+
static flags: {
|
|
6
|
+
chdir: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
7
|
+
debug: import("@oclif/core/interfaces").BooleanFlag<boolean>;
|
|
8
|
+
deploy: import("@oclif/core/interfaces").BooleanFlag<boolean>;
|
|
9
|
+
pin: import("@oclif/core/interfaces").BooleanFlag<boolean>;
|
|
10
|
+
profile: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
11
|
+
select: import("@oclif/core/interfaces").OptionFlag<string[], import("@oclif/core/interfaces").CustomOptions>;
|
|
12
|
+
};
|
|
13
|
+
run(): Promise<void>;
|
|
14
|
+
}
|
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
import { Command, Flags } from '@oclif/core';
|
|
2
|
+
import { getConfigManager } from '../../../lib/config/index.js';
|
|
3
|
+
import { gitUtils } from '../../../lib/git-utils.js';
|
|
4
|
+
import { setDebug } from '../../../lib/log.js';
|
|
5
|
+
import DeleteState from '../../delete-state/index.js';
|
|
6
|
+
import Down from '../../down/index.js';
|
|
7
|
+
import WorkspaceCreate from '../../workspace/create/index.js';
|
|
8
|
+
import WorkspaceDelete from '../../workspace/delete/index.js';
|
|
9
|
+
export default class FlowDown extends Command {
|
|
10
|
+
static description = 'Create a git branch-based workspace and destroy all packages';
|
|
11
|
+
static examples = [
|
|
12
|
+
'<%= config.bin %> <%= command.id %>',
|
|
13
|
+
'<%= config.bin %> <%= command.id %> --debug',
|
|
14
|
+
'<%= config.bin %> <%= command.id %> --profile staging',
|
|
15
|
+
'<%= config.bin %> <%= command.id %> --pin',
|
|
16
|
+
];
|
|
17
|
+
static flags = {
|
|
18
|
+
chdir: Flags.string({
|
|
19
|
+
description: `
|
|
20
|
+
Directory where the command will be executed.
|
|
21
|
+
If not specified, it defaults to the current working directory.
|
|
22
|
+
Alternatively, you can define the project root by setting the HEREYA_PROJECT_ROOT_DIR environment variable.
|
|
23
|
+
`,
|
|
24
|
+
required: false,
|
|
25
|
+
}),
|
|
26
|
+
debug: Flags.boolean({
|
|
27
|
+
default: false,
|
|
28
|
+
description: 'enable debug mode',
|
|
29
|
+
}),
|
|
30
|
+
deploy: Flags.boolean({
|
|
31
|
+
description: 'destroy deployment companion packages',
|
|
32
|
+
required: false,
|
|
33
|
+
}),
|
|
34
|
+
pin: Flags.boolean({
|
|
35
|
+
description: 'append git commit SHA to workspace name for commit-specific isolation',
|
|
36
|
+
required: false,
|
|
37
|
+
}),
|
|
38
|
+
profile: Flags.string({
|
|
39
|
+
description: 'profile to use for the workspace (will be appended to workspace name)',
|
|
40
|
+
required: false,
|
|
41
|
+
}),
|
|
42
|
+
select: Flags.string({
|
|
43
|
+
char: 's',
|
|
44
|
+
default: [],
|
|
45
|
+
description: 'select the packages to destroy',
|
|
46
|
+
multiple: true,
|
|
47
|
+
}),
|
|
48
|
+
};
|
|
49
|
+
async run() {
|
|
50
|
+
const { flags } = await this.parse(FlowDown);
|
|
51
|
+
setDebug(flags.debug);
|
|
52
|
+
const projectRootDir = flags.chdir || process.env.HEREYA_PROJECT_ROOT_DIR;
|
|
53
|
+
// Load project config
|
|
54
|
+
const configManager = getConfigManager();
|
|
55
|
+
const loadConfigOutput = await configManager.loadConfig({ projectRootDir });
|
|
56
|
+
if (!loadConfigOutput.found) {
|
|
57
|
+
this.error("Project not initialized. Run 'hereya init' first.");
|
|
58
|
+
}
|
|
59
|
+
// Get current git branch
|
|
60
|
+
const gitBranch = await gitUtils.getCurrentGitBranch(projectRootDir);
|
|
61
|
+
// Sanitize branch name
|
|
62
|
+
const sanitizedBranch = gitUtils.sanitizeBranchName(gitBranch);
|
|
63
|
+
if (!sanitizedBranch) {
|
|
64
|
+
this.error('Branch name contains only special characters and cannot be used for workspace name');
|
|
65
|
+
}
|
|
66
|
+
// Get commit SHA if pin flag is set
|
|
67
|
+
const commitSHA = flags.pin ? await gitUtils.getShortCommitSHA(projectRootDir) : null;
|
|
68
|
+
// Build workspace name parts
|
|
69
|
+
const parts = [loadConfigOutput.config.project, sanitizedBranch];
|
|
70
|
+
if (flags.profile)
|
|
71
|
+
parts.push(flags.profile);
|
|
72
|
+
if (commitSHA)
|
|
73
|
+
parts.push(commitSHA);
|
|
74
|
+
const workspaceName = parts.join('---');
|
|
75
|
+
// Create workspace with mirror
|
|
76
|
+
const createArgs = [workspaceName, '--mirror', loadConfigOutput.config.workspace];
|
|
77
|
+
if (projectRootDir) {
|
|
78
|
+
createArgs.push('--chdir', projectRootDir);
|
|
79
|
+
}
|
|
80
|
+
if (flags.debug) {
|
|
81
|
+
createArgs.push('--debug');
|
|
82
|
+
}
|
|
83
|
+
if (flags.profile) {
|
|
84
|
+
createArgs.push('--profile', flags.profile);
|
|
85
|
+
}
|
|
86
|
+
await WorkspaceCreate.run(createArgs);
|
|
87
|
+
// Run down command with the new workspace and all flags
|
|
88
|
+
const downArgs = ['--workspace', workspaceName];
|
|
89
|
+
// Pass through all flags
|
|
90
|
+
if (flags.chdir)
|
|
91
|
+
downArgs.push('--chdir', flags.chdir);
|
|
92
|
+
if (flags.debug)
|
|
93
|
+
downArgs.push('--debug');
|
|
94
|
+
if (flags.deploy)
|
|
95
|
+
downArgs.push('--deploy');
|
|
96
|
+
for (const pkg of flags.select) {
|
|
97
|
+
downArgs.push('--select', pkg);
|
|
98
|
+
}
|
|
99
|
+
await Down.run(downArgs);
|
|
100
|
+
// Delete state
|
|
101
|
+
const deleteStateArgs = ['--workspace', workspaceName];
|
|
102
|
+
if (projectRootDir) {
|
|
103
|
+
deleteStateArgs.push('--chdir', projectRootDir);
|
|
104
|
+
}
|
|
105
|
+
await DeleteState.run(deleteStateArgs);
|
|
106
|
+
// Delete workspace
|
|
107
|
+
const deleteWorkspaceArgs = [workspaceName];
|
|
108
|
+
await WorkspaceDelete.run(deleteWorkspaceArgs);
|
|
109
|
+
}
|
|
110
|
+
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { Command } from '@oclif/core';
|
|
2
|
+
export default class FlowUp extends Command {
|
|
3
|
+
static description: string;
|
|
4
|
+
static examples: string[];
|
|
5
|
+
static flags: {
|
|
6
|
+
chdir: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
7
|
+
debug: import("@oclif/core/interfaces").BooleanFlag<boolean>;
|
|
8
|
+
deploy: import("@oclif/core/interfaces").BooleanFlag<boolean>;
|
|
9
|
+
pin: import("@oclif/core/interfaces").BooleanFlag<boolean>;
|
|
10
|
+
profile: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
11
|
+
select: import("@oclif/core/interfaces").OptionFlag<string[], import("@oclif/core/interfaces").CustomOptions>;
|
|
12
|
+
};
|
|
13
|
+
run(): Promise<void>;
|
|
14
|
+
}
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
import { Command, Flags } from '@oclif/core';
|
|
2
|
+
import { getConfigManager } from '../../../lib/config/index.js';
|
|
3
|
+
import { gitUtils } from '../../../lib/git-utils.js';
|
|
4
|
+
import { setDebug } from '../../../lib/log.js';
|
|
5
|
+
import Up from '../../up/index.js';
|
|
6
|
+
import WorkspaceCreate from '../../workspace/create/index.js';
|
|
7
|
+
export default class FlowUp extends Command {
|
|
8
|
+
static description = 'Create a git branch-based workspace and provision all packages';
|
|
9
|
+
static examples = [
|
|
10
|
+
'<%= config.bin %> <%= command.id %>',
|
|
11
|
+
'<%= config.bin %> <%= command.id %> --debug',
|
|
12
|
+
'<%= config.bin %> <%= command.id %> --profile staging',
|
|
13
|
+
'<%= config.bin %> <%= command.id %> --pin',
|
|
14
|
+
];
|
|
15
|
+
static flags = {
|
|
16
|
+
chdir: Flags.string({
|
|
17
|
+
description: `
|
|
18
|
+
Directory where the command will be executed.
|
|
19
|
+
If not specified, it defaults to the current working directory.
|
|
20
|
+
Alternatively, you can define the project root by setting the HEREYA_PROJECT_ROOT_DIR environment variable.
|
|
21
|
+
`,
|
|
22
|
+
required: false,
|
|
23
|
+
}),
|
|
24
|
+
debug: Flags.boolean({
|
|
25
|
+
default: false,
|
|
26
|
+
description: 'enable debug mode',
|
|
27
|
+
}),
|
|
28
|
+
deploy: Flags.boolean({
|
|
29
|
+
description: 'provision deployment companion packages',
|
|
30
|
+
required: false,
|
|
31
|
+
}),
|
|
32
|
+
pin: Flags.boolean({
|
|
33
|
+
description: 'append git commit SHA to workspace name for commit-specific isolation',
|
|
34
|
+
required: false,
|
|
35
|
+
}),
|
|
36
|
+
profile: Flags.string({
|
|
37
|
+
description: 'profile to use for the workspace (will be appended to workspace name)',
|
|
38
|
+
required: false,
|
|
39
|
+
}),
|
|
40
|
+
select: Flags.string({
|
|
41
|
+
char: 's',
|
|
42
|
+
default: [],
|
|
43
|
+
description: 'select the packages to provision',
|
|
44
|
+
multiple: true,
|
|
45
|
+
}),
|
|
46
|
+
};
|
|
47
|
+
async run() {
|
|
48
|
+
const { flags } = await this.parse(FlowUp);
|
|
49
|
+
setDebug(flags.debug);
|
|
50
|
+
const projectRootDir = flags.chdir || process.env.HEREYA_PROJECT_ROOT_DIR;
|
|
51
|
+
// Load project config
|
|
52
|
+
const configManager = getConfigManager();
|
|
53
|
+
const loadConfigOutput = await configManager.loadConfig({ projectRootDir });
|
|
54
|
+
if (!loadConfigOutput.found) {
|
|
55
|
+
this.error("Project not initialized. Run 'hereya init' first.");
|
|
56
|
+
}
|
|
57
|
+
// Get current git branch
|
|
58
|
+
const gitBranch = await gitUtils.getCurrentGitBranch(projectRootDir);
|
|
59
|
+
// Sanitize branch name
|
|
60
|
+
const sanitizedBranch = gitUtils.sanitizeBranchName(gitBranch);
|
|
61
|
+
if (!sanitizedBranch) {
|
|
62
|
+
this.error('Branch name contains only special characters and cannot be used for workspace name');
|
|
63
|
+
}
|
|
64
|
+
// Get commit SHA if pin flag is set
|
|
65
|
+
const commitSHA = flags.pin ? await gitUtils.getShortCommitSHA(projectRootDir) : null;
|
|
66
|
+
// Build workspace name parts
|
|
67
|
+
const parts = [loadConfigOutput.config.project, sanitizedBranch];
|
|
68
|
+
if (flags.profile)
|
|
69
|
+
parts.push(flags.profile);
|
|
70
|
+
if (commitSHA)
|
|
71
|
+
parts.push(commitSHA);
|
|
72
|
+
const workspaceName = parts.join('---');
|
|
73
|
+
// Create workspace with mirror
|
|
74
|
+
const createArgs = [workspaceName, '--mirror', loadConfigOutput.config.workspace];
|
|
75
|
+
if (projectRootDir) {
|
|
76
|
+
createArgs.push('--chdir', projectRootDir);
|
|
77
|
+
}
|
|
78
|
+
if (flags.debug) {
|
|
79
|
+
createArgs.push('--debug');
|
|
80
|
+
}
|
|
81
|
+
if (flags.profile) {
|
|
82
|
+
createArgs.push('--profile', flags.profile);
|
|
83
|
+
}
|
|
84
|
+
await WorkspaceCreate.run(createArgs);
|
|
85
|
+
// Run up command with the new workspace and all flags
|
|
86
|
+
const upArgs = ['--workspace', workspaceName];
|
|
87
|
+
// Pass through all flags
|
|
88
|
+
if (flags.chdir)
|
|
89
|
+
upArgs.push('--chdir', flags.chdir);
|
|
90
|
+
if (flags.debug)
|
|
91
|
+
upArgs.push('--debug');
|
|
92
|
+
if (flags.deploy)
|
|
93
|
+
upArgs.push('--deploy');
|
|
94
|
+
for (const pkg of flags.select) {
|
|
95
|
+
upArgs.push('--select', pkg);
|
|
96
|
+
}
|
|
97
|
+
await Up.run(upArgs);
|
|
98
|
+
}
|
|
99
|
+
}
|
|
@@ -8,6 +8,7 @@ export default class Remove extends Command {
|
|
|
8
8
|
static flags: {
|
|
9
9
|
chdir: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
10
10
|
debug: import("@oclif/core/interfaces").BooleanFlag<boolean>;
|
|
11
|
+
workspace: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
11
12
|
};
|
|
12
13
|
run(): Promise<void>;
|
|
13
14
|
}
|
|
@@ -30,6 +30,11 @@ export default class Remove extends Command {
|
|
|
30
30
|
default: false,
|
|
31
31
|
description: 'enable debug mode',
|
|
32
32
|
}),
|
|
33
|
+
workspace: Flags.string({
|
|
34
|
+
char: 'w',
|
|
35
|
+
description: 'name of the workspace to remove the package from (defaults to current workspace)',
|
|
36
|
+
required: false,
|
|
37
|
+
}),
|
|
33
38
|
};
|
|
34
39
|
async run() {
|
|
35
40
|
const { args, flags } = await this.parse(Remove);
|
|
@@ -53,6 +58,8 @@ export default class Remove extends Command {
|
|
|
53
58
|
throw new Error("Project not initialized. Run 'hereya init' first.");
|
|
54
59
|
}
|
|
55
60
|
ctx.configOutput = loadConfigOutput;
|
|
61
|
+
// Use workspace from flag if provided, otherwise use config workspace
|
|
62
|
+
ctx.workspace = flags.workspace || loadConfigOutput.config.workspace;
|
|
56
63
|
const { config } = loadConfigOutput;
|
|
57
64
|
if (!(ctx.package in (config.packages ?? {})) && !(ctx.package in (config.deploy ?? {}))) {
|
|
58
65
|
throw new Error(`Package ${ctx.package} not found in the project.`);
|
|
@@ -65,7 +72,7 @@ export default class Remove extends Command {
|
|
|
65
72
|
async task(ctx) {
|
|
66
73
|
const parameterManager = getParameterManager();
|
|
67
74
|
const backend = await getBackend();
|
|
68
|
-
const profile = await getProfileFromWorkspace(backend, ctx.
|
|
75
|
+
const profile = await getProfileFromWorkspace(backend, ctx.workspace);
|
|
69
76
|
const parametersOutput = await parameterManager.getPackageParameters({
|
|
70
77
|
package: ctx.package,
|
|
71
78
|
profile,
|
|
@@ -93,7 +100,7 @@ export default class Remove extends Command {
|
|
|
93
100
|
project: ctx.configOutput.config.project,
|
|
94
101
|
projectRootDir,
|
|
95
102
|
skipDeploy: true,
|
|
96
|
-
workspace: ctx.
|
|
103
|
+
workspace: ctx.workspace,
|
|
97
104
|
});
|
|
98
105
|
if (!destroyOutput.success) {
|
|
99
106
|
throw new Error(destroyOutput.reason);
|
|
@@ -109,7 +116,7 @@ export default class Remove extends Command {
|
|
|
109
116
|
env: ctx.destroyOutput.env,
|
|
110
117
|
infra: ctx.destroyOutput.metadata.infra,
|
|
111
118
|
projectRootDir,
|
|
112
|
-
workspace: ctx.
|
|
119
|
+
workspace: ctx.workspace,
|
|
113
120
|
});
|
|
114
121
|
await delay(500);
|
|
115
122
|
},
|
|
@@ -128,11 +135,11 @@ export default class Remove extends Command {
|
|
|
128
135
|
title: 'Removing package from hereya manifest',
|
|
129
136
|
},
|
|
130
137
|
{
|
|
131
|
-
async task() {
|
|
138
|
+
async task(ctx) {
|
|
132
139
|
const backend = await getBackend();
|
|
133
140
|
const configManager = getConfigManager();
|
|
134
141
|
const { config: newConfig } = await configManager.loadConfig({ projectRootDir });
|
|
135
|
-
await backend.saveState(newConfig);
|
|
142
|
+
await backend.saveState(newConfig, ctx.workspace);
|
|
136
143
|
await delay(500);
|
|
137
144
|
},
|
|
138
145
|
title: 'Saving state',
|
package/dist/lib/env/index.js
CHANGED
|
@@ -2,6 +2,7 @@ import fs from 'node:fs/promises';
|
|
|
2
2
|
import path from 'node:path';
|
|
3
3
|
import { getExecutor } from '../../executor/index.js';
|
|
4
4
|
import { getAnyPath } from '../filesystem.js';
|
|
5
|
+
import { stripOrgPrefix } from '../org-utils.js';
|
|
5
6
|
import { load, parseYaml, save } from '../yaml-utils.js';
|
|
6
7
|
export class EnvManager {
|
|
7
8
|
async addProjectEnv(input) {
|
|
@@ -92,7 +93,8 @@ export class EnvManager {
|
|
|
92
93
|
return null;
|
|
93
94
|
}
|
|
94
95
|
async getEnvPath(input) {
|
|
95
|
-
|
|
96
|
+
const workspaceName = stripOrgPrefix(input.workspace);
|
|
97
|
+
return getAnyPath(path.join(input.projectRootDir ?? process.cwd(), '.hereya', `env.${workspaceName}.yaml`), path.join(input.projectRootDir ?? process.cwd(), '.hereya', `env.${workspaceName}.yml`));
|
|
96
98
|
}
|
|
97
99
|
async getUserEnvPaths(profile, projectRootDir) {
|
|
98
100
|
const paths = await Promise.all([
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
export declare const gitUtils: {
|
|
2
|
+
/**
|
|
3
|
+
* Gets the current git branch name.
|
|
4
|
+
* @param cwd The working directory to execute git command in
|
|
5
|
+
* @returns The current branch name
|
|
6
|
+
* @throws Error if not in a git repository or git command fails
|
|
7
|
+
*/
|
|
8
|
+
getCurrentGitBranch(cwd?: string): Promise<string>;
|
|
9
|
+
/**
|
|
10
|
+
* Gets the short commit SHA of the current HEAD.
|
|
11
|
+
* @param cwd The working directory to execute git command in
|
|
12
|
+
* @returns The short commit SHA (7 characters by default)
|
|
13
|
+
* @throws Error if not in a git repository or git command fails
|
|
14
|
+
*/
|
|
15
|
+
getShortCommitSHA(cwd?: string): Promise<string>;
|
|
16
|
+
/**
|
|
17
|
+
* Checks if the current directory is a git repository.
|
|
18
|
+
* @param cwd The working directory to check
|
|
19
|
+
* @returns true if in a git repository, false otherwise
|
|
20
|
+
*/
|
|
21
|
+
isGitRepository(cwd?: string): Promise<boolean>;
|
|
22
|
+
/**
|
|
23
|
+
* Sanitizes a git branch name for use in workspace names.
|
|
24
|
+
* Keeps only alphanumeric characters, hyphens (-), and underscores (_).
|
|
25
|
+
* @param branch The branch name to sanitize
|
|
26
|
+
* @returns The sanitized branch name
|
|
27
|
+
*/
|
|
28
|
+
sanitizeBranchName(branch: string): string;
|
|
29
|
+
};
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
import { runShell } from './shell.js';
|
|
2
|
+
export const gitUtils = {
|
|
3
|
+
/**
|
|
4
|
+
* Gets the current git branch name.
|
|
5
|
+
* @param cwd The working directory to execute git command in
|
|
6
|
+
* @returns The current branch name
|
|
7
|
+
* @throws Error if not in a git repository or git command fails
|
|
8
|
+
*/
|
|
9
|
+
async getCurrentGitBranch(cwd) {
|
|
10
|
+
try {
|
|
11
|
+
const { stdout } = await runShell('git', ['rev-parse', '--abbrev-ref', 'HEAD'], { directory: cwd });
|
|
12
|
+
return stdout.trim();
|
|
13
|
+
}
|
|
14
|
+
catch (error) {
|
|
15
|
+
if (error.message.includes('not a git repository') || error.message.includes('exit code "128"')) {
|
|
16
|
+
throw new Error('Not in a git repository. The flow commands require git integration.');
|
|
17
|
+
}
|
|
18
|
+
throw new Error(`Failed to get current git branch: ${error.message}`);
|
|
19
|
+
}
|
|
20
|
+
},
|
|
21
|
+
/**
|
|
22
|
+
* Gets the short commit SHA of the current HEAD.
|
|
23
|
+
* @param cwd The working directory to execute git command in
|
|
24
|
+
* @returns The short commit SHA (7 characters by default)
|
|
25
|
+
* @throws Error if not in a git repository or git command fails
|
|
26
|
+
*/
|
|
27
|
+
async getShortCommitSHA(cwd) {
|
|
28
|
+
try {
|
|
29
|
+
const { stdout } = await runShell('git', ['rev-parse', '--short', 'HEAD'], { directory: cwd });
|
|
30
|
+
return stdout.trim();
|
|
31
|
+
}
|
|
32
|
+
catch (error) {
|
|
33
|
+
if (error.message.includes('not a git repository') || error.message.includes('exit code "128"')) {
|
|
34
|
+
throw new Error('Not in a git repository. The flow commands require git integration.');
|
|
35
|
+
}
|
|
36
|
+
throw new Error(`Failed to get commit SHA: ${error.message}`);
|
|
37
|
+
}
|
|
38
|
+
},
|
|
39
|
+
/**
|
|
40
|
+
* Checks if the current directory is a git repository.
|
|
41
|
+
* @param cwd The working directory to check
|
|
42
|
+
* @returns true if in a git repository, false otherwise
|
|
43
|
+
*/
|
|
44
|
+
async isGitRepository(cwd) {
|
|
45
|
+
try {
|
|
46
|
+
await runShell('git', ['rev-parse', '--git-dir'], { directory: cwd });
|
|
47
|
+
return true;
|
|
48
|
+
}
|
|
49
|
+
catch {
|
|
50
|
+
return false;
|
|
51
|
+
}
|
|
52
|
+
},
|
|
53
|
+
/**
|
|
54
|
+
* Sanitizes a git branch name for use in workspace names.
|
|
55
|
+
* Keeps only alphanumeric characters, hyphens (-), and underscores (_).
|
|
56
|
+
* @param branch The branch name to sanitize
|
|
57
|
+
* @returns The sanitized branch name
|
|
58
|
+
*/
|
|
59
|
+
sanitizeBranchName(branch) {
|
|
60
|
+
return branch.replaceAll(/[^a-zA-Z0-9_-]/g, '');
|
|
61
|
+
}
|
|
62
|
+
};
|