Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
27 changes: 20 additions & 7 deletions go/cmd/gitter/gitter.go
Original file line number Diff line number Diff line change
Expand Up @@ -346,8 +346,16 @@ func isAuthError(err error) bool {
errString := err.Error()

return strings.Contains(errString, "could not read Username") ||
strings.Contains(errString, "Authentication failed") ||
strings.Contains(errString, "The requested URL returned error: 403")
strings.Contains(errString, "Authentication failed")
}

func isForbiddenError(err error) bool {
if err == nil {
return false
}
errString := err.Error()

return strings.Contains(errString, "The requested URL returned error: 403")
}

func isNotFoundError(err error) bool {
Expand Down Expand Up @@ -540,6 +548,11 @@ func FetchRepo(ctx context.Context, repoURL string, forceUpdate bool) error {

// If still failing or recovery wasn't attempted, reclone the repo as final fallback
if err != nil {
if isForbiddenError(err) {
logger.WarnContext(ctx, "Fetch failed with 403 Forbidden. Using local repo.", slog.Duration("sinceLastFetch", time.Since(accessTime)), slog.Any("err", err))
return nil
}

logger.WarnContext(ctx, "Fetch and reset failed after recovery attempt, deleting repo and recloning", slog.Any("err", err))
if err := os.RemoveAll(repoPath); err != nil {
return fmt.Errorf("failed to remove repo directory for reclone: %w", err)
Expand Down Expand Up @@ -732,7 +745,7 @@ func gitHandler(w http.ResponseWriter, r *http.Request) {

// Fetch repo first
if err := doFetch(ctx, repoURL, forceUpdate); err != nil {
if isAuthError(err) {
if isAuthError(err) || isForbiddenError(err) {
statusCode = http.StatusForbidden
} else if isNotFoundError(err) {
statusCode = http.StatusNotFound
Expand Down Expand Up @@ -799,7 +812,7 @@ func cacheHandler(w http.ResponseWriter, r *http.Request) {
logger.DebugContext(ctx, "Received request: /cache")

if _, err := getFreshRepo(ctx, repoURL, body.GetForceUpdate()); err != nil {
if isAuthError(err) {
if isAuthError(err) || isForbiddenError(err) {
statusCode = http.StatusForbidden
} else if isNotFoundError(err) {
statusCode = http.StatusNotFound
Expand Down Expand Up @@ -870,7 +883,7 @@ func affectedCommitsHandler(w http.ResponseWriter, r *http.Request) {

repo, err := getFreshRepo(ctx, repoURL, body.GetForceUpdate())
if err != nil {
if isAuthError(err) {
if isAuthError(err) || isForbiddenError(err) {
statusCode = http.StatusForbidden
} else if isNotFoundError(err) {
statusCode = http.StatusNotFound
Expand Down Expand Up @@ -1010,7 +1023,7 @@ func tagsHandler(w http.ResponseWriter, r *http.Request) {
return nil, FetchRepo(ctx, repoURL, false)
}); errFetch != nil {
logger.ErrorContext(ctx, "Error fetching repo", slog.Any("error", errFetch))
if isAuthError(errFetch) {
if isAuthError(errFetch) || isForbiddenError(errFetch) {
invalidRepoCache.SetWithTTL(repoURL, http.StatusForbidden, 1, invalidRepoTTL)
statusCode = http.StatusForbidden
http.Error(w, fmt.Sprintf("Error fetching repository: %v", errFetch), statusCode)
Expand Down Expand Up @@ -1048,7 +1061,7 @@ func tagsHandler(w http.ResponseWriter, r *http.Request) {
return repo.GetRemoteTags(ctx)
})
if errLsRemote != nil {
if isAuthError(errLsRemote) {
if isAuthError(errLsRemote) || isForbiddenError(errLsRemote) {
invalidRepoCache.SetWithTTL(repoURL, http.StatusForbidden, 1, invalidRepoTTL)
statusCode = http.StatusForbidden
http.Error(w, fmt.Sprintf("Repository authentication failed: %v", errLsRemote), statusCode)
Expand Down
19 changes: 18 additions & 1 deletion go/cmd/gitter/gitter_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -146,9 +146,9 @@ func TestIsAuthError(t *testing.T) {
{errors.New("fatal: Authentication failed for 'https://github.com/google/this-repo-does-not-exist-12345.git/'"), true},
{errors.New("remote: Repository not found"), false},
{errors.New("fatal: could not read Username for 'https://github.com': terminal prompts disabled"), true},
{errors.New("The requested URL returned error: 403"), true},
{errors.New("some other error"), false},
{errors.New("git clone failed: exit status 128"), false},
{nil, false},
}

for _, tt := range tests {
Expand All @@ -158,6 +158,23 @@ func TestIsAuthError(t *testing.T) {
}
}

func TestIsForbiddenError(t *testing.T) {
tests := []struct {
err error
expected bool
}{
{errors.New("fatal: unable to access 'https://github.com/composer/composer/': The requested URL returned error: 403"), true},
{errors.New("some other error"), false},
{nil, false},
}

for _, tt := range tests {
if result := isForbiddenError(tt.err); result != tt.expected {
t.Errorf("isForbiddenError(%v) = %v, expected %v", tt.err, result, tt.expected)
}
}
}

func TestIsNotFoundError(t *testing.T) {
tests := []struct {
err error
Expand Down
Loading