Skip to content

Commit 74dea3c

Browse files
committed
Merge branch 'develop' into feature/be-6106-upload
2 parents f13f447 + c51cdd3 commit 74dea3c

9 files changed

Lines changed: 264 additions & 1 deletion

File tree

docs/build/variable/download.md

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
# `appcircle build variable download`
2+
3+
Download environment variables as JSON
4+
5+
```plaintext
6+
appcircle build variable download [options]
7+
```
8+
9+
## Examples
10+
11+
```plaintext
12+
$ appcircle build variable download --variableGroupId "Variable Group ID"
13+
14+
$ appcircle build variable download --variableGroupId "Variable Group ID" --path "/path/to/save"
15+
```
16+
17+
## Options
18+
19+
```plaintext
20+
--variableGroupId <uuid> Variable Groups ID
21+
--path <string> [OPTIONAL] The path for JSON file to be downloaded (Defaults to the current directory)
22+
```
23+
24+
## Options inherited from parent commands
25+
26+
```plaintext
27+
--help Show help for command
28+
```

docs/build/variable/index.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,4 +17,5 @@ appcircle build variable [command] [options]
1717
- [`group`](group/index.md)
1818
- [`create`](create.md)
1919
- [`view`](view.md)
20+
- [`download`](download.md)
2021

docs/organization/create-sub.md

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
# `appcircle organization create-sub`
2+
3+
Create a new sub-organization under the current organization.
4+
5+
```plaintext
6+
appcircle organization create-sub [options]
7+
```
8+
9+
## Options
10+
11+
```plaintext
12+
--name <string> Name of the sub-organization
13+
```
14+
## Options inherited from parent commands
15+
16+
```plaintext
17+
--help Show help for command
18+
```

docs/organization/index.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ appcircle organization [command] [options]
1515
## Subcommands
1616

1717
- [`view`](view.md)
18+
- [`create-sub`](create-sub.md)
1819
- [`user`](user/index.md)
1920
- [`role`](role/index.md)
2021

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
# `appcircle publish variable group download`
2+
3+
Download publish environment variables as JSON
4+
5+
```plaintext
6+
appcircle publish variable group download [options]
7+
```
8+
9+
## Examples
10+
11+
```plaintext
12+
$ appcircle publish variable group download --publishVariableGroupId "Variable Group ID"
13+
14+
$ appcircle publish variable group download --publishVariableGroupId "Variable Group ID" --path "/path/to/save"
15+
```
16+
17+
## Options
18+
19+
```plaintext
20+
--publishVariableGroupId <uuid> Variable Group ID
21+
--path <string> [OPTIONAL] The path for JSON file to be downloaded (Defaults to the current directory)
22+
```
23+
24+
## Options inherited from parent commands
25+
26+
```plaintext
27+
--help Show help for command
28+
```

docs/publish/variable/group/index.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,4 +17,5 @@ appcircle publish profile variable group [command] [options]
1717
- [`list`](list.md)
1818
- [`view`](view.md)
1919
- [`upload`](upload.md)
20+
- [`download`](download.md)
2021

src/core/command-runner.ts

