Skip to content

fix(compose): fix package command with cross-service dependency outputs#13438

Open
tmatilai wants to merge 3 commits into
serverless:mainfrom
tmatilai:fix-compore-package-with-refs
Open

fix(compose): fix package command with cross-service dependency outputs#13438
tmatilai wants to merge 3 commits into
serverless:mainfrom
tmatilai:fix-compore-package-with-refs

Conversation

@tmatilai

@tmatilai tmatilai commented Mar 27, 2026

Copy link
Copy Markdown

serverless package in a compose setup with service dependencies (e.g. ${service-a.queueUrl}) failed because package was not handled in the param resolution fallback — only print and remove were.

Additionally, updateLocalState treated empty state ({}) from commands that don't query CloudFormation as meaningful, which would overwrite previously saved outputs in the remote state store. Now only state with actual outputs is persisted, and the remote store is used as fallback.

Also fix unit tests in a non-UTC timezone.

Closes: #13437

Summary by CodeRabbit

  • Tests

    • Enhanced unit tests for datetime parsing with UTC normalization
    • Added comprehensive test suite for multi-service composition parameter resolution and state persistence
  • Bug Fixes

    • Improved handling of missing cross-service dependency outputs during package and print operations
    • Refined state persistence logic to prevent empty runner states from being unnecessarily stored

…puts

`serverless package` in a compose setup with service dependencies (e.g.
`${service-a.queueUrl}`) failed because `package` was not handled in the
param resolution fallback — only `print` and `remove` were.

Additionally, `updateLocalState` treated empty state (`{}`) from commands that
don't query CloudFormation as meaningful, which would overwrite previously
saved outputs in the remote state store. Now only state with actual outputs is
persisted, and the remote store is used as fallback.
@github-actions

github-actions Bot commented Mar 27, 2026

Copy link
Copy Markdown

All contributors have signed the CLA ✍️ ✅
Posted by the CLA Assistant Lite bot.

@Mmarzex

Mmarzex commented Mar 27, 2026

Copy link
Copy Markdown
Contributor

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

coderabbitai Bot commented Mar 27, 2026

Copy link
Copy Markdown
Contributor
📝 Walkthrough

Walkthrough

Fixed the package command failure in Compose setups with cross-service dependencies. Replaced the sentinel value used for missing dependency outputs, applied it to both package and print commands, and refactored state persistence logic to only persist non-empty output states. Added comprehensive test coverage for parameter resolution and state management.

Changes

Cohort / File(s) Summary
Test Coverage for Compose Dependency Resolution
packages/sf-core/tests/unit/runners/compose/index.test.js
New Jest test suite verifying parseComposeGraph behavior across package, print, deploy, and remove commands. Tests parameter resolution when dependencies lack outputs (using placeholder NOT_AVAILABLE_AT_PACKAGE_TIME for package/print), state persistence rules (non-empty outputs only), and remote state fallback behavior.
Compose Runner Logic Update
packages/sf-core/src/lib/runners/compose/index.js
Changed missing dependency output sentinel from NOT_AVAILABLE_IN_PRINT_COMMAND to NOT_AVAILABLE_AT_PACKAGE_TIME and applied to package command alongside print. Added hasOutputs flag to condition state persistence on non-empty outputs for commands other than get-state.
DateTime Parsing Test Updates
packages/serverless/test/unit/lib/plugins/aws/appsync/utils.test.js
Updated parseDateTimeOrDuration test snapshots to normalize UTC datetime output from +00:00 offset notation to Z form by calling .toUTC().toISO() on parsed values before assertion.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Poem

🐰 Cross-service paths now flow with grace,
No more errors in the compose space!
When outputs vanish mid-package time,
A placeholder stands—not quite sublime.
The state persists, the logic refined,
Tests ensure no bugs left behind. ✨

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately reflects the main change: fixing the package command to work with cross-service dependency outputs in Compose setups, which aligns with the PR's primary objective.
Linked Issues check ✅ Passed The code changes address the core requirement from issue #13437: enabling the package command to resolve cross-service dependency outputs by adding it to the parameter resolution fallback logic alongside print.
Out of Scope Changes check ✅ Passed The changes are scoped appropriately: fixes to compose parameter resolution, state persistence logic updates, and test suite additions for verification. The unit test timezone normalization is necessary for test reliability.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.

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

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

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.

@tmatilai

Copy link
Copy Markdown
Author

