Skip to content

Commit

Permalink
Migrate commands from webapp Makefile to CLI
Browse files Browse the repository at this point in the history
  • Loading branch information
pziemkowski committed Sep 7, 2023
1 parent 8d82928 commit 2f8b852
Show file tree
Hide file tree
Showing 15 changed files with 151 additions and 74 deletions.
3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,8 @@
"scripts": {
"aws-vault:shell": "aws-vault exec $AWS_VAULT_PROFILE -- $SHELL",
"login:qa": "env-cmd -f .env.qa npm run aws-vault:shell",
"prepare": "husky install"
"prepare": "husky install",
"postinstall": "pnpm nx run cli:build"
},
"devDependencies": {
"@apollo/client": "^3.7.9",
Expand Down
14 changes: 1 addition & 13 deletions packages/internal/cli/bin/run
Original file line number Diff line number Diff line change
Expand Up @@ -2,16 +2,4 @@

const oclif = require('@oclif/core')

const path = require('path')
const project = path.join(__dirname, '..', 'tsconfig.json')

// In dev mode -> use ts-node and dev plugins
process.env.NODE_ENV = 'development'

require('ts-node').register({project})

// In dev mode, always show stack traces
oclif.settings.debug = true;

// Start the CLI
oclif.run().then(oclif.flush).catch(oclif.Errors.handle)
oclif.run().then(require('@oclif/core/flush')).catch(require('@oclif/core/handle'))
19 changes: 17 additions & 2 deletions packages/internal/cli/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -58,8 +58,23 @@
],
"topicSeparator": " ",
"topics": {
"hello": {
"description": "Say hello to the world and others"
"aws": {
"description": "Groups various AWS-related commands that for example allow you to switch between environment stages"
},
"db": {
"description": "Manage local database instance"
},
"webapp": {
"description": "Manage webapp package and service in AWS"
},
"backend": {
"description": "Manage backend package and service in AWS"
},
"workers": {
"description": "Manage workers package and service in AWS"
},
"infra": {
"description": "Configure and deploy infrastructure to AWS"
}
}
},
Expand Down
8 changes: 8 additions & 0 deletions packages/internal/cli/project.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
{
"name": "cli",
"$schema": "../../../node_modules/nx/schemas/project-schema.json",
"sourceRoot": "packages/internal/cli/src",
"projectType": "library",
"targets": {},
"tags": []
}
4 changes: 2 additions & 2 deletions packages/internal/cli/src/commands/backend/test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@ import { color } from '@oclif/color';
import { initConfig } from '../../config/init';
import { runCommand } from '../../lib/runCommand';

