Skip to content

feat: build and package AWS::Serverless::WebFunction with local code - #9340

Open
seshubaws wants to merge 21 commits into
aws:developfrom
seshubaws:seshub/webfunction-build-package
Open

seshubaws wants to merge 21 commits into
aws:developfrom
seshubaws:seshub/webfunction-build-package

Conversation

@seshubaws

@seshubaws seshubaws commented Oct 14, 2026 •

Copy link
Copy Markdown
Contributor

Which issue(s) does this change fix?

N/A

Why is this change necessary?

AWS::Serverless::WebFunction (aws-sam-translator 1.115.0) only worked with code that was already in S3. sam build skipped it, and sam package/sam deploy left a local CodeUri unchanged.

Web Function code also can't simply go to the managed bucket. A Web Function reads its code from S3 with the lambda.amazonaws.com service principal for as long as a revision exists, not just at deploy time. If the object, or the pinned version, is deleted, the revision fails permanently. The managed bucket is shared across the account and lacks a Lambda read policy. Users can also empty or delete it today without affecting Event Functions, and sam delete removes artifacts before the stack.

How does it address the issue?

sam build

  • WebFunction (in samcli/lib/providers/provider.py) models a buildable Web Function: runtime, code, entry point, metadata and build info. Its package type is always Zip, and it builds for x86_64.
  • SamWebFunctionProvider extracts Web Functions from the stacks, including nested stacks, and skips ones whose code is already in S3. SamFunctionProvider is unchanged, so sam local commands never see Web Functions.
  • The build accepts BuildableFunction (Function or WebFunction):
    • get_build_entry_point() gives the builders a Lambda function's handler, or a Web Function's EntryPoint (default index.js).
    • The build graph skips the Lambda-only fields (imageuri) for Web Functions.
  • BuildContext collects Web Functions for full builds, single-resource builds (sam build MyWebFn), --exclude, and the "not found" message.
  • Metadata.BuildMethod is supported. The built template points the WebFunction CodeUri at the build output.
  • With BuildMethod: esbuild, the built template's EntryPoint points at the bundled file, for example src/server.ts becomes server.js, the same way a Lambda function's handler is updated. esbuild gets the EntryPoint file path as is (not split on the first . like a Lambda handler), so paths like ./src/v1.2/server.config.ts work and bundle to server.config.js. Source maps set NODE_OPTIONS in the Web Function's EnvironmentVariables.
  • Web Functions can't use layers, so their dependencies always stay in the build artifact. That's true even when sam sync separates function dependencies for the auto dependency layer, which only covers Lambda functions.

Packaging

  • WebFunction CodeUri is a packageable local path (ServerlessWebFunctionResource), uploaded through a new Destination.WEB_FUNCTION_S3. That destination falls back to the normal S3 uploader when no separate bucket is set.

