eas-cli
Version:
EAS command line tool
154 lines (153 loc) • 6.65 kB
JavaScript
Object.defineProperty(exports, "__esModule", { value: true });
const tslib_1 = require("tslib");
const spawn_async_1 = tslib_1.__importDefault(require("@expo/spawn-async"));
const chalk_1 = tslib_1.__importDefault(require("chalk"));
const EasCommand_1 = tslib_1.__importDefault(require("../../commandUtils/EasCommand"));
const flags_1 = require("../../commandUtils/flags");
const EnvironmentVariablesQuery_1 = require("../../graphql/queries/EnvironmentVariablesQuery");
const log_1 = tslib_1.__importDefault(require("../../log"));
const prompts_1 = require("../../utils/prompts");
const variableUtils_1 = require("../../utils/variableUtils");
class EnvExec extends EasCommand_1.default {
static description = 'execute a command with environment variables from the selected environment';
static contextDefinition = {
...this.ContextOptions.ProjectId,
...this.ContextOptions.LoggedIn,
};
static flags = {
...flags_1.EASNonInteractiveFlag,
};
static args = [
{
name: 'environment',
required: true,
description: "Environment to execute the command in. One of 'production', 'preview', or 'development'.",
},
{
name: 'bash_command',
required: true,
description: 'bash command to execute with the environment variables from the environment',
},
];
isNonInteractive = false;
async runAsync() {
const { flags, args } = await this.parse(EnvExec);
const parsedFlags = this.sanitizeFlagsAndArgs(flags, args);
const { projectId, loggedIn: { graphqlClient }, } = await this.getContextAsync(EnvExec, {
nonInteractive: parsedFlags.nonInteractive,
});
this.isNonInteractive = parsedFlags.nonInteractive;
const environment = parsedFlags.environment ??
(await (0, prompts_1.promptVariableEnvironmentAsync)({ nonInteractive: parsedFlags.nonInteractive }));
const environmentVariables = await this.loadEnvironmentVariablesAsync({
graphqlClient,
projectId,
environment,
nonInteractive: parsedFlags.nonInteractive,
});
if (parsedFlags.nonInteractive) {
await this.runCommandNonInteractiveWithEnvVarsAsync({
command: parsedFlags.command,
environmentVariables,
});
}
else {
await this.runCommandWithEnvVarsAsync({
command: parsedFlags.command,
environmentVariables,
});
}
}
sanitizeFlagsAndArgs(rawFlags, { bash_command, environment }) {
if (rawFlags['non-interactive'] && (!bash_command || !environment)) {
throw new Error("You must specify both environment and bash command when running in non-interactive mode. Run command as `eas env:exec ENVIRONMENT 'bash command'`.");
}
environment = environment?.toUpperCase();
if (!(0, variableUtils_1.isEnvironment)(environment)) {
throw new Error("Invalid environment. Use one of 'production', 'preview', or 'development'.");
}
return {
nonInteractive: rawFlags['non-interactive'],
environment,
command: bash_command,
};
}
async runCommandNonInteractiveWithEnvVarsAsync({ command, environmentVariables, }) {
await (0, spawn_async_1.default)('bash', ['-c', command], {
stdio: 'inherit',
env: {
...process.env,
...environmentVariables,
},
});
}
// eslint-disable-next-line async-protect/async-suffix
async catch(err) {
// when in non-interactive, make the behavior of this command a pure passthrough, outputting only the subprocess' stdout and stderr and exiting with the
// sub-command's exit status
if (this.isNonInteractive) {
process.exitCode = process.exitCode ?? err.status ?? 1;
}
else {
await super.catch(err);
}
}
async runCommandWithEnvVarsAsync({ command, environmentVariables, }) {
log_1.default.log(`Running command: ${chalk_1.default.bold(command)}`);
const spawnPromise = (0, spawn_async_1.default)('bash', ['-c', command], {
stdio: ['inherit', 'pipe', 'pipe'],
env: {
...process.env,
...environmentVariables,
},
});
const { child: { stdout, stderr }, } = spawnPromise;
if (!stdout || !stderr) {
throw new Error(`Failed to spawn ${command}`);
}
stdout.on('data', data => {
for (const line of data.toString().trim().split('\n')) {
log_1.default.log(`${chalk_1.default.gray('[stdout]')} ${line}`);
}
});
stderr.on('data', data => {
for (const line of data.toString().trim().split('\n')) {
log_1.default.warn(`${chalk_1.default.gray('[stderr]')} ${line}`);
}
});
try {
await spawnPromise;
}
catch (error) {
log_1.default.error(`❌ ${chalk_1.default.bold(command)} failed`);
throw error;
}
}
async loadEnvironmentVariablesAsync({ graphqlClient, projectId, environment, nonInteractive, }) {
const environmentVariablesQueryResult = await EnvironmentVariablesQuery_1.EnvironmentVariablesQuery.byAppIdWithSensitiveAsync(graphqlClient, {
appId: projectId,
environment,
});
const nonSecretEnvironmentVariables = environmentVariablesQueryResult.filter(({ value }) => !!value);
if (!nonInteractive) {
if (nonSecretEnvironmentVariables.length > 0) {
log_1.default.log(`Environment variables with visibility "Plain text" and "Sensitive" loaded from the "${environment.toLowerCase()}" environment on EAS: ${nonSecretEnvironmentVariables
.map(e => e.name)
.join(', ')}.`);
}
else {
log_1.default.log(`No environment variables with visibility "Plain text" and "Sensitive" found for the "${environment.toLowerCase()}" environment on EAS.`);
}
log_1.default.newLine();
}
const environmentVariables = {};
for (const { name, value } of nonSecretEnvironmentVariables) {
if (value) {
environmentVariables[name] = value;
}
}
return environmentVariables;
}
}
exports.default = EnvExec;
;