export default class BackendBuild extends Command {
static description = 'Starts all backend services';
export default class BackendTest extends Command {
static description = 'Runs all backend tests in docker container';

static examples = [`$ <%= config.bin %> <%= command.id %>`];

Expand Down
34 changes: 34 additions & 0 deletions packages/internal/cli/src/commands/webapp/build.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
import { Command } from '@oclif/core';
import { color } from '@oclif/color';

import { initConfig } from '../../config/init';
import { runCommand } from '../../lib/runCommand';
import { ENV_STAGE_LOCAL } from '../../config/env';
import { assertChamberInstalled, loadChamberEnv } from '../../lib/chamber';

export default class WebappBuild extends Command {
static description = 'Build webapp artifact';

static examples = [`$ <%= config.bin %> <%= command.id %>`];

async run(): Promise<void> {
const { envStage, version, awsRegion, awsAccountId, projectEnvName } =
await initConfig(this, { requireAws: 'allow-local' });

if (envStage !== ENV_STAGE_LOCAL) {
await assertChamberInstalled();
await loadChamberEnv(this, {
serviceName: `env-${projectEnvName}-webapp`,
});
}

this.log(`Building webapp:
envStage: ${color.green(envStage)}
version: ${color.green(version)}
AWS account: ${awsAccountId ? color.green(awsAccountId) : 'none'}
AWS region: ${awsRegion ? color.green(awsRegion) : 'none'}
`);

await runCommand('pnpm', ['nx', 'run', 'webapp:build']);
}
}
16 changes: 16 additions & 0 deletions packages/internal/cli/src/commands/webapp/deploy.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import { Command } from '@oclif/core';

import { initConfig } from '../../config/init';
import { runCommand } from '../../lib/runCommand';

export default class WebappDeploy extends Command {
static description = 'Deploys webapp to AWS using previously built artifact';

static examples = [`$ <%= config.bin %> <%= command.id %>`];

async run(): Promise<void> {
await initConfig(this, {});

await runCommand('pnpm', ['nx', 'run', 'webapp:deploy']);
}
}
16 changes: 16 additions & 0 deletions packages/internal/cli/src/commands/webapp/test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import { Command } from '@oclif/core';

import { initConfig } from '../../config/init';
import { runCommand } from '../../lib/runCommand';

export default class WebappTest extends Command {
static description = 'Runs all webapp tests in docker container';

static examples = [`$ <%= config.bin %> <%= command.id %>`];

async run(): Promise<void> {
await initConfig(this, {});

await runCommand('pnpm', ['nx', 'run', 'webapp:test']);
}
}
27 changes: 6 additions & 21 deletions packages/internal/cli/src/config/aws.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,11 @@ import { lookpath } from 'lookpath';
import { validateStageEnv } from './env';
import { color } from '@oclif/color';
import { isAwsVaultInstalled } from '../lib/awsVault';
import { assertChamberInstalled, isChamberInstalled } from '../lib/chamber';
import {
assertChamberInstalled,
isChamberInstalled,
loadChamberEnv,
} from '../lib/chamber';

const exec = promisify(childProcess.exec);

Expand All @@ -24,26 +28,7 @@ async function loadStageEnv(
shouldValidate = true
) {
await assertChamberInstalled();

let chamberOutput;
try {
const { stdout } = await exec(`chamber export ${envStage} --format dotenv`);
chamberOutput = stdout;
} catch (err) {
context.error(
`Failed to load environmental variables from SSM Parameter Store using chamber: ${err}`
);
}

const parsed = dotenv.parse(Buffer.from(chamberOutput));
context.log(
`Loaded ${
Object.keys(parsed).length
} environmental variables from SSM Parameter Store using chamber.\n`
);

// @ts-ignore
dotenv.populate(process.env, parsed, { override: true });
await loadChamberEnv(context, { serviceName: envStage });

if (shouldValidate) {
const validationResult = await validateStageEnv();
Expand Down
23 changes: 12 additions & 11 deletions packages/internal/cli/src/config/init.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,16 +12,15 @@ import { loadEnvStage } from './storage';
const exec = promisify(childProcess.exec);

type InitConfigOptions = {
requireAws?: boolean;
requireAws?: boolean | 'allow-local';
validateEnvStageVariables?: boolean;
requireLocalEnvStage?: boolean;
};


const getRootPath = async () => {
const { stdout } = await exec('pnpm root -w');
return resolve(stdout, '..');
}
return resolve(stdout, '..');
};

export const initConfig = async (
context: Command,
Expand Down Expand Up @@ -53,21 +52,23 @@ Please call \`saas aws set-env local\` first or open a new terminal.`
let awsAccountId: string | undefined;
let awsRegion: string | undefined;
if (requireAws) {
if (envStage === ENV_STAGE_LOCAL) {
if (envStage === ENV_STAGE_LOCAL && requireAws !== 'allow-local') {
context.error(
`Remote environment stage required.\nPlease call \`${color.green(
'saas aws set-env [stage-name]'
)}\` first. Do not use \`local\` value.`
);
}

const awsMetadata = await initAWS(context, {
envStage,
validateEnvStageVariables,
});
if (envStage !== ENV_STAGE_LOCAL) {
const awsMetadata = await initAWS(context, {
envStage,
validateEnvStageVariables,
});

awsAccountId = awsMetadata.awsAccountId;
awsRegion = awsMetadata.awsRegion;
awsAccountId = awsMetadata.awsAccountId;
awsRegion = awsMetadata.awsRegion;
}
}

const projectEnvName = `${projectName}-${envStage}`;
Expand Down
34 changes: 34 additions & 0 deletions packages/internal/cli/src/lib/chamber.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@ import { CLIError } from '@oclif/errors';
import * as childProcess from 'child_process';
import { promisify } from 'util';
import { lookpath } from 'lookpath';
import { Command } from '@oclif/core';
import * as dotenv from 'dotenv';

const exec = promisify(childProcess.exec);

Expand All @@ -16,3 +18,35 @@ export const assertChamberInstalled = async () => {
command. Go to https://github.com/segmentio/chamber and learn how to install and configure it.`);
}
};

type LoadChamberEnvOptions = {
serviceName: string;
};
export async function loadChamberEnv(
context: Command,
{ serviceName }: LoadChamberEnvOptions
) {
await assertChamberInstalled();

let chamberOutput;
try {
const { stdout } = await exec(
`chamber export ${serviceName} --format dotenv`
);
chamberOutput = stdout;
} catch (err) {
context.error(
`Failed to load environmental variables from SSM Parameter Store using chamber: ${err}`
);
}

const parsed = dotenv.parse(Buffer.from(chamberOutput));
context.log(
`Loaded environmental variables from SSM Parameter Store using chamber:
service (prefix): ${serviceName}
count: ${Object.keys(parsed).length}\n`
);

// @ts-ignore
dotenv.populate(process.env, parsed, { override: true });
}
3 changes: 2 additions & 1 deletion packages/internal/cli/tsconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,8 @@
"outDir": "dist",
"rootDir": "src",
"strict": true,
"target": "es2019"
"target": "es2019",
"noEmit": false
},
"include": ["src/**/*"]
}
13 changes: 0 additions & 13 deletions packages/webapp/Makefile

This file was deleted.

2 changes: 1 addition & 1 deletion packages/webapp/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
"version": "2.0.3",
"private": true,
"scripts": {
"build": "pnpm nx run build-with-env",
"build": "pnpm nx run build-vite",
"extract-intl": "formatjs extract 'src/**/!(*.d).(js|jsx|ts|tsx)' '../webapp-libs/*/src/**/!(*.d).(js|jsx|ts|tsx)' --id-interpolation-pattern '[sha512:contenthash:base64:6]' --out-file ../webapp-libs/webapp-core/src/translations/en.json --ignore src/tests/mocks/** --ignore ../webapp-libs/*src/tests/mocks/**",
"lint": "pnpm run lint:js && pnpm run lint:css",
"lint:css": "stylelint './src/**/*.ts'",
Expand Down
9 changes: 0 additions & 9 deletions packages/webapp/project.json
Original file line number Diff line number Diff line change
Expand Up @@ -51,15 +51,6 @@
},
"dependsOn": ["graphql:generate-types"]
},
"build-with-env": {
"executor": "nx:run-commands",
"options": {
"cwd": "packages/webapp",
"color": true,
"command": "pnpm nx run tools:chamber-exec webapp nx run webapp:build-vite"
},
"dependsOn": ["graphql:generate-types"]
},
"lint": {
"executor": "@nx/linter:eslint",
"outputs": ["{options.outputFile}"],
Expand Down

0 comments on commit 2f8b852

Please sign in to comment.