Skip to content

Commit 07c7e43

Browse files
authored
pin cdk versions for create amplify (#2535)
* pin cdk versions for create amplify * change to json and refactor update script to be run as git hook * add check for create amplify deps * fix test * import json instead of using fsp * run for prod packages
1 parent e25e96b commit 07c7e43

16 files changed

+512
-42
lines changed

.changeset/fifty-ads-boil.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
'create-amplify': patch
3+
---
4+
5+
pin cdk versions for create amplify

.eslint_dictionary.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -184,6 +184,7 @@
184184
"tsconfig",
185185
"tsdoc",
186186
"tslint",
187+
"tsx",
187188
"typename",
188189
"typeof",
189190
"ubuntu",

.github/workflows/health_checks.yml

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -694,6 +694,22 @@ jobs:
694694
cdk-lib-version: ${{ needs.resolve_inputs.outputs.cdk_lib_version }}
695695
cdk-cli-version: ${{ needs.resolve_inputs.outputs.cdk_cli_version }}
696696
- run: npm run check:api
697+
check_create_amplify_deps:
698+
runs-on: ubuntu-latest
699+
needs:
700+
- install
701+
- resolve_inputs
702+
steps:
703+
- uses: actions/checkout@0ad4b8fadaa221de15dcec353f45205ec38ea70b # version 4.1.4
704+
- uses: ./.github/actions/setup_node
705+
with:
706+
node-version: 18
707+
- uses: ./.github/actions/restore_install_cache
708+
with:
709+
node-version: 18
710+
cdk-lib-version: ${{ needs.resolve_inputs.outputs.cdk_lib_version }}
711+
cdk-cli-version: ${{ needs.resolve_inputs.outputs.cdk_cli_version }}
712+
- run: npm run check:create-amplify-deps
697713
docs_build_and_publish:
698714
runs-on: ubuntu-latest
699715
needs:

.husky/pre-commit

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
#!/bin/sh
22
. "$(dirname "$0")/_/husky.sh"
33

4+
npm run update:create-amplify-deps
45
npm run update:tsconfig-refs
56
npm run check:package-lock
67
npx lint-staged

package.json

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
"scripts": {
77
"build": "tsc --build packages/* scripts",
88
"check:api": "npm run update:api && tsx scripts/check_api_extract.ts",
9+
"check:create-amplify-deps": "npm run update:create-amplify-deps && tsx scripts/check_no_git_diff.ts",
910
"check:dependencies": "tsx scripts/check_dependencies.ts",
1011
"check:package-lock": "tsx scripts/check_package_lock.ts",
1112
"check:package-versions": "tsx scripts/check_package_versions.ts",
@@ -35,6 +36,7 @@
3536
"test:dir": "tsx scripts/run_tests.ts",
3637
"test:scripts": "npm run test:dir $(glob --cwd=scripts --absolute **/*.test.ts)",
3738
"update:api": "tsx scripts/concurrent_workspace_script.ts update:api --if-present",
39+
"update:create-amplify-deps": "tsx scripts/update_create_amplify_deps.ts",
3840
"update:tsconfig-refs": "tsx scripts/update_tsconfig_refs.ts",
3941
"vend": "npm run start:npm-proxy && npm run publish:local",
4042
"watch": "npm run build -- --watch"

packages/create-amplify/src/amplify_project_creator.ts

Lines changed: 7 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import { PackageManagerController } from '@aws-amplify/plugin-types';
44
import { ProjectRootValidator } from './project_root_validator.js';
55
import { GitIgnoreInitializer } from './gitignore_initializer.js';
66
import { InitialProjectFileGenerator } from './initial_project_file_generator.js';
7+
import defaultPackages from './default_packages.json';
78

89
const LEARN_MORE_USAGE_DATA_TRACKING_LINK =
910
'https://docs.amplify.aws/react/reference/telemetry';
@@ -12,19 +13,8 @@ const LEARN_MORE_USAGE_DATA_TRACKING_LINK =
1213
* Orchestration class that sets up a new Amplify project
1314
*/
1415
export class AmplifyProjectCreator {
15-
private readonly defaultDevPackages = [
16-
'@aws-amplify/backend',
17-
'@aws-amplify/backend-cli',
18-
'aws-cdk@^2',
19-
'aws-cdk-lib@^2',
20-
'constructs@^10.0.0',
21-
'typescript@^5.0.0',
22-
'tsx',
23-
'esbuild',
24-
];
25-
26-
private readonly defaultProdPackages = ['aws-amplify'];
27-
16+
private readonly defaultDevPackages: string[];
17+
private readonly defaultProdPackages: string[];
2818
/**
2919
* Orchestrator for the create-amplify workflow.
3020
* Delegates out to other classes that handle parts of the getting started experience
@@ -35,7 +25,10 @@ export class AmplifyProjectCreator {
3525
private readonly projectRootValidator: ProjectRootValidator,
3626
private readonly gitIgnoreInitializer: GitIgnoreInitializer,
3727
private readonly initialProjectFileGenerator: InitialProjectFileGenerator
38-
) {}
28+
) {
29+
this.defaultDevPackages = defaultPackages.defaultDevPackages;
30+
this.defaultProdPackages = defaultPackages.defaultProdPackages;
31+
}
3932

4033
/**
4134
* Executes the create-amplify workflow
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
{
2+
"defaultDevPackages": [
3+
"@aws-amplify/backend",
4+
"@aws-amplify/backend-cli",
5+
6+
7+
"constructs@^10.0.0",
8+
"typescript@^5.0.0",
9+
"tsx",
10+
"esbuild"
11+
],
12+
"defaultProdPackages": ["aws-amplify"]
13+
}

packages/create-amplify/tsconfig.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
{
22
"extends": "../../tsconfig.base.json",
33
"compilerOptions": { "rootDir": "src", "outDir": "lib" },
4+
"include": ["**/*", "src/**/*.json"],
45
"exclude": ["templates", "lib"],
56
"references": [
67
{ "path": "../cli-core" },
Lines changed: 145 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,145 @@
1+
import assert from 'assert';
2+
import fsp from 'fs/promises';
3+
import { beforeEach, describe, it, mock } from 'node:test';
4+
import { createAmplifyDepUpdater } from './create_amplify_dep_updater.js';
5+
6+
void describe('createAmplifyDepUpdater', () => {
7+
const mockedFsReadFile = mock.method(fsp, 'readFile', () =>
8+
JSON.stringify({
9+
defaultDevPackages: [
10+
'@aws-amplify/backend',
11+
'@aws-amplify/backend-cli',
12+
13+
14+
'constructs@^10.0.0',
15+
'typescript@^5.0.0',
16+
'tsx',
17+
'esbuild',
18+
],
19+
defaultProdPackages: ['aws-amplify', '[email protected]'],
20+
})
21+
);
22+
const mockedFsWriteFile = mock.method(fsp, 'writeFile', mock.fn());
23+
24+
beforeEach(() => {
25+
mockedFsReadFile.mock.resetCalls();
26+
mockedFsWriteFile.mock.resetCalls();
27+
});
28+
29+
void it('successfully pins new dev version', async () => {
30+
await createAmplifyDepUpdater([{ name: 'aws-cdk', version: '2.1.0' }]);
31+
assert.strictEqual(mockedFsReadFile.mock.callCount(), 1);
32+
assert.strictEqual(mockedFsWriteFile.mock.callCount(), 1);
33+
assert.deepStrictEqual(
34+
mockedFsWriteFile.mock.calls[0].arguments[1],
35+
JSON.stringify(
36+
{
37+
defaultDevPackages: [
38+
'@aws-amplify/backend',
39+
'@aws-amplify/backend-cli',
40+
'[email protected]', // updated
41+
42+
'constructs@^10.0.0',
43+
'typescript@^5.0.0',
44+
'tsx',
45+
'esbuild',
46+
],
47+
defaultProdPackages: ['aws-amplify', '[email protected]'],
48+
},
49+
null,
50+
2
51+
)
52+
);
53+
});
54+
55+
void it('successfully pins new prod version', async () => {
56+
await createAmplifyDepUpdater(
57+
[{ name: 'test-prod-package', version: '1.1.0' }],
58+
['test-prod-package']
59+
);
60+
assert.strictEqual(mockedFsReadFile.mock.callCount(), 1);
61+
assert.strictEqual(mockedFsWriteFile.mock.callCount(), 1);
62+
assert.deepStrictEqual(
63+
mockedFsWriteFile.mock.calls[0].arguments[1],
64+
JSON.stringify(
65+
{
66+
defaultDevPackages: [
67+
'@aws-amplify/backend',
68+
'@aws-amplify/backend-cli',
69+
70+
71+
'constructs@^10.0.0',
72+
'typescript@^5.0.0',
73+
'tsx',
74+
'esbuild',
75+
],
76+
defaultProdPackages: [
77+
'aws-amplify',
78+
'[email protected]', // updated
79+
],
80+
},
81+
null,
82+
2
83+
)
84+
);
85+
});
86+
87+
void it('successfully pins multiple new versions', async () => {
88+
await createAmplifyDepUpdater(
89+
[
90+
{ name: 'aws-cdk', version: '2.1.0' },
91+
{ name: 'test-prod-package', version: '1.1.0' },
92+
],
93+
['aws-cdk', 'aws-cdk-lib', 'test-prod-package']
94+
);
95+
assert.strictEqual(mockedFsReadFile.mock.callCount(), 1);
96+
assert.strictEqual(mockedFsWriteFile.mock.callCount(), 1);
97+
assert.deepStrictEqual(
98+
mockedFsWriteFile.mock.calls[0].arguments[1],
99+
JSON.stringify(
100+
{
101+
defaultDevPackages: [
102+
'@aws-amplify/backend',
103+
'@aws-amplify/backend-cli',
104+
'[email protected]', // updated
105+
106+
'constructs@^10.0.0',
107+
'typescript@^5.0.0',
108+
'tsx',
109+
'esbuild',
110+
],
111+
defaultProdPackages: [
112+
'aws-amplify',
113+
'[email protected]', // updated
114+
],
115+
},
116+
null,
117+
2
118+
)
119+
);
120+
});
121+
122+
void it('does nothing if there are no provided dependencies', async () => {
123+
await createAmplifyDepUpdater([]);
124+
assert.strictEqual(mockedFsReadFile.mock.callCount(), 0);
125+
assert.strictEqual(mockedFsWriteFile.mock.callCount(), 0);
126+
});
127+
128+
void it('does nothing if provided dependencies are not part of target dependencies for updates', async () => {
129+
await createAmplifyDepUpdater([{ name: 'test-dep', version: '2.1.0' }]);
130+
assert.strictEqual(mockedFsReadFile.mock.callCount(), 0);
131+
assert.strictEqual(mockedFsWriteFile.mock.callCount(), 0);
132+
});
133+
134+
void it('does not update if provided dependency versions already match create amplify dependencies', async () => {
135+
await createAmplifyDepUpdater(
136+
[
137+
{ name: 'aws-cdk', version: '2.0.0' },
138+
{ name: 'aws-cdk-lib', version: '2.0.0' },
139+
],
140+
['aws-cdk', 'aws-cdk-lib', 'test-prod-package']
141+
);
142+
assert.strictEqual(mockedFsReadFile.mock.callCount(), 1);
143+
assert.strictEqual(mockedFsWriteFile.mock.callCount(), 0);
144+
});
145+
});
Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
import fsp from 'fs/promises';
2+
import path from 'path';
3+
import { Dependency } from './get_dependencies_from_package_lock.js';
4+
5+
/**
6+
* Modifies target dependencies used for create amplify
7+
*/
8+
export const createAmplifyDepUpdater = async (
9+
dependencies: Dependency[],
10+
createAmplifyDepsToFilter: string[] = ['aws-cdk', 'aws-cdk-lib']
11+
) => {
12+
const targetDependencies: Dependency[] = dependencies.filter((dependency) =>
13+
createAmplifyDepsToFilter.includes(dependency.name)
14+
);
15+
16+
if (targetDependencies.length === 0) {
17+
return;
18+
}
19+
20+
const defaultPackagesPath = path.join(
21+
process.cwd(),
22+
'packages/create-amplify/src/default_packages.json'
23+
);
24+
25+
const dependenciesToUpdate = new Map(
26+
targetDependencies.map((dep) => [dep.name, dep.version])
27+
);
28+
const defaultPackagesContent = JSON.parse(
29+
await fsp.readFile(defaultPackagesPath, 'utf-8')
30+
);
31+
const defaultDevPackages: string[] =
32+
defaultPackagesContent.defaultDevPackages;
33+
const defaultProdPackages: string[] =
34+
defaultPackagesContent.defaultProdPackages;
35+
let update = false; // keeps track if any create amplify dep was updated
36+
37+
// create new array of dev packages with possible updates
38+
const newDevPackages = defaultDevPackages.map((depString) => {
39+
if (!depString.includes('@')) {
40+
return depString;
41+
}
42+
43+
const [depName] = depString.split('@');
44+
const expectedDepString = `${depName}@${dependenciesToUpdate.get(depName)}`;
45+
const hasDepName = dependenciesToUpdate.has(depName);
46+
update = update || (hasDepName && depString !== expectedDepString);
47+
return dependenciesToUpdate.has(depName) ? expectedDepString : depString;
48+
});
49+
50+
// create new array of prod packages with possible updates
51+
const newProdPackages = defaultProdPackages.map((depString) => {
52+
if (!depString.includes('@')) {
53+
return depString;
54+
}
55+
56+
const [depName] = depString.split('@');
57+
const expectedDepString = `${depName}@${dependenciesToUpdate.get(depName)}`;
58+
const hasDepName = dependenciesToUpdate.has(depName);
59+
update = update || (hasDepName && depString !== expectedDepString);
60+
return dependenciesToUpdate.has(depName) ? expectedDepString : depString;
61+
});
62+
63+
if (update) {
64+
await fsp.writeFile(
65+
defaultPackagesPath,
66+
JSON.stringify(
67+
{
68+
defaultDevPackages: newDevPackages,
69+
defaultProdPackages: newProdPackages,
70+
},
71+
null,
72+
2
73+
)
74+
);
75+
}
76+
};

0 commit comments

Comments
 (0)