Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: sandbox deployment events #254

Merged
merged 100 commits into from
Sep 27, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
100 commits
Select commit Hold shift + click to select a range
8bbde6d
feat: sandbox options add format
zhamujun Sep 15, 2023
7ad12f1
test: add format to available options
zhamujun Sep 15, 2023
0ef8755
fix: sandbox command option format
zhamujun Sep 15, 2023
1d7c2f9
Merge branch 'main' into sandbox-option-format
zhamujun Sep 15, 2023
92a49e7
add changeset
zhamujun Sep 15, 2023
0063a4d
chore: update API.md
zhamujun Sep 15, 2023
7a77b27
refactor: move get_config_path to client-config
zhamujun Sep 18, 2023
a45c889
chore: type and lint
zhamujun Sep 18, 2023
5c58fe4
chore: update API.md
zhamujun Sep 18, 2023
eefeaf0
Merge branch 'main' into sandbox-option-format
zhamujun Sep 18, 2023
bd0f86e
chore: import formatChoices to sandbox
zhamujun Sep 18, 2023
c861be3
Merge branch 'main' into sandbox-option-format
zhamujun Sep 19, 2023
6309b05
chore: change template literal
zhamujun Sep 19, 2023
87530a6
chore: update types, use Enum
zhamujun Sep 19, 2023
f176750
chore: update types for FormatOption
zhamujun Sep 19, 2023
1986cd0
chore: fix type
zhamujun Sep 19, 2023
ea110b3
chore: move getConfigPath to internal api
zhamujun Sep 19, 2023
516bb8a
chore: rename getClientConfigPath
zhamujun Sep 19, 2023
c1f1c0f
chore: rename FormatChoice
zhamujun Sep 19, 2023
40d20fb
chore: update API.md
zhamujun Sep 19, 2023
cf25eac
chore: add index.js to internal.ts
zhamujun Sep 19, 2023
75f6be7
chore: remove configFileName and formatChoices from API
zhamujun Sep 19, 2023
cddb7c2
fix: test
zhamujun Sep 20, 2023
94625e7
Merge branch 'main' into sandbox-option-format
zhamujun Sep 20, 2023
0feeafe
sandbox: initial implementation of deployment hooks
sdstolworthy Sep 20, 2023
05075f9
sandbox: simplify hook registration example
sdstolworthy Sep 20, 2023
bdb2f65
lint: fix lints
sdstolworthy Sep 20, 2023
c77acac
refactor: use events instead of hooks
sdstolworthy Sep 20, 2023
1e973a9
api: update api description files
sdstolworthy Sep 20, 2023
f98b49f
logging: added debug logging
sdstolworthy Sep 20, 2023
f43c10f
tests: fix broken test
sdstolworthy Sep 20, 2023
39d0d46
sandbox: base event handler on node:events EventEmitter
sdstolworthy Sep 20, 2023
8c546d1
tests: fix broken test
sdstolworthy Sep 20, 2023
57ec633
chore: move getConfigPath from GenerateConfigCommand to generateClien…
zhamujun Sep 20, 2023
3575c06
Update packages/client-config/src/paths/get_client_config_path.ts
0618 Sep 20, 2023
f941266
chore: rename FormatChoice to ClientConfigFormat
zhamujun Sep 20, 2023
944f373
refactor: generateClientConfigToFile to accept out and format
zhamujun Sep 20, 2023
5153d15
test: update tests for generate config and sandbox
zhamujun Sep 20, 2023
3b93e66
Update packages/cli/src/commands/sandbox/sandbox_command.ts
0618 Sep 20, 2023
42d79f2
test: misc var change
zhamujun Sep 20, 2023
692b804
chore: move ClientConfigFormat to public API
zhamujun Sep 20, 2023
b85d43e
chore: update API.md
zhamujun Sep 20, 2023
d53ccb1
test: add test for getClientConfigPath
zhamujun Sep 20, 2023
915b7b8
test: use path.join to resolve windows slash
zhamujun Sep 20, 2023
a60d541
test: use path.join to resolve windows slash
zhamujun Sep 21, 2023
fc86f13
chore: fix linting error
zhamujun Sep 21, 2023
aa35750
chore: fix linting error
zhamujun Sep 21, 2023
bda8e37
chore: remove defaultOptions
zhamujun Sep 21, 2023
006628f
test: add asserts for both out and format
zhamujun Sep 21, 2023
4813824
test: add absolut path test
zhamujun Sep 21, 2023
134f2a5
Merge branch 'main' into sandbox-hooks
sdstolworthy Sep 21, 2023
c1f2f00
Merge branch 'sandbox-option-format' into sandbox-hooks
sdstolworthy Sep 21, 2023
e378e28
fix: throw error if provided file path
zhamujun Sep 21, 2023
da5987d
fix: broken test
sdstolworthy Sep 21, 2023
5acd13a
Merge branch 'main' into sandbox-option-format
zhamujun Sep 21, 2023
8dd2666
fix: integrate format into event callback
sdstolworthy Sep 21, 2023
406a9fa
Merge branch 'sandbox-option-format' into sandbox-hooks
sdstolworthy Sep 21, 2023
f109014
api: update api description files
sdstolworthy Sep 21, 2023
2002f12
fix: address pr comments
sdstolworthy Sep 21, 2023
6498e71
Merge branch 'main' into sandbox-option-format
zhamujun Sep 21, 2023
fd3a87f
chore: rename --out to --outDir
zhamujun Sep 21, 2023
0098475
fix: use lstatSync to detect file path
zhamujun Sep 21, 2023
3a8dc90
chore: update API.md
zhamujun Sep 21, 2023
a9ca6ca
chore: changeset
zhamujun Sep 21, 2023
6f7bf38
chore: remove un-used var
zhamujun Sep 21, 2023
f17ca5a
fix: package-lock resolve registry
zhamujun Sep 21, 2023
cbc6e3b
chore: ignore spell of lstat
zhamujun Sep 21, 2023
810b694
chore: refactor mock-fs with node:mock
zhamujun Sep 21, 2023
4b7b051
chore: remove un-used var
zhamujun Sep 21, 2023
135d263
chore: make getClientConfigPath async
zhamujun Sep 21, 2023
5cb83a9
Merge branch 'sandbox-option-format' into sandbox-hooks
sdstolworthy Sep 21, 2023
4105ee0
fix: path for windows
zhamujun Sep 21, 2023
dbaed8c
Merge branch 'main' into sandbox-option-format
zhamujun Sep 21, 2023
cbd4e46
chore: remove auto-generated changelogs
zhamujun Sep 21, 2023
28a15b2
Merge branch 'sandbox-option-format' into sandbox-hooks
sdstolworthy Sep 21, 2023
305c2ca
fix: remove references to deleted events
sdstolworthy Sep 21, 2023
964b9be
api: update api description files
sdstolworthy Sep 21, 2023
49e3f11
Merge branch 'main' of github.com:aws-amplify/samsara-cli into sandbo…
sdstolworthy Sep 22, 2023
49dc760
refactor: rename event, move generate-config-adapter
sdstolworthy Sep 22, 2023
3da09fa
refactor: remove sandbox config adapter
sdstolworthy Sep 22, 2023
8ed1025
refactor: use args.out directly for config write path
sdstolworthy Sep 22, 2023
2ba6fd0
refactor: use exported getClientConfigPath from client-config package
sdstolworthy Sep 22, 2023
046eb3f
refactor: use mocks for test
sdstolworthy Sep 22, 2023
2c71a88
fix: explicitly export getClientConfigPath
sdstolworthy Sep 22, 2023
ff06a37
Update packages/sandbox/src/file_watching_sandbox.ts
sdstolworthy Sep 22, 2023
1356052
fix: remove unused import
sdstolworthy Sep 22, 2023
6c390d9
Merge branch 'sandbox-hooks' of github.com:sdstolworthy/samsara-cli i…
sdstolworthy Sep 22, 2023
30f5572
Update packages/cli/src/commands/sandbox/sandbox_command.ts
sdstolworthy Sep 22, 2023
a816b14
refactor: extract getBackendIdentifier
sdstolworthy Sep 22, 2023
6c201eb
test: add test to validate that successfulDeployment event is emitted
sdstolworthy Sep 22, 2023
bd5d258
test: refactor to allow asserting that a specific callback was regist…
sdstolworthy Sep 22, 2023
dcbcbc7
fix: remove unused import
sdstolworthy Sep 22, 2023
008406e
Merge branch 'main' into sandbox-hooks
sdstolworthy Sep 22, 2023
67f118a
refactor: creator method for registering sandbox events
sdstolworthy Sep 22, 2023
afd1012
fix: remove unused import
sdstolworthy Sep 22, 2023
6607c76
fix: fix naming, refactor for readability
sdstolworthy Sep 22, 2023
f2ab03e
Sandbox hooks (#274)
sdstolworthy Sep 22, 2023
7885a8c
Merge branch 'main' of github.com:aws-amplify/samsara-cli into sandbo…
sdstolworthy Sep 27, 2023
2f700db
fix: add delay
sdstolworthy Sep 27, 2023
f0b70c3
Merge branch 'e2e-sandbox-events' of github.com:aws-amplify/samsara-c…
sdstolworthy Sep 27, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions .changeset/moody-rats-wonder.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
---
'@aws-amplify/sandbox': minor
'@aws-amplify/backend-cli': minor
---

Add event handlers for Sandbox
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,8 @@ import {
TestCommandRunner,
} from '../../../test-utils/command_runner.js';
import assert from 'node:assert';
import { ClientConfigGeneratorAdapter } from './client_config_generator_adapter.js';
import { BackendIdentifierResolver } from '../../../backend-identifier/backend_identifier_resolver.js';
import { ClientConfigGeneratorAdapter } from '../../../client-config/client_config_generator_adapter.js';

void describe('generate config command', () => {
const clientConfigGeneratorAdapter = new ClientConfigGeneratorAdapter(
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { ArgumentsCamelCase, Argv, CommandModule } from 'yargs';
import { ClientConfigFormat } from '@aws-amplify/client-config';
import { ClientConfigGeneratorAdapter } from './client_config_generator_adapter.js';
import { BackendIdentifierResolver } from '../../../backend-identifier/backend_identifier_resolver.js';
import { ClientConfigGeneratorAdapter } from '../../../client-config/client_config_generator_adapter.js';

export type GenerateConfigCommandOptions = {
stack: string | undefined;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,12 @@ import { CommandModule } from 'yargs';
import { GenerateCommand } from './generate_command.js';
import { GenerateConfigCommand } from './config/generate_config_command.js';
import { fromNodeProviderChain } from '@aws-sdk/credential-providers';
import { ClientConfigGeneratorAdapter } from './config/client_config_generator_adapter.js';
import { GenerateFormsCommand } from './forms/generate_forms_command.js';
import { CwdPackageJsonLoader } from '../../cwd_package_json_loader.js';
import { GenerateGraphqlClientCodeCommand } from './graphql-client-code/generate_graphql_client_code_command.js';
import { LocalAppNameResolver } from '../../backend-identifier/local_app_name_resolver.js';
import { BackendIdentifierResolver } from '../../backend-identifier/backend_identifier_resolver.js';
import { ClientConfigGeneratorAdapter } from '../../client-config/client_config_generator_adapter.js';
import { FormGenerationHandler } from './forms/form_generation_handler.js';
import { BackendOutputClient } from '@aws-amplify/deployed-backend-client';
import { GenerateApiCodeAdapter } from './graphql-client-code/generate_api_code_adapter.js';
Expand Down
41 changes: 21 additions & 20 deletions packages/cli/src/commands/sandbox/sandbox_command.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,11 @@ import {
} from '../../test-utils/command_runner.js';
import assert from 'node:assert';
import fs from 'fs';
import { SandboxCommand } from './sandbox_command.js';
import { EventHandler, SandboxCommand } from './sandbox_command.js';
import { createSandboxCommand } from './sandbox_command_factory.js';
import { SandboxDeleteCommand } from './sandbox-delete/sandbox_delete_command.js';
import { Sandbox, SandboxSingletonFactory } from '@aws-amplify/sandbox';
import { ClientConfigGeneratorAdapter } from '../../client-config/client_config_generator_adapter.js';
import { createSandboxSecretCommand } from './sandbox-secret/sandbox_secret_command_factory.js';

void describe('sandbox command factory', () => {
Expand All @@ -23,6 +24,9 @@ void describe('sandbox command', () => {
let commandRunner: TestCommandRunner;
let sandbox: Sandbox;
let sandboxStartMock = mock.fn<typeof sandbox.start>();
const mockGenerate =
mock.fn<ClientConfigGeneratorAdapter['generateClientConfigToFile']>();
const generationMock = mock.fn<EventHandler>();

beforeEach(async () => {
const sandboxFactory = new SandboxSingletonFactory(() =>
Expand All @@ -32,13 +36,25 @@ void describe('sandbox command', () => {

sandboxStartMock = mock.method(sandbox, 'start', () => Promise.resolve());
const sandboxDeleteCommand = new SandboxDeleteCommand(sandboxFactory);
const sandboxCommand = new SandboxCommand(sandboxFactory, [
sandboxDeleteCommand,
createSandboxSecretCommand(),
]);

const sandboxCommand = new SandboxCommand(
sandboxFactory,
[sandboxDeleteCommand, createSandboxSecretCommand()],
() => ({
successfulDeployment: [generationMock],
})
);
const parser = yargs().command(sandboxCommand as unknown as CommandModule);
commandRunner = new TestCommandRunner(parser);
sandboxStartMock.mock.resetCalls();
mockGenerate.mock.resetCalls();
});

void it('registers a callback on the "successfulDeployment" event', async () => {
const mockOn = mock.method(sandbox, 'on');
await commandRunner.runCommand('sandbox');
assert.equal(mockOn.mock.calls[0].arguments[0], 'successfulDeployment');
assert.equal(mockOn.mock.calls[0].arguments[1], generationMock);
});

void it('starts sandbox without any additional flags', async () => {
Expand All @@ -56,21 +72,6 @@ void describe('sandbox command', () => {
);
});

void it('starts sandbox with user provided output directory for client config', async () => {
await commandRunner.runCommand(
'sandbox --outDir test/location --format js'
);
assert.equal(sandboxStartMock.mock.callCount(), 1);
assert.deepStrictEqual(
sandboxStartMock.mock.calls[0].arguments[0].clientConfigFilePath,
'test/location'
);
assert.deepStrictEqual(
sandboxStartMock.mock.calls[0].arguments[0].format,
'js'
);
});

void it('shows available options in help output', async () => {
const output = await commandRunner.runCommand('sandbox --help');
assert.match(output, /--name/);
Expand Down
49 changes: 41 additions & 8 deletions packages/cli/src/commands/sandbox/sandbox_command.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,11 @@
import { ArgumentsCamelCase, Argv, CommandModule } from 'yargs';
import { ClientConfigFormat } from '@aws-amplify/client-config';
import fs from 'fs';
import { AmplifyPrompter } from '../prompter/amplify_prompts.js';
import { SandboxSingletonFactory } from '@aws-amplify/sandbox';
import {
ClientConfigFormat,
getClientConfigPath,
} from '@aws-amplify/client-config';

export type SandboxCommandOptions = {
dirToWatch: string | undefined;
Expand All @@ -13,6 +16,22 @@ export type SandboxCommandOptions = {
profile: string | undefined;
};

export type EventHandler = () => void;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Based on this line it looks like the return type here should be Promise<void>?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

node:EventEmitter does not accept Promise<void>. It is fire and forget. See here: #254 (comment)


export type SandboxEventHandlers = {
successfulDeployment: EventHandler[];
};

export type SandboxEventHandlerParams = {
appName?: string;
outDir?: string;
format?: ClientConfigFormat;
};

export type SandboxEventHandlerCreator = (
params: SandboxEventHandlerParams
) => SandboxEventHandlers;

/**
* Command that starts sandbox.
*/
Expand All @@ -36,7 +55,8 @@ export class SandboxCommand
*/
constructor(
private readonly sandboxFactory: SandboxSingletonFactory,
private readonly sandboxSubCommands: CommandModule[]
private readonly sandboxSubCommands: CommandModule[],
private readonly sandboxEventHandlerCreator?: SandboxEventHandlerCreator
) {
this.command = 'sandbox';
this.describe = 'Starts sandbox, watch mode for amplify deployments';
Expand All @@ -48,15 +68,28 @@ export class SandboxCommand
handler = async (
args: ArgumentsCamelCase<SandboxCommandOptions>
): Promise<void> => {
const sandbox = await this.sandboxFactory.getInstance();
this.appName = args.name;
await (
await this.sandboxFactory.getInstance()
).start({
const eventHandlers = this.sandboxEventHandlerCreator?.({
appName: args.name,
format: args.format,
outDir: args.outDir,
});
if (eventHandlers) {
Object.entries(eventHandlers).forEach(([event, handlers]) => {
handlers.forEach((handler) => sandbox.on(event, handler));
});
}
const watchExclusions = args.exclude ?? [];
const clientConfigWritePath = await getClientConfigPath(
args.outDir,
args.format
);
watchExclusions.push(clientConfigWritePath);
await sandbox.start({
dir: args.dirToWatch,
exclude: args.exclude,
exclude: watchExclusions,
name: args.name,
format: args.format,
clientConfigFilePath: args.outDir,
profile: args.profile,
});
process.once('SIGINT', () => void this.sigIntHandler());
Expand Down
45 changes: 38 additions & 7 deletions packages/cli/src/commands/sandbox/sandbox_command_factory.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,15 @@
import { CommandModule } from 'yargs';

import { SandboxCommand, SandboxCommandOptions } from './sandbox_command.js';
import {
SandboxCommand,
SandboxCommandOptions,
SandboxEventHandlerCreator,
} from './sandbox_command.js';
import { SandboxSingletonFactory } from '@aws-amplify/sandbox';
import { SandboxDeleteCommand } from './sandbox-delete/sandbox_delete_command.js';
import { SandboxIdResolver } from './sandbox_id_resolver.js';
import { CwdPackageJsonLoader } from '../../cwd_package_json_loader.js';
import { ClientConfigGeneratorAdapter } from '../../client-config/client_config_generator_adapter.js';
import { fromNodeProviderChain } from '@aws-sdk/credential-providers';
import { LocalAppNameResolver } from '../../backend-identifier/local_app_name_resolver.js';
import { createSandboxSecretCommand } from './sandbox-secret/sandbox_secret_command_factory.js';

Expand All @@ -15,13 +20,39 @@ export const createSandboxCommand = (): CommandModule<
object,
SandboxCommandOptions
> => {
const credentialProvider = fromNodeProviderChain();
const sandboxIdResolver = new SandboxIdResolver(
new LocalAppNameResolver(new CwdPackageJsonLoader())
);
const sandboxFactory = new SandboxSingletonFactory(sandboxIdResolver.resolve);

return new SandboxCommand(sandboxFactory, [
new SandboxDeleteCommand(sandboxFactory),
createSandboxSecretCommand(),
]);
const clientConfigGeneratorAdapter = new ClientConfigGeneratorAdapter(
credentialProvider
);
const getBackendIdentifier = async (appName?: string) => {
const sandboxId = appName ?? (await sandboxIdResolver.resolve());
return { backendId: sandboxId, branchName: 'sandbox' };
};
const sandboxEventHandlerCreator: SandboxEventHandlerCreator = ({
appName,
outDir,
format,
}) => {
return {
successfulDeployment: [
async () => {
const id = await getBackendIdentifier(appName);
await clientConfigGeneratorAdapter.generateClientConfigToFile(
id,
outDir,
format
);
},
],
};
};
return new SandboxCommand(
sandboxFactory,
[new SandboxDeleteCommand(sandboxFactory), createSandboxSecretCommand()],
sandboxEventHandlerCreator
);
};
1 change: 1 addition & 0 deletions packages/client-config/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,3 +4,4 @@ export * from './client-config-types/client_config.js';
export * from './client-config-types/auth_client_config.js';
export * from './client-config-types/graphql_client_config.js';
export * from './client-config-types/storage_client_config.js';
export * from './paths/get_client_config_path.js';
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,8 @@ export class ProcessController {
if (typeof currentInteraction.payload === 'string') {
if (currentInteraction.payload === CONTROL_C) {
if (process.platform.startsWith('win')) {
// Wait X milliseconds before sending kill in hopes of draining the node event queue
await new Promise((resolve) => setTimeout(resolve, 5000));
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

approved as long as we add a GH issue to the backlog to track this. Bonus points for linking to that issue in the comment here

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

// turns out killing child process on Windows is a huge PITA
// https://stackoverflow.com/questions/23706055/why-can-i-not-kill-my-child-process-in-nodejs-on-windows
// https://github.com/sindresorhus/execa#killsignal-options
Expand Down
9 changes: 7 additions & 2 deletions packages/sandbox/API.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,28 +4,33 @@

```ts

/// <reference types="node" />

import { ClientConfigFormat } from '@aws-amplify/client-config';
import EventEmitter from 'events';

// @public
export type Sandbox = {
start: (options: SandboxOptions) => Promise<void>;
stop: () => Promise<void>;
delete: (options: SandboxDeleteOptions) => Promise<void>;
};
} & EventEmitter;

// @public (undocumented)
export type SandboxDeleteOptions = {
name?: string;
};

// @public (undocumented)
export type SandboxEvents = 'successfulDeployment';

// @public (undocumented)
export type SandboxOptions = {
dir?: string;
exclude?: string[];
name?: string;
format?: ClientConfigFormat;
profile?: string;
clientConfigFilePath?: string;
};

// @public
Expand Down
34 changes: 0 additions & 34 deletions packages/sandbox/src/config/client_config_generator_adapter.ts

This file was deleted.

Loading