-
Notifications
You must be signed in to change notification settings - Fork 824
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: Separate prod and dev lambda function builds (#6494)
- Loading branch information
1 parent
209c4ff
commit 2977c6a
Showing
53 changed files
with
740 additions
and
446 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
74 changes: 74 additions & 0 deletions
74
...egory-function/src/__tests__/provider-utils/awscloudformation/utils/buildFunction.test.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,74 @@ | ||
import { $TSContext, pathManager } from 'amplify-cli-core'; | ||
import { BuildType, FunctionRuntimeLifecycleManager } from 'amplify-function-plugin-interface'; | ||
import { buildFunction } from '../../../..'; | ||
|
||
jest.mock('amplify-cli-core'); | ||
|
||
const pathManager_mock = pathManager as jest.Mocked<typeof pathManager>; | ||
pathManager_mock.getBackendDirPath.mockReturnValue('mockpath'); | ||
describe('build function', () => { | ||
beforeEach(() => { | ||
jest.clearAllMocks(); | ||
}); | ||
const runtimePlugin_stub = ({ | ||
checkDependencies: jest.fn().mockResolvedValue({ hasRequiredDependencies: true }), | ||
build: jest.fn().mockResolvedValue({ rebuilt: true }), | ||
} as unknown) as jest.Mocked<FunctionRuntimeLifecycleManager>; | ||
|
||
const context_stub = ({ | ||
amplify: { | ||
readBreadcrumbs: jest.fn().mockReturnValue({ pluginId: 'testPluginId' }), | ||
loadRuntimePlugin: jest.fn().mockResolvedValue(runtimePlugin_stub), | ||
updateamplifyMetaAfterBuild: jest.fn(), | ||
}, | ||
} as unknown) as jest.Mocked<$TSContext>; | ||
it('delegates dependency checks to the runtime manager before building', async () => { | ||
let depCheck = false; | ||
runtimePlugin_stub.checkDependencies.mockImplementationOnce(async () => { | ||
depCheck = true; | ||
return { | ||
hasRequiredDependencies: true, | ||
}; | ||
}); | ||
|
||
runtimePlugin_stub.build.mockImplementationOnce(async () => { | ||
if (!depCheck) { | ||
throw new Error('Dep check not called before build'); | ||
} | ||
return { | ||
rebuilt: true, | ||
}; | ||
}); | ||
|
||
await buildFunction(context_stub, { resourceName: 'testFunc' }); | ||
|
||
expect(runtimePlugin_stub.checkDependencies.mock.calls.length).toBe(1); | ||
expect(runtimePlugin_stub.build.mock.calls.length).toBe(1); | ||
}); | ||
|
||
it('updates amplify meta after prod', async () => { | ||
await buildFunction(context_stub, { resourceName: 'testFunc' }); | ||
|
||
expect((context_stub.amplify.updateamplifyMetaAfterBuild as jest.Mock).mock.calls[0]).toEqual([ | ||
{ category: 'function', resourceName: 'testFunc' }, | ||
'PROD', | ||
]); | ||
}); | ||
|
||
it('updates amplify meta after dev build', async () => { | ||
await buildFunction(context_stub, { resourceName: 'testFunc', buildType: BuildType.DEV }); | ||
|
||
expect((context_stub.amplify.updateamplifyMetaAfterBuild as jest.Mock).mock.calls[0]).toEqual([ | ||
{ category: 'function', resourceName: 'testFunc' }, | ||
'DEV', | ||
]); | ||
}); | ||
|
||
it('doesnt update amplify meta if function not rebuilt', async () => { | ||
runtimePlugin_stub.build.mockResolvedValueOnce({ rebuilt: false }); | ||
|
||
await buildFunction(context_stub, { resourceName: 'testFunc' }); | ||
|
||
expect((context_stub.amplify.updateamplifyMetaAfterBuild as jest.Mock).mock.calls.length).toBe(0); | ||
}); | ||
}); |
53 changes: 53 additions & 0 deletions
53
...ory-function/src/__tests__/provider-utils/awscloudformation/utils/packageFunction.test.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,53 @@ | ||
import { getRuntimeManager } from '../../../../provider-utils/awscloudformation/utils/functionPluginLoader'; | ||
import { $TSContext, pathManager } from 'amplify-cli-core'; | ||
import { FunctionRuntimeLifecycleManager } from 'amplify-function-plugin-interface'; | ||
import { packageFunction } from '../../../../provider-utils/awscloudformation/utils/packageFunction'; | ||
import { PackageRequestMeta } from '../../../../provider-utils/awscloudformation/types/packaging-types'; | ||
|
||
jest.mock('fs-extra'); | ||
jest.mock('amplify-cli-core'); | ||
jest.mock('../../../../provider-utils/awscloudformation/utils/functionPluginLoader'); | ||
|
||
const context_stub = { | ||
amplify: { | ||
getEnvInfo: jest.fn().mockReturnValue('mockEnv'), | ||
updateAmplifyMetaAfterPackage: jest.fn(), | ||
}, | ||
}; | ||
|
||
const pathManager_mock = pathManager as jest.Mocked<typeof pathManager>; | ||
const getRuntimeManager_mock = getRuntimeManager as jest.MockedFunction<typeof getRuntimeManager>; | ||
|
||
pathManager_mock.getBackendDirPath.mockReturnValue('backend/dir/path'); | ||
|
||
const runtimeManager_mock = { | ||
package: jest.fn().mockResolvedValue({ | ||
packageHash: 'testpackagehash', | ||
}), | ||
}; | ||
getRuntimeManager_mock.mockResolvedValue(runtimeManager_mock as any); | ||
|
||
const resourceRequest: PackageRequestMeta = { | ||
category: 'testcategory', | ||
resourceName: 'testResourceName', | ||
service: 'testservice', | ||
build: true, | ||
lastPackageTimeStamp: 'lastpackagetime', | ||
lastBuildTimeStamp: 'lastbuildtime', | ||
distZipFilename: 'testzipfile', | ||
skipHashing: false, | ||
}; | ||
|
||
describe('package function', () => { | ||
it('delegates packaging to the runtime manager', async () => { | ||
await packageFunction((context_stub as unknown) as $TSContext, resourceRequest); | ||
|
||
expect(runtimeManager_mock.package.mock.calls[0][0].srcRoot).toEqual('backend/dir/path/testcategory/testResourceName'); | ||
}); | ||
|
||
it('updates amplify meta after packaging', async () => { | ||
await packageFunction((context_stub as unknown) as $TSContext, resourceRequest); | ||
|
||
expect(context_stub.amplify.updateAmplifyMetaAfterPackage.mock.calls[0][0]).toEqual(resourceRequest); | ||
}); | ||
}); |
53 changes: 39 additions & 14 deletions
53
packages/amplify-category-function/src/commands/function/build.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,18 +1,43 @@ | ||
import { category as categoryName } from '../../constants'; | ||
import { $TSContext } from 'amplify-cli-core'; | ||
import { ServiceName } from '../..'; | ||
import { category } from '../../constants'; | ||
import { PackageRequestMeta } from '../../provider-utils/awscloudformation/types/packaging-types'; | ||
import { buildFunction } from '../../provider-utils/awscloudformation/utils/buildFunction'; | ||
import { packageResource } from '../../provider-utils/awscloudformation/utils/package'; | ||
|
||
const subcommand = 'build'; | ||
export const name = 'build'; | ||
|
||
module.exports = { | ||
name: subcommand, | ||
run: async context => { | ||
const { amplify, parameters } = context; | ||
const resourceName = parameters.first; | ||
/** | ||
* To maintain existing behavior, this function builds and then packages lambda functions | ||
*/ | ||
export const run = async (context: $TSContext) => { | ||
const resourceName = context?.input?.subCommands?.[0]; | ||
const confirmContinue = | ||
!!resourceName || | ||
context.input?.options?.yes || | ||
(await context.amplify.confirmPrompt( | ||
'This will build all functions and layers in your project. Are you sure you want to continue?', | ||
false, | ||
)); | ||
if (!confirmContinue) { | ||
return; | ||
} | ||
try { | ||
const resourcesToBuild = (await getSelectedResources(context, resourceName)) | ||
.filter(resource => resource.build) | ||
.filter(resource => resource.service === ServiceName.LambdaFunction); | ||
for await (const resource of resourcesToBuild) { | ||
resource.lastBuildTimeStamp = await buildFunction(context, resource); | ||
await packageResource(context, resource); | ||
} | ||
} catch (err) { | ||
context.print.info(err.stack); | ||
context.print.error('There was an error building the function resources'); | ||
context.usageData.emitError(err); | ||
process.exitCode = 1; | ||
} | ||
}; | ||
|
||
return amplify.buildResources(context, categoryName, resourceName).catch(err => { | ||
context.print.info(err.stack); | ||
context.print.error('There was an error building the function resources'); | ||
context.usageData.emitError(err); | ||
process.exitCode = 1; | ||
}); | ||
}, | ||
const getSelectedResources = async (context: $TSContext, resourceName?: string) => { | ||
return (await context.amplify.getResourceStatus(category, resourceName)).allResources as PackageRequestMeta[]; | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
12 changes: 12 additions & 0 deletions
12
...s/amplify-category-function/src/provider-utils/awscloudformation/types/packaging-types.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
import { $TSContext, ResourceTuple } from 'amplify-cli-core'; | ||
|
||
export type PackageRequestMeta = ResourceTuple & { | ||
service: string; | ||
build: boolean; | ||
distZipFilename: string; | ||
lastBuildTimeStamp?: string; | ||
lastPackageTimeStamp?: string; | ||
skipHashing: boolean; | ||
}; | ||
|
||
export type Packager = (context: $TSContext, resource: PackageRequestMeta) => Promise<{ zipFilename: string; zipFilePath: string }>; |
Oops, something went wrong.