Repository: palantir/policy-bot (go)

Issue:
Re-add SSH signature support
Support for SSH signatures was added in #504 and reverted in #507. The required `SshSignature` GraphQL type is only available in GitHub.com and GitHub Enterprise 3.7 and newer. On GHE 3.6 (what we're currently running internally), all evaluations fail with this error:

```
failed to compute approval status: failed to list commits: failed to load commits: No such type SshSignature, so it can't be a fragment condition
```

I reverted the feature to unblock other fixes, but we should add it again if either:

1. We also add feature detection so that it is only enabled when GitHub supports it
2. We upgrade to GHE 3.7 internally and are ready to drop support for older versions in Policy Bot

Pull request description:
Restore support for SSH signatures
The required API for this feature is only available in GitHub Enterprise 3.7 or newer, so merging this means we will drop support for GHE 3.6 and older. Given GHE 3.8 has been available for a few months, I think this is reasonable.

Closes #508.

Patch:
diff --git a/pull/context.go b/pull/context.go
index 44da64b..d093206 100644
--- a/pull/context.go
+++ b/pull/context.go
@@ -173,14 +173,16 @@ type SignatureType string
 const (
 	SignatureGpg   SignatureType = "GpgSignature"
 	SignatureSmime SignatureType = "SmimeSignature"
+	SignatureSSH   SignatureType = "SshSignature"
 )
 
 type Signature struct {
-	Type    SignatureType
-	IsValid bool
-	KeyID   string
-	Signer  string
-	State   string
+	Type           SignatureType
+	IsValid        bool
+	KeyID          string
+	KeyFingerprint string
+	Signer         string
+	State          string
 }
 
 type Comment struct {
diff --git a/pull/github.go b/pull/github.go
index 10c5ab5..e6a9e03 100644
--- a/pull/github.go
+++ b/pull/github.go
@@ -1210,6 +1210,7 @@ type v4GitSignature struct {
 	Type  string           `graphql:"__typename"`
 	GPG   v4GpgSignature   `graphql:"... on GpgSignature"`
 	SMIME v4SmimeSignature `graphql:"... on SmimeSignature"`
+	SSH   v4SshSignature   `graphql:"... on SshSignature"`
 }
 
 func (s *v4GitSignature) ToSignature() *Signature {
@@ -1229,6 +1230,14 @@ func (s *v4GitSignature) ToSignature() *Signature {
 			State:   s.SMIME.State,
 			Type:    SignatureSmime,
 		}
+	case SignatureSSH:
+		return &Signature{
+			IsValid:        s.SSH.IsValid,
+			KeyFingerprint: s.SSH.KeyFingerprint,
+			Signer:         s.SSH.Signer.GetV3Login(),
+			State:          s.SSH.State,
+			Type:           SignatureSSH,
+		}
 	default:
 		return nil
 	}
@@ -1254,3 +1263,14 @@ type v4GpgSignature struct {
 	State             string
 	WasSignedByGitHub bool
 }
+
+type v4SshSignature struct {
+	Email             string
+	IsValid           bool
+	KeyFingerprint    string
+	Payload           string
+	Signature         string
+	Signer            *v4Actor
+	State             string
+	WasSignedByGitHub bool
+}


Test patch:
diff --git a/policy/predicate/signature_test.go b/policy/predicate/signature_test.go
index 0733f74..9a33f06 100644
--- a/policy/predicate/signature_test.go
+++ b/policy/predicate/signature_test.go
@@ -30,7 +30,7 @@ func TestHasValidSignatures(t *testing.T) {
 
 	testCases := []SignatureTestCase{
 		{
-			"ValidSignature",
+			"ValidGpgSignature",
 			&pulltest.Context{
 				AuthorValue: "mhaypenny",
 				CommitsValue: []*pull.Commit{
@@ -54,6 +54,31 @@ func TestHasValidSignatures(t *testing.T) {
 				ConditionValues: []string{"valid signatures"},
 			},
 		},
+		{
+			"ValidSshSignature",
+			&pulltest.Context{
+				AuthorValue: "mhaypenny",
+				CommitsValue: []*pull.Commit{
+					{
+						SHA:       "abcdef123456789",
+						Author:    "mhaypenny",
+						Committer: "mhaypenny",
+						Signature: &pull.Signature{
+							Type:           pull.SignatureSSH,
+							IsValid:        true,
+							Signer:         "ttest",
+							State:          "VALID",
+							KeyFingerprint: "Hello",
+						},
+					},
+				},
+			},
+			&common.PredicateResult{
+				Satisfied:       true,
+				Values:          []string{"abcdef123456789"},
+				ConditionValues: []string{"valid signatures"},
+			},
+		},
 		{
 			"InvalidSignature",
 			&pulltest.Context{