Welcome to mirror list, hosted at ThFree Co, Russian Federation.

gitlab.com/gitlab-org/gitaly.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJohn Cai <jcai@gitlab.com>2022-07-25 17:15:41 +0300
committerJohn Cai <jcai@gitlab.com>2022-07-25 18:10:12 +0300
commit231bf5e66916b7460902228a765b0a44025b609a (patch)
tree63c0c613ba3da5cc860bf922c394f5178f2658bc
parent17a3fc6cae47ba8b9c96250bfb38441350c9ee8b (diff)
operations: Remove CherryPickStructuredErrors feature flagjc-remove-user-cherry-pick-ff
Now that we have been running this feature flag in production for a week without issue, we can remove it.
-rw-r--r--cmd/gitaly-git2go-v15/cherry_pick.go17
-rw-r--r--cmd/gitaly-git2go-v15/cherry_pick_test.go23
-rw-r--r--internal/gitaly/service/operations/cherry_pick.go149
-rw-r--r--internal/gitaly/service/operations/cherry_pick_test.go164
-rw-r--r--internal/metadata/featureflag/ff_cherry_pick_structured_errors.go10
5 files changed, 122 insertions, 241 deletions
diff --git a/cmd/gitaly-git2go-v15/cherry_pick.go b/cmd/gitaly-git2go-v15/cherry_pick.go
index ada0c3b97..5ebbb26b0 100644
--- a/cmd/gitaly-git2go-v15/cherry_pick.go
+++ b/cmd/gitaly-git2go-v15/cherry_pick.go
@@ -12,7 +12,6 @@ import (
git "github.com/libgit2/git2go/v33"
"gitlab.com/gitlab-org/gitaly/v15/cmd/gitaly-git2go-v15/git2goutil"
"gitlab.com/gitlab-org/gitaly/v15/internal/git2go"
- "gitlab.com/gitlab-org/gitaly/v15/internal/metadata/featureflag"
)
type cherryPickSubcommand struct{}
@@ -93,18 +92,14 @@ func (cmd *cherryPickSubcommand) cherryPick(ctx context.Context, r *git2go.Cherr
}
if index.HasConflicts() {
- if featureflag.CherryPickStructuredErrors.IsEnabled(ctx) {
- conflictingFiles, err := getConflictingFiles(index)
- if err != nil {
- return "", fmt.Errorf("getting conflicting files: %w", err)
- }
-
- return "", git2go.ConflictingFilesError{
- ConflictingFiles: conflictingFiles,
- }
+ conflictingFiles, err := getConflictingFiles(index)
+ if err != nil {
+ return "", fmt.Errorf("getting conflicting files: %w", err)
}
- return "", git2go.HasConflictsError{}
+ return "", git2go.ConflictingFilesError{
+ ConflictingFiles: conflictingFiles,
+ }
}
tree, err := index.WriteTreeTo(repo)
diff --git a/cmd/gitaly-git2go-v15/cherry_pick_test.go b/cmd/gitaly-git2go-v15/cherry_pick_test.go
index 2e3ebe78e..e9b82c8db 100644
--- a/cmd/gitaly-git2go-v15/cherry_pick_test.go
+++ b/cmd/gitaly-git2go-v15/cherry_pick_test.go
@@ -3,7 +3,6 @@
package main
import (
- "context"
"testing"
"time"
@@ -13,7 +12,6 @@ import (
"gitlab.com/gitlab-org/gitaly/v15/cmd/gitaly-git2go-v15/git2goutil"
"gitlab.com/gitlab-org/gitaly/v15/internal/git/gittest"
"gitlab.com/gitlab-org/gitaly/v15/internal/git2go"
- "gitlab.com/gitlab-org/gitaly/v15/internal/metadata/featureflag"
"gitlab.com/gitlab-org/gitaly/v15/internal/testhelper"
"gitlab.com/gitlab-org/gitaly/v15/internal/testhelper/testcfg"
)
@@ -161,11 +159,7 @@ func TestCherryPick(t *testing.T) {
}
t.Run(tc.desc, func(t *testing.T) {
- ctx := featureflag.ContextWithFeatureFlag(
- testhelper.Context(t),
- featureflag.CherryPickStructuredErrors,
- true,
- )
+ ctx := testhelper.Context(t)
committer := git.Signature{
Name: "Baz",
@@ -224,12 +218,8 @@ func TestCherryPick(t *testing.T) {
}
func TestCherryPickStructuredErrors(t *testing.T) {
- testhelper.NewFeatureSets(featureflag.CherryPickStructuredErrors).Run(t,
- testCherryPickStructuredErrors,
- )
-}
+ ctx := testhelper.Context(t)
-func testCherryPickStructuredErrors(t *testing.T, ctx context.Context) {
cfg, repo, repoPath := testcfg.BuildWithRepo(t)
testcfg.BuildGitalyGit2Go(t, cfg)
@@ -278,11 +268,6 @@ func testCherryPickStructuredErrors(t *testing.T, ctx context.Context) {
Commit: commit,
})
- if featureflag.CherryPickStructuredErrors.IsEnabled(ctx) {
- require.EqualError(t, err, "cherry-pick: there are conflicting files")
- require.ErrorAs(t, err, &git2go.ConflictingFilesError{})
- } else {
- require.EqualError(t, err, "cherry-pick: could not apply due to conflicts")
- require.ErrorAs(t, err, &git2go.HasConflictsError{})
- }
+ require.EqualError(t, err, "cherry-pick: there are conflicting files")
+ require.ErrorAs(t, err, &git2go.ConflictingFilesError{})
}
diff --git a/internal/gitaly/service/operations/cherry_pick.go b/internal/gitaly/service/operations/cherry_pick.go
index 23b0566fd..8732f84cb 100644
--- a/internal/gitaly/service/operations/cherry_pick.go
+++ b/internal/gitaly/service/operations/cherry_pick.go
@@ -11,7 +11,6 @@ import (
"gitlab.com/gitlab-org/gitaly/v15/internal/git/updateref"
"gitlab.com/gitlab-org/gitaly/v15/internal/git2go"
"gitlab.com/gitlab-org/gitaly/v15/internal/helper"
- "gitlab.com/gitlab-org/gitaly/v15/internal/metadata/featureflag"
"gitlab.com/gitlab-org/gitaly/v15/proto/go/gitalypb"
"google.golang.org/grpc/codes"
"google.golang.org/grpc/status"
@@ -64,62 +63,43 @@ func (s *Server) UserCherryPick(ctx context.Context, req *gitalypb.UserCherryPic
Mainline: mainline,
})
if err != nil {
- if featureflag.CherryPickStructuredErrors.IsEnabled(ctx) {
- var conflictErr git2go.ConflictingFilesError
- var emptyErr git2go.EmptyError
-
- switch {
- case errors.As(err, &conflictErr):
- conflictingFiles := make([][]byte, 0, len(conflictErr.ConflictingFiles))
- for _, conflictingFile := range conflictErr.ConflictingFiles {
- conflictingFiles = append(conflictingFiles, []byte(conflictingFile))
- }
-
- detailedErr, errGeneratingDetailedErr := helper.ErrWithDetails(
- helper.ErrFailedPreconditionf("cherry pick: %w", err),
- &gitalypb.UserCherryPickError{
- Error: &gitalypb.UserCherryPickError_CherryPickConflict{
- CherryPickConflict: &gitalypb.MergeConflictError{
- ConflictingFiles: conflictingFiles,
- },
+ var conflictErr git2go.ConflictingFilesError
+ var emptyErr git2go.EmptyError
+
+ switch {
+ case errors.As(err, &conflictErr):
+ conflictingFiles := make([][]byte, 0, len(conflictErr.ConflictingFiles))
+ for _, conflictingFile := range conflictErr.ConflictingFiles {
+ conflictingFiles = append(conflictingFiles, []byte(conflictingFile))
+ }
+
+ detailedErr, errGeneratingDetailedErr := helper.ErrWithDetails(
+ helper.ErrFailedPreconditionf("cherry pick: %w", err),
+ &gitalypb.UserCherryPickError{
+ Error: &gitalypb.UserCherryPickError_CherryPickConflict{
+ CherryPickConflict: &gitalypb.MergeConflictError{
+ ConflictingFiles: conflictingFiles,
},
},
- )
- if errGeneratingDetailedErr != nil {
- return nil, helper.ErrInternalf("error details: %w", err)
- }
-
- return nil, detailedErr
- case errors.As(err, &emptyErr):
- detailedErr, errGeneratingDetailedErr := helper.ErrWithDetails(
- helper.ErrFailedPrecondition(err),
- &gitalypb.UserCherryPickError{
- Error: &gitalypb.UserCherryPickError_ChangesAlreadyApplied{},
- },
- )
- if errGeneratingDetailedErr != nil {
- return nil, helper.ErrInternalf("error details: %w", err)
- }
-
- return nil, detailedErr
- case errors.Is(err, git2go.ErrInvalidArgument):
- return nil, helper.ErrInvalidArgument(err)
- default:
- return nil, helper.ErrInternalf("cherry-pick command: %w", err)
+ },
+ )
+ if errGeneratingDetailedErr != nil {
+ return nil, helper.ErrInternalf("error details: %w", err)
}
- }
- switch {
- case errors.As(err, &git2go.HasConflictsError{}) || errors.As(err, &git2go.ConflictingFilesError{}):
- return &gitalypb.UserCherryPickResponse{
- CreateTreeError: err.Error(),
- CreateTreeErrorCode: gitalypb.UserCherryPickResponse_CONFLICT,
- }, nil
- case errors.As(err, &git2go.EmptyError{}):
- return &gitalypb.UserCherryPickResponse{
- CreateTreeError: err.Error(),
- CreateTreeErrorCode: gitalypb.UserCherryPickResponse_EMPTY,
- }, nil
+ return nil, detailedErr
+ case errors.As(err, &emptyErr):
+ detailedErr, errGeneratingDetailedErr := helper.ErrWithDetails(
+ helper.ErrFailedPrecondition(err),
+ &gitalypb.UserCherryPickError{
+ Error: &gitalypb.UserCherryPickError_ChangesAlreadyApplied{},
+ },
+ )
+ if errGeneratingDetailedErr != nil {
+ return nil, helper.ErrInternalf("error details: %w", err)
+ }
+
+ return nil, detailedErr
case errors.Is(err, git2go.ErrInvalidArgument):
return nil, helper.ErrInvalidArgument(err)
default:
@@ -148,57 +128,46 @@ func (s *Server) UserCherryPick(ctx context.Context, req *gitalypb.UserCherryPic
return nil, err
}
if !ancestor {
- if featureflag.CherryPickStructuredErrors.IsEnabled(ctx) {
- detailedErr, errGeneratingDetailedErr := helper.ErrWithDetails(
- helper.ErrFailedPrecondition(errors.New("cherry-pick: branch diverged")),
- &gitalypb.UserCherryPickError{
- Error: &gitalypb.UserCherryPickError_TargetBranchDiverged{
- TargetBranchDiverged: &gitalypb.NotAncestorError{
- ParentRevision: []byte(oldrev.Revision()),
- ChildRevision: []byte(newrev),
- },
+ detailedErr, errGeneratingDetailedErr := helper.ErrWithDetails(
+ helper.ErrFailedPrecondition(errors.New("cherry-pick: branch diverged")),
+ &gitalypb.UserCherryPickError{
+ Error: &gitalypb.UserCherryPickError_TargetBranchDiverged{
+ TargetBranchDiverged: &gitalypb.NotAncestorError{
+ ParentRevision: []byte(oldrev.Revision()),
+ ChildRevision: []byte(newrev),
},
- })
-
- if errGeneratingDetailedErr != nil {
- return nil, helper.ErrInternalf("error details: %w", err)
- }
+ },
+ })
- return nil, detailedErr
+ if errGeneratingDetailedErr != nil {
+ return nil, helper.ErrInternalf("error details: %w", err)
}
- return &gitalypb.UserCherryPickResponse{
- CommitError: "Branch diverged",
- }, nil
+ return nil, detailedErr
}
}
if err := s.updateReferenceWithHooks(ctx, req.GetRepository(), req.User, quarantineDir, referenceName, newrev, oldrev); err != nil {
- if featureflag.CherryPickStructuredErrors.IsEnabled(ctx) {
- var customHookErr updateref.CustomHookError
-
- if errors.As(err, &customHookErr) {
- detailedErr, errGeneratingDetailedErr := helper.ErrWithDetails(
- helper.ErrFailedPrecondition(errors.New("access check failed")),
- &gitalypb.UserCherryPickError{
- Error: &gitalypb.UserCherryPickError_AccessCheck{
- AccessCheck: &gitalypb.AccessCheckError{
- ErrorMessage: strings.TrimSuffix(customHookErr.Error(), "\n"),
- },
- },
- })
+ var customHookErr updateref.CustomHookError
- if errGeneratingDetailedErr != nil {
- return nil, helper.ErrInternalf("error details: %w", err)
- }
+ if errors.As(err, &customHookErr) {
+ detailedErr, errGeneratingDetailedErr := helper.ErrWithDetails(
+ helper.ErrFailedPrecondition(errors.New("access check failed")),
+ &gitalypb.UserCherryPickError{
+ Error: &gitalypb.UserCherryPickError_AccessCheck{
+ AccessCheck: &gitalypb.AccessCheckError{
+ ErrorMessage: strings.TrimSuffix(customHookErr.Error(), "\n"),
+ },
+ },
+ })
- return nil, detailedErr
+ if errGeneratingDetailedErr != nil {
+ return nil, helper.ErrInternalf("error details: %w", err)
}
- return nil, fmt.Errorf("update reference with hooks: %w", err)
+ return nil, detailedErr
}
- var customHookErr updateref.CustomHookError
if errors.As(err, &customHookErr) {
return &gitalypb.UserCherryPickResponse{
PreReceiveError: customHookErr.Error(),
diff --git a/internal/gitaly/service/operations/cherry_pick_test.go b/internal/gitaly/service/operations/cherry_pick_test.go
index ccc8bc6e9..6fad1115f 100644
--- a/internal/gitaly/service/operations/cherry_pick_test.go
+++ b/internal/gitaly/service/operations/cherry_pick_test.go
@@ -3,7 +3,6 @@
package operations
import (
- "context"
"errors"
"fmt"
"path/filepath"
@@ -16,7 +15,6 @@ import (
"gitlab.com/gitlab-org/gitaly/v15/internal/git/localrepo"
"gitlab.com/gitlab-org/gitaly/v15/internal/helper"
"gitlab.com/gitlab-org/gitaly/v15/internal/helper/text"
- "gitlab.com/gitlab-org/gitaly/v15/internal/metadata/featureflag"
"gitlab.com/gitlab-org/gitaly/v15/internal/testhelper"
"gitlab.com/gitlab-org/gitaly/v15/proto/go/gitalypb"
"google.golang.org/grpc/codes"
@@ -349,13 +347,7 @@ func TestServer_UserCherryPick_failedValidations(t *testing.T) {
func TestServer_UserCherryPick_failedWithPreReceiveError(t *testing.T) {
t.Parallel()
- testhelper.NewFeatureSets(featureflag.CherryPickStructuredErrors).Run(t, testServerUserCherryPickFailedWithPreReceiveError)
-}
-
-func testServerUserCherryPickFailedWithPreReceiveError(t *testing.T, ctx context.Context) {
- t.Parallel()
-
- ctx, cfg, repoProto, repoPath, client := setupOperationsService(t, ctx)
+ ctx, cfg, repoProto, repoPath, client := setupOperationsService(t, testhelper.Context(t))
repo := localrepo.NewTestRepo(t, cfg, repoProto)
@@ -380,37 +372,27 @@ func testServerUserCherryPickFailedWithPreReceiveError(t *testing.T, ctx context
gittest.WriteCustomHook(t, repoPath, hookName, hookContent)
response, err := client.UserCherryPick(ctx, request)
- if featureflag.CherryPickStructuredErrors.IsEnabled(ctx) {
- require.Nil(t, response)
- testhelper.RequireGrpcError(t, errWithDetails(t,
- helper.ErrFailedPrecondition(
- errors.New("access check failed"),
- ),
- &gitalypb.UserCherryPickError{
- Error: &gitalypb.UserCherryPickError_AccessCheck{
- AccessCheck: &gitalypb.AccessCheckError{
- ErrorMessage: "GL_ID=user-123",
- },
+ require.Nil(t, response)
+ testhelper.RequireGrpcError(t, errWithDetails(t,
+ helper.ErrFailedPrecondition(
+ errors.New("access check failed"),
+ ),
+ &gitalypb.UserCherryPickError{
+ Error: &gitalypb.UserCherryPickError_AccessCheck{
+ AccessCheck: &gitalypb.AccessCheckError{
+ ErrorMessage: "GL_ID=user-123",
},
},
- ), err)
- } else {
- require.NoError(t, err)
- require.Contains(t, response.PreReceiveError, "GL_ID="+gittest.TestUser.GlId)
- }
+ },
+ ), err)
})
}
}
func TestServer_UserCherryPick_failedWithCreateTreeError(t *testing.T) {
t.Parallel()
- testhelper.NewFeatureSets(featureflag.CherryPickStructuredErrors).Run(t, testServerUserCherryPickFailedWithCreateTreeError)
-}
-func testServerUserCherryPickFailedWithCreateTreeError(t *testing.T, ctx context.Context) {
- t.Parallel()
-
- ctx, cfg, repoProto, repoPath, client := setupOperationsService(t, ctx)
+ ctx, cfg, repoProto, repoPath, client := setupOperationsService(t, testhelper.Context(t))
repo := localrepo.NewTestRepo(t, cfg, repoProto)
@@ -430,32 +412,21 @@ func testServerUserCherryPickFailedWithCreateTreeError(t *testing.T, ctx context
}
response, err := client.UserCherryPick(ctx, request)
- if featureflag.CherryPickStructuredErrors.IsEnabled(ctx) {
- require.Nil(t, response)
- testhelper.RequireGrpcError(t, errWithDetails(t,
- helper.ErrFailedPrecondition(
- errors.New("cherry-pick: could not apply because the result was empty"),
- ),
- &gitalypb.UserCherryPickError{
- Error: &gitalypb.UserCherryPickError_ChangesAlreadyApplied{},
- },
- ), err)
- } else {
- require.NoError(t, err)
- require.NotEmpty(t, response.CreateTreeError)
- require.Equal(t, gitalypb.UserCherryPickResponse_EMPTY, response.CreateTreeErrorCode)
- }
+ require.Nil(t, response)
+ testhelper.RequireGrpcError(t, errWithDetails(t,
+ helper.ErrFailedPrecondition(
+ errors.New("cherry-pick: could not apply because the result was empty"),
+ ),
+ &gitalypb.UserCherryPickError{
+ Error: &gitalypb.UserCherryPickError_ChangesAlreadyApplied{},
+ },
+ ), err)
}
func TestServer_UserCherryPick_failedWithCommitError(t *testing.T) {
t.Parallel()
- testhelper.NewFeatureSets(featureflag.CherryPickStructuredErrors).Run(t, testServerUserCherryPickFailedWithCommitError)
-}
-func testServerUserCherryPickFailedWithCommitError(t *testing.T, ctx context.Context) {
- t.Parallel()
-
- ctx, cfg, repoProto, repoPath, client := setupOperationsService(t, ctx)
+ ctx, cfg, repoProto, repoPath, client := setupOperationsService(t, testhelper.Context(t))
repo := localrepo.NewTestRepo(t, cfg, repoProto)
@@ -477,36 +448,24 @@ func testServerUserCherryPickFailedWithCommitError(t *testing.T, ctx context.Con
}
response, err := client.UserCherryPick(ctx, request)
- if featureflag.CherryPickStructuredErrors.IsEnabled(ctx) {
- require.Nil(t, response)
- s, ok := status.FromError(err)
- require.True(t, ok)
-
- details := s.Details()
- require.Len(t, details, 1)
- detailedErr, ok := details[0].(*gitalypb.UserCherryPickError)
- require.True(t, ok)
-
- targetBranchDivergedErr, ok := detailedErr.Error.(*gitalypb.UserCherryPickError_TargetBranchDiverged)
- require.True(t, ok)
- assert.Equal(t, []byte("8a0f2ee90d940bfb0ba1e14e8214b0649056e4ab"), targetBranchDivergedErr.TargetBranchDiverged.ParentRevision)
- } else {
- require.NoError(t, err)
- require.Equal(t, "Branch diverged", response.CommitError)
- }
+ require.Nil(t, response)
+ s, ok := status.FromError(err)
+ require.True(t, ok)
+
+ details := s.Details()
+ require.Len(t, details, 1)
+ detailedErr, ok := details[0].(*gitalypb.UserCherryPickError)
+ require.True(t, ok)
+
+ targetBranchDivergedErr, ok := detailedErr.Error.(*gitalypb.UserCherryPickError_TargetBranchDiverged)
+ require.True(t, ok)
+ assert.Equal(t, []byte("8a0f2ee90d940bfb0ba1e14e8214b0649056e4ab"), targetBranchDivergedErr.TargetBranchDiverged.ParentRevision)
}
func TestServerUserCherryPickRailedWithConflict(t *testing.T) {
t.Parallel()
- testhelper.NewFeatureSets(featureflag.CherryPickStructuredErrors).Run(
- t,
- testServerUserCherryPickRailedWithConflict,
- )
-}
-
-func testServerUserCherryPickRailedWithConflict(t *testing.T, ctx context.Context) {
- ctx, cfg, repoProto, repoPath, client := setupOperationsService(t, ctx)
+ ctx, cfg, repoProto, repoPath, client := setupOperationsService(t, testhelper.Context(t))
repo := localrepo.NewTestRepo(t, cfg, repoProto)
@@ -526,25 +485,19 @@ func testServerUserCherryPickRailedWithConflict(t *testing.T, ctx context.Contex
}
response, err := client.UserCherryPick(ctx, request)
- if featureflag.CherryPickStructuredErrors.IsEnabled(ctx) {
- require.Nil(t, response)
- s, ok := status.FromError(err)
- require.True(t, ok)
-
- details := s.Details()
- require.Len(t, details, 1)
- detailedErr, ok := details[0].(*gitalypb.UserCherryPickError)
- require.True(t, ok)
-
- conflictErr, ok := detailedErr.Error.(*gitalypb.UserCherryPickError_CherryPickConflict)
- require.True(t, ok)
- require.Len(t, conflictErr.CherryPickConflict.ConflictingFiles, 1)
- assert.Equal(t, []byte("NEW_FILE.md"), conflictErr.CherryPickConflict.ConflictingFiles[0])
- } else {
- require.NoError(t, err)
- require.NotEmpty(t, response.CreateTreeError)
- require.Equal(t, gitalypb.UserCherryPickResponse_CONFLICT, response.CreateTreeErrorCode)
- }
+ require.Nil(t, response)
+ s, ok := status.FromError(err)
+ require.True(t, ok)
+
+ details := s.Details()
+ require.Len(t, details, 1)
+ detailedErr, ok := details[0].(*gitalypb.UserCherryPickError)
+ require.True(t, ok)
+
+ conflictErr, ok := detailedErr.Error.(*gitalypb.UserCherryPickError_CherryPickConflict)
+ require.True(t, ok)
+ require.Len(t, conflictErr.CherryPickConflict.ConflictingFiles, 1)
+ assert.Equal(t, []byte("NEW_FILE.md"), conflictErr.CherryPickConflict.ConflictingFiles[0])
}
func TestServer_UserCherryPick_successfulWithGivenCommits(t *testing.T) {
@@ -605,13 +558,7 @@ func TestServer_UserCherryPick_successfulWithGivenCommits(t *testing.T) {
func TestServer_UserCherryPick_quarantine(t *testing.T) {
t.Parallel()
- testhelper.NewFeatureSets(featureflag.CherryPickStructuredErrors).Run(t, testServerUserCherryPickQuarantine)
-}
-
-func testServerUserCherryPickQuarantine(t *testing.T, ctx context.Context) {
- t.Parallel()
-
- ctx, cfg, repoProto, repoPath, client := setupOperationsService(t, ctx)
+ ctx, cfg, repoProto, repoPath, client := setupOperationsService(t, testhelper.Context(t))
repo := localrepo.NewTestRepo(t, cfg, repoProto)
// Set up a hook that parses the new object and then aborts the update. Like this, we can
@@ -636,14 +583,9 @@ func testServerUserCherryPickQuarantine(t *testing.T, ctx context.Context) {
}
response, err := client.UserCherryPick(ctx, request)
- if featureflag.CherryPickStructuredErrors.IsEnabled(ctx) {
- require.Nil(t, response)
- require.NotNil(t, err)
- assert.Contains(t, err.Error(), "access check failed")
- } else {
- require.NoError(t, err)
- require.NotNil(t, response)
- }
+ require.Nil(t, response)
+ require.NotNil(t, err)
+ assert.Contains(t, err.Error(), "access check failed")
hookOutput := testhelper.MustReadFile(t, outputPath)
oid, err := git.ObjectHashSHA1.FromHex(text.ChompBytes(hookOutput))
diff --git a/internal/metadata/featureflag/ff_cherry_pick_structured_errors.go b/internal/metadata/featureflag/ff_cherry_pick_structured_errors.go
deleted file mode 100644
index 594fddf3c..000000000
--- a/internal/metadata/featureflag/ff_cherry_pick_structured_errors.go
+++ /dev/null
@@ -1,10 +0,0 @@
-package featureflag
-
-// CherryPickStructuredErrors enables the UserCherryPick RPC to return
-// structured errors.
-var CherryPickStructuredErrors = NewFeatureFlag(
- "cherry_pick_structured_errors",
- "v15.2.0",
- "https://gitlab.com/gitlab-org/gitaly/-/issues/4325",
- false,
-)