Lines changed: 116 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -114,6 +114,7 @@ import {
114114
commitEnterpriseFileUpload,
115115
updateTestingDistributionReleaseNotes,
116116
getLatestAppVersionId,
117+
createSubOrganization
117118
} from '../services';
118119
import { commandWriter, configWriter } from './writer';
119120
import { trustAppcircleCertificate } from '../security/trust-url-certificate';
@@ -261,6 +262,16 @@ const handleOrganizationCommand = async (command: ProgramCommand, params: any) =
261262
fullCommandName: command.fullCommandName,
262263
data: userInfo.roles,
263264
});
265+
} else if (command.fullCommandName === `${PROGRAM_NAME}-organization-create-sub`) {
266+
const spinner = createOra('Creating sub-organization...').start();
267+
try {
268+
const response = await createSubOrganization({ name: params.name });
269+
const successMessage = `${params.name} sub organization created successfully!`;
270+
spinner.succeed(successMessage);
271+
} catch (error: any) {
272+
const errorMessage = error.response?.data?.message || error.message || 'Failed to create sub-organization';
273+
spinner.fail(`Error: ${errorMessage}`);
274+
}
264275
} else {
265276
const beutufiyCommandName = command.fullCommandName.split('-').join(' ');
266277
console.error(`"${beutufiyCommandName} ..." command not found \nRun "${beutufiyCommandName} --help" for more information`);
@@ -477,6 +488,59 @@ const handlePublishCommand = async (command: ProgramCommand, params: any) => {
477488
spinner.fail('Failed to upload environment variables');
478489
throw e;
479490
}
491+
} else if (command.fullCommandName === `${PROGRAM_NAME}-publish-variable-group-download`) {
492+
const spinner = createOra('Downloading publish environment variables...').start();
493+
try {
494+
const variableGroups = await getPublishVariableGroups();
495+
const variableGroup = variableGroups.find((group: any) => group.id === params.publishVariableGroupId);
496+
497+
if (!variableGroup) {
498+
spinner.fail(`Variable group with ID ${params.publishVariableGroupId} not found`);
499+
throw new Error(`Variable group not found`);
500+
}
501+
502+
const variables = await getPublishVariableListByGroupId(params);
503+
504+
let formattedVariables = variables.variables.map((variable: any) => ({
505+
key: variable.key,
506+
value: variable.value,
507+
isSecret: variable.isSecret,
508+
isFile: variable.isFile || false,
509+
id: variable.key
510+
}));
511+
512+
formattedVariables.sort((a: any, b: any) => {
513+
const aKey = a.key;
514+
const bKey = b.key;
515+
return bKey.localeCompare(aKey);
516+
});
517+
518+
const timestamp = Date.now();
519+
const fileName = `${variableGroup.name}_${timestamp}.json`;
520+
521+
let filePath = params.path || process.cwd();
522+
523+
if (filePath.includes('~')) {
524+
filePath = filePath.replace(/~/g, os.homedir());
525+
}
526+
527+
filePath = path.resolve(filePath);
528+
529+
if (!fs.existsSync(filePath)) {
530+
fs.mkdirSync(filePath, { recursive: true });
531+
}
532+
533+
if (fs.statSync(filePath).isDirectory()) {
534+
filePath = path.join(filePath, fileName);
535+
}
536+
537+
fs.writeFileSync(filePath, JSON.stringify(formattedVariables));
538+
539+
spinner.succeed(`Publish environment variables downloaded successfully to ${filePath}`);
540+
} catch (e) {
541+
spinner.fail('Failed to download publish environment variables');
542+
throw e;
543+
}
480544
} else if(command.fullCommandName === `${PROGRAM_NAME}-publish-profile-version-list`){
481545
const spinner = createOra('Fetching...').start();
482546
const appVersions = await getAppVersions(params);
@@ -556,7 +620,7 @@ const handleBuildCommand = async (command: ProgramCommand, params:any) => {
556620
fullCommandName: command.fullCommandName,
557621
data: responseData,
558622
});
559-
}else if(command.fullCommandName === `${PROGRAM_NAME}-build-profile-branch-list`) {
623+
}else if(command.fullCommandName === `${PROGRAM_NAME}-build-profile-branch-list`){
560624
const spinner = createOra('Fetching...').start();
561625
const responseData = await getBranches(params);
562626
spinner.succeed();
@@ -683,6 +747,57 @@ const handleBuildCommand = async (command: ProgramCommand, params:any) => {
683747
fullCommandName: command.fullCommandName,
684748
data: responseData,
685749
});
750+
} else if(command.fullCommandName === `${PROGRAM_NAME}-build-variable-download`){
751+
const spinner = createOra('Downloading environment variables...').start();
752+
try {
753+
const variableGroups = await getEnvironmentVariableGroups();
754+
const variableGroup = variableGroups.find((group: any) => group.id === params.variableGroupId);
755+
756+
if (!variableGroup) {
757+
spinner.fail(`Variable group with ID ${params.variableGroupId} not found`);
758+
throw new Error(`Variable group not found`);
759+
}
760+
761+
const responseData = await getEnvironmentVariables(params);
762+
763+
let formattedVariables = responseData.map((variable: any) => ({
764+
key: variable.key,
765+
value: variable.value,
766+
isSecret: variable.isSecret,
767+
isFile: variable.isFile || false,
768+
id: variable.key
769+
}));
770+
771+
formattedVariables.sort((a: any, b: any) => {
772+
const aKey = a.key;
773+
const bKey = b.key;
774+
return bKey.localeCompare(aKey);
775+
});
776+
777+
const timestamp = Date.now();
778+
const fileName = `${variableGroup.name}_${timestamp}.json`;
779+
let filePath = params.path || process.cwd();
780+
781+
if (filePath.includes('~')) {
782+
filePath = filePath.replace(/~/g, os.homedir());
783+
}
784+
785+
filePath = path.resolve(filePath);
786+
787+
if (!fs.existsSync(filePath)) {
788+
fs.mkdirSync(filePath, { recursive: true });
789+
}
790+
791+
if (fs.statSync(filePath).isDirectory()) {
792+
filePath = path.join(filePath, fileName);
793+
}
794+
795+
fs.writeFileSync(filePath, JSON.stringify(formattedVariables));
796+
spinner.succeed(`Environment variables downloaded successfully to ${filePath}`);
797+
} catch (e) {
798+
spinner.fail('Failed to download environment variables');
799+
throw e;
800+
}
686801
} else if(command.fullCommandName === `${PROGRAM_NAME}-build-variable-create`){
687802
const spinner = createOra('Creating environment variable').start();
688803
try {

src/core/commands.ts

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -568,6 +568,26 @@ export const Commands: CommandType[] = [
568568
valueType: 'uuid',
569569
},
570570
],
571+
},
572+
{
573+
command: "download",
574+
description: 'Download environment variables as JSON',
575+
params: [
576+
{
577+
name: 'variableGroupId',
578+
description: 'Variable Groups ID',
579+
type: CommandParameterTypes.SELECT,
580+
valueType: 'uuid',
581+
},
582+
{
583+
name: 'path',
584+
description: '[OPTIONAL] The path for JSON file to be downloaded',
585+
longDescription:'[OPTIONAL] The path for JSON file to be downloaded (Defaults to the current directory)',
586+
type: CommandParameterTypes.STRING,
587+
valueType: 'string',
588+
required: false,
589+
}
590+
],
571591
}
572592
],
573593
params: []
@@ -1503,7 +1523,27 @@ export const Commands: CommandType[] = [
15031523
required: true
15041524
}
15051525
],
1526+
},
1527+
{
1528+
command: "download",
1529+
description: 'Download environment variables as JSON',
1530+
params: [
1531+
{
1532+
name: 'variableGroupId',
1533+
description: 'Variable Groups ID',
1534+
type: CommandParameterTypes.SELECT,
1535+
valueType: 'uuid',
1536+
},
1537+
{
1538+
name: 'path',
1539+
description: '[OPTIONAL] The path for JSON file to be downloaded',
1540+
longDescription:'[OPTIONAL] The path for JSON file to be downloaded (Defaults to the current directory)',
1541+
type: CommandParameterTypes.STRING,
1542+
valueType: 'string',
1543+
required: false,
15061544
}
1545+
],
1546+
},
15071547
]
15081548
}
15091549
]
@@ -1755,6 +1795,18 @@ export const Commands: CommandType[] = [
17551795
required: false,
17561796
}],
17571797
},
1798+
{
1799+
command: 'create-sub',
1800+
description: 'Create a sub-organization',
1801+
longDescription: 'Create a new sub-organization under the current organization.',
1802+
params: [{
1803+
name: 'name',
1804+
description: 'Name of the sub-organization',
1805+
type: CommandParameterTypes.STRING,
1806+
valueType: 'string',
1807+
required: true,
1808+
}],
1809+
},
17581810
{
17591811
command: 'user',
17601812
description: 'User management',

src/services/organization.ts

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -208,4 +208,23 @@ export const getOrganizationUserinfo = async (options: OptionsType<{ organizatio
208208
}
209209

210210
return user;
211+
};
212+
213+
/**
214+
* Creates a sub-organization under the current organization.
215+
*
216+
* @param {OptionsType<{ name: string }>} options - Object containing name of the sub-organization to be created.
217+
* @return {Promise<any>} The data returned from the creation response.
218+
*/
219+
export const createSubOrganization = async (options: OptionsType<{ name: string }>) => {
220+
const response = await appcircleApi.post(
221+
`identity/v1/organizations/current/sub-organizations`,
222+
{
223+
name: options.name
224+
},
225+
{
226+
headers: getHeaders(),
227+
}
228+
);
229+
return response.data;
211230
};

0 commit comments

Comments
 (0)