@solidactions/cli 0.1.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 +56 -0
- package/dist/commands/deploy.js +454 -0
- package/dist/commands/env-create.js +87 -0
- package/dist/commands/env-delete.js +123 -0
- package/dist/commands/env-list.js +178 -0
- package/dist/commands/env-map.js +66 -0
- package/dist/commands/env-pull.js +134 -0
- package/dist/commands/init.js +97 -0
- package/dist/commands/logs-build.js +50 -0
- package/dist/commands/logs.js +103 -0
- package/dist/commands/pull.js +59 -0
- package/dist/commands/run.js +96 -0
- package/dist/commands/runs.js +97 -0
- package/dist/commands/schedule-delete.js +73 -0
- package/dist/commands/schedule-list.js +88 -0
- package/dist/commands/schedule-set.js +74 -0
- package/dist/index.js +191 -0
- package/package.json +58 -0
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.envDelete = envDelete;
|
|
7
|
+
const axios_1 = __importDefault(require("axios"));
|
|
8
|
+
const chalk_1 = __importDefault(require("chalk"));
|
|
9
|
+
const prompts_1 = __importDefault(require("prompts"));
|
|
10
|
+
const init_1 = require("./init");
|
|
11
|
+
async function envDelete(keyOrProject, keyIfProject, options = {}) {
|
|
12
|
+
const config = (0, init_1.getConfig)();
|
|
13
|
+
if (!config?.apiKey) {
|
|
14
|
+
console.error(chalk_1.default.red('Not initialized. Run "solidactions init <api-key>" first.'));
|
|
15
|
+
process.exit(1);
|
|
16
|
+
}
|
|
17
|
+
// Determine mode: if keyIfProject is provided, it's project mapping delete
|
|
18
|
+
const isProjectMode = keyIfProject !== undefined;
|
|
19
|
+
const projectName = isProjectMode ? keyOrProject : undefined;
|
|
20
|
+
const key = isProjectMode ? keyIfProject : keyOrProject;
|
|
21
|
+
try {
|
|
22
|
+
if (isProjectMode) {
|
|
23
|
+
// Delete project variable mapping
|
|
24
|
+
console.log(chalk_1.default.blue(`Deleting variable mapping "${key}" from project "${projectName}"...`));
|
|
25
|
+
// First, get the mapping to find its ID
|
|
26
|
+
const listResponse = await axios_1.default.get(`${config.host}/api/v1/projects/${projectName}/variable-mappings`, {
|
|
27
|
+
headers: {
|
|
28
|
+
'Authorization': `Bearer ${config.apiKey}`,
|
|
29
|
+
'Accept': 'application/json',
|
|
30
|
+
},
|
|
31
|
+
});
|
|
32
|
+
const mappings = listResponse.data || [];
|
|
33
|
+
const mapping = mappings.find((m) => m.env_name === key);
|
|
34
|
+
if (!mapping) {
|
|
35
|
+
console.error(chalk_1.default.red(`Variable mapping "${key}" not found in project "${projectName}".`));
|
|
36
|
+
process.exit(1);
|
|
37
|
+
}
|
|
38
|
+
// Confirm deletion unless --yes flag is provided
|
|
39
|
+
if (!options.yes) {
|
|
40
|
+
const response = await (0, prompts_1.default)({
|
|
41
|
+
type: 'confirm',
|
|
42
|
+
name: 'confirm',
|
|
43
|
+
message: mapping.is_yaml_declared
|
|
44
|
+
? `Clear YAML-declared variable "${key}"? (The mapping will be preserved but value cleared)`
|
|
45
|
+
: `Delete variable mapping "${key}" from project "${projectName}"?`,
|
|
46
|
+
initial: false,
|
|
47
|
+
});
|
|
48
|
+
if (!response.confirm) {
|
|
49
|
+
console.log(chalk_1.default.gray('Cancelled.'));
|
|
50
|
+
return;
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
// Delete the mapping
|
|
54
|
+
await axios_1.default.delete(`${config.host}/api/v1/projects/${projectName}/variable-mappings/${mapping.id}`, {
|
|
55
|
+
headers: {
|
|
56
|
+
'Authorization': `Bearer ${config.apiKey}`,
|
|
57
|
+
'Accept': 'application/json',
|
|
58
|
+
},
|
|
59
|
+
});
|
|
60
|
+
if (mapping.is_yaml_declared) {
|
|
61
|
+
console.log(chalk_1.default.green(`Variable mapping "${key}" cleared successfully.`));
|
|
62
|
+
}
|
|
63
|
+
else {
|
|
64
|
+
console.log(chalk_1.default.green(`Variable mapping "${key}" deleted successfully.`));
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
else {
|
|
68
|
+
// Delete global variable
|
|
69
|
+
console.log(chalk_1.default.blue(`Deleting global variable "${key}"...`));
|
|
70
|
+
// First, get the variable to find its ID
|
|
71
|
+
const listResponse = await axios_1.default.get(`${config.host}/api/v1/variables`, {
|
|
72
|
+
headers: {
|
|
73
|
+
'Authorization': `Bearer ${config.apiKey}`,
|
|
74
|
+
'Accept': 'application/json',
|
|
75
|
+
},
|
|
76
|
+
});
|
|
77
|
+
const variables = listResponse.data?.data || [];
|
|
78
|
+
const variable = variables.find((v) => v.key === key);
|
|
79
|
+
if (!variable) {
|
|
80
|
+
console.error(chalk_1.default.red(`Global variable "${key}" not found.`));
|
|
81
|
+
process.exit(1);
|
|
82
|
+
}
|
|
83
|
+
// Confirm deletion unless --yes flag is provided
|
|
84
|
+
if (!options.yes) {
|
|
85
|
+
const response = await (0, prompts_1.default)({
|
|
86
|
+
type: 'confirm',
|
|
87
|
+
name: 'confirm',
|
|
88
|
+
message: `Delete global variable "${key}"? This may affect projects using this variable.`,
|
|
89
|
+
initial: false,
|
|
90
|
+
});
|
|
91
|
+
if (!response.confirm) {
|
|
92
|
+
console.log(chalk_1.default.gray('Cancelled.'));
|
|
93
|
+
return;
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
// Delete the variable
|
|
97
|
+
await axios_1.default.delete(`${config.host}/api/v1/variables/${variable.id}`, {
|
|
98
|
+
headers: {
|
|
99
|
+
'Authorization': `Bearer ${config.apiKey}`,
|
|
100
|
+
'Accept': 'application/json',
|
|
101
|
+
},
|
|
102
|
+
});
|
|
103
|
+
console.log(chalk_1.default.green(`Global variable "${key}" deleted successfully.`));
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
catch (error) {
|
|
107
|
+
if (error.response) {
|
|
108
|
+
if (error.response.status === 401) {
|
|
109
|
+
console.error(chalk_1.default.red('Authentication failed. Run "solidactions init <api-key>" to re-configure.'));
|
|
110
|
+
}
|
|
111
|
+
else if (error.response.status === 404) {
|
|
112
|
+
console.error(chalk_1.default.red(isProjectMode ? `Project "${projectName}" not found.` : `Variable "${key}" not found.`));
|
|
113
|
+
}
|
|
114
|
+
else {
|
|
115
|
+
console.error(chalk_1.default.red(`Failed: ${error.response.status}`), error.response.data);
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
else {
|
|
119
|
+
console.error(chalk_1.default.red('Connection failed:'), error.message);
|
|
120
|
+
}
|
|
121
|
+
process.exit(1);
|
|
122
|
+
}
|
|
123
|
+
}
|
|
@@ -0,0 +1,178 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.envList = envList;
|
|
7
|
+
const axios_1 = __importDefault(require("axios"));
|
|
8
|
+
const chalk_1 = __importDefault(require("chalk"));
|
|
9
|
+
const init_1 = require("./init");
|
|
10
|
+
/**
|
|
11
|
+
* Format a value for display, with inherited badge if applicable.
|
|
12
|
+
*/
|
|
13
|
+
function formatEnvValue(value, source, isSecret) {
|
|
14
|
+
if (isSecret) {
|
|
15
|
+
return chalk_1.default.yellow('••••••');
|
|
16
|
+
}
|
|
17
|
+
if (value === null || value === undefined) {
|
|
18
|
+
if (source && source.startsWith('inherit_')) {
|
|
19
|
+
return chalk_1.default.gray('(inherited)');
|
|
20
|
+
}
|
|
21
|
+
return chalk_1.default.gray('-');
|
|
22
|
+
}
|
|
23
|
+
const displayValue = value.substring(0, 18);
|
|
24
|
+
if (source && source.startsWith('inherit_')) {
|
|
25
|
+
return chalk_1.default.gray(`${displayValue} (inh)`);
|
|
26
|
+
}
|
|
27
|
+
return displayValue;
|
|
28
|
+
}
|
|
29
|
+
async function envList(projectName, options = {}) {
|
|
30
|
+
const config = (0, init_1.getConfig)();
|
|
31
|
+
if (!config?.apiKey) {
|
|
32
|
+
console.error(chalk_1.default.red('Not initialized. Run "solidactions init <api-key>" first.'));
|
|
33
|
+
process.exit(1);
|
|
34
|
+
}
|
|
35
|
+
try {
|
|
36
|
+
if (projectName) {
|
|
37
|
+
// List project variable mappings
|
|
38
|
+
console.log(chalk_1.default.blue(`Environment variables for project "${projectName}":`));
|
|
39
|
+
const response = await axios_1.default.get(`${config.host}/api/v1/projects/${projectName}/variable-mappings`, {
|
|
40
|
+
headers: {
|
|
41
|
+
'Authorization': `Bearer ${config.apiKey}`,
|
|
42
|
+
'Accept': 'application/json',
|
|
43
|
+
},
|
|
44
|
+
});
|
|
45
|
+
const mappings = response.data || [];
|
|
46
|
+
if (mappings.length === 0) {
|
|
47
|
+
console.log(chalk_1.default.gray('No variable mappings found.'));
|
|
48
|
+
return;
|
|
49
|
+
}
|
|
50
|
+
console.log('');
|
|
51
|
+
console.log(chalk_1.default.gray('KEY'.padEnd(30) + 'VALUE'.padEnd(30) + 'SOURCE'.padEnd(12) + 'GLOBAL KEY'));
|
|
52
|
+
console.log(chalk_1.default.gray('-'.repeat(100)));
|
|
53
|
+
for (const mapping of mappings) {
|
|
54
|
+
const key = mapping.env_name || '?';
|
|
55
|
+
const value = mapping.is_secret ? chalk_1.default.yellow('********') : (mapping.value || '-');
|
|
56
|
+
const source = mapping.source || 'manual';
|
|
57
|
+
const globalKey = mapping.global_variable_key || chalk_1.default.gray('(local)');
|
|
58
|
+
const sourceColor = source === 'yaml' ? chalk_1.default.cyan : (source === 'override' ? chalk_1.default.yellow : chalk_1.default.gray);
|
|
59
|
+
console.log(key.padEnd(30) +
|
|
60
|
+
(mapping.is_secret ? chalk_1.default.yellow('********'.padEnd(30)) : (mapping.value || '-').toString().substring(0, 28).padEnd(30)) +
|
|
61
|
+
sourceColor(source.padEnd(12)) +
|
|
62
|
+
(mapping.global_variable_key || chalk_1.default.gray('(local)')));
|
|
63
|
+
}
|
|
64
|
+
console.log('');
|
|
65
|
+
console.log(chalk_1.default.gray(`${mappings.length} variable(s)`));
|
|
66
|
+
}
|
|
67
|
+
else {
|
|
68
|
+
// List global variables with per-environment values
|
|
69
|
+
console.log(chalk_1.default.blue('Global environment variables:'));
|
|
70
|
+
const response = await axios_1.default.get(`${config.host}/api/v1/variables`, {
|
|
71
|
+
headers: {
|
|
72
|
+
'Authorization': `Bearer ${config.apiKey}`,
|
|
73
|
+
'Accept': 'application/json',
|
|
74
|
+
},
|
|
75
|
+
});
|
|
76
|
+
const variables = response.data?.data || [];
|
|
77
|
+
if (variables.length === 0) {
|
|
78
|
+
console.log(chalk_1.default.gray('No global variables found.'));
|
|
79
|
+
return;
|
|
80
|
+
}
|
|
81
|
+
console.log('');
|
|
82
|
+
// If --env filter is set, show only that environment's values
|
|
83
|
+
if (options.env) {
|
|
84
|
+
const env = options.env.toLowerCase();
|
|
85
|
+
console.log(chalk_1.default.gray('KEY'.padEnd(30) + 'VALUE'.padEnd(40) + 'TYPE'));
|
|
86
|
+
console.log(chalk_1.default.gray('-'.repeat(80)));
|
|
87
|
+
for (const variable of variables) {
|
|
88
|
+
const key = variable.key || '?';
|
|
89
|
+
let value = null;
|
|
90
|
+
let source = null;
|
|
91
|
+
if (env === 'production') {
|
|
92
|
+
value = variable.production_value;
|
|
93
|
+
}
|
|
94
|
+
else if (env === 'staging') {
|
|
95
|
+
value = variable.staging_source === 'inherit_production'
|
|
96
|
+
? variable.production_value
|
|
97
|
+
: variable.staging_value;
|
|
98
|
+
source = variable.staging_source;
|
|
99
|
+
}
|
|
100
|
+
else if (env === 'dev') {
|
|
101
|
+
if (variable.dev_source === 'inherit_production') {
|
|
102
|
+
value = variable.production_value;
|
|
103
|
+
}
|
|
104
|
+
else if (variable.dev_source === 'inherit_staging') {
|
|
105
|
+
value = variable.staging_source === 'inherit_production'
|
|
106
|
+
? variable.production_value
|
|
107
|
+
: variable.staging_value;
|
|
108
|
+
}
|
|
109
|
+
else {
|
|
110
|
+
value = variable.dev_value;
|
|
111
|
+
}
|
|
112
|
+
source = variable.dev_source;
|
|
113
|
+
}
|
|
114
|
+
const displayValue = formatEnvValue(value, source, variable.is_secret);
|
|
115
|
+
const type = variable.is_secret ? chalk_1.default.yellow('secret') : chalk_1.default.gray('plain');
|
|
116
|
+
console.log(key.padEnd(30) +
|
|
117
|
+
displayValue.padEnd(40) +
|
|
118
|
+
type);
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
else {
|
|
122
|
+
// Show all environments in columns
|
|
123
|
+
console.log(chalk_1.default.gray('KEY'.padEnd(24) +
|
|
124
|
+
chalk_1.default.green('PRODUCTION').padEnd(20) +
|
|
125
|
+
chalk_1.default.yellow('STAGING').padEnd(20) +
|
|
126
|
+
chalk_1.default.blue('DEV').padEnd(20) +
|
|
127
|
+
'TYPE'));
|
|
128
|
+
console.log(chalk_1.default.gray('-'.repeat(100)));
|
|
129
|
+
for (const variable of variables) {
|
|
130
|
+
const key = variable.key || '?';
|
|
131
|
+
// Production value
|
|
132
|
+
const prodValue = formatEnvValue(variable.production_value, null, variable.is_secret);
|
|
133
|
+
// Staging value with inheritance
|
|
134
|
+
const stagingValue = formatEnvValue(variable.staging_source === 'inherit_production' ? variable.production_value : variable.staging_value, variable.staging_source, variable.is_secret);
|
|
135
|
+
// Dev value with inheritance chain
|
|
136
|
+
let devActualValue = variable.dev_value;
|
|
137
|
+
if (variable.dev_source === 'inherit_production') {
|
|
138
|
+
devActualValue = variable.production_value;
|
|
139
|
+
}
|
|
140
|
+
else if (variable.dev_source === 'inherit_staging') {
|
|
141
|
+
devActualValue = variable.staging_source === 'inherit_production'
|
|
142
|
+
? variable.production_value
|
|
143
|
+
: variable.staging_value;
|
|
144
|
+
}
|
|
145
|
+
const devValue = formatEnvValue(devActualValue, variable.dev_source, variable.is_secret);
|
|
146
|
+
const type = variable.is_secret ? chalk_1.default.yellow('secret') : chalk_1.default.gray('plain');
|
|
147
|
+
console.log(key.substring(0, 22).padEnd(24) +
|
|
148
|
+
prodValue.padEnd(20) +
|
|
149
|
+
stagingValue.padEnd(20) +
|
|
150
|
+
devValue.padEnd(20) +
|
|
151
|
+
type);
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
console.log('');
|
|
155
|
+
console.log(chalk_1.default.gray(`${variables.length} variable(s)`));
|
|
156
|
+
if (!options.env) {
|
|
157
|
+
console.log(chalk_1.default.gray('Use --env <production|staging|dev> to filter by environment'));
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
catch (error) {
|
|
162
|
+
if (error.response) {
|
|
163
|
+
if (error.response.status === 401) {
|
|
164
|
+
console.error(chalk_1.default.red('Authentication failed. Run "solidactions init <api-key>" to re-configure.'));
|
|
165
|
+
}
|
|
166
|
+
else if (error.response.status === 404) {
|
|
167
|
+
console.error(chalk_1.default.red(projectName ? `Project "${projectName}" not found.` : 'Resource not found.'));
|
|
168
|
+
}
|
|
169
|
+
else {
|
|
170
|
+
console.error(chalk_1.default.red(`Failed: ${error.response.status}`), error.response.data);
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
else {
|
|
174
|
+
console.error(chalk_1.default.red('Connection failed:'), error.message);
|
|
175
|
+
}
|
|
176
|
+
process.exit(1);
|
|
177
|
+
}
|
|
178
|
+
}
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.envMap = envMap;
|
|
7
|
+
const axios_1 = __importDefault(require("axios"));
|
|
8
|
+
const chalk_1 = __importDefault(require("chalk"));
|
|
9
|
+
const init_1 = require("./init");
|
|
10
|
+
async function envMap(projectName, projectKey, globalKey) {
|
|
11
|
+
const config = (0, init_1.getConfig)();
|
|
12
|
+
if (!config?.apiKey) {
|
|
13
|
+
console.error(chalk_1.default.red('Not initialized. Run "solidactions init <api-key>" first.'));
|
|
14
|
+
process.exit(1);
|
|
15
|
+
}
|
|
16
|
+
console.log(chalk_1.default.blue(`Mapping global variable "${globalKey}" to project key "${projectKey}" in "${projectName}"...`));
|
|
17
|
+
try {
|
|
18
|
+
// First, get the global variable ID by key
|
|
19
|
+
const varsResponse = await axios_1.default.get(`${config.host}/api/v1/variables`, {
|
|
20
|
+
headers: {
|
|
21
|
+
'Authorization': `Bearer ${config.apiKey}`,
|
|
22
|
+
'Accept': 'application/json',
|
|
23
|
+
},
|
|
24
|
+
});
|
|
25
|
+
const variables = varsResponse.data.data || varsResponse.data;
|
|
26
|
+
const globalVar = variables.find((v) => v.key === globalKey);
|
|
27
|
+
if (!globalVar) {
|
|
28
|
+
console.error(chalk_1.default.red(`Global variable "${globalKey}" not found.`));
|
|
29
|
+
console.log(chalk_1.default.gray('Create it with: solidactions env:create ' + globalKey + ' <value>'));
|
|
30
|
+
process.exit(1);
|
|
31
|
+
}
|
|
32
|
+
// Create the mapping
|
|
33
|
+
await axios_1.default.post(`${config.host}/api/v1/projects/${projectName}/variable-mappings`, {
|
|
34
|
+
project_key: projectKey,
|
|
35
|
+
global_variable_id: globalVar.id,
|
|
36
|
+
}, {
|
|
37
|
+
headers: {
|
|
38
|
+
'Authorization': `Bearer ${config.apiKey}`,
|
|
39
|
+
'Accept': 'application/json',
|
|
40
|
+
'Content-Type': 'application/json',
|
|
41
|
+
},
|
|
42
|
+
});
|
|
43
|
+
console.log(chalk_1.default.green(`Variable mapping created!`));
|
|
44
|
+
console.log(chalk_1.default.gray(` ${globalKey} -> ${projectKey} (in ${projectName})`));
|
|
45
|
+
}
|
|
46
|
+
catch (error) {
|
|
47
|
+
if (error.response) {
|
|
48
|
+
if (error.response.status === 401) {
|
|
49
|
+
console.error(chalk_1.default.red('Authentication failed. Run "solidactions init <api-key>" to re-configure.'));
|
|
50
|
+
}
|
|
51
|
+
else if (error.response.status === 404) {
|
|
52
|
+
console.error(chalk_1.default.red(`Project "${projectName}" not found.`));
|
|
53
|
+
}
|
|
54
|
+
else if (error.response.status === 422) {
|
|
55
|
+
console.error(chalk_1.default.red('Validation error:'), error.response.data.message || error.response.data.errors);
|
|
56
|
+
}
|
|
57
|
+
else {
|
|
58
|
+
console.error(chalk_1.default.red(`Failed: ${error.response.status}`), error.response.data);
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
else {
|
|
62
|
+
console.error(chalk_1.default.red('Connection failed:'), error.message);
|
|
63
|
+
}
|
|
64
|
+
process.exit(1);
|
|
65
|
+
}
|
|
66
|
+
}
|
|
@@ -0,0 +1,134 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.envPull = envPull;
|
|
7
|
+
const fs_1 = __importDefault(require("fs"));
|
|
8
|
+
const path_1 = __importDefault(require("path"));
|
|
9
|
+
const axios_1 = __importDefault(require("axios"));
|
|
10
|
+
const chalk_1 = __importDefault(require("chalk"));
|
|
11
|
+
const readline_1 = __importDefault(require("readline"));
|
|
12
|
+
const init_1 = require("./init");
|
|
13
|
+
/**
|
|
14
|
+
* Prompt the user for confirmation (unless --yes flag is set).
|
|
15
|
+
*/
|
|
16
|
+
async function confirm(message) {
|
|
17
|
+
const rl = readline_1.default.createInterface({
|
|
18
|
+
input: process.stdin,
|
|
19
|
+
output: process.stdout,
|
|
20
|
+
});
|
|
21
|
+
return new Promise((resolve) => {
|
|
22
|
+
rl.question(`${message} [y/n]: `, (answer) => {
|
|
23
|
+
rl.close();
|
|
24
|
+
resolve(answer.toLowerCase() === 'y' || answer.toLowerCase() === 'yes');
|
|
25
|
+
});
|
|
26
|
+
});
|
|
27
|
+
}
|
|
28
|
+
async function envPull(projectName, options = {}) {
|
|
29
|
+
const config = (0, init_1.getConfig)();
|
|
30
|
+
if (!config?.apiKey) {
|
|
31
|
+
console.error(chalk_1.default.red('Not initialized. Run "solidactions init <api-key>" first.'));
|
|
32
|
+
process.exit(1);
|
|
33
|
+
}
|
|
34
|
+
const environment = options.env || 'production';
|
|
35
|
+
// Build the project slug for lookup
|
|
36
|
+
const projectSlug = environment === 'production'
|
|
37
|
+
? projectName
|
|
38
|
+
: `${projectName}-${environment}`;
|
|
39
|
+
// Determine output file
|
|
40
|
+
const outputFile = options.output || (environment === 'production' ? '.env' : `.env.${environment}`);
|
|
41
|
+
const outputPath = path_1.default.resolve(outputFile);
|
|
42
|
+
console.log(chalk_1.default.blue(`Pulling environment variables from "${projectName}" (${environment})...`));
|
|
43
|
+
try {
|
|
44
|
+
// First, check if there are any secrets
|
|
45
|
+
const checkResponse = await axios_1.default.get(`${config.host}/api/v1/projects/${projectSlug}/variable-mappings`, {
|
|
46
|
+
headers: {
|
|
47
|
+
'Authorization': `Bearer ${config.apiKey}`,
|
|
48
|
+
'Accept': 'application/json',
|
|
49
|
+
},
|
|
50
|
+
});
|
|
51
|
+
const mappings = checkResponse.data || [];
|
|
52
|
+
if (mappings.length === 0) {
|
|
53
|
+
console.log(chalk_1.default.yellow('No environment variables found for this project.'));
|
|
54
|
+
process.exit(0);
|
|
55
|
+
}
|
|
56
|
+
// Check for secrets
|
|
57
|
+
const hasSecrets = mappings.some((m) => m.is_secret);
|
|
58
|
+
if (hasSecrets && !options.yes) {
|
|
59
|
+
console.log(chalk_1.default.yellow('\nThis project contains secret values.'));
|
|
60
|
+
const confirmed = await confirm('This will expose secret values in plain text. Continue?');
|
|
61
|
+
if (!confirmed) {
|
|
62
|
+
console.log(chalk_1.default.gray('Cancelled.'));
|
|
63
|
+
process.exit(0);
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
// Now fetch with reveal=true to get actual values
|
|
67
|
+
const response = await axios_1.default.get(`${config.host}/api/v1/projects/${projectSlug}/variable-mappings?reveal=true`, {
|
|
68
|
+
headers: {
|
|
69
|
+
'Authorization': `Bearer ${config.apiKey}`,
|
|
70
|
+
'Accept': 'application/json',
|
|
71
|
+
},
|
|
72
|
+
});
|
|
73
|
+
const variables = response.data || [];
|
|
74
|
+
// Build .env file content
|
|
75
|
+
const lines = [];
|
|
76
|
+
lines.push(`# Environment variables for ${projectName} (${environment})`);
|
|
77
|
+
lines.push(`# Generated by solidactions env:pull on ${new Date().toISOString()}`);
|
|
78
|
+
lines.push('');
|
|
79
|
+
let count = 0;
|
|
80
|
+
let secretCount = 0;
|
|
81
|
+
for (const variable of variables) {
|
|
82
|
+
const key = variable.env_name;
|
|
83
|
+
const value = variable.value;
|
|
84
|
+
if (value === null || value === undefined) {
|
|
85
|
+
// Skip variables with no value
|
|
86
|
+
lines.push(`# ${key}= (no value configured)`);
|
|
87
|
+
continue;
|
|
88
|
+
}
|
|
89
|
+
// Quote values that contain special characters
|
|
90
|
+
let formattedValue = value;
|
|
91
|
+
if (typeof value === 'string' && (value.includes(' ') ||
|
|
92
|
+
value.includes('"') ||
|
|
93
|
+
value.includes("'") ||
|
|
94
|
+
value.includes('\n') ||
|
|
95
|
+
value.includes('=') ||
|
|
96
|
+
value.includes('#'))) {
|
|
97
|
+
// Escape double quotes and wrap in double quotes
|
|
98
|
+
formattedValue = `"${value.replace(/"/g, '\\"')}"`;
|
|
99
|
+
}
|
|
100
|
+
lines.push(`${key}=${formattedValue}`);
|
|
101
|
+
count++;
|
|
102
|
+
if (variable.is_secret) {
|
|
103
|
+
secretCount++;
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
lines.push('');
|
|
107
|
+
// Write to file
|
|
108
|
+
fs_1.default.writeFileSync(outputPath, lines.join('\n'));
|
|
109
|
+
console.log(chalk_1.default.green(`\n✓ Wrote ${count} variables to ${outputFile}`));
|
|
110
|
+
if (secretCount > 0) {
|
|
111
|
+
console.log(chalk_1.default.yellow(` (includes ${secretCount} secret value${secretCount > 1 ? 's' : ''})`));
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
catch (error) {
|
|
115
|
+
if (error.response) {
|
|
116
|
+
if (error.response.status === 401) {
|
|
117
|
+
console.error(chalk_1.default.red('Authentication failed. Run "solidactions init <api-key>" to re-configure.'));
|
|
118
|
+
}
|
|
119
|
+
else if (error.response.status === 404) {
|
|
120
|
+
console.error(chalk_1.default.red(`Project "${projectSlug}" not found.`));
|
|
121
|
+
if (environment !== 'production') {
|
|
122
|
+
console.log(chalk_1.default.gray(`Try deploying with: solidactions deploy ${projectName} --env ${environment} --create`));
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
else {
|
|
126
|
+
console.error(chalk_1.default.red(`Failed: ${error.response.status}`), error.response.data);
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
else {
|
|
130
|
+
console.error(chalk_1.default.red('Connection failed:'), error.message);
|
|
131
|
+
}
|
|
132
|
+
process.exit(1);
|
|
133
|
+
}
|
|
134
|
+
}
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.getConfig = getConfig;
|
|
7
|
+
exports.saveConfig = saveConfig;
|
|
8
|
+
exports.clearConfig = clearConfig;
|
|
9
|
+
exports.init = init;
|
|
10
|
+
exports.logout = logout;
|
|
11
|
+
exports.whoami = whoami;
|
|
12
|
+
const fs_1 = __importDefault(require("fs"));
|
|
13
|
+
const path_1 = __importDefault(require("path"));
|
|
14
|
+
const os_1 = __importDefault(require("os"));
|
|
15
|
+
const chalk_1 = __importDefault(require("chalk"));
|
|
16
|
+
const CONFIG_DIR = path_1.default.join(os_1.default.homedir(), '.solidactions');
|
|
17
|
+
const CONFIG_FILE = path_1.default.join(CONFIG_DIR, 'config.json');
|
|
18
|
+
function getConfig() {
|
|
19
|
+
if (!fs_1.default.existsSync(CONFIG_FILE)) {
|
|
20
|
+
return null;
|
|
21
|
+
}
|
|
22
|
+
try {
|
|
23
|
+
const config = JSON.parse(fs_1.default.readFileSync(CONFIG_FILE, 'utf-8'));
|
|
24
|
+
// Handle legacy config format (token -> apiKey)
|
|
25
|
+
if (config.token && !config.apiKey) {
|
|
26
|
+
config.apiKey = config.token;
|
|
27
|
+
}
|
|
28
|
+
return config;
|
|
29
|
+
}
|
|
30
|
+
catch {
|
|
31
|
+
return null;
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
function saveConfig(config) {
|
|
35
|
+
if (!fs_1.default.existsSync(CONFIG_DIR)) {
|
|
36
|
+
fs_1.default.mkdirSync(CONFIG_DIR, { recursive: true, mode: 0o700 });
|
|
37
|
+
}
|
|
38
|
+
fs_1.default.writeFileSync(CONFIG_FILE, JSON.stringify(config, null, 2), { mode: 0o600 });
|
|
39
|
+
}
|
|
40
|
+
function clearConfig() {
|
|
41
|
+
if (fs_1.default.existsSync(CONFIG_FILE)) {
|
|
42
|
+
fs_1.default.unlinkSync(CONFIG_FILE);
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
async function init(apiKey, options) {
|
|
46
|
+
// Determine host
|
|
47
|
+
let host;
|
|
48
|
+
if (options.host) {
|
|
49
|
+
host = options.host;
|
|
50
|
+
}
|
|
51
|
+
else if (options.dev) {
|
|
52
|
+
host = 'http://localhost:8000';
|
|
53
|
+
}
|
|
54
|
+
else {
|
|
55
|
+
host = 'https://solidactions.io';
|
|
56
|
+
}
|
|
57
|
+
// Validate API key format (should be a Sanctum token)
|
|
58
|
+
if (!apiKey || apiKey.trim().length === 0) {
|
|
59
|
+
console.error(chalk_1.default.red('Error: API key is required.'));
|
|
60
|
+
console.log(chalk_1.default.gray('Generate an API key at: ') + chalk_1.default.blue(`${host}/settings/api-keys`));
|
|
61
|
+
process.exit(1);
|
|
62
|
+
}
|
|
63
|
+
console.log(chalk_1.default.blue(`Initializing SolidActions CLI...`));
|
|
64
|
+
console.log(chalk_1.default.gray(`Host: ${host}`));
|
|
65
|
+
// Save the configuration
|
|
66
|
+
saveConfig({
|
|
67
|
+
host,
|
|
68
|
+
apiKey: apiKey.trim(),
|
|
69
|
+
});
|
|
70
|
+
console.log(chalk_1.default.green('CLI initialized successfully!'));
|
|
71
|
+
console.log(chalk_1.default.gray(`Configuration saved to ${CONFIG_FILE}`));
|
|
72
|
+
console.log('');
|
|
73
|
+
console.log(chalk_1.default.blue('Quick start:'));
|
|
74
|
+
console.log(chalk_1.default.gray(' solidactions deploy <project-name> Deploy current directory'));
|
|
75
|
+
console.log(chalk_1.default.gray(' solidactions run <project> <workflow> Run a workflow'));
|
|
76
|
+
console.log(chalk_1.default.gray(' solidactions runs List recent runs'));
|
|
77
|
+
}
|
|
78
|
+
async function logout() {
|
|
79
|
+
if (fs_1.default.existsSync(CONFIG_FILE)) {
|
|
80
|
+
clearConfig();
|
|
81
|
+
console.log(chalk_1.default.green('Logged out successfully.'));
|
|
82
|
+
}
|
|
83
|
+
else {
|
|
84
|
+
console.log(chalk_1.default.gray('Not logged in.'));
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
async function whoami() {
|
|
88
|
+
const config = getConfig();
|
|
89
|
+
if (!config) {
|
|
90
|
+
console.log(chalk_1.default.yellow('Not initialized.'));
|
|
91
|
+
console.log(chalk_1.default.gray('Run "solidactions init <api-key>" to configure.'));
|
|
92
|
+
process.exit(1);
|
|
93
|
+
}
|
|
94
|
+
console.log(chalk_1.default.blue('Current configuration:'));
|
|
95
|
+
console.log(` Host: ${config.host}`);
|
|
96
|
+
console.log(` API Key: ${config.apiKey.substring(0, 8)}...${config.apiKey.slice(-4)}`);
|
|
97
|
+
}
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.logsBuild = logsBuild;
|
|
7
|
+
const axios_1 = __importDefault(require("axios"));
|
|
8
|
+
const chalk_1 = __importDefault(require("chalk"));
|
|
9
|
+
const init_1 = require("./init");
|
|
10
|
+
async function logsBuild(projectName) {
|
|
11
|
+
const config = (0, init_1.getConfig)();
|
|
12
|
+
if (!config?.apiKey) {
|
|
13
|
+
console.error(chalk_1.default.red('Not initialized. Run "solidactions init <api-key>" first.'));
|
|
14
|
+
process.exit(1);
|
|
15
|
+
}
|
|
16
|
+
console.log(chalk_1.default.blue(`Fetching build logs for project "${projectName}"...`));
|
|
17
|
+
try {
|
|
18
|
+
const response = await axios_1.default.get(`${config.host}/api/v1/projects/${projectName}/build-log`, {
|
|
19
|
+
headers: {
|
|
20
|
+
'Authorization': `Bearer ${config.apiKey}`,
|
|
21
|
+
'Accept': 'application/json',
|
|
22
|
+
},
|
|
23
|
+
});
|
|
24
|
+
const buildLog = response.data.build_log || response.data;
|
|
25
|
+
if (!buildLog || buildLog.length === 0) {
|
|
26
|
+
console.log(chalk_1.default.gray('No build logs available.'));
|
|
27
|
+
return;
|
|
28
|
+
}
|
|
29
|
+
console.log(chalk_1.default.gray('---'));
|
|
30
|
+
console.log(buildLog);
|
|
31
|
+
console.log(chalk_1.default.gray('---'));
|
|
32
|
+
}
|
|
33
|
+
catch (error) {
|
|
34
|
+
if (error.response) {
|
|
35
|
+
if (error.response.status === 401) {
|
|
36
|
+
console.error(chalk_1.default.red('Authentication failed. Run "solidactions init <api-key>" to re-configure.'));
|
|
37
|
+
}
|
|
38
|
+
else if (error.response.status === 404) {
|
|
39
|
+
console.error(chalk_1.default.red(`Project "${projectName}" not found.`));
|
|
40
|
+
}
|
|
41
|
+
else {
|
|
42
|
+
console.error(chalk_1.default.red(`Failed: ${error.response.status}`), error.response.data);
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
else {
|
|
46
|
+
console.error(chalk_1.default.red('Connection failed:'), error.message);
|
|
47
|
+
}
|
|
48
|
+
process.exit(1);
|
|
49
|
+
}
|
|
50
|
+
}
|