@@ -245,12 +245,14 @@ def _load_cfnlint_result_file(f, prefix, results):
245245 return
246246 if not isinstance (data , list ):
247247 return
248- # Derive key from the template filename inside the JSON, not the results filename.
249- # cfn-lint results filenames may differ from the actual template filename
250- # (e.g., results file "metadata.json" for template "metdata.yaml"). The file
251- # extension is kept as part of the key (".yaml" -> "_yaml") so a template
252- # authored in both JSON and YAML maps to two distinct keys, matching the
253- # engine report names.
248+
249+ # The default key comes from the result filename, whose stem now embeds the
250+ # source extension as a suffix (template "metdata.yaml" -> result
251+ # "metadata_yaml.json")
252+ # Prefer the template filename read from the JSON's `Filename` field: the
253+ # result filename's base may differ from the real template name (e.g. result
254+ # "metadata_yaml.json" for template "metdata.yaml"), and the engine report is
255+ # keyed off the true template path.
254256 key = f"{ prefix } _{ f .stem } "
255257 if data and isinstance (data [0 ], dict ) and data [0 ].get ("Filename" ):
256258 tpl = data [0 ]["Filename" ].replace ("test/fixtures/templates/" , "" )
@@ -259,25 +261,29 @@ def _load_cfnlint_result_file(f, prefix, results):
259261 key = derived
260262 else :
261263 # An empty result list (cfn-lint found nothing) carries no `Filename`, so
262- # the extension cannot be read from the diagnostics. Recover it by mirroring
263- # the result path into the templates tree and adopting the real template
264- # extension; otherwise the key stays suffix-less and never matches the
265- # extension-suffixed engine report, silently dropping the template from the
266- # comparison.
264+ # the true template extension cannot be read from the diagnostics. Confirm
265+ # it instead by locating the mirror template under the templates tree; if
266+ # none exists the default key (from the result filename) is kept as-is.
267267 derived = _derive_key_from_template_path (f )
268268 if derived :
269269 key = derived
270270 results [key ] = normalize_cfnlint_diags (data )
271271
272272
273273def _derive_key_from_template_path (result_file ):
274- """Recover the extension-suffixed key for a result file by locating the mirror
275- template under CFN_LINT_TEMPLATES. Returns None if no matching template exists."""
274+ """Recover the extension-suffixed key for an empty-result file by locating the
275+ mirror template under CFN_LINT_TEMPLATES. The result stem now embeds the source
276+ extension as a suffix (e.g. "foo_yaml.json"), so split that suffix back off, find
277+ the matching template, and rebuild the key from its real extension. Returns None
278+ if no matching template exists (leaving the caller's default key in place)."""
276279 relative = result_file .relative_to (CFN_LINT_RESULTS )
277- stem_path = str (relative .with_suffix ("" )).replace (os .sep , "_" )
278- for ext in (".yaml" , ".yml" , ".json" ):
279- if (CFN_LINT_TEMPLATES / relative .with_suffix (ext )).exists ():
280- return f"{ stem_path } _{ ext .lstrip ('.' )} "
280+ stem = relative .stem # drops ".json"; still carries the "_yaml"/"_yml"/"_json" suffix
281+ for ext in ("yaml" , "yml" , "json" ):
282+ base = stem [: - (len (ext ) + 1 )] if stem .endswith (f"_{ ext } " ) else stem
283+ template = relative .with_name (f"{ base } .{ ext } " )
284+ if (CFN_LINT_TEMPLATES / template ).exists ():
285+ key_path = str (template .with_suffix ("" )).replace (os .sep , "_" )
286+ return f"{ key_path } _{ ext } "
281287 return None
282288
283289
0 commit comments