Skip to content

Commit

Permalink
Support pushing to existing secret and sensitive variables
Browse files Browse the repository at this point in the history
  • Loading branch information
khamilowicz committed Dec 13, 2024
1 parent 1c964d2 commit 422485f
Show file tree
Hide file tree
Showing 2 changed files with 45 additions and 24 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ This is the log of notable changes to EAS CLI and related packages.
- Remove random branch name generation for --auto branch name non-vcs fallback. ([#2747](https://github.com/expo/eas-cli/pull/2747) by [@wschurman](https://github.com/wschurman))
- Upgrade @expo/multipart-body-parser. ([#2751](https://github.com/expo/eas-cli/pull/2751) by [@wschurman](https://github.com/wschurman))
- Pass env var flag to worker deployments. ([#2763](https://github.com/expo/eas-cli/pull/2763) by [@kadikraman](https://github.com/kadikraman))
- Support pushing existing secret and sensitive environment variables. ([#2765](https://github.com/expo/eas-cli/pull/2765) by [@khamilowicz](https://github.com/khamilowicz))

### 🧹 Chores

Expand Down
68 changes: 44 additions & 24 deletions packages/eas-cli/src/commands/env/push.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ import {
import { EnvironmentVariablesQuery } from '../../graphql/queries/EnvironmentVariablesQuery';
import Log from '../../log';
import { confirmAsync, promptAsync } from '../../prompts';
import uniq from '../../utils/expodash/uniq';
import { promptVariableEnvironmentAsync } from '../../utils/prompts';
import { isEnvironment } from '../../utils/variableUtils';

Expand All @@ -32,6 +33,10 @@ export default class EnvPush extends EasCommand {

static override flags = {
...EASMultiEnvironmentFlag,
force: Flags.boolean({
description: 'Overwrite existing variables without prompting',
default: false,
}),
path: Flags.string({
description: 'Path to the input `.env` file',
default: '.env.local',
Expand All @@ -50,7 +55,7 @@ export default class EnvPush extends EasCommand {
async runAsync(): Promise<void> {
const { args, flags } = await this.parse(EnvPush);

let { environment: environments, path: envPath } = this.parseFlagsAndArgs(flags, args);
let { environment: environments, path: envPath, force } = this.parseFlagsAndArgs(flags, args);

const {
projectId,
Expand All @@ -59,7 +64,7 @@ export default class EnvPush extends EasCommand {
nonInteractive: false,
});

if (!environments) {
if (!environments?.length) {
environments = await promptVariableEnvironmentAsync({
nonInteractive: false,
multiple: true,
Expand Down Expand Up @@ -101,6 +106,10 @@ export default class EnvPush extends EasCommand {
variable => variable.scope === EnvironmentVariableScope.Shared
);

let variablesToOverwrite: string[] = existingDifferentVariables.map(
variable => variable.name
);

if (existingDifferentSharedVariables.length > 0) {
const existingDifferentSharedVariablesNames = existingDifferentSharedVariables.map(
variable => variable.name
Expand All @@ -113,7 +122,7 @@ export default class EnvPush extends EasCommand {
throw new Error('Account-wide variables cannot be overwritten by eas env:push command');
}

if (existingDifferentVariables.length > 0) {
if (existingDifferentVariables.length > 0 && !force) {
Log.warn(`Some variables already exist in the ${displayedEnvironment} environment.`);
const variableNames = existingDifferentVariables.map(variable => variable.name);

Expand All @@ -128,15 +137,11 @@ export default class EnvPush extends EasCommand {
message: confirmationMessage,
});

let variablesToOverwrite: string[] = [];

if (!confirm && existingDifferentVariables.length === 0) {
throw new Error('No new variables to push.');
}

if (confirm) {
variablesToOverwrite = existingDifferentVariables.map(variable => variable.name);
} else {
if (!confirm) {
const promptResult = await promptAsync({
type: 'multiselect',
name: 'variablesToOverwrite',
Expand All @@ -152,28 +157,35 @@ export default class EnvPush extends EasCommand {
});
variablesToOverwrite = promptResult.variablesToOverwrite;
}
}

for (const existingVariable of existingVariables) {
const name = existingVariable.name;
if (variablesToOverwrite.includes(name)) {
updateVariables[name]['overwrite'] = true;
} else {
delete updateVariables[name];
for (const existingVariable of existingVariables) {
const { name } = existingVariable;
if (variablesToOverwrite.includes(name)) {
updateVariables[name]['overwrite'] = true;
updateVariables[name]['environments'] = uniq([
...environments,
...(existingVariable.environments ?? []),
]);
if (existingVariable.visibility) {
updateVariables[name]['visibility'] = existingVariable.visibility;
}
} else {
delete updateVariables[name];
}
}

// Check if any of the sensitive variables already exist in the environment. Prompt the user to overwrite them.
// Check if any of the secret variables already exist in the environment. Prompt the user to overwrite them.
const existingSensitiveVariables = existingVariables.filter(
variable => variable.visibility !== EnvironmentVariableVisibility.Public
);

if (existingSensitiveVariables.length > 0) {
if (existingSensitiveVariables.length > 0 && !force) {
const existingSensitiveVariablesNames = existingSensitiveVariables.map(
variable => `- ${variable.name}`
);
const confirm = await confirmAsync({
message: `You are about to overwrite sensitive variables.\n${existingSensitiveVariablesNames.join(
message: `You are about to overwrite secret variables.\n${existingSensitiveVariablesNames.join(
'\n'
)}\n Do you want to continue?`,
});
Expand All @@ -199,20 +211,28 @@ export default class EnvPush extends EasCommand {
}

parseFlagsAndArgs(
flags: { path: string; environment: EnvironmentVariableEnvironment[] | undefined },
flags: {
path: string;
environment: EnvironmentVariableEnvironment[] | undefined;
force: boolean;
},
{ environment }: Record<string, string>
): { environment?: EnvironmentVariableEnvironment[]; path: string } {
if (environment && !isEnvironment(environment.toUpperCase())) {
): { environment?: EnvironmentVariableEnvironment[]; path: string; force: boolean } {
const environments = [...(flags.environment ?? []), environment]
.filter(Boolean)
.map(e => e.toUpperCase());

if (environments.some(environment => !isEnvironment(environment))) {
throw new Error("Invalid environment. Use one of 'production', 'preview', or 'development'.");
}

const environments =
flags.environment ??
(environment ? [environment.toUpperCase() as EnvironmentVariableEnvironment] : undefined);
if (environments.length === 0 && flags.force) {
throw new Error('At least one environment must be specified.');
}

return {
...flags,
environment: environments,
environment: environments as EnvironmentVariableEnvironment[],
};
}

Expand Down

0 comments on commit 422485f

Please sign in to comment.