Skip to content

Commit 56458b5

Browse files
committed
chore: wip
1 parent ccfc3a2 commit 56458b5

3 files changed

Lines changed: 79 additions & 77 deletions

File tree

resources/export.sh

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -59,11 +59,6 @@ done
5959
# echo "No arguments"
6060
#fi
6161

62-
if [ ! -n "${package}" ]; then
63-
echo "ERROR: No package specified" >&2
64-
print_help
65-
fi
66-
6762
if [ ! -n "${output}" ]; then
6863
echo "ERROR: No output (directory) specified" >&2
6964
print_help
@@ -78,8 +73,14 @@ cd ${WORK_DIR}
7873

7974
export reqsFile=${WORK_DIR}/requirements-${package}.txt
8075
export outputDir=${output}
76+
77+
export package_args=""
78+
if [ -n "${package}" ]; then
79+
package_args = "--package ${package}"
80+
fi
81+
8182
uv sync --python-preference=only-system --compile-bytecode --no-dev --frozen --no-editable
82-
uv export --package "${package}" --no-dev --frozen --no-editable --no-sources > "${reqsFile}"
83+
uv export ${package_args} --no-dev --frozen --no-editable --no-sources > "${reqsFile}"
8384

8485
# --no-sources installs workspace packages properly, not just providing a .pth file
8586
uv pip install -r "${reqsFile}" --target "${outputDir}" --compile-bytecode --link-mode=copy --exact --no-sources

src/bundling.ts

