-
Notifications
You must be signed in to change notification settings - Fork 67
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
pass valid props to root stack #1675
base: main
Are you sure you want to change the base?
Conversation
🦋 Changeset detectedLatest commit: 898a4cc The changes in this PR will be included in the next version bump. This PR includes changesets to release 1 package
Not sure what this means? Click here to learn what changesets are. Click here if you're a maintainer who wants to add another changeset to this PR |
packages/backend/API.md
Outdated
@@ -70,7 +71,7 @@ export { ConstructFactoryGetInstanceProps } | |||
export { defineAuth } | |||
|
|||
// @public | |||
export const defineBackend: <T extends DefineBackendProps>(constructFactories: T) => Backend<T>; | |||
export const defineBackend: <T extends DefineBackendProps>(constructFactories: T, mainStackProps?: MainStackProps) => Backend<T>; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We should prepare this API for further expansion. I.e. main stack props might not be the only extension we do in the future.
Therefore, we should have defineBackend(constructFactories T, props?: DefineBackendProps)
and then DefineBackendProps
should have mainStackProps: MainStackProps
as optional property.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Have updated in commits/93b77dc.
packages/backend/API.md
Outdated
@@ -89,6 +90,9 @@ export { GenerateContainerEntryProps } | |||
|
|||
export { ImportPathVerifier } | |||
|
|||
// @public | |||
export type MainStackProps = Pick<StackProps, 'description' | 'env' | 'tags' | 'analyticsReporting' | 'crossRegionReferences' | 'suppressTemplateIndentation'>; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is this minimal set of picked properties to solve the problem? If not, please narrow it.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Wasn't minimal for my specific issue. I have narrowed it in e931b42
stack?: Stack, | ||
mainStackProps?: MainStackProps |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
stack
and mainStackProps
should be mutually exclusive.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Have added constructor overloads to ensure this exclusivity in 3b24347
@sobolk Thank you for reviewing my PR. Please let me know if I should rebase into a single commit at some point or if you prefer the history. |
We're using "squash merge" strategy for pull request so rebase is not necessary. It's actually not desired as it makes incremental reviews impossible to track in GitHub UI sometimes. |
packages/backend/API.md
Outdated
export type DefineBackendConstructFactories = Record<string, ConstructFactory<ResourceProvider & Partial<ResourceAccessAcceptorFactory<never>>>> & { | ||
[K in keyof BackendBase]?: never; | ||
}; | ||
|
||
// @public (undocumented) | ||
export type DefineBackendProps = { | ||
mainStackProps: MainStackProps; | ||
}; | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm sorry I didn't realize that DefineBackendProps
already exist as a type while providing initial feedback.
We should revert back to existing naming there (otherwise this is breaking change) and name new type something different.
Perhaps DefineBackendOptions
. @Amplifiyer @edwardfoyle what do you think?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I have changed the new arg to DefineBackendOptions, but can change again easily enough, and DefineBackendConstructFactories has been reverted to DefineBackendProps.
constructor( | ||
constructFactories: T, | ||
stack: Stack, | ||
props?: ExplicitOmit<DefineBackendOptions, 'mainStackProps'> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
does a type of never
here not work?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
never
would prevent passing anything in props, but only mainStackProps
conflicts with a passed Stack. While there are currently no other props in the DefineBackendOptions
type, @sobolk requested this implementation for the further expansion of the API and backend options could potentially be used for anything in the process tree, not only for the root Stack config. Semantically it also makes sense to allow DefineBackendOptions
to be passed to defineBackend
even if a Stack is passed, as long as those options aren't specific to the root Stack definition.
FYI I did try with built-in Omit, but it's not explicit so doesn't prevent passing mainStackProps
. Hence the ExplicitOmit
implementation.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We should maybe change the props
key to options
though, for consistency sake. Thoughts?
Hey @renevatium 👋 thanks for taking the time to file this! We agree this is something we'd like to address, though are actively discussing this internally to gauge the direction. |
Hi @josefaidt 👋 No problem at all, big proponent of Amplify and keen to be more a part of the community. Considering it a point of conversation right now, I'll put my 2 cents in: Currently, this PR is a decent solution for my issue, but if I consider future flexibility, it does seem like exposing the explicit functionality necessary to define the App and Root Stack as independent objects and passing them into the (exposed) |
Amplify needs this desperately, without it I can't add a function created via |
Problem
Currently, it is not possible to pass instantiation props to the Amplify root CDK Stack, and, by convention, any Nested Stack created through
backend.createStack
. This prevents certain resource deployments: An EdgeFunction for instance requires the region to be explicitly set. Furthermore, while Nested Stacks inherit their region from their parent stack, Amplify has a single root node convention, so multiple root stacks are not an option. Evaluation in CDK appears to be strict so the only way to do deploy an EdgeFunction from an Amplify project looks to be at instantiation of an explicit region on the root Stack.Note: I used 'main' instead of 'root' because that is the naming convention used in the current code.
See #1663 for more information on trying to deploy an EdgeFunction with current version.
Changes
This implementation specifically avoids breaking changes, but does require argument mutation. The relevant args are not typed as
const
so this may be fine, but if it goes against an established convention, let me know as I can update it easily enough. This was needed because the relevant calls are being made as default argument values in both BackendFactory constructor and createDefaultStack respectively.This PR introduces a
mainStackProps
argument to thedefineBackend
function. This gets passed down the callstack and used to define the root Stack in theAmplifyStack
class.Props for root CDK Stack
AWS documentation for aws-cdk-lib.StackProps
Props are picked to ensure explicit addition of new StackProps is required.
StackProps incompatible with Amplify's intended hierarchy, build or deployment processes are omitted:
defineBackend
).Props are passed down from
defineBackend
. e.g:Validation
All existing unit, e2e and deployment tests pass. Coverage is unchanged.
Using the npm proxy, I have fully deployed and tested the EdgeFunction case with various configurations.
This change simply passes props tested in aws-cdk-lib/core/test/stack.test.ts. i.e It already follows defined convention. As such, I am not sure what automated testing would actually be useful. I did try though, so please let me know if you would like me to some tests back in?
I started out writing unit tests, but struggled to find a way to validate anything useful there. I could potentially check that
${AWS::Region}
does not exist in the generated Stack Template but that seems like a stretch.I wrote e2e and deployment tests, but they don't really do much to actually test anything in scope and they add a lot of unnecessary overhead. The deployment tests for instance, require that I update the test stack generation process and/or write the tests without following the conventions established by the existing test structure. Again, if you would prefer these be in, I can put them back.
Checklist
run-e2e
label set.By submitting this pull request, I confirm that my contribution is made under the terms of the Apache 2.0 license.