Per-stack code bucket

  • When it's used: sam deploy (--resolve-s3 or guided) or sam sync is using the managed bucket, and the template, including nested stacks, has a WebFunction with local code.
  • What SAM CLI does: it gets or creates a <stack>-<hash>-WebFunctionCode stack (samcli/lib/bootstrap/web_function_code_bucket.py) and uploads only the Web Function code there.
  • The bucket:
    • versioned, SSE-S3, public access blocked, insecure transport denied
    • a policy letting lambda.amazonaws.com call s3:GetObject/s3:GetObjectVersion, scoped with aws:SourceAccount and aws:SourceArn matching …:web-function/*/revision/*
  • Protection against accidental deletion: the code bucket stack exports its bucket name, and packaging writes the WebFunction CodeUri as {Bucket: !ImportValue <export>, Key: <key>} (plus Version, if any). CloudFormation then refuses to delete the code bucket stack while any stack, including nested stacks, reads code from it.
  • Everything else is unchanged: other artifacts and the packaged template still go to the managed bucket, and the managed stack and its bucket are not modified.
  • sam delete deletes the other artifacts and the stack as before, and only after the stack is deleted empties the code bucket (all versions) and deletes the code bucket stack.
    • ServerlessWebFunctionResource.delete is a no-op, so code is never deleted while revisions might still read it.
    • Stacks without the ManagedStackSource: AwsSamCli tag are left alone.
    • Only a missing code bucket stack is skipped. Other errors (access, throttling, credentials) are raised, so the bucket isn't left behind silently.
    • If an earlier sam delete left the code bucket stack behind after deleting the stack, running sam delete again deletes it.
    • If a WebFunction is retained (DeletionPolicy: Retain or RetainExceptOnCreate, or in retain_resources), its revisions keep reading code from the bucket. So sam delete keeps the code bucket stack, turns on its termination protection, and tells the user how to delete it later. sam delete never deletes a code bucket stack that has termination protection on, including on a re-run.

sam package --resolve-s3

  • sam package has no stack name, so it can't create a per-stack code bucket, and Web Function code can't go to the shared managed bucket. When the template, including nested stacks, has a WebFunction with local code, sam package --resolve-s3 fails before creating or using the managed bucket. The error says to use sam deploy (per-stack code bucket) or --s3-bucket with a versioned bucket whose policy lets Lambda read the code.
  • sam package --s3-bucket works as below.

--s3-bucket

  • With an explicit bucket, Web Function code goes to that bucket. Before uploading, packaging checks it.
  • Fails when the deploy is certain to fail. All such problems are listed in one error, and nothing is uploaded:
    • the bucket isn't versioned (unversioned or suspended)
    • --kms-key-id is an AWS managed key
  • Warns when the check is a heuristic or couldn't run:
    • the bucket policy has no Allow statement letting lambda.amazonaws.com read the uploaded objects (prefix and partition are considered; conditions aren't evaluated)
    • a customer managed key whose policy has no matching kms:Decrypt statement
    • the bucket's versioning, its policy, or the key couldn't be read
  • Warnings go to stderr. An unexpected error while checking never fails packaging.

Language extensions (Fn::ForEach)

  • Not supported for Web Functions yet. When SAM CLI expands language extensions locally (--language-extensions), and a Fn::ForEach generates an AWS::Serverless::WebFunction with local code, sam build, sam package, sam deploy and sam sync fail with WebFunctionInForEachError. This includes nested Fn::ForEach blocks and nested stacks.
  • Why: a Fn::ForEach whose items have different code puts each item's code location into generated Mappings. The location imports the code bucket's name (Fn::ImportValue), and CloudFormation doesn't allow intrinsics in Mappings.
  • Web Functions outside Fn::ForEach, and templates SAM CLI doesn't expand locally, are unaffected.

sam sync --watch

  • Web Function code isn't watched, because every code change creates a new revision. Web Functions aren't in the code trigger list (CodeTriggerFactory.GENERATOR_MAPPING), so a code change never triggers a sync by itself. The code is deployed with the next infrastructure sync, for example when the template changes.
  • When the template, including nested stacks, has a WebFunction with local code, sam sync --watch prints a note at startup: "Web Function code isn't watched; code changes are deployed with the next infrastructure sync."

Nested stacks

  • Build and package handle WebFunctions in child templates. Their code goes to the root stack's code bucket.

What side effects does this change have?

  • A stack with WebFunctions that deploys through the managed bucket gets one extra stack and bucket in the account, which sam delete removes.
  • Packaging a template with WebFunctions to an explicit --s3-bucket makes up to two extra S3 calls, plus two KMS calls with --kms-key-id.
  • --kms-key-id isn't applied to the code bucket uploads, which use the bucket's SSE-S3 default.
  • If a template's only S3 artifacts are WebFunction code, sam delete prints the existing "Cannot resolve s3 bucket information" warning and leaves the packaged template file in the managed bucket, as it does today for templates with no other artifacts.
  • Not included:
    • A sam sync flow for Web Functions. sam sync deploys them with an infrastructure sync, and sam sync --watch doesn't watch their code (see above).
    • sam local support.
    • Web Functions with local code inside Fn::ForEach (rejected, see above).
    • A CDK-style code bucket inside the deployed stack (staged through the managed bucket and copied by a custom resource during deployment), which would let sam package --resolve-s3 work for Web Functions. It would add a helper Lambda function and bucket-cleanup resources to every stack.

Testing

  • Unit tests for:
    • WebFunction, SamWebFunctionProvider, the BuildContext collection and the build graph entry point
    • the build template update
    • packaging and uploader routing
    • the code bucket stack: name, template, get or create, emptying and deletion
    • PackageContext
    • the sam delete order (the code bucket is deleted after the stack)
    • the --s3-bucket checks
  • pytest tests/unit (excluding cfn_language_extensions): 94.07% coverage. One existing test, test_template.py::Test_update_sam_mappings_relative_paths::test_updates_imageuri_when_pointing_to_local_archive, fails locally both with and without this change. It writes ../../my-image.tar.gz relative to the checkout, which isn't writable in my environment.
  • black, ruff and mypy pass.
  • End to end in us-east-2, with a WebFunction with a local CodeUri and an npm dependency:
    • sam build installed the dependency.
    • sam deploy --resolve-s3 created the …-WebFunctionCode stack and uploaded the code there. The deployed template's CodeUri points at the code bucket, and the endpoint returned 200 from the dependency-using code. The managed stack's LastUpdatedTime didn't change.
    • The deployed template's CodeUri uses Fn::ImportValue: <stack>-<hash>-WebFunctionCode-Bucket, and list-imports shows the app stack importing it.
    • aws cloudformation delete-stack on the code bucket stack was refused ("Delete canceled. Cannot delete export … as it is in use by …"). The stack stayed CREATE_COMPLETE, and the endpoint kept returning 200.
    • sam delete --no-prompts deleted the stack, then the code bucket stack. The bucket and the export no longer exist.
    • After deleting only the app stack through CloudFormation, sam delete removed the leftover code bucket stack.
    • With DeletionPolicy: Retain on the WebFunction: sam delete kept the code bucket stack with termination protection on, a second sam delete kept it, a direct aws cloudformation delete-stack was blocked, and the retained function kept returning 200.
    • The same with a nested AWS::Serverless::Application whose child template has the WebFunction: built, deployed, 200 from the child endpoint, deleted in order.
  • With --language-extensions, sam build and sam package on a Fn::ForEach that generates Web Functions failed with the new error. A template with a Web Function outside Fn::ForEach, next to a Fn::ForEach of SNS topics, built normally.
  • sam sync (auto dependency layer on) on a template with a WebFunction and a Node.js Lambda function: the WebFunction artifact kept node_modules while the Lambda function's dependencies went to the layer. The synced WebFunction returned 200 using its dependency, and sam delete cleaned up.
  • esbuild: a WebFunction with EntryPoint: src/server.ts built to server.js with EntryPoint: server.js in the built template, deployed, and returned 200 using its bundled dependency. EntryPoint: ./src/v1.2/server.config.ts built to server.config.js (it failed with "entry point ... does not exist" before the fix).
  • sam sync --watch on the WebFunction project printed the note before the sync confirmation prompt.
  • sam package --resolve-s3 on a template with a local-code WebFunction, and on a nested template whose child has one, failed with the new error, without creating any AWS resources.
  • --s3-bucket checks with sam package against new buckets:
    • Unversioned with no policy: failed with the versioning error after the policy warning, and nothing was uploaded.
    • Versioned with no policy: the policy warning, then packaged.
    • Versioned with a Lambda read policy: no warnings.
    • Versioned with --kms-key-id alias/aws/s3: failed with the AWS managed key error.
    • With the template written to stdout, the warnings go to stderr and the template stays valid.

Mandatory Checklist

PRs will only be reviewed after checklist is complete

By submitting this pull request, I confirm that my contribution is made under the terms of the Apache 2.0 license.

sam build:
- SamFunctionProvider extracts AWS::Serverless::WebFunction resources when
  include_web_functions is set, which only BuildContext does, so sam local
  commands don't treat Web Functions as invokable functions. EntryPoint
  (default index.js) takes the handler's place.
- The built template points the WebFunction CodeUri at the build output.

sam package / sam deploy:
- WebFunction CodeUri is a packageable local path, zipped and uploaded like
  a Function's CodeUri.

Managed bucket:
- The managed stack's bucket policy lets lambda.amazonaws.com read objects
  (s3:GetObject, s3:GetObjectVersion) for this account's Web Function
  revisions, which Web Functions need to read their code.
- sam deploy and sam sync update an existing managed stack that lacks the
  statement when the template has a WebFunction.
@seshubaws
seshubaws requested a review from a team as a code owner October 14, 2026 19:00
@seshubaws seshubaws changed the title feat: build and package AWS::Serverless::WebFunction with local code feat: AWS::Serverless::WebFunction support Oct 14, 2026
@github-actions github-actions Bot added area/deploy sam deploy command area/build sam build command area/sync sam sync command pr/internal labels Oct 14, 2026
…ed stacks

- When the template, including nested stacks, has an
  AWS::Serverless::WebFunction with local code, packaging warns if the
  target bucket isn't versioned, if its policy doesn't let
  lambda.amazonaws.com read the uploaded code (s3:GetObject,
  s3:GetObjectVersion), or if --kms-key-id is an AWS managed key or a key
  whose policy doesn't let Lambda call kms:Decrypt. The checks are
  warnings and never fail packaging.
- The managed stack upgrade looks for Web Functions in nested stacks too,
  and only for Web Functions with local code.
@seshubaws seshubaws changed the title feat: AWS::Serverless::WebFunction support feat: build and package AWS::Serverless::WebFunction with local code Oct 14, 2026

@aws-sam-tooling-bot aws-sam-tooling-bot Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review Results

Reviewed: 7bf8efb..19d25cb
Files: 21
Comments: 2

Comment thread samcli/commands/package/package_context.py Outdated
Comment thread samcli/commands/deploy/command.py Outdated
Comment thread samcli/lib/providers/sam_function_provider.py Outdated
Comment thread samcli/lib/providers/sam_function_provider.py Outdated
Comment thread samcli/commands/deploy/command.py Outdated
Comment thread samcli/commands/package/package_context.py Outdated
Comment thread samcli/commands/package/package_context.py Outdated
import click
from botocore.exceptions import ClientError

from samcli.lib.providers.provider import Stack

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is the circular import error mentioned in the other files because you're importing Stack here?

Here you're only using Stack for type checking, so the best way to just solve this so you don't have to deal with circular imports in the other files is to use if TYPE_CHECKING before this import

Like

from typing import TYPE_CHECKING
if TYPE_CHECKING: # pragma: no cover
from samcli.lib.providers.provider import ResourceIdentifier

Suggested change
from samcli.lib.providers.provider import Stack
from typing import TYPE_CHECKING
if TYPE_CHECKING: # pragma: no cover
from samcli.lib.providers.provider import Stack

…naged bucket

Web Functions read their code from S3 for as long as a revision exists, so
the code no longer goes to the shared managed bucket, which users can empty
or delete without affecting Event Functions. The managed stack and its
bucket are unchanged.

- When sam deploy (--resolve-s3 or guided) or sam sync uses the managed
  bucket and the template, including nested stacks, has an
  AWS::Serverless::WebFunction with local code, SAM CLI gets or creates a
  <stack>-<hash>-WebFunctionCode stack with a versioned, SSE-S3 bucket whose
  policy lets lambda.amazonaws.com read the code for this account's Web
  Function revisions. Only Web Function code is uploaded there.
- sam delete deletes that stack's artifacts other than Web Function code as
  before, deletes the stack, and only then empties and deletes the code
  bucket stack.
- With --s3-bucket, Web Function code goes to that bucket as before, with
  the access warnings.
- Removes the managed stack bucket policy statement and upgrade check.

@aws-sam-tooling-bot aws-sam-tooling-bot Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review Results

Reviewed: 7bf8efb..5e105bf
Files: 24
Comments: 2

Comment thread samcli/commands/deploy/command.py Outdated
"Runtime": resource_properties.get("Runtime"),
"Timeout": resource_properties.get("Timeout"),
"FunctionName": resource_properties.get("FunctionName", name),
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[BUG] Web Function Architectures is dropped, so arm64 Web Functions are built for x86_64
_convert_sam_web_function_resource passes only an allow-listed build_properties dict to _build_function_configuration. That function reads resource_properties.get("Architectures"), which here is always None, so Function.architecture falls back to X86_64.

ApplicationBuilder passes function.architecture into the build definition, so a Web Function with Architectures: [arm64] gets an x86_64 build image and native dependencies, and fails at runtime. The wrong architecture is also written to build.toml. Passing Architectures through fixes it.

Suggested change
}
"FunctionName": resource_properties.get("FunctionName", name),
"Architectures": resource_properties.get("Architectures"),

Five other candidates were checked by verifiers and scored 7, below the posting threshold of 8, so they're left out:

  • the code bucket is deleted even when a WebFunction has DeletionPolicy: Retain
  • the delete waiter and delete_objects errors aren't handled
  • every describe_stacks error is treated as "no stack"
  • esbuild entry points come out wrong for file-path EntryPoint values like ./server.js
  • the built template keeps the source EntryPoint for esbuild Web Functions

The PR description doesn't match the code. It says the shared managed bucket's policy gets an AllowLambdaWebFunctionCodeAccess statement and existing managed stacks are upgraded. The diff instead creates a separate code bucket stack for each deployed stack, and sam delete empties and deletes it. I reviewed the code as written.

Both earlier findings were dismissed, so neither was posted again.

…while in use

The code bucket stack exports its bucket name, and packaging writes a Web
Function's CodeUri as {Bucket: !ImportValue <export>, Key: <key>} (keeping
the Version, if any) when the code goes to that bucket. CloudFormation then
refuses to delete the code bucket stack while a stack that reads code from
it exists. sam delete is unaffected: it deletes the importing stack first.
sam package has no stack to create a Web Function code bucket for, and the
code can't go to the shared managed bucket. When the template, including
nested stacks, has an AWS::Serverless::WebFunction with local code,
sam package --resolve-s3 now fails before creating or using the managed
bucket, and points to sam deploy or --s3-bucket.

@aws-sam-tooling-bot aws-sam-tooling-bot Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review Results

Reviewed: 7bf8efb..21bf368
Files: 27
Comments: 1

Comment thread samcli/lib/package/packageable_resources.py
The warnings went to stdout, which corrupted --output json and packaged
templates that sam package writes to stdout.
… Web Function code

Lambda always rejects a Web Function revision whose code is in an
unversioned bucket or encrypted with an AWS managed KMS key, so packaging
now fails before uploading in those cases (WebFunctionCodeBucketError),
listing every such problem. Bucket and key policy problems and checks that
couldn't run stay warnings.

@aws-sam-tooling-bot aws-sam-tooling-bot Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review Results

Reviewed: 7bf8efb..f41fde5
Files: 27
Comments: 2

Comment thread samcli/commands/build/build_context.py Outdated
Comment thread samcli/lib/providers/sam_function_provider.py Outdated
….update

The attribute is always set in __init__, so the getattr fallback isn't needed.

@aws-sam-tooling-bot aws-sam-tooling-bot Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review Results

Reviewed: 7bf8efb..654be6e
Files: 27
Comments: 1

Comment thread samcli/lib/package/packageable_resources.py
…ilds

Web Functions were built as Function objects whose handler held the entry
point, with an include_web_functions flag on SamFunctionProvider to keep
them out of sam local.

- WebFunction (provider.py) holds only what a Web Function has: runtime,
  code, entry point, metadata and build info. Its package type is always
  Zip and it builds for x86_64.
- SamWebFunctionProvider extracts them from the stacks; SamFunctionProvider
  is back to Lambda functions only, so sam local can't see Web Functions.
- The build accepts BuildableFunction (Function or WebFunction).
  get_build_entry_point returns a function's handler or a Web Function's
  entry point for the builders; only the build graph reads Lambda-only
  fields, and it skips them for Web Functions.
- BuildContext collects Web Functions from SamWebFunctionProvider for all
  builds, single-resource builds and the not-found message.
Language extensions aren't supported for Web Functions yet: a Fn::ForEach
whose items have different code would put the Web Function's code location,
which can import the code bucket's name, into generated Mappings, which
CloudFormation doesn't allow. When SAM CLI expands language extensions
locally and a Fn::ForEach (including nested ones and ones in nested stacks)
generates an AWS::Serverless::WebFunction with local code, sam build,
sam package, sam deploy and sam sync now fail with
WebFunctionInForEachError. Web Functions outside Fn::ForEach, and templates
SAM CLI doesn't expand, are unaffected.
…pted stack name

In guided mode the deployed stack is the one from the Stack Name prompt, not
--stack-name. Using --stack-name left the code bucket off when it wasn't set,
sending Web Function code to the managed bucket, and named the bucket stack
after the wrong stack when it differed, so sam delete couldn't find it.

@aws-sam-tooling-bot aws-sam-tooling-bot Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review Results

Reviewed: 7bf8efb..0d6d12a
Files: 29
Comments: 1

Comment thread samcli/lib/package/packageable_resources.py
upload_local_artifacts returns an s3:// CodeUri unchanged, and the export
then rewrote it to import the code bucket, pointing it at an object that was
never uploaded there. Only rewrite CodeUri for code this export uploaded.

@aws-sam-tooling-bot aws-sam-tooling-bot Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review Results

Reviewed: 7bf8efb..51d617e
Files: 29
Comments: 1

Comment thread samcli/lib/bootstrap/web_function_code_bucket.py
Every Web Function code change creates a new revision, so continuously
syncing it doesn't make sense, and watch mode never watched Web Function
code anyway: code changes were skipped and only deployed with the next
template change. sam sync --watch now fails before doing anything when the
template, including nested stacks, has an AWS::Serverless::WebFunction with
local code, and points to sam sync without --watch or sam deploy.
…ode isn't watched

Reverts the sam sync --watch error for Web Functions (6c9b004). Watch mode
has no code watcher for AWS::Serverless::WebFunction, so a code change never
creates a revision by itself; the code is deployed with the next
infrastructure sync. sam sync --watch now prints a note saying so when the
template, including nested stacks, has a Web Function with local code.
…ndency layer

sam sync builds with combine_dependencies=False so that function
dependencies go to a separate directory for the auto dependency layer.
Web Functions can't use layers and the dependency layer stack only covers
Lambda functions, so their dependencies were left out and the deployed
Web Function couldn't load them. Web Function builds now always combine
dependencies into the artifact.
Web Function code was zipped with make_zip, which keeps each file's mode, so
files Lambda couldn't read (for example 0600) were uploaded as is. Add
AWS::Serverless::WebFunction to LAMBDA_LOCAL_RESOURCES so it's zipped with
make_zip_with_lambda_permissions, like Lambda functions. The list's only
other use is that zip-method choice.
delete_web_function_code_bucket treated every describe_stacks error as "no
code bucket stack", so access, throttling and credential errors left the
code bucket, its stack and its export behind with no warning. Only a
missing stack is treated that way now; other errors are raised.

Re-running sam delete couldn't recover either, because it stops when the
deployed stack is gone. It now still deletes a leftover code bucket stack
in that case.

@aws-sam-tooling-bot aws-sam-tooling-bot Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review Results

Reviewed: 7bf8efb..494af7a
Files: 29
Comments: 1

Comment thread samcli/lib/package/web_function_code_access.py
With BuildMethod: esbuild, a Web Function's EntryPoint (for example
src/server.ts) was bundled to server.js at the artifact root, but the built
template kept the source path, and Web Functions didn't count toward
esbuild detection, so source map pre-processing was skipped for them.

- esbuild_configured() also checks Web Functions.
- The built template's EntryPoint is rewritten to the bundled file when the
  configured one isn't in the artifact, like a Lambda function's handler.
- Sourcemap handling reads and writes NODE_OPTIONS in a Web Function's
  EnvironmentVariables.

@aws-sam-tooling-bot aws-sam-tooling-bot Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review Results

Reviewed: 7bf8efb..7b587bb
Files: 31
Comments: 1

dependencies_dir,
download_dependencies,
self._combine_dependencies,
self._combine_dependencies or self._is_web_function(function_name),

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[BUG] A Web Function that shares a build definition with a Lambda function is built without its dependencies
_is_web_function(function_name) only checks the name passed to _build_function. The build strategy passes build_definition.get_function_name(), which is the first function in the definition, and then copies that artifact to every other function in the definition.

FunctionBuildDefinition.__eq__ doesn't compare resource type, and this PR makes Web Functions match on the fields it does compare: imageuri is None, the architecture is x86_64, and the env vars are the same. So an AWS::Serverless::Function and an AWS::Serverless::WebFunction with the same CodeUri, runtime and metadata go into one definition. collect_all_build_resources adds Lambda functions first, so the Lambda function becomes functions[0] and _is_web_function returns False.

With sam sync's auto dependency layer (combine_dependencies=False), the shared artifact is built without dependencies and copied to the Web Function. Web Functions can't use layers, so the deployed Web Function has no dependencies at runtime. Two possible fixes:

  • Make the resource type part of build-definition equality, so Web Functions never share a definition with Lambda functions.
  • Decide combine_dependencies based on whether any function in the build definition is a WebFunction.

The Fn::ForEach check counted any dict CodeUri without a literal Bucket as
local code, so a per-item S3 location such as !Sub "s3://bucket/${Name}.zip"
was rejected even though packaging never uploads dict values. Treat every
dict CodeUri (an S3 object or an intrinsic) as remote, consistently with
Resource.export and stacks_have_web_functions.

@aws-sam-tooling-bot aws-sam-tooling-bot Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review Results

Reviewed: 7bf8efb..26c525b
Files: 31
Comments: 2

Comment thread samcli/lib/build/app_builder.py
Comment thread samcli/commands/delete/delete_context.py Outdated
sam delete always emptied and deleted the code bucket after deleting the
stack, even when a WebFunction had DeletionPolicy: Retain (or
RetainExceptOnCreate) or was in retain_resources. A retained Web Function
keeps reading its code from the bucket, so deleting it broke the function.

- sam delete keeps the code bucket stack when the deleted template has a
  retained WebFunction, turns on its termination protection, and says how
  to delete it later.
- Deleting a code bucket stack skips stacks with termination protection on,
  so re-running sam delete after the stack is gone leaves it in place too.
A Web Function's EntryPoint was split on the first '.' like a Lambda handler,
so ./server.ts, src/v1.2/server.ts and server.config.ts gave esbuild the wrong
entry file.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area/build sam build command area/deploy sam deploy command area/sync sam sync command pr/internal

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants