eas-cli 13.2.3 → 13.4.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 +359 -162
- package/build/build/build.js +3 -3
- package/build/build/evaluateConfigWithEnvVarsAsync.js +18 -2
- package/build/build/utils/url.d.ts +1 -0
- package/build/build/utils/url.js +5 -1
- package/build/commandUtils/flags.d.ts +5 -4
- package/build/commandUtils/flags.js +6 -8
- package/build/commands/env/create.d.ts +6 -6
- package/build/commands/env/create.js +27 -28
- package/build/commands/env/delete.d.ts +5 -5
- package/build/commands/env/delete.js +15 -13
- package/build/commands/env/exec.d.ts +0 -1
- package/build/commands/env/exec.js +1 -2
- package/build/commands/env/get.d.ts +5 -5
- package/build/commands/env/get.js +16 -13
- package/build/commands/env/link.d.ts +1 -1
- package/build/commands/env/link.js +12 -13
- package/build/commands/env/list.d.ts +5 -5
- package/build/commands/env/list.js +14 -12
- package/build/commands/env/pull.d.ts +1 -2
- package/build/commands/env/pull.js +8 -9
- package/build/commands/env/push.d.ts +1 -2
- package/build/commands/env/push.js +9 -10
- package/build/commands/env/unlink.d.ts +1 -1
- package/build/commands/env/unlink.js +11 -10
- package/build/commands/env/update.d.ts +6 -6
- package/build/commands/env/update.js +18 -15
- package/build/commands/secret/create.d.ts +1 -0
- package/build/commands/secret/create.js +3 -0
- package/build/commands/secret/delete.d.ts +1 -0
- package/build/commands/secret/delete.js +3 -0
- package/build/commands/secret/list.d.ts +1 -0
- package/build/commands/secret/list.js +3 -0
- package/build/commands/secret/push.d.ts +1 -0
- package/build/commands/secret/push.js +3 -0
- package/build/commands/update/index.js +19 -2
- package/build/commands/workflow/create.d.ts +18 -0
- package/build/commands/workflow/create.js +100 -0
- package/build/commands/workflow/run.d.ts +0 -2
- package/build/commands/workflow/run.js +25 -6
- package/build/commands/workflow/validate.d.ts +9 -1
- package/build/commands/workflow/validate.js +47 -50
- package/build/graphql/generated.d.ts +199 -28
- package/build/graphql/generated.js +10 -1
- package/build/graphql/mutations/EnvironmentVariableMutation.d.ts +1 -0
- package/build/graphql/mutations/WorkflowRevisionMutation.d.ts +33 -0
- package/build/graphql/mutations/WorkflowRevisionMutation.js +32 -0
- package/build/graphql/types/Update.js +9 -0
- package/build/project/publish.d.ts +23 -1
- package/build/project/publish.js +71 -11
- package/build/project/resolveRuntimeVersionAsync.d.ts +2 -0
- package/build/project/resolveRuntimeVersionAsync.js +4 -0
- package/build/update/republish.js +19 -0
- package/build/utils/expodash/mapMapAsync.d.ts +1 -0
- package/build/utils/expodash/mapMapAsync.js +12 -0
- package/build/utils/fingerprintCli.d.ts +21 -3
- package/build/utils/fingerprintCli.js +62 -13
- package/build/utils/prompts.d.ts +1 -1
- package/build/utils/prompts.js +1 -1
- package/build/utils/workflowFile.d.ts +16 -0
- package/build/utils/workflowFile.js +64 -0
- package/oclif.manifest.json +84 -52
- package/package.json +10 -4
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var _a;
|
|
3
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
4
|
+
exports.WorkflowCreate = void 0;
|
|
5
|
+
const tslib_1 = require("tslib");
|
|
6
|
+
const chalk_1 = tslib_1.__importDefault(require("chalk"));
|
|
7
|
+
const promises_1 = tslib_1.__importDefault(require("fs/promises"));
|
|
8
|
+
const fs_extra_1 = tslib_1.__importDefault(require("fs-extra"));
|
|
9
|
+
const path_1 = tslib_1.__importDefault(require("path"));
|
|
10
|
+
const prompts_1 = tslib_1.__importDefault(require("prompts"));
|
|
11
|
+
const EasCommand_1 = tslib_1.__importDefault(require("../../commandUtils/EasCommand"));
|
|
12
|
+
const flags_1 = require("../../commandUtils/flags");
|
|
13
|
+
const log_1 = tslib_1.__importDefault(require("../../log"));
|
|
14
|
+
const workflowFile_1 = require("../../utils/workflowFile");
|
|
15
|
+
const DEFAULT_WORKFLOW_NAME = 'workflow.yml';
|
|
16
|
+
const HELLO_WORLD_TEMPLATE = `name: Hello World
|
|
17
|
+
|
|
18
|
+
on:
|
|
19
|
+
push:
|
|
20
|
+
branches: ['*']
|
|
21
|
+
|
|
22
|
+
jobs:
|
|
23
|
+
hello_world:
|
|
24
|
+
steps:
|
|
25
|
+
- uses: eas/checkout
|
|
26
|
+
- run: echo "Hello, World"
|
|
27
|
+
`;
|
|
28
|
+
class WorkflowCreate extends EasCommand_1.default {
|
|
29
|
+
async runAsync() {
|
|
30
|
+
const { args: { name: argFileName }, flags, } = await this.parse(_a);
|
|
31
|
+
const { projectDir } = await this.getContextAsync(_a, {
|
|
32
|
+
nonInteractive: flags['non-interactive'],
|
|
33
|
+
});
|
|
34
|
+
let fileName = argFileName;
|
|
35
|
+
if (!fileName) {
|
|
36
|
+
const response = await (0, prompts_1.default)({
|
|
37
|
+
type: 'text',
|
|
38
|
+
name: 'fileName',
|
|
39
|
+
message: 'What would you like to name your workflow file?',
|
|
40
|
+
initial: DEFAULT_WORKFLOW_NAME,
|
|
41
|
+
validate: value => {
|
|
42
|
+
try {
|
|
43
|
+
workflowFile_1.WorkflowFile.validateYamlExtension(value);
|
|
44
|
+
return true;
|
|
45
|
+
}
|
|
46
|
+
catch (error) {
|
|
47
|
+
return error instanceof Error ? error.message : 'Invalid file name';
|
|
48
|
+
}
|
|
49
|
+
},
|
|
50
|
+
});
|
|
51
|
+
if (!response.fileName) {
|
|
52
|
+
log_1.default.warn('Workflow creation cancelled.');
|
|
53
|
+
process.exit(0);
|
|
54
|
+
}
|
|
55
|
+
fileName = response.fileName;
|
|
56
|
+
}
|
|
57
|
+
try {
|
|
58
|
+
await this.ensureWorkflowsDirectoryExistsAsync({ projectDir });
|
|
59
|
+
await this.createWorkflowFileAsync({ fileName, projectDir });
|
|
60
|
+
}
|
|
61
|
+
catch (error) {
|
|
62
|
+
log_1.default.error('Failed to create workflow file.');
|
|
63
|
+
throw error;
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
async ensureWorkflowsDirectoryExistsAsync({ projectDir, }) {
|
|
67
|
+
try {
|
|
68
|
+
await promises_1.default.access(path_1.default.join(projectDir, '.eas', 'workflows'));
|
|
69
|
+
}
|
|
70
|
+
catch {
|
|
71
|
+
await promises_1.default.mkdir(path_1.default.join(projectDir, '.eas', 'workflows'), { recursive: true });
|
|
72
|
+
log_1.default.withTick(`Created directory ${chalk_1.default.bold(path_1.default.join(projectDir, '.eas', 'workflows'))}`);
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
async createWorkflowFileAsync({ fileName, projectDir, }) {
|
|
76
|
+
workflowFile_1.WorkflowFile.validateYamlExtension(fileName);
|
|
77
|
+
const filePath = path_1.default.join(projectDir, '.eas', 'workflows', fileName);
|
|
78
|
+
if (await fs_extra_1.default.pathExists(filePath)) {
|
|
79
|
+
throw new Error(`Workflow file already exists: ${filePath}`);
|
|
80
|
+
}
|
|
81
|
+
await promises_1.default.writeFile(filePath, HELLO_WORLD_TEMPLATE);
|
|
82
|
+
log_1.default.withTick(`Created ${chalk_1.default.bold(filePath)}`);
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
exports.WorkflowCreate = WorkflowCreate;
|
|
86
|
+
_a = WorkflowCreate;
|
|
87
|
+
WorkflowCreate.description = 'create a new workflow configuration YAML file';
|
|
88
|
+
WorkflowCreate.args = [
|
|
89
|
+
{
|
|
90
|
+
name: 'name',
|
|
91
|
+
description: 'Name of the workflow file (must end with .yml or .yaml)',
|
|
92
|
+
required: false,
|
|
93
|
+
},
|
|
94
|
+
];
|
|
95
|
+
WorkflowCreate.flags = {
|
|
96
|
+
...flags_1.EASNonInteractiveFlag,
|
|
97
|
+
};
|
|
98
|
+
WorkflowCreate.contextDefinition = {
|
|
99
|
+
..._a.ContextOptions.ProjectDir,
|
|
100
|
+
};
|
|
@@ -2,28 +2,34 @@
|
|
|
2
2
|
var _a;
|
|
3
3
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
4
4
|
const tslib_1 = require("tslib");
|
|
5
|
-
const
|
|
5
|
+
const core_1 = require("@urql/core");
|
|
6
6
|
const path = tslib_1.__importStar(require("node:path"));
|
|
7
7
|
const url_1 = require("../../build/utils/url");
|
|
8
8
|
const EasCommand_1 = tslib_1.__importDefault(require("../../commandUtils/EasCommand"));
|
|
9
9
|
const flags_1 = require("../../commandUtils/flags");
|
|
10
10
|
const generated_1 = require("../../graphql/generated");
|
|
11
|
+
const WorkflowRevisionMutation_1 = require("../../graphql/mutations/WorkflowRevisionMutation");
|
|
11
12
|
const WorkflowRunMutation_1 = require("../../graphql/mutations/WorkflowRunMutation");
|
|
12
13
|
const log_1 = tslib_1.__importStar(require("../../log"));
|
|
13
14
|
const projectUtils_1 = require("../../project/projectUtils");
|
|
14
15
|
const uploadAccountScopedEasJsonAsync_1 = require("../../project/uploadAccountScopedEasJsonAsync");
|
|
15
16
|
const uploadAccountScopedProjectSourceAsync_1 = require("../../project/uploadAccountScopedProjectSourceAsync");
|
|
17
|
+
const workflowFile_1 = require("../../utils/workflowFile");
|
|
16
18
|
class WorkflowRun extends EasCommand_1.default {
|
|
17
19
|
async runAsync() {
|
|
18
20
|
const { flags, args } = await this.parse(_a);
|
|
19
|
-
log_1.default.warn('Workflows are in beta and subject to breaking changes.');
|
|
20
21
|
const { getDynamicPrivateProjectConfigAsync, loggedIn: { graphqlClient }, vcsClient, projectDir, } = await this.getContextAsync(_a, {
|
|
21
22
|
nonInteractive: flags['non-interactive'],
|
|
22
23
|
withServerSideEnvironment: null,
|
|
23
24
|
});
|
|
24
25
|
let yamlConfig;
|
|
25
26
|
try {
|
|
26
|
-
|
|
27
|
+
const workflowFileContents = await workflowFile_1.WorkflowFile.readWorkflowFileContentsAsync({
|
|
28
|
+
projectDir,
|
|
29
|
+
filePath: args.file,
|
|
30
|
+
});
|
|
31
|
+
log_1.default.log(`Using workflow file from ${workflowFileContents.filePath}`);
|
|
32
|
+
yamlConfig = workflowFileContents.yamlConfig;
|
|
27
33
|
}
|
|
28
34
|
catch (err) {
|
|
29
35
|
log_1.default.error('Failed to read workflow file.');
|
|
@@ -31,6 +37,22 @@ class WorkflowRun extends EasCommand_1.default {
|
|
|
31
37
|
}
|
|
32
38
|
const { projectId, exp: { slug: projectName }, } = await getDynamicPrivateProjectConfigAsync();
|
|
33
39
|
const account = await (0, projectUtils_1.getOwnerAccountForProjectIdAsync)(graphqlClient, projectId);
|
|
40
|
+
try {
|
|
41
|
+
await WorkflowRevisionMutation_1.WorkflowRevisionMutation.validateWorkflowYamlConfigAsync(graphqlClient, {
|
|
42
|
+
appId: projectId,
|
|
43
|
+
yamlConfig,
|
|
44
|
+
});
|
|
45
|
+
}
|
|
46
|
+
catch (error) {
|
|
47
|
+
if (error instanceof core_1.CombinedError) {
|
|
48
|
+
workflowFile_1.WorkflowFile.maybePrintWorkflowFileValidationErrors({
|
|
49
|
+
error,
|
|
50
|
+
accountName: account.name,
|
|
51
|
+
projectName,
|
|
52
|
+
});
|
|
53
|
+
throw error;
|
|
54
|
+
}
|
|
55
|
+
}
|
|
34
56
|
let projectArchiveBucketKey;
|
|
35
57
|
let easJsonBucketKey;
|
|
36
58
|
try {
|
|
@@ -75,9 +97,6 @@ class WorkflowRun extends EasCommand_1.default {
|
|
|
75
97
|
}
|
|
76
98
|
_a = WorkflowRun;
|
|
77
99
|
WorkflowRun.description = 'Run an EAS workflow';
|
|
78
|
-
// TODO(@sjchmiela): Keep command hidden until workflows are live
|
|
79
|
-
WorkflowRun.hidden = true;
|
|
80
|
-
WorkflowRun.state = 'beta';
|
|
81
100
|
WorkflowRun.args = [{ name: 'file', description: 'Path to the workflow file to run' }];
|
|
82
101
|
WorkflowRun.flags = {
|
|
83
102
|
...flags_1.EASNonInteractiveFlag,
|
|
@@ -1,11 +1,19 @@
|
|
|
1
1
|
import EasCommand from '../../commandUtils/EasCommand';
|
|
2
2
|
export declare class WorkflowValidate extends EasCommand {
|
|
3
3
|
static description: string;
|
|
4
|
-
static hidden: boolean;
|
|
5
4
|
static args: {
|
|
6
5
|
name: string;
|
|
7
6
|
description: string;
|
|
8
7
|
required: boolean;
|
|
9
8
|
}[];
|
|
9
|
+
static flags: {
|
|
10
|
+
'non-interactive': import("@oclif/core/lib/interfaces").BooleanFlag<boolean>;
|
|
11
|
+
};
|
|
12
|
+
static contextDefinition: {
|
|
13
|
+
loggedIn: import("../../commandUtils/context/LoggedInContextField").default;
|
|
14
|
+
projectDir: import("../../commandUtils/context/ProjectDirContextField").default;
|
|
15
|
+
getDynamicPublicProjectConfigAsync: import("../../commandUtils/context/DynamicProjectConfigContextField").DynamicPublicProjectConfigContextField;
|
|
16
|
+
getDynamicPrivateProjectConfigAsync: import("../../commandUtils/context/DynamicProjectConfigContextField").DynamicPrivateProjectConfigContextField;
|
|
17
|
+
};
|
|
10
18
|
runAsync(): Promise<void>;
|
|
11
19
|
}
|
|
@@ -1,19 +1,44 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
+
var _a;
|
|
2
3
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
4
|
exports.WorkflowValidate = void 0;
|
|
4
5
|
const tslib_1 = require("tslib");
|
|
5
|
-
const
|
|
6
|
-
const path_1 = tslib_1.__importDefault(require("path"));
|
|
6
|
+
const core_1 = require("@urql/core");
|
|
7
7
|
const YAML = tslib_1.__importStar(require("yaml"));
|
|
8
8
|
const EasCommand_1 = tslib_1.__importDefault(require("../../commandUtils/EasCommand"));
|
|
9
|
+
const flags_1 = require("../../commandUtils/flags");
|
|
10
|
+
const WorkflowRevisionMutation_1 = require("../../graphql/mutations/WorkflowRevisionMutation");
|
|
9
11
|
const log_1 = tslib_1.__importDefault(require("../../log"));
|
|
10
12
|
const ora_1 = require("../../ora");
|
|
13
|
+
const projectUtils_1 = require("../../project/projectUtils");
|
|
14
|
+
const workflowFile_1 = require("../../utils/workflowFile");
|
|
11
15
|
class WorkflowValidate extends EasCommand_1.default {
|
|
12
16
|
async runAsync() {
|
|
13
|
-
const { args: { path: filePath }, } = await this.parse(
|
|
17
|
+
const { args: { path: filePath }, flags, } = await this.parse(_a);
|
|
18
|
+
const { getDynamicPrivateProjectConfigAsync, loggedIn: { graphqlClient }, projectDir, } = await this.getContextAsync(_a, {
|
|
19
|
+
nonInteractive: flags['non-interactive'],
|
|
20
|
+
withServerSideEnvironment: null,
|
|
21
|
+
});
|
|
22
|
+
const { projectId, exp: { slug: projectName }, } = await getDynamicPrivateProjectConfigAsync();
|
|
23
|
+
const account = await (0, projectUtils_1.getOwnerAccountForProjectIdAsync)(graphqlClient, projectId);
|
|
14
24
|
const spinner = (0, ora_1.ora)().start('Validating the workflow YAML file…');
|
|
15
25
|
try {
|
|
16
|
-
await
|
|
26
|
+
const workflowFileContents = await workflowFile_1.WorkflowFile.readWorkflowFileContentsAsync({
|
|
27
|
+
projectDir,
|
|
28
|
+
filePath,
|
|
29
|
+
});
|
|
30
|
+
log_1.default.log(`Using workflow file from ${workflowFileContents.filePath}`);
|
|
31
|
+
const parsedYaml = YAML.parse(workflowFileContents.yamlConfig);
|
|
32
|
+
// Check if the parsed result is empty or null
|
|
33
|
+
if (parsedYaml === null ||
|
|
34
|
+
parsedYaml === undefined ||
|
|
35
|
+
(typeof parsedYaml === 'object' && Object.keys(parsedYaml).length === 0)) {
|
|
36
|
+
throw new Error('YAML file is empty or contains only comments.');
|
|
37
|
+
}
|
|
38
|
+
await WorkflowRevisionMutation_1.WorkflowRevisionMutation.validateWorkflowYamlConfigAsync(graphqlClient, {
|
|
39
|
+
appId: projectId,
|
|
40
|
+
yamlConfig: workflowFileContents.yamlConfig,
|
|
41
|
+
});
|
|
17
42
|
spinner.succeed('Workflow configuration YAML is valid.');
|
|
18
43
|
}
|
|
19
44
|
catch (error) {
|
|
@@ -21,19 +46,27 @@ class WorkflowValidate extends EasCommand_1.default {
|
|
|
21
46
|
if (error instanceof YAML.YAMLParseError) {
|
|
22
47
|
log_1.default.error(`YAML syntax error: ${error.message}`);
|
|
23
48
|
}
|
|
49
|
+
else if (error instanceof core_1.CombinedError) {
|
|
50
|
+
workflowFile_1.WorkflowFile.maybePrintWorkflowFileValidationErrors({
|
|
51
|
+
error,
|
|
52
|
+
accountName: account.name,
|
|
53
|
+
projectName,
|
|
54
|
+
});
|
|
55
|
+
throw error;
|
|
56
|
+
}
|
|
24
57
|
else if (error instanceof Error) {
|
|
25
58
|
log_1.default.error(error.message);
|
|
26
59
|
}
|
|
27
60
|
else {
|
|
28
61
|
log_1.default.error(`Unexpected error: ${String(error)}`);
|
|
29
62
|
}
|
|
30
|
-
|
|
63
|
+
throw error;
|
|
31
64
|
}
|
|
32
65
|
}
|
|
33
66
|
}
|
|
34
67
|
exports.WorkflowValidate = WorkflowValidate;
|
|
68
|
+
_a = WorkflowValidate;
|
|
35
69
|
WorkflowValidate.description = 'validate a workflow configuration yaml file';
|
|
36
|
-
WorkflowValidate.hidden = true;
|
|
37
70
|
WorkflowValidate.args = [
|
|
38
71
|
{
|
|
39
72
|
name: 'path',
|
|
@@ -41,47 +74,11 @@ WorkflowValidate.args = [
|
|
|
41
74
|
required: true,
|
|
42
75
|
},
|
|
43
76
|
];
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
}
|
|
52
|
-
function checkIfValidYAMLFileExtension(filePath) {
|
|
53
|
-
const fileExtension = path_1.default.extname(filePath).toLowerCase();
|
|
54
|
-
if (fileExtension !== '.yml' && fileExtension !== '.yaml') {
|
|
55
|
-
throw new Error('File must have a .yml or .yaml extension');
|
|
56
|
-
}
|
|
57
|
-
}
|
|
58
|
-
async function validateYAMLAsync(filePath) {
|
|
59
|
-
await checkIfFileExistsAsync(filePath);
|
|
60
|
-
checkIfValidYAMLFileExtension(filePath);
|
|
61
|
-
try {
|
|
62
|
-
const fileContents = await promises_1.default.readFile(filePath, 'utf8');
|
|
63
|
-
// First check if the file is empty or only contains whitespace
|
|
64
|
-
if (!fileContents.trim()) {
|
|
65
|
-
throw new Error('YAML file is empty or contains only comments.');
|
|
66
|
-
}
|
|
67
|
-
const parsedYaml = YAML.parse(fileContents);
|
|
68
|
-
// Check if the parsed result is empty or null
|
|
69
|
-
if (parsedYaml === null ||
|
|
70
|
-
parsedYaml === undefined ||
|
|
71
|
-
(typeof parsedYaml === 'object' && Object.keys(parsedYaml).length === 0)) {
|
|
72
|
-
throw new Error('YAML file is empty or contains only comments.');
|
|
73
|
-
}
|
|
74
|
-
}
|
|
75
|
-
catch (error) {
|
|
76
|
-
if (error instanceof Error &&
|
|
77
|
-
error.message === 'YAML file is empty or contains only comments.') {
|
|
78
|
-
throw error;
|
|
79
|
-
}
|
|
80
|
-
if (error instanceof YAML.YAMLParseError || error instanceof Error) {
|
|
81
|
-
throw new Error(`YAML parsing error: ${error.message}`);
|
|
82
|
-
}
|
|
83
|
-
else {
|
|
84
|
-
throw new Error(`YAML parsing error: ${String(error)}`);
|
|
85
|
-
}
|
|
86
|
-
}
|
|
87
|
-
}
|
|
77
|
+
WorkflowValidate.flags = {
|
|
78
|
+
...flags_1.EASNonInteractiveFlag,
|
|
79
|
+
};
|
|
80
|
+
WorkflowValidate.contextDefinition = {
|
|
81
|
+
..._a.ContextOptions.DynamicProjectConfig,
|
|
82
|
+
..._a.ContextOptions.ProjectDir,
|
|
83
|
+
..._a.ContextOptions.LoggedIn,
|
|
84
|
+
};
|