hereya-cli 0.48.0 → 0.50.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.
@@ -1,6 +1,6 @@
1
1
  import { Command, Flags } from '@oclif/core';
2
2
  import { getConfigManager } from '../../../lib/config/index.js';
3
- import { gitUtils } from '../../../lib/git-utils.js';
3
+ import { buildFlowWorkspaceName } from '../../../lib/flow-utils.js';
4
4
  import { setDebug } from '../../../lib/log.js';
5
5
  import DeleteState from '../../delete-state/index.js';
6
6
  import Down from '../../down/index.js';
@@ -56,22 +56,13 @@ export default class FlowDown extends Command {
56
56
  if (!loadConfigOutput.found) {
57
57
  this.error("Project not initialized. Run 'hereya init' first.");
58
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('---');
59
+ // Build workspace name using flow utility
60
+ const workspaceName = await buildFlowWorkspaceName({
61
+ pin: flags.pin,
62
+ profile: flags.profile,
63
+ project: loadConfigOutput.config.project,
64
+ projectRootDir,
65
+ });
75
66
  // Create workspace with mirror
76
67
  const createArgs = [workspaceName, '--mirror', loadConfigOutput.config.workspace];
77
68
  if (projectRootDir) {
@@ -0,0 +1,15 @@
1
+ import { Command } from '@oclif/core';
2
+ export default class FlowEnv extends Command {
3
+ static args: {
4
+ name: import("@oclif/core/interfaces").Arg<string | undefined, 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
+ list: import("@oclif/core/interfaces").BooleanFlag<boolean>;
11
+ pin: import("@oclif/core/interfaces").BooleanFlag<boolean>;
12
+ profile: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
13
+ };
14
+ run(): Promise<void>;
15
+ }
@@ -0,0 +1,64 @@
1
+ import { Args, Command, Flags } from '@oclif/core';
2
+ import { getConfigManager } from '../../../lib/config/index.js';
3
+ import { buildFlowWorkspaceName } from '../../../lib/flow-utils.js';
4
+ import Env from '../../env/index.js';
5
+ export default class FlowEnv extends Command {
6
+ static args = {
7
+ name: Args.string({ description: 'name of the env to display', required: false }),
8
+ };
9
+ static description = 'Print project environment variables for a git branch-based workspace';
10
+ static examples = [
11
+ '<%= config.bin %> <%= command.id %>',
12
+ '<%= config.bin %> <%= command.id %> myEnv',
13
+ '<%= config.bin %> <%= command.id %> --profile staging',
14
+ '<%= config.bin %> <%= command.id %> --pin',
15
+ '<%= config.bin %> <%= command.id %> -l',
16
+ ];
17
+ static flags = {
18
+ chdir: Flags.string({
19
+ description: 'project root directory',
20
+ required: false,
21
+ }),
22
+ list: Flags.boolean({
23
+ char: 'l',
24
+ description: 'list only the env vars without values',
25
+ required: false,
26
+ }),
27
+ pin: Flags.boolean({
28
+ description: 'append git commit SHA to workspace name for commit-specific isolation',
29
+ required: false,
30
+ }),
31
+ profile: Flags.string({
32
+ description: 'profile to use for the workspace (will be appended to workspace name)',
33
+ required: false,
34
+ }),
35
+ };
36
+ async run() {
37
+ const { args, flags } = await this.parse(FlowEnv);
38
+ const projectRootDir = flags.chdir || process.env.HEREYA_PROJECT_ROOT_DIR;
39
+ // Load project config
40
+ const configManager = getConfigManager();
41
+ const loadConfigOutput = await configManager.loadConfig({ projectRootDir });
42
+ if (!loadConfigOutput.found) {
43
+ this.error("Project not initialized. Run 'hereya init' first.");
44
+ }
45
+ // Build workspace name using flow utility
46
+ const workspaceName = await buildFlowWorkspaceName({
47
+ pin: flags.pin,
48
+ profile: flags.profile,
49
+ project: loadConfigOutput.config.project,
50
+ projectRootDir,
51
+ });
52
+ // Build args for env command
53
+ const envArgs = ['--workspace', workspaceName];
54
+ // Pass through all flags
55
+ if (flags.chdir)
56
+ envArgs.push('--chdir', flags.chdir);
57
+ if (flags.list)
58
+ envArgs.push('--list');
59
+ // Add the env name argument if provided
60
+ if (args.name)
61
+ envArgs.push(args.name);
62
+ await Env.run(envArgs);
63
+ }
64
+ }
@@ -0,0 +1,14 @@
1
+ import { Command } from '@oclif/core';
2
+ export default class FlowRemove extends Command {
3
+ static args: {
4
+ package: 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
+ debug: import("@oclif/core/interfaces").BooleanFlag<boolean>;
11
+ profile: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
12
+ };
13
+ run(): Promise<void>;
14
+ }
@@ -0,0 +1,75 @@
1
+ import { Args, Command, Flags } from '@oclif/core';
2
+ import { getConfigManager } from '../../../lib/config/index.js';
3
+ import { buildFlowWorkspaceName } from '../../../lib/flow-utils.js';
4
+ import { setDebug } from '../../../lib/log.js';
5
+ import Remove from '../../remove/index.js';
6
+ import WorkspaceCreate from '../../workspace/create/index.js';
7
+ export default class FlowRemove extends Command {
8
+ static args = {
9
+ package: Args.string({
10
+ description: `Remove a previously added package.`,
11
+ required: true,
12
+ }),
13
+ };
14
+ static description = 'Remove a package from the project in a git branch-based workspace';
15
+ static examples = [
16
+ '<%= config.bin %> <%= command.id %> cloudy/docker_postgres',
17
+ '<%= config.bin %> <%= command.id %> cloudy/docker_postgres --profile staging',
18
+ ];
19
+ static flags = {
20
+ chdir: Flags.string({
21
+ description: `
22
+ Directory where the command will be executed.
23
+ If not specified, it defaults to the current working directory.
24
+ Alternatively, you can define the project root by setting the HEREYA_PROJECT_ROOT_DIR environment variable.
25
+ `,
26
+ required: false,
27
+ }),
28
+ debug: Flags.boolean({
29
+ default: false,
30
+ description: 'enable debug mode',
31
+ }),
32
+ profile: Flags.string({
33
+ description: 'profile to use for the workspace (will be appended to workspace name)',
34
+ required: false,
35
+ }),
36
+ };
37
+ async run() {
38
+ const { args, flags } = await this.parse(FlowRemove);
39
+ setDebug(flags.debug);
40
+ const projectRootDir = flags.chdir || process.env.HEREYA_PROJECT_ROOT_DIR;
41
+ // Load project config
42
+ const configManager = getConfigManager();
43
+ const loadConfigOutput = await configManager.loadConfig({ projectRootDir });
44
+ if (!loadConfigOutput.found) {
45
+ this.error("Project not initialized. Run 'hereya init' first.");
46
+ }
47
+ // Build workspace name using flow utility (no pin support)
48
+ const workspaceName = await buildFlowWorkspaceName({
49
+ pin: false,
50
+ profile: flags.profile,
51
+ project: loadConfigOutput.config.project,
52
+ projectRootDir,
53
+ });
54
+ // Create workspace with mirror
55
+ const createArgs = [workspaceName, '--mirror', loadConfigOutput.config.workspace];
56
+ if (projectRootDir) {
57
+ createArgs.push('--chdir', projectRootDir);
58
+ }
59
+ if (flags.debug) {
60
+ createArgs.push('--debug');
61
+ }
62
+ if (flags.profile) {
63
+ createArgs.push('--profile', flags.profile);
64
+ }
65
+ await WorkspaceCreate.run(createArgs);
66
+ // Build args for remove command
67
+ const removeArgs = [args.package, '--workspace', workspaceName];
68
+ // Pass through all flags
69
+ if (flags.chdir)
70
+ removeArgs.push('--chdir', flags.chdir);
71
+ if (flags.debug)
72
+ removeArgs.push('--debug');
73
+ await Remove.run(removeArgs);
74
+ }
75
+ }
@@ -1,6 +1,6 @@
1
1
  import { Args, Command, Flags } from '@oclif/core';
2
2
  import { getConfigManager } from '../../../lib/config/index.js';
3
- import { gitUtils } from '../../../lib/git-utils.js';
3
+ import { buildFlowWorkspaceName } from '../../../lib/flow-utils.js';
4
4
  import Run from '../../run/index.js';
5
5
  export default class FlowRun extends Command {
6
6
  static args = {
@@ -36,22 +36,13 @@ export default class FlowRun extends Command {
36
36
  if (!loadConfigOutput.found) {
37
37
  this.error("Project not initialized. Run 'hereya init' first.");
38
38
  }
39
- // Get current git branch
40
- const gitBranch = await gitUtils.getCurrentGitBranch(projectRootDir);
41
- // Sanitize branch name
42
- const sanitizedBranch = gitUtils.sanitizeBranchName(gitBranch);
43
- if (!sanitizedBranch) {
44
- this.error('Branch name contains only special characters and cannot be used for workspace name');
45
- }
46
- // Get commit SHA if pin flag is set
47
- const commitSHA = flags.pin ? await gitUtils.getShortCommitSHA(projectRootDir) : null;
48
- // Build workspace name parts
49
- const parts = [loadConfigOutput.config.project, sanitizedBranch];
50
- if (flags.profile)
51
- parts.push(flags.profile);
52
- if (commitSHA)
53
- parts.push(commitSHA);
54
- const workspaceName = parts.join('---');
39
+ // Build workspace name using flow utility
40
+ const workspaceName = await buildFlowWorkspaceName({
41
+ pin: flags.pin,
42
+ profile: flags.profile,
43
+ project: loadConfigOutput.config.project,
44
+ projectRootDir,
45
+ });
55
46
  // Build args for run command
56
47
  const runArgs = ['--workspace', workspaceName];
57
48
  // Pass through chdir flag
@@ -1,6 +1,6 @@
1
1
  import { Command, Flags } from '@oclif/core';
2
2
  import { getConfigManager } from '../../../lib/config/index.js';
3
- import { gitUtils } from '../../../lib/git-utils.js';
3
+ import { buildFlowWorkspaceName } from '../../../lib/flow-utils.js';
4
4
  import { setDebug } from '../../../lib/log.js';
5
5
  import Up from '../../up/index.js';
6
6
  import WorkspaceCreate from '../../workspace/create/index.js';
@@ -54,22 +54,13 @@ export default class FlowUp extends Command {
54
54
  if (!loadConfigOutput.found) {
55
55
  this.error("Project not initialized. Run 'hereya init' first.");
56
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('---');
57
+ // Build workspace name using flow utility
58
+ const workspaceName = await buildFlowWorkspaceName({
59
+ pin: flags.pin,
60
+ profile: flags.profile,
61
+ project: loadConfigOutput.config.project,
62
+ projectRootDir,
63
+ });
73
64
  // Create workspace with mirror
74
65
  const createArgs = [workspaceName, '--mirror', loadConfigOutput.config.workspace];
75
66
  if (projectRootDir) {
@@ -90,7 +90,7 @@ export default class Import extends Command {
90
90
  const userSpecifiedParameters = arrayOfStringToObject(ctx.userSpecifiedParameters);
91
91
  const parameterManager = getParameterManager();
92
92
  const backend = await getBackend();
93
- const profile = await getProfileFromWorkspace(backend, ctx.workspace);
93
+ const profile = await getProfileFromWorkspace(backend, ctx.workspace, ctx.configOutput.config.project);
94
94
  const parametersOutput = await parameterManager.getPackageParameters({
95
95
  package: ctx.package,
96
96
  profile,
@@ -72,7 +72,7 @@ export default class Remove extends Command {
72
72
  async task(ctx) {
73
73
  const parameterManager = getParameterManager();
74
74
  const backend = await getBackend();
75
- const profile = await getProfileFromWorkspace(backend, ctx.workspace);
75
+ const profile = await getProfileFromWorkspace(backend, ctx.workspace, ctx.configOutput.config.project);
76
76
  const parametersOutput = await parameterManager.getPackageParameters({
77
77
  package: ctx.package,
78
78
  profile,
@@ -43,7 +43,7 @@ export default class Run extends Command {
43
43
  this.error('you must specify a workspace to run the command in');
44
44
  }
45
45
  const backend = await getBackend();
46
- const profile = await getProfileFromWorkspace(backend, workspace);
46
+ const profile = await getProfileFromWorkspace(backend, workspace, config.project);
47
47
  const envManager = getEnvManager();
48
48
  const getProjectEnvOutput = await envManager.getProjectEnv({
49
49
  profile,
@@ -56,7 +56,7 @@ export default class Undeploy extends Command {
56
56
  {
57
57
  async task(ctx) {
58
58
  const backend = await getBackend();
59
- const profile = await getProfileFromWorkspace(backend, ctx.workspace);
59
+ const profile = await getProfileFromWorkspace(backend, ctx.workspace, ctx.configOutput.config.project);
60
60
  const envManager = getEnvManager();
61
61
  const getProjectEnvOutput = await envManager.getProjectEnv({
62
62
  markSecret: true,
@@ -111,7 +111,7 @@ export default class Undeploy extends Command {
111
111
  async task(_, task) {
112
112
  const parameterManager = getParameterManager();
113
113
  const backend = await getBackend();
114
- const profile = await getProfileFromWorkspace(backend, ctx.workspace);
114
+ const profile = await getProfileFromWorkspace(backend, ctx.workspace, ctx.configOutput.config.project);
115
115
  const { parameters } = await parameterManager.getPackageParameters({
116
116
  package: packageName,
117
117
  profile,
@@ -151,7 +151,7 @@ export default class Undeploy extends Command {
151
151
  async task(_, task) {
152
152
  const parameterManager = getParameterManager();
153
153
  const backend = await getBackend();
154
- const profile = await getProfileFromWorkspace(backend, ctx.workspace);
154
+ const profile = await getProfileFromWorkspace(backend, ctx.workspace, ctx.configOutput.config.project);
155
155
  const { parameters } = await parameterManager.getPackageParameters({
156
156
  package: packageName,
157
157
  profile,
@@ -104,7 +104,7 @@ export default class Up extends Command {
104
104
  async task(_, task) {
105
105
  const parameterManager = getParameterManager();
106
106
  const backend = await getBackend();
107
- const profile = await getProfileFromWorkspace(backend, workspace);
107
+ const profile = await getProfileFromWorkspace(backend, workspace, ctx.configOutput.config.project);
108
108
  const { parameters } = await parameterManager.getPackageParameters({
109
109
  package: packageName,
110
110
  profile,
@@ -150,7 +150,7 @@ export default class Up extends Command {
150
150
  async task(_, task) {
151
151
  const parameterManager = getParameterManager();
152
152
  const backend = await getBackend();
153
- const profile = await getProfileFromWorkspace(backend, ctx.workspace);
153
+ const profile = await getProfileFromWorkspace(backend, ctx.workspace, ctx.configOutput.config.project);
154
154
  const { parameters } = await parameterManager.getPackageParameters({
155
155
  package: packageName,
156
156
  profile,
@@ -0,0 +1,7 @@
1
+ export interface BuildFlowWorkspaceNameOptions {
2
+ pin?: boolean;
3
+ profile?: string;
4
+ project: string;
5
+ projectRootDir?: string;
6
+ }
7
+ export declare function buildFlowWorkspaceName(options: BuildFlowWorkspaceNameOptions): Promise<string>;
@@ -0,0 +1,22 @@
1
+ import { gitUtils } from './git-utils.js';
2
+ export async function buildFlowWorkspaceName(options) {
3
+ const { pin, profile, project, projectRootDir } = options;
4
+ // Get current git branch
5
+ const gitBranch = await gitUtils.getCurrentGitBranch(projectRootDir);
6
+ // Sanitize branch name
7
+ const sanitizedBranch = gitUtils.sanitizeBranchName(gitBranch);
8
+ if (!sanitizedBranch) {
9
+ throw new Error('Branch name contains only special characters and cannot be used for workspace name');
10
+ }
11
+ // Get commit SHA if pin is enabled
12
+ const commitSHA = pin ? await gitUtils.getShortCommitSHA(projectRootDir) : null;
13
+ // Build workspace name parts
14
+ const parts = [project, sanitizedBranch];
15
+ if (profile) {
16
+ parts.push(profile);
17
+ }
18
+ if (commitSHA) {
19
+ parts.push(commitSHA);
20
+ }
21
+ return parts.join('---');
22
+ }
@@ -9,7 +9,7 @@ export function extractOrgPrefix(name) {
9
9
  return { name };
10
10
  }
11
11
  export function addOrgPrefix(org, name) {
12
- if (!org || name.includes('/')) {
12
+ if (!org || !name || name.includes('/')) {
13
13
  return name;
14
14
  }
15
15
  return `${org}/${name}`;
@@ -45,20 +45,6 @@ export class ParameterManager {
45
45
  };
46
46
  }
47
47
  const pkgName = getPackageCanonicalName(input.package);
48
- const paramFilesExist = await Promise.all([
49
- [`${pkgName}.yaml`, `${pkgName}.yml`],
50
- [`${pkgName}.${input.workspace}.yaml`, `${pkgName}.${input.workspace}.yml`],
51
- ].map(async ([filename, altFilename]) => {
52
- const filePath = await getAnyPath(path.join(await this.getParametersFolder(input.projectRootDir), filename), path.join(await this.getParametersFolder(input.projectRootDir), altFilename));
53
- const { found } = await load(filePath);
54
- return found;
55
- }));
56
- if (paramFilesExist.some(Boolean)) {
57
- return {
58
- filePath: null,
59
- saved: false,
60
- };
61
- }
62
48
  const filePath = path.join(await this.getParametersFolder(input.projectRootDir), `${pkgName}.yaml`);
63
49
  await save(input.parameters, filePath);
64
50
  return {
@@ -1,2 +1,2 @@
1
1
  import { Backend } from '../backend/common.js';
2
- export declare function getProfileFromWorkspace(backend: Backend, workspaceName: string): Promise<string>;
2
+ export declare function getProfileFromWorkspace(backend: Backend, workspaceName: string, project?: string): Promise<string>;
@@ -1,5 +1,8 @@
1
- export async function getProfileFromWorkspace(backend, workspaceName) {
2
- const workspace$ = await backend.getWorkspace(workspaceName);
1
+ import { resolveWorkspaceName } from './workspace-utils.js';
2
+ export async function getProfileFromWorkspace(backend, workspaceName, project) {
3
+ // Resolve workspace name with org prefix if needed
4
+ const resolvedWorkspaceName = resolveWorkspaceName(workspaceName, project);
5
+ const workspace$ = await backend.getWorkspace(resolvedWorkspaceName);
3
6
  if (!workspace$.found || workspace$.hasError) {
4
7
  // Fallback to workspace name if workspace not found
5
8
  return workspaceName;
@@ -0,0 +1,16 @@
1
+ /**
2
+ * Resolves a workspace name by adding org prefix from project if needed.
3
+ *
4
+ * If the project has an org prefix and the workspace doesn't already have one,
5
+ * the org prefix from the project will be added to the workspace name.
6
+ *
7
+ * @param workspace - The workspace name
8
+ * @param project - Optional project name that may contain org prefix
9
+ * @returns The resolved workspace name
10
+ *
11
+ * @example
12
+ * resolveWorkspaceName('dev', 'myorg/myproject') // returns 'myorg/dev'
13
+ * resolveWorkspaceName('myorg/dev', 'myorg/myproject') // returns 'myorg/dev'
14
+ * resolveWorkspaceName('dev', 'myproject') // returns 'dev'
15
+ */
16
+ export declare function resolveWorkspaceName(workspace: string, project?: string): string;
@@ -0,0 +1,26 @@
1
+ import { addOrgPrefix, extractOrgPrefix } from './org-utils.js';
2
+ /**
3
+ * Resolves a workspace name by adding org prefix from project if needed.
4
+ *
5
+ * If the project has an org prefix and the workspace doesn't already have one,
6
+ * the org prefix from the project will be added to the workspace name.
7
+ *
8
+ * @param workspace - The workspace name
9
+ * @param project - Optional project name that may contain org prefix
10
+ * @returns The resolved workspace name
11
+ *
12
+ * @example
13
+ * resolveWorkspaceName('dev', 'myorg/myproject') // returns 'myorg/dev'
14
+ * resolveWorkspaceName('myorg/dev', 'myorg/myproject') // returns 'myorg/dev'
15
+ * resolveWorkspaceName('dev', 'myproject') // returns 'dev'
16
+ */
17
+ export function resolveWorkspaceName(workspace, project) {
18
+ if (!project) {
19
+ return workspace;
20
+ }
21
+ const { org: projectOrg } = extractOrgPrefix(project);
22
+ if (!projectOrg) {
23
+ return workspace;
24
+ }
25
+ return addOrgPrefix(projectOrg, workspace);
26
+ }