-
Notifications
You must be signed in to change notification settings - Fork 3.9k
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(aws-cdk): add CDK app version negotiation #988
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -4,6 +4,24 @@ | |
|
||
import { Environment } from './environment'; | ||
|
||
/** | ||
* Bump this to the library version if and only if the CX protocol changes. | ||
* | ||
* We could also have used 1, 2, 3, ... here to indicate protocol versions, but | ||
* those then still need to be mapped to software versions to be useful. So we | ||
* might as well use the software version as protocol version and immediately | ||
* generate a useful error message from this. | ||
* | ||
* Note the following: | ||
* | ||
* - The versions are not compared in a semver way, they are used as | ||
* opaque ordered tokens. | ||
* - The version needs to be set to the NEXT releasable version when it's | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Hmmmmnmnmmm this smells like something that one might forget to do, since it happens in a different place than the other version bumps. I don't know that this is a real concern / reason not to, but I wanted to have it up there. |
||
* updated (as the current verison in package.json has already been released!) | ||
* - The request does not have versioning yet, only the response. | ||
*/ | ||
export const PROTO_RESPONSE_VERSION = '0.14.0'; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Let's either use separate versioning or use the version of the cx-api module as the version. I don't think manually aligning those makes sense. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. That only works if we move to "bump-when-changed" versioning of libraries, which we're not doing yet. If we use the version of There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. So let's just define a separate version line for the interface. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. So do you mean switch to How do you propose to map this version number to an actionable and helpful instruction for the user? As in:
Where do we get the const INTERFACE_VERSION = 3;
const VERSION_MAPS = {
1: '0.12.0',
2: '0.13.2',
3: '0.16.0',
}; And then go Or you do just want to say:
We can have 2 versions in the protocol:
So that if the There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I would still use semantic versioning though, not just "1,2,3" There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. But why no version map?A problem of the So if the toolkit has this data:
And it receives
So that the toolkit can provide the appropriate error message. Then the newer toolkit has the following information internally:
It will only ever read the CURRENT_PROTOCOL_VERSION from the version map, never any other, so we could also simplify it to:
And send both of those on every response. The only thing that's different between this code and the PR is that in the PR those 2 versions fields (which always bump versions together) have been collapsed into one. Because: why have two fields if one of them conveys strictly more information than the other one? But why not semantic versioning?I don't think semantic versioning makes sense in this case. With semantic versioning a provider can express to a consumer the notion: "this interface can do at least what you expect, and potentially more." It is used in situations where a provider advertises a version number beforehand, and a consumer can compare this this number to their required version number, and then decide whether or not to proceed with the request. That is, the consumer makes the continue/stop decision based on the advertised information by the provider. In this case though, who is the provider, and who is the consumer? I would argue that the toolkit is the provider that renders services (such as reading context variables, packaging assets, deploying resources) to the CDK app. The CDK app is the consumer, making a request to the toolkit to "please perform some actions." In that sense, there is no way in which the app can bump their version number in a way that an older toolkit that doesn't know about the changes can still service the request. The app might be requesting new features that the toolkit does not know how to deliver. The best thing we can do at this point is say to the user something like:
That's ludicrous, and way too hand-wavy for users to be able to deal with in practice. The answer at this point is to fail and tell the user to upgrade, because whatever they're trying to do, it probably won't work.
The version number in the protocol is much more like a protocol version number in version negotation. By the time the request gets to the provider: they have full information, they know whether they recognize the request version or not. There are two cases:
But I really want semantic versioning!We can reverse it: the toolkit can advertise their feature set in a semver way via an environment variable and the app can look at that version and decide whether to proceed (continuing if the advertised version number is a semantic superset of the app's version number). We could even make it emit older output in case we want to maintain backwards compatibility. But for some reason, it feels much more natural to me, and safer, to maintain these kinds of checks in the toolkit. |
||
|
||
export const OUTFILE_NAME = 'cdk.out'; | ||
export const OUTDIR_ENV = 'CDK_OUTDIR'; | ||
export const CONTEXT_ENV = 'CDK_CONTEXT_JSON'; | ||
|
@@ -21,6 +39,10 @@ export interface MissingContext { | |
} | ||
|
||
export interface SynthesizeResponse { | ||
/** | ||
* Protocol version | ||
*/ | ||
version: string; | ||
stacks: SynthesizedStack[]; | ||
runtime?: AppRuntime; | ||
} | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -39,6 +39,7 @@ | |
"@types/request": "^2.47.1", | ||
"@types/uuid": "^3.4.3", | ||
"@types/yargs": "^8.0.3", | ||
"@types/semver": "^5.5.0", | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. You add a dependency on There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. And |
||
"cdk-build-tools": "^0.13.0", | ||
"mockery": "^2.1.0", | ||
"pkglint": "^0.13.0" | ||
|
@@ -58,6 +59,7 @@ | |
"promptly": "^0.2.0", | ||
"proxy-agent": "^3.0.1", | ||
"request": "^2.83.0", | ||
"semver": "^5.5.0", | ||
"source-map-support": "^0.5.6", | ||
"yargs": "^9.0.1" | ||
}, | ||
|
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.
Why not, though? Your verification code uses
semver
already and I reckon a protocol-breaking change should derive in a version bump... So you could totally semver that.