Skip to content

Commit ab05f13

Browse files
committed
fix(codepipeline): stop E3701 flagging Fn::If OutputArtifact names as duplicates
An OutputArtifacts Name given as an Fn::If is validated once per branch and each branch instance is visited twice at the identical path, so the rule compared the second visit against the entry it had just recorded for itself and reported the name as already defined. Record the instance path alongside the name and condition status and skip entries from the same path when checking for duplicates. Genuine duplicates at different paths are still reported. Fixes #4584
1 parent 9ef0eff commit ab05f13

2 files changed

Lines changed: 47 additions & 7 deletions

File tree

src/cfnlint/rules/resources/codepipeline/PipelineArtifactNames.py

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ def __init__(self) -> None:
3030
"Resources/AWS::CodePipeline::Pipeline/Properties/Stages/*/Actions/*/OutputArtifacts/*/Name",
3131
],
3232
)
33-
self._output_artifact_names: dict[str, list[tuple[str, dict]]] = {}
33+
self._output_artifact_names: dict[str, list[tuple[str, dict, tuple]]] = {}
3434

3535
def initialize(self, cfn):
3636
self._output_artifact_names = {}
@@ -49,11 +49,14 @@ def validate(
4949
if resource_name not in self._output_artifact_names:
5050
self._output_artifact_names[resource_name] = []
5151

52+
path = tuple(validator.context.path.path)
5253
if "OutputArtifacts" in validator.context.path.path:
53-
for output_name, output_condition in self._output_artifact_names[
54-
resource_name
55-
]:
56-
if output_name != instance:
54+
for (
55+
output_name,
56+
output_condition,
57+
output_path,
58+
) in self._output_artifact_names[resource_name]:
59+
if output_name != instance or output_path == path:
5760
continue
5861
try:
5962
validator.evolve(
@@ -72,10 +75,10 @@ def validate(
7275
pass
7376

7477
self._output_artifact_names[resource_name].append(
75-
(instance, validator.context.conditions.status)
78+
(instance, validator.context.conditions.status, path)
7679
)
7780
elif "InputArtifacts" in validator.context.path.path:
78-
for output_name, output_condition in self._output_artifact_names[
81+
for output_name, output_condition, _ in self._output_artifact_names[
7982
resource_name
8083
]:
8184
if output_name != instance:

test/unit/rules/resources/codepipeline/test_pipeline_artifact_names.py

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -273,6 +273,43 @@ def _append_queues(queue1: Iterable, queue2: Iterable) -> deque:
273273
),
274274
],
275275
),
276+
(
277+
[
278+
(
279+
"Foo",
280+
_append_queues(
281+
_standard_path,
282+
[0, "Actions", 0, "OutputArtifacts", 0, "Name", "Fn::If", 1],
283+
),
284+
{"IsUsEast1": True},
285+
),
286+
(
287+
"Foo",
288+
_append_queues(
289+
_standard_path,
290+
[0, "Actions", 0, "OutputArtifacts", 0, "Name", "Fn::If", 1],
291+
),
292+
{"IsUsEast1": True},
293+
),
294+
(
295+
"Bar",
296+
_append_queues(
297+
_standard_path,
298+
[0, "Actions", 0, "OutputArtifacts", 0, "Name", "Fn::If", 2],
299+
),
300+
{"IsUsEast1": False},
301+
),
302+
(
303+
"Bar",
304+
_append_queues(
305+
_standard_path,
306+
[0, "Actions", 0, "OutputArtifacts", 0, "Name", "Fn::If", 2],
307+
),
308+
{"IsUsEast1": False},
309+
),
310+
],
311+
[],
312+
),
276313
],
277314
)
278315
def test_validate(instances, expected, rule, validator):

0 commit comments

Comments
 (0)