I have read the CLA Document and I hereby sign the CLA

@tmatilai

tmatilai commented Mar 27, 2026

Copy link
Copy Markdown
Author

Disclaimer: AI has been heavily used to diagnose and fix the issues, and for writing the unit tests.

@coderabbitai coderabbitai Bot left a comment

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.

Actionable comments posted: 2

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@packages/sf-core/src/lib/runners/compose/index.js`:
- Around line 322-327: The check treating stateValue as missing incorrectly
flags valid falsy outputs (0, false, ''); update the unresolved-output condition
in the block that reads stateValue =
state?.localState?.[splitKey[0]]?.outputs?.[splitKey[1]] so it only treats
null/undefined as unresolved (use explicit null/undefined check or stateValue ==
null), then keep the existing branches that set serviceParams[key] to
'NOT_AVAILABLE_AT_PACKAGE_TIME' for command[0] === 'print' || 'package' and the
remove handling for 'remove'.

In `@packages/sf-core/tests/unit/runners/compose/index.test.js`:
- Around line 1-4: Move the static import of parseComposeGraph so the
jest.unstable_mockModule declaration runs first: remove or relocate the line
importing parseComposeGraph from '../../../../src/lib/runners/compose/index.js'
and instead import parseComposeGraph after calling
jest.unstable_mockModule('@serverless/util', ...) and awaiting or using dynamic
import (e.g., via await import(...)) so the mocked '@serverless/util' is applied
before parseComposeGraph (refer to parseComposeGraph and
jest.unstable_mockModule to find the relevant code).
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 32433cfc-3572-444c-93e0-945f9791e621

📥 Commits

Reviewing files that changed from the base of the PR and between 8905d7a and 301dfb5.

📒 Files selected for processing (3)
  • packages/serverless/test/unit/lib/plugins/aws/appsync/utils.test.js
  • packages/sf-core/src/lib/runners/compose/index.js
  • packages/sf-core/tests/unit/runners/compose/index.test.js

Comment on lines 322 to 327
const stateValue =
state?.localState?.[splitKey[0]]?.outputs?.[splitKey[1]]
if (!stateValue) {
if (command[0] === 'print') {
serviceParams[key] = 'NOT_AVAILABLE_IN_PRINT_COMMAND'
if (command[0] === 'print' || command[0] === 'package') {
serviceParams[key] = 'NOT_AVAILABLE_AT_PACKAGE_TIME'
} else if (command[0] === 'remove') {

@coderabbitai coderabbitai Bot Mar 27, 2026

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.

⚠️ Potential issue | 🟠 Major

Treat only null/undefined as unresolved cross-service outputs.

The current check treats valid falsy outputs as missing. If a dependency output is 0, false, or '', it will incorrectly fall into placeholder/error logic.

💡 Proposed fix
-                  if (!stateValue) {
+                  if (stateValue === undefined || stateValue === null) {
                     if (command[0] === 'print' || command[0] === 'package') {
                       serviceParams[key] = 'NOT_AVAILABLE_AT_PACKAGE_TIME'
                     } else if (command[0] === 'remove') {
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@packages/sf-core/src/lib/runners/compose/index.js` around lines 322 - 327,
The check treating stateValue as missing incorrectly flags valid falsy outputs
(0, false, ''); update the unresolved-output condition in the block that reads
stateValue = state?.localState?.[splitKey[0]]?.outputs?.[splitKey[1]] so it only
treats null/undefined as unresolved (use explicit null/undefined check or
stateValue == null), then keep the existing branches that set serviceParams[key]
to 'NOT_AVAILABLE_AT_PACKAGE_TIME' for command[0] === 'print' || 'package' and
the remove handling for 'remove'.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

This sounds like a correct finding, but it's not directly related to the issue that this PR is fixing. So I would say it's out of scope here, but I'll leave it to the maintainers.

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.

@tmatilai, understood — the fix here is specifically about enabling package to resolve cross-service dependency outputs, so this is indeed a pre-existing edge case. Would you like me to open a follow-up GitHub issue to track fixing the falsy-output check (!stateValuestateValue == null) so it doesn't get lost?

Comment thread packages/sf-core/tests/unit/runners/compose/index.test.js
…ith-refs

# Conflicts:
#	packages/serverless/test/unit/lib/plugins/aws/appsync/utils.test.js
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

package command fails on Compose with cross-service dependency outputs

2 participants