Lines changed: 10 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -84,28 +84,27 @@ export interface BundlingProps extends BundlingOptions {
8484
*/
8585
export class Bundling {
8686
public static bundle(options: BundlingProps): AssetCode {
87-
const {
88-
hashableAssetExclude = HASHABLE_DEPENDENCIES_EXCLUDE,
89-
...bundlingOptions
90-
} = options;
87+
const { hashableAssetExclude = HASHABLE_DEPENDENCIES_EXCLUDE, ...bundlingOptions } = options;
9188
const bundling = new Bundling(bundlingOptions);
9289
const buildContainerId = Bundling.containerBuilders[bundling.containerBuilderKey];
93-
if (!buildContainerId) {
90+
if (!buildContainerId && !bundling.skip) {
9491
throw new Error("Bundling container not found");
9592
}
9693

9794
const hostFunctionOutputDir = `${process.env.CDK_OUTDIR}/${bundling.containerBuilderKey}/${bundling.functionOutDir}`;
98-
// mkdirSync(hostFunctionOutputDir, { recursive: true });
95+
if (bundling.skip) {
96+
mkdirSync(hostFunctionOutputDir, { recursive: true });
97+
}
9998

10099
return Code.fromCustomCommand(
101100
hostFunctionOutputDir,
102101
[
102+
...(bundling.skip ? ["echo", "Skipping bundling"] : []),
103103
"docker",
104104
"exec",
105105
bundling.containerBuilderKey ?? "", // Key is only unset in 'skip' mode
106106
"/root/export.sh",
107-
"--package",
108-
options.workspacePackage ?? "uh-oh", // TODO - add support for root package
107+
...(options.workspacePackage ? ["--package", options.workspacePackage] : []),
109108
"--output",
110109
`/uvbuild/${bundling.functionOutDir}/`,
111110
],
@@ -125,6 +124,7 @@ export class Bundling {
125124
public readonly securityOpt?: string | undefined;
126125
public readonly network?: string | undefined;
127126
public readonly bundlingFileAccess?: BundlingFileAccess | undefined;
127+
public readonly skip: boolean;
128128

129129
/**
130130
* Unique key for the container for this bundling configuration.
@@ -171,6 +171,7 @@ export class Bundling {
171171
this.securityOpt = props.securityOpt;
172172
this.network = props.network;
173173
this.bundlingFileAccess = props.bundlingFileAccess;
174+
this.skip = !!props.skip;
174175

175176
// If skip is true then don't call DockerImage.fromBuild as that calls dockerExec.
176177
// Return a dummy object of the right type as it's not going to be used.
@@ -189,7 +190,7 @@ export class Bundling {
189190

190191
// Create a hash of the props to use as a key for the build container cache
191192
this.containerBuilderKey = `uv-bundling-${hash(hashableProperties)}`;
192-
this.functionOutDir = props.workspacePackage ?? "";
193+
this.functionOutDir = props.workspacePackage ?? "$$uv_root";
193194
const existingBuilder = Bundling.containerBuilders[this.containerBuilderKey];
194195
if (!existingBuilder) {
195196
const buildImage = DockerImage.fromBuild(path.resolve(__dirname, '..', 'resources'), {

test/function.test.ts

Lines changed: 62 additions & 62 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,8 @@ const execAsync = promisify(exec);
1212

1313
const resourcesPath = path.resolve(__dirname, 'resources');
1414

15+
const TEST_TIMEOUT = Number(process.env.TEST_TIMEOUT ?? "999999");
16+
1517
/**
1618
* Determine the optimal Lambda Function architecture based on the Docker host's CPU
1719
* architecture. This allows GHA runners to work without slow QEMU Arm emulation.
@@ -56,43 +58,43 @@ beforeEach(async () => {
5658
process.env.CDK_OUTDIR = await fs.mkdtemp(
5759
path.join(os.tmpdir(), 'uv-python-lambda-test-'),
5860
);
59-
}, 999999);
61+
}, TEST_TIMEOUT);
6062

6163
afterEach(async () => {
6264
if (process.env.CDK_OUTDIR) {
6365
await fs.rm(process.env.CDK_OUTDIR, { recursive: true });
6466
}
6567
process.env = OLD_ENV;
66-
}, 999999);
68+
}, TEST_TIMEOUT);
6769

68-
// test('Create a function from basic_app', async () => {
69-
// const { app, stack } = await createStack();
70+
test('Create a function from basic_app', async () => {
71+
const { app, stack } = await createStack();
7072

71-
// new PythonFunction(stack, 'basic_app', {
72-
// rootDir: path.join(resourcesPath, 'basic_app'),
73-
// index: 'handler.py',
74-
// handler: 'lambda_handler',
75-
// runtime: Runtime.PYTHON_3_12,
76-
// architecture: await getDockerHostArch(),
77-
// });
73+
new PythonFunction(stack, 'basic_app', {
74+
rootDir: path.join(resourcesPath, 'basic_app'),
75+
index: 'handler.py',
76+
handler: 'lambda_handler',
77+
runtime: Runtime.PYTHON_3_12,
78+
architecture: await getDockerHostArch(),
79+
});
7880

79-
// const template = Template.fromStack(stack);
81+
const template = Template.fromStack(stack);
8082

81-
// template.hasResourceProperties('AWS::Lambda::Function', {
82-
// Handler: 'handler.lambda_handler',
83-
// Runtime: 'python3.12',
84-
// Code: {
85-
// S3Bucket: Match.anyValue(),
86-
// S3Key: Match.anyValue(),
87-
// },
88-
// });
89-
// const functions = Object.values(
90-
// template.findResources('AWS::Lambda::Function'),
91-
// );
92-
// expect(functions).toHaveLength(1);
93-
// const contents = await getFunctionAssetContents(functions[0], app);
94-
// expect(contents).toContain('handler.py');
95-
// });
83+
template.hasResourceProperties('AWS::Lambda::Function', {
84+
Handler: 'handler.lambda_handler',
85+
Runtime: 'python3.12',
86+
Code: {
87+
S3Bucket: Match.anyValue(),
88+
S3Key: Match.anyValue(),
89+
},
90+
});
91+
const functions = Object.values(
92+
template.findResources('AWS::Lambda::Function'),
93+
);
94+
expect(functions).toHaveLength(1);
95+
const contents = await getFunctionAssetContents(functions[0], app);
96+
expect(contents).toContain('handler.py');
97+
});
9698

9799
// test('Create a function from basic_app with no .py index extension', async () => {
98100
// const { stack } = await createStack();
@@ -139,45 +141,43 @@ afterEach(async () => {
139141
// bundlingSpy.mockRestore();
140142
// });
141143

142-
test('Create a function with workspaces_app', async () => {
143-
const { app, stack } = await createStack('wstest');
144+
// test('Create a function with workspaces_app', async () => {
145+
// const { app, stack } = await createStack('wstest');
144146

145-
new PythonFunction(stack, 'workspaces_app', {
146-
rootDir: path.join(resourcesPath, 'workspaces_app'),
147-
workspacePackage: 'app',
148-
index: 'app_handler.py',
149-
handler: 'handle_event',
150-
runtime: Runtime.PYTHON_3_10,
151-
architecture: await getDockerHostArch(),
152-
});
147+
// new PythonFunction(stack, 'workspaces_app', {
148+
// rootDir: path.join(resourcesPath, 'workspaces_app'),
149+
// workspacePackage: 'app',
150+
// index: 'app_handler.py',
151+
// handler: 'handle_event',
152+
// runtime: Runtime.PYTHON_3_10,
153+
// architecture: await getDockerHostArch(),
154+
// });
153155

154-
const template = Template.fromStack(stack);
156+
// const template = Template.fromStack(stack);
155157

156-
template.hasResourceProperties('AWS::Lambda::Function', {
157-
Handler: 'app_handler.handle_event',
158-
Runtime: 'python3.10',
159-
Code: {
160-
S3Bucket: Match.anyValue(),
161-
S3Key: Match.anyValue(),
162-
},
163-
});
158+
// template.hasResourceProperties('AWS::Lambda::Function', {
159+
// Handler: 'app_handler.handle_event',
160+
// Runtime: 'python3.10',
161+
// Code: {
162+
// S3Bucket: Match.anyValue(),
163+
// S3Key: Match.anyValue(),
164+
// },
165+
// });
164166

165-
const functions = Object.values(
166-
template.findResources('AWS::Lambda::Function'),
167-
);
168-
expect(functions).toHaveLength(1);
169-
const contents = await getFunctionAssetContents(functions[0], app);
170-
for (const entry of [
171-
'app',
172-
'common',
173-
'pydantic',
174-
'httpx',
175-
'_common.pth',
176-
'app_handler.py',
177-
]) {
178-
expect(contents).toContain(entry);
179-
}
180-
}, 999999);
167+
// const functions = Object.values(
168+
// template.findResources('AWS::Lambda::Function'),
169+
// );
170+
// expect(functions).toHaveLength(1);
171+
// const contents = await getFunctionAssetContents(functions[0], app);
172+
// for (const entry of [
173+
// 'common',
174+
// 'pydantic',
175+
// 'httpx',
176+
// 'app_handler.py',
177+
// ]) {
178+
// expect(contents).toContain(entry);
179+
// }
180+
// }, TEST_TIMEOUT);
181181

182182
// biome-ignore lint/suspicious/noExplicitAny: <explanation>
183183
async function getFunctionAssetContents(functionResource: any, app: App) {

0 commit comments

Comments
 (0)