Repository: notaryproject/notation-go
Pull request #529: refactor: update error names to align with Go convention
Author: login: qba73
Created: 2025-04-02T06:51:23Z | Merged: 2025-04-11T07:24:06Z

This PR fixes https://github.com/notaryproject/notation-go/issues/528 and adds the following changes:

- add new custom errors (naming aligned with [Go convention](https://go.dev/doc/effective_go#errors))
- mark old custom error deprecated


Diff:
diff --git a/errors.go b/errors.go
index bda0be58..edfc9630 100644
--- a/errors.go
+++ b/errors.go
@@ -15,11 +15,17 @@ package notation
 
 // ErrorPushSignatureFailed is used when failed to push signature to the
 // target registry.
-type ErrorPushSignatureFailed struct {
+//
+// Deprecated: Use PushSignatureFailedError instead.
+type ErrorPushSignatureFailed = PushSignatureFailedError
+
+// PushSignatureFailedError is used when failed to push signature to the
+// target registry.
+type PushSignatureFailedError struct {
 	Msg string
 }
 
-func (e ErrorPushSignatureFailed) Error() string {
+func (e PushSignatureFailedError) Error() string {
 	if e.Msg != "" {
 		return "failed to push signature to registry with error: " + e.Msg
 	}
@@ -28,11 +34,17 @@ func (e ErrorPushSignatureFailed) Error() string {
 
 // ErrorVerificationInconclusive is used when signature verification fails due
 // to a runtime error (e.g. a network error)
-type ErrorVerificationInconclusive struct {
+//
+// Deprecated: Use VerificationInconclusiveError instead.
+type ErrorVerificationInconclusive = VerificationInconclusiveError
+
+// VerificationInconclusiveError is used when signature verification fails due
+// to a runtime error (e.g. a network error)
+type VerificationInconclusiveError struct {
 	Msg string
 }
 
-func (e ErrorVerificationInconclusive) Error() string {
+func (e VerificationInconclusiveError) Error() string {
 	if e.Msg != "" {
 		return e.Msg
 	}
@@ -41,11 +53,17 @@ func (e ErrorVerificationInconclusive) Error() string {
 
 // ErrorNoApplicableTrustPolicy is used when there is no trust policy that
 // applies to the given artifact
-type ErrorNoApplicableTrustPolicy struct {
+//
+// Deprecated: Use NoApplicableTrustPolicyError instead.
+type ErrorNoApplicableTrustPolicy = NoApplicableTrustPolicyError
+
+// NoApplicableTrustPolicyError is used when there is no trust policy that
+// applies to the given artifact
+type NoApplicableTrustPolicyError struct {
 	Msg string
 }
 
-func (e ErrorNoApplicableTrustPolicy) Error() string {
+func (e NoApplicableTrustPolicyError) Error() string {
 	if e.Msg != "" {
 		return e.Msg
 	}
@@ -54,11 +72,17 @@ func (e ErrorNoApplicableTrustPolicy) Error() string {
 
 // ErrorSignatureRetrievalFailed is used when notation is unable to retrieve the
 // digital signature/s for the given artifact
-type ErrorSignatureRetrievalFailed struct {
+//
+// Deprecated: Use SignatureRetrievalFailedError instead.
+type ErrorSignatureRetrievalFailed = SignatureRetrievalFailedError
+
+// SignatureRetrievalFailedError is used when notation is unable to retrieve the
+// digital signature/s for the given artifact
+type SignatureRetrievalFailedError struct {
 	Msg string
 }
 
-func (e ErrorSignatureRetrievalFailed) Error() string {
+func (e SignatureRetrievalFailedError) Error() string {
 	if e.Msg != "" {
 		return e.Msg
 	}
@@ -67,11 +91,17 @@ func (e ErrorSignatureRetrievalFailed) Error() string {
 
 // ErrorVerificationFailed is used when it is determined that the digital
 // signature/s is not valid for the given artifact
-type ErrorVerificationFailed struct {
+//
+// Deprecated: Use VerificationFailedError instead.
+type ErrorVerificationFailed = VerificationFailedError
+
+// VerificationFailedError is used when it is determined that the digital
+// signature/s is not valid for the given artifact
+type VerificationFailedError struct {
 	Msg string
 }
 
-func (e ErrorVerificationFailed) Error() string {
+func (e VerificationFailedError) Error() string {
 	if e.Msg != "" {
 		return e.Msg
 	}
@@ -80,11 +110,17 @@ func (e ErrorVerificationFailed) Error() string {
 
 // ErrorUserMetadataVerificationFailed is used when the signature does not
 // contain the user specified metadata
-type ErrorUserMetadataVerificationFailed struct {
+//
+// Deprecated: Use UserMetadataVerificationFailedError instead.
+type ErrorUserMetadataVerificationFailed = UserMetadataVerificationFailedError
+
+// UserMetadataVerificationFailedError is used when the signature does not
+// contain the user specified metadata
+type UserMetadataVerificationFailedError struct {
 	Msg string
 }
 
-func (e ErrorUserMetadataVerificationFailed) Error() string {
+func (e UserMetadataVerificationFailedError) Error() string {
 	if e.Msg != "" {
 		return e.Msg
 	}
diff --git a/errors_test.go b/errors_test.go
index 29aed6ba..8b0f837b 100644
--- a/errors_test.go
+++ b/errors_test.go
@@ -91,3 +91,80 @@ func TestErrorMessages(t *testing.T) {
 		})
 	}
 }
+
+func TestCustomErrorPrintsCorrectMessage(t *testing.T) {
+	tests := []struct {
+		name string
+		err  error
+		want string
+	}{
+		{
+			name: "PushSignatureFailedError with message",
+			err:  PushSignatureFailedError{Msg: "test message"},
+			want: "failed to push signature to registry with error: test message",
+		},
+		{
+			name: "PushSignatureFailedError without message",
+			err:  PushSignatureFailedError{},
+			want: "failed to push signature to registry",
+		},
+		{
+			name: "VerificationInconclusiveError with message",
+			err:  VerificationInconclusiveError{Msg: "test message"},
+			want: "test message",
+		},
+		{
+			name: "VerificationInconclusiveError without message",
+			err:  VerificationInconclusiveError{},
+			want: "signature verification was inclusive due to an unexpected error",
+		},
+		{
+			name: "NoApplicableTrustPolicyError with message",
+			err:  NoApplicableTrustPolicyError{Msg: "test message"},
+			want: "test message",
+		},
+		{
+			name: "NoApplicableTrustPolicyError without message",
+			err:  NoApplicableTrustPolicyError{},
+			want: "there is no applicable trust policy for the given artifact",
+		},
+		{
+			name: "SignatureRetrievalFailedError with message",
+			err:  SignatureRetrievalFailedError{Msg: "test message"},
+			want: "test message",
+		},
+		{
+			name: "SignatureRetrievalFailedError without message",
+			err:  SignatureRetrievalFailedError{},
+			want: "unable to retrieve the digital signature from the registry",
+		},
+		{
+			name: "VerificationFailedError with message",
+			err:  VerificationFailedError{Msg: "test message"},
+			want: "test message",
+		},
+		{
+			name: "VerificationFailedError without message",
+			err:  VerificationFailedError{},
+			want: "signature verification failed",
+		},
+		{
+			name: "UserMetadataVerificationFailedError with message",
+			err:  UserMetadataVerificationFailedError{Msg: "test message"},
+			want: "test message",
+		},
+		{
+			name: "UserMetadataVerificationFailedError without message",
+			err:  UserMetadataVerificationFailedError{},
+			want: "unable to find specified metadata in the signature",
+		},
+	}
+
+	for _, tt := range tests {
+		t.Run(tt.name, func(t *testing.T) {
+			if got := tt.err.Error(); got != tt.want {
+				t.Errorf("Error() = %v, want %v", got, tt.want)
+			}
+		})
+	}
+}


Reviews:
user: login: shizhMSFT
state: CHANGES_REQUESTED
author_association: CONTRIBUTOR
submitted_at: 2025-04-03T06:48:36Z
user: login: qba73
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-04-03T19:13:18Z
user: login: shizhMSFT
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-04-07T05:39:15Z
user: login: qba73
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-04-08T11:42:07Z
body: LGTM
state: APPROVED
author_association: NONE
submitted_at: 2025-04-09T02:10:26Z
user: login: JeyJeyGao
body: LGTM
state: APPROVED
author_association: CONTRIBUTOR
submitted_at: 2025-04-09T02:13:11Z
user: login: shizhMSFT
body: LGTM
state: APPROVED
author_association: CONTRIBUTOR
submitted_at: 2025-04-11T07:20:23Z

Review comments:
diff_hunk: @@ -15,6 +15,8 @@ package notation
 
 // ErrorPushSignatureFailed is used when failed to push signature to the
 // target registry.
+//
+// Deprecated: Use PushSignatureFailedError instead.
 type ErrorPushSignatureFailed struct {
path: errors.go
user: login: shizhMSFT
body: Since `ErrorPushSignatureFailed` and `PushSignatureFailedError` are the exact same thing, can you do
```
type ErrorPushSignatureFailed = PushSignatureFailedError
```
The same comment applies to other types.
created_at: 2025-04-03T06:48:32Z
author_association: CONTRIBUTOR
diff_hunk: @@ -15,6 +15,8 @@ package notation
 
 // ErrorPushSignatureFailed is used when failed to push signature to the
 // target registry.
+//
+// Deprecated: Use PushSignatureFailedError instead.
 type ErrorPushSignatureFailed struct {
path: errors.go
user: login: qba73
body: > Since `ErrorPushSignatureFailed` and `PushSignatureFailedError` are the exact same thing, can you do
> 
> ```
> type ErrorPushSignatureFailed = PushSignatureFailedError
> ```
> 
> The same comment applies to other types.

@shizhMSFT updated, please let me know if it looks like you want
created_at: 2025-04-03T19:13:18Z
author_association: CONTRIBUTOR
diff_hunk: @@ -15,6 +15,8 @@ package notation
 
 // ErrorPushSignatureFailed is used when failed to push signature to the
 // target registry.
+//
+// Deprecated: Use PushSignatureFailedError instead.
 type ErrorPushSignatureFailed struct {
path: errors.go
user: login: shizhMSFT
body: LoL. I mean you can do something like
```go
// ErrorPushSignatureFailed is used when failed to push signature to the
// target registry.
//
// Deprecated: Use PushSignatureFailedError instead.
type ErrorPushSignatureFailed = PushSignatureFailedError

// PushSignatureFailedError is used when failed to push signature to the
// target registry.
type PushSignatureFailedError struct {
	Msg string
}

func (e PushSignatureFailedError) Error() string {
	if e.Msg != "" {
		return "failed to push signature to registry with error: " + e.Msg
	}
	return "failed to push signature to registry"
}
```
instead of putting it in the comment block.
created_at: 2025-04-07T05:39:12Z
author_association: CONTRIBUTOR
diff_hunk: @@ -15,6 +15,8 @@ package notation
 
 // ErrorPushSignatureFailed is used when failed to push signature to the
 // target registry.
+//
+// Deprecated: Use PushSignatureFailedError instead.
 type ErrorPushSignatureFailed struct {
path: errors.go
user: login: qba73
body: done
created_at: 2025-04-08T11:42:07Z
author_association: CONTRIBUTOR

PR comments:
user: login: FeynmanZhou
created_at: 2025-04-03T00:28:24Z
body: @qba73 Thanks for your contribution! Would you mind signing off your git commit? See the details at https://github.com/notaryproject/notation-go/pull/529/checks?check_run_id=39824512392

author_association: MEMBER
user: login: codecov[bot]
created_at: 2025-04-03T06:50:22Z
body: ## [Codecov](https://app.codecov.io/gh/notaryproject/notation-go/pull/529?dropdown=coverage&src=pr&el=h1&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=notaryproject) Report
All modified and coverable lines are covered by tests :white_check_mark:
> Project coverage is 80.92%. Comparing base [(`3bd0ac9`)](https://app.codecov.io/gh/notaryproject/notation-go/commit/3bd0ac92b2bad47e477723bdb16a968a089738ae?dropdown=coverage&el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=notaryproject) to head [(`3266304`)](https://app.codecov.io/gh/notaryproject/notation-go/commit/326630486861314517df5265200e8ede85d8ca1e?dropdown=coverage&el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=notaryproject).
> Report is 1 commits behind head on main.

<details><summary>Additional details and impacted files</summary>


```diff
@@           Coverage Diff           @@
##             main     #529   +/-   ##
=======================================
  Coverage   80.92%   80.92%           
=======================================
  Files          36       36           
  Lines        3355     3355           
=======================================
  Hits         2715     2715           
  Misses        493      493           
  Partials      147      147           
```

</details>

[:umbrella: View full report in Codecov by Sentry](https://app.codecov.io/gh/notaryproject/notation-go/pull/529?dropdown=coverage&src=pr&el=continue&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=notaryproject).   
:loudspeaker: Have feedback on the report? [Share it here](https://about.codecov.io/codecov-pr-comment-feedback/?utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=notaryproject).

<details><summary> :rocket: New features to boost your workflow: </summary>

- :snowflake: [Test Analytics](https://docs.codecov.com/docs/test-analytics): Detect flaky tests, report on failures, and find test suite problems.
</details>
author_association: NONE
user: login: qba73
created_at: 2025-04-04T06:43:09Z
body: > @qba73 Thanks for your contribution! Would you mind signing off your git commit? See the details at https://github.com/notaryproject/notation-go/pull/529/checks?check_run_id=39824512392

Done
author_association: CONTRIBUTOR