Skip to content

fix: restrict SAM/CFN project detection to SAM-supported extensions - #13739

Merged
czubocha merged 1 commit into
mainfrom
fix/sam-template-extension-detection
Jul 24, 2026
Merged

fix: restrict SAM/CFN project detection to SAM-supported extensions#13739
czubocha merged 1 commit into
mainfrom
fix/sam-template-extension-detection

Conversation

@czubocha

@czubocha czubocha commented Jul 23, 2026

Copy link
Copy Markdown
Contributor

Summary

  • Restrict SAM/CloudFormation project detection to the file names the AWS SAM CLI itself supports: template.{yaml,yml,json} and samconfig.{toml,yaml,yml} (packages/sf-core/src/lib/runners/cfn/cfn.js, packages/sf-core/src/lib/router.js)
  • Apply the same restriction to the template lookup performed for samconfig projects, and fail with a clear TEMPLATE_FILE_NOT_FOUND error when a samconfig file has no SAM-supported template next to it (previously crashed reading a null path)
  • Remove the unused getConfigFileDetails helper (packages/sf-core/src/utils/fs/config-file.js), which duplicated this discovery logic and has no callers

Root cause

Runner discovery matched directory files against known config names by base name only, ignoring the extension. Any file named template.* or samconfig.* — for example a template.mjs application module — selected the SAM/CloudFormation runner, which only supports deploy, remove, info, and print. That hid the framework commands from serverless help, made serverless package fail with "Command not found", shadowed an existing serverless.yml in the same directory, and loaded (for js/mjs/cjs/ts, executed) the file during initialization. Files with unparseable extensions such as template.html crashed every command in the directory, including help.

Behavior changes

  • template.* / samconfig.* files with extensions SAM does not support no longer affect project detection and are no longer loaded at startup; discovery falls through to the framework config or onboarding
  • Stray template.* files with unparseable extensions no longer crash the CLI
  • Detection of serverless.* and serverless-compose.* configs is unchanged for every extension (pinned by tests)
  • template.{yaml,yml,json} and samconfig.{toml,yaml,yml} projects behave exactly as before

Test plan

  • New unit tests: 21 runner-discovery cases (SAM-supported names still select the CFN runner; unsupported extensions are ignored; serverless.yml/serverless.mjs/serverless-compose.yml selection unchanged; serverless.yml no longer shadowed by template.mjs) plus getConfigFilePath extension-filter tests and a TEMPLATE_FILE_NOT_FOUND case
  • Full sf-core unit suite passes
  • Live source-CLI verification across six directory layouts: serverless.yml+template.mjs, template.mjs alone, template.yaml alone, template.html+serverless.yml, samconfig.toml+template.yaml, samconfig.toml+template.mjs
  • Differential check of the old vs new matcher predicate over 1,400 filename/runner combinations: zero behavior changes outside the intended CFN cases

Fixes #13738

Summary by CodeRabbit

  • Bug Fixes

    • Improved configuration discovery by matching supported file extensions, preventing unrelated files from being selected.
    • Added support for SAM configuration and template files in YAML, YML, JSON, and TOML formats.
    • Improved error messages when an expected SAM template is missing.
    • Ensured runner selection follows the correct precedence when multiple configuration files are present.
  • Tests

    • Added coverage for runner discovery, supported file formats, precedence rules, and missing-template errors.

Any file named template.* or samconfig.* in the working directory made
the CLI treat the project as a SAM/CloudFormation stack, regardless of
extension. A template.mjs application module hijacked runner selection
away from serverless.yml, was loaded (and executed, for js/mjs/cjs/ts)
during initialization, and left only the CFN commands available; files
with unparseable extensions such as template.html crashed every command
in the directory, including help.

Project detection and template lookup now only consider the file names
the AWS SAM CLI itself supports: template.{yaml,yml,json} and
samconfig.{toml,yaml,yml}. Files with other extensions are ignored, so
discovery falls through to the framework config or onboarding. A
samconfig file without a SAM-supported template next to it now fails
with a clear TEMPLATE_FILE_NOT_FOUND error instead of crashing on a
null path. Also removes the unused getConfigFileDetails helper, which
duplicated this discovery logic and had no callers.

