Skip to content

fix(python): build lambda layer for layer-only services#13541

Merged
czubocha merged 1 commit into
mainfrom
sc-3939
May 5, 2026
Merged

fix(python): build lambda layer for layer-only services#13541
czubocha merged 1 commit into
mainfrom
sc-3939

Conversation

@czubocha
Copy link
Copy Markdown
Contributor

@czubocha czubocha commented May 4, 2026

Summary

The built-in python plugin skipped the lambda layer build for services that declared custom.pythonRequirements.layer but had no functions: block. The service-level runtime guard returned false when no python functions and no python agents were present, so the before/after hooks (which install requirements and call layerRequirements()) never ran. Result: no PythonRequirementsLambdaLayer resource and no PythonRequirementsLambdaLayerQualifiedArn / Hash / S3Key outputs in the generated CloudFormation template.

This restores parity with the standalone serverless-python-requirements plugin's behaviour for layer-only services.

Changes

  • isFunctionRuntimePython now also returns true for service-level hooks when custom.pythonRequirements.layer is truthy and the provider runtime starts with python. The runtime gate is preserved so non-python services with stale pythonRequirements config remain unaffected.
  • installAllRequirements runs the shared install step when the service is layer-only (no python functions and options.layer set), so layerRequirements() has a populated .serverless/requirements.txt to zip.
  • New integration test fixture tests/python/tests/layer_only/ and a test in tests/python/test.js that asserts the layer resource, layer outputs, and packaged dependency are present.

Behaviour notes

  • Layer-only services with a non-python provider runtime remain inactive (no pip invocation), preserving existing behaviour.
  • Services that previously hit this bug succeeded silently with an empty stack; after this fix serverless package will now actually invoke pip. If the local environment lacks the pythonX.Y binary matching the configured runtime, packaging will fail loudly. Set pythonBin or use dockerizePip to resolve.

Test plan

  • New tests/python/tests/layer_only test passes.
  • Existing tests/python suite unchanged.
  • Manual reproduction (custom.pythonRequirements.layer: true, no functions:) now produces PythonRequirementsLambdaLayer and the three layer outputs.
  • Manual regression check: layer + python function still produces both the function and the layer resources.
  • Manual regression check: enabling the community plugin via plugins: [serverless-python-requirements] continues to work unchanged (built-in is overridden).
  • Manual regression check: layer config with non-python provider runtime stays inactive (no pip invocation).

Summary by CodeRabbit

  • New Features

    • Added support for services that package Python requirements as Lambda layers without containing any functions. The Python plugin now recognizes and properly handles layer-only configurations.
  • Tests

    • Added comprehensive test coverage for layer-only services, verifying correct Lambda layer generation and archive contents.

Note

Medium Risk
Moderate risk: changes the runtime gating so the Python packaging hooks now run for services with custom.pythonRequirements.layer even when functions is empty, which can newly invoke pip during sls package and fail in misconfigured environments.

Overview
Fixes the built-in Python requirements plugin so layer-only services (configured with custom.pythonRequirements.layer but no functions) still run the packaging hooks and generate PythonRequirementsLambdaLayer outputs.

Updates the requirements installer to perform the shared install step for these layer-only services, ensuring .serverless/requirements is populated before zipping. Adds an integration test fixture (tests/python/tests/layer_only) verifying the CloudFormation layer resource/outputs and that dependencies are present in .serverless/pythonRequirements.zip.

Reviewed by Cursor Bugbot for commit 1a2eb49. Bugbot is set up for automated code reviews on this repo. Configure here.

The built-in python plugin's runtime check returned false at the
service level when no functions were defined, causing before/after
hooks to be skipped. As a result, services configured with
custom.pythonRequirements.layer and no functions: block produced no
PythonRequirementsLambdaLayer resource or related CFN outputs.

- Treat a python provider runtime + custom.pythonRequirements.layer
  as a valid trigger for the service-level hooks.
- Run the shared requirements install when there are no python
  functions but a layer is configured, so layerRequirements() finds
  a populated .serverless/requirements directory to zip.
- Add an integration fixture and test asserting the layer resource
  and outputs are generated for a layer-only service.
@Mmarzex
Copy link
Copy Markdown
Contributor

Mmarzex commented May 4, 2026

Snyk checks have passed. No issues have been found so far.

Status Scan Engine Critical High Medium Low Total (0)
Open Source Security 0 0 0 0 0 issues
Licenses 0 0 0 0 0 issues
Code Security 0 0 0 0 0 issues

💻 Catch issues earlier using the plugins for VS Code, JetBrains IDEs, Visual Studio, and Eclipse.

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented May 4, 2026

📝 Walkthrough

Walkthrough

This PR extends Python plugin support to recognize and properly package "layer-only" services—those configured with custom.pythonRequirements.layer: true but without Python functions. The detection and installation logic are updated, and a new test fixture validates the behavior.

Changes

Python Layer-Only Service Support

Layer / File(s) Summary
Runtime Detection Logic
packages/serverless/lib/plugins/python/index.js
Plugin hook activation now includes hasPythonLayerOnly check: detects when custom.pythonRequirements.layer is configured and provider runtime starts with python.
Dependency Installation Logic
packages/serverless/lib/plugins/python/lib/pip.js
installAllRequirements now triggers shared packaging for layer-only services by computing isLayerOnlyService (no Python functions but layer configured) and expanding the conditional that runs requirements installation.
Test Infrastructure
packages/sf-core/tests/python/test.js, packages/sf-core/tests/python/tests/layer_only/*
New test fixture with serverless.yml, package.json, requirements.txt, and corresponding test case that packages the fixture and verifies PythonRequirementsLambdaLayer resource and python/six archive content exist.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Possibly related issues

Poem

🐰 A layer so neat, with no functions in sight,
Yet Python requirements packed oh-so-tight!
We found the bug, made the plugin see true—
Layer-only services now work just like new!

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed The title accurately summarizes the main change: enabling lambda layer building for 'layer-only' services in the Python plugin.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch sc-3939

Tip

💬 Introducing Slack Agent: The best way for teams to turn conversations into code.

Slack Agent is built on CodeRabbit's deep understanding of your code, so your team can collaborate across the entire SDLC without losing context.

  • Generate code and open pull requests
  • Plan features and break down work
  • Investigate incidents and troubleshoot customer tickets together
  • Automate recurring tasks and respond to alerts with triggers
  • Summarize progress and report instantly

Built for teams:

  • Shared memory across your entire org—no repeating context
  • Per-thread sandboxes to safely plan and execute work
  • Governance built-in—scoped access, auditability, and budget controls

One agent for your entire SDLC. Right inside Slack.

👉 Get started


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@czubocha
Copy link
Copy Markdown
Contributor Author

czubocha commented May 4, 2026

@cursor review

Copy link
Copy Markdown

@cursor cursor Bot left a comment

Choose a reason for hiding this comment

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

✅ Bugbot reviewed your changes and found no new issues!

Comment @cursor review or bugbot run to trigger another review on this PR

Reviewed by Cursor Bugbot for commit 1a2eb49. Configure here.

@czubocha czubocha merged commit c9dec98 into main May 5, 2026
20 of 24 checks passed
@czubocha czubocha deleted the sc-3939 branch May 5, 2026 14:32
@github-actions github-actions Bot locked and limited conversation to collaborators May 5, 2026
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Built-in python requirements plugin skips layer-only services (no functions defined)

2 participants