Repository: aws-cloudformation/cfn-lint

Issue:
[cfn-lint] E0002:Unknown exception while processing rule E2541: unhashable type: 'dict_node'
*cfn-lint version: 0.16.0

I got the error message:

`[cfn-lint] E0002:Unknown exception while processing rule E2541: unhashable type: 'dict_node'
`

If I put a "!Ref Name" in the source action Name: see below
      
```
Stages:
        - Name: GitHub
          Actions:
          - Name: !Ref GitHubSourceRepo1
            ActionTypeId:
              Category: Source
              Owner: Custom
              Version: 1
              Provider: GitHUBcustom
.
.
.
.
```

If I remove  the !Ref, the cfn-lint works fine.


Discussion:

Resolving patch:
diff --git a/src/cfnlint/rules/resources/codepipeline/CodepipelineStageActions.py b/src/cfnlint/rules/resources/codepipeline/CodepipelineStageActions.py
--- a/src/cfnlint/rules/resources/codepipeline/CodepipelineStageActions.py
+++ b/src/cfnlint/rules/resources/codepipeline/CodepipelineStageActions.py
@@ -14,6 +14,7 @@
   OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
   SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 """
+import six
 from cfnlint import CloudFormationLintRule
 from cfnlint import RuleMatch
 
@@ -44,6 +45,12 @@ class CodepipelineStageActions(CloudFormationLintRule):
                     'OutputArtifactRange': (0, 5),
                 }
             },
+            'Build': {
+                'CodeBuild': {
+                    'InputArtifactRange': (1, 5),
+                    'OutputArtifactRange': (0, 5),
+                }
+            },
             'Approval': {
                 'Manual': {
                     'InputArtifactRange': 0,
@@ -167,12 +174,14 @@ def check_names_unique(self, action, path, action_names):
         """Check that action names are unique."""
         matches = []
 
-        if action.get('Name') in action_names:
-            message = 'All action names within a stage must be unique. ({name})'.format(
-                name=action.get('Name')
-            )
-            matches.append(RuleMatch(path + ['Name'], message))
-        action_names.add(action.get('Name'))
+        action_name = action.get('Name')
+        if isinstance(action_name, six.string_types):
+            if action.get('Name') in action_names:
+                message = 'All action names within a stage must be unique. ({name})'.format(
+                    name=action.get('Name')
+                )
+                matches.append(RuleMatch(path + ['Name'], message))
+            action_names.add(action.get('Name'))
 
         return matches
 


Test patch:
diff --git a/test/fixtures/templates/bad/resources_codepipeline_stages_second_stage.yaml b/test/fixtures/templates/bad/resources_codepipeline_stages_second_stage.yaml
--- a/test/fixtures/templates/bad/resources_codepipeline_stages_second_stage.yaml
+++ b/test/fixtures/templates/bad/resources_codepipeline_stages_second_stage.yaml
@@ -29,7 +29,7 @@ Resources:
                 OAuthToken: 'secret-token'
         - Name: MoreSource
           Actions:
-            - Name: Github
+            - Name: !Ref Github
               ActionTypeId:
                 Category: Source
                 Owner: ThirdParty
diff --git a/test/fixtures/templates/good/resources/codepipeline/stage_actions.yaml b/test/fixtures/templates/good/resources/codepipeline/stage_actions.yaml
new file mode 100644
--- /dev/null
+++ b/test/fixtures/templates/good/resources/codepipeline/stage_actions.yaml
@@ -0,0 +1,44 @@
+AWSTemplateFormatVersion: 2010-09-09
+Description: >
+  Good CodePipeline Template
+Parameters:
+  CodeBuild:
+    Type: String
+Resources:
+  TestPipeline:
+    Type: AWS::CodePipeline::Pipeline
+    Properties:
+      Name: Test-pipeline
+      ArtifactStore:
+        Location: 'pipeline-bucket'
+        Type: S3
+      RoleArn: arn:aws:iam:::role/AWSCodePipelineRole
+      Stages:
+        - Name: Source
+          Actions:
+            - Name: Github
+              ActionTypeId:
+                Category: Source
+                Owner: ThirdParty
+                Provider: GitHub
+                Version: "1"
+              OutputArtifacts:
+                - Name: MyApp
+              Configuration:
+                Owner: aws-cloudformation
+                Repo: cfn-python-lint
+                PollForSourceChanges: true
+                Branch: master
+                OAuthToken: 'secret-token'
+        - Name: MoreSource
+          Actions:
+            - Name: !Ref CodeBuild   # doesn't fail when Ref is used
+              ActionTypeId:
+                Category: Build
+                Owner: AWS
+                Version: "1"
+                Provider: CodeBuild
+              Configuration:
+                ProjectName: cfn-python-lint
+              InputArtifacts:
+              - Name: MyApp
diff --git a/test/rules/resources/codepipeline/test_stageactions.py b/test/rules/resources/codepipeline/test_stageactions.py
--- a/test/rules/resources/codepipeline/test_stageactions.py
+++ b/test/rules/resources/codepipeline/test_stageactions.py
@@ -24,6 +24,9 @@ def setUp(self):
         """Setup"""
         super(TestCodePipelineStageActions, self).setUp()
         self.collection.register(CodepipelineStageActions())
+        self.success_templates = [
+            'test/fixtures/templates/good/resources/codepipeline/stage_actions.yaml'
+        ]
 
     def test_file_positive(self):
         """Test Positive"""