Fixes #13738
@Mmarzex

Mmarzex commented Jul 23, 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 Jul 23, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

📝 Walkthrough

Walkthrough

Runner discovery now applies extension allowlists, SAM template resolution restricts supported formats, findRunner is exported, and obsolete configuration-file utilities are removed. New tests cover runner selection, precedence, filtered path lookup, and missing SAM templates.

Changes

Runner discovery filtering

Layer / File(s) Summary
Extension-aware runner discovery
packages/sf-core/src/lib/router.js, packages/sf-core/src/utils/fs/index.js
Runner selection and config-path lookup now honor provided, case-insensitive extension allowlists.
SAM configuration and template resolution
packages/sf-core/src/lib/runners/cfn/cfn.js
SAM config and template extensions are declared explicitly, applied during lookup, and listed in missing-template errors.
Discovery validation and utility cleanup
packages/sf-core/tests/unit/lib/runner-discovery.test.js, packages/sf-core/tests/unit/utils/fs/get-config-file-path.test.js, packages/sf-core/src/utils/index.js, packages/sf-core/src/utils/fs/config-file.js
Tests cover supported filenames, precedence, filtered lookup, and missing templates; the obsolete config-file utility is removed from exports and the filesystem module.

Estimated code review effort: 3 (Moderate) | ~20 minutes

Sequence Diagram(s)

sequenceDiagram
  participant findRunner
  participant CfnRunner
  participant getConfigFilePath
  findRunner->>CfnRunner: Read allowed config extensions
  findRunner->>getConfigFilePath: Search basename with extension filter
  getConfigFilePath-->>findRunner: Return matching path or null
  findRunner-->>CfnRunner: Select runner
Loading
🚥 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 summarizes the main change: narrowing SAM/CFN detection to supported extensions.
Linked Issues check ✅ Passed The PR fixes #13738 by ignoring unsupported template.* files, preserving Serverless config selection, and restricting SAM lookup to supported extensions.
Out of Scope Changes check ✅ Passed The changes are focused on the detection fix and accompanying tests; no unrelated code paths stand out.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
✨ 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 fix/sam-template-extension-detection

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.

@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: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@packages/sf-core/src/lib/router.js`:
- Around line 253-263: Normalize configured extension allowlists to lowercase
before comparing them with the discovered extension in the router’s
file-matching logic. Also normalize supplied extensions to lowercase before
constructing candidate paths in getConfigFilePath; apply these changes in
packages/sf-core/src/lib/router.js lines 253-263 and
packages/sf-core/src/utils/fs/index.js line 292, and add mixed-case coverage.
🪄 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 Plus

Run ID: af0ea947-2562-4f45-b577-26fccb83ef3a

📥 Commits

Reviewing files that changed from the base of the PR and between bd9ed54 and dddf66a.

📒 Files selected for processing (7)
  • packages/sf-core/src/lib/router.js
  • packages/sf-core/src/lib/runners/cfn/cfn.js
  • packages/sf-core/src/utils/fs/config-file.js
  • packages/sf-core/src/utils/fs/index.js
  • packages/sf-core/src/utils/index.js
  • packages/sf-core/tests/unit/lib/runner-discovery.test.js
  • packages/sf-core/tests/unit/utils/fs/get-config-file-path.test.js
💤 Files with no reviewable changes (2)
  • packages/sf-core/src/utils/index.js
  • packages/sf-core/src/utils/fs/config-file.js

Comment thread packages/sf-core/src/lib/router.js
@czubocha
czubocha merged commit daa0bfc into main Jul 24, 2026
12 checks passed
@czubocha
czubocha deleted the fix/sam-template-extension-detection branch July 24, 2026 14:11
@github-actions github-actions Bot locked and limited conversation to collaborators Jul 24, 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.

sls package says "command not found" and isn't listed in sls help when there is a template.mjs file in the root

2 participants