Skip to content

Commit 558f5de

Browse files
authored
runner: fallback when git extensions are unsupported (#1074)
## Summary - add a `project.WithAllowUnsupportedGitExtensions` option for `NewDirProject` - when enabled, fall back to plain directory mode if go-git fails on unsupported repository extensions - enable this option in runner v2 project conversion so startup sessions do not fail in repos with `extensions.worktreeConfig` - add a focused test that reproduces unsupported extension behavior and verifies fallback ## Testing - go test ./project -run '^TestNewDirProject_FallbackOnUnsupportedGitExtensions$' - go test ./runnerv2service -run '^TestRunnerServiceServerCreateSession$' - go test ./pkg/agent/server ## Notes - `go test ./project` fails in this local environment because `direnv` is not installed; unchanged pre-existing dependency in project tests. --------- Signed-off-by: Jeremy lewi <jeremy@lewi.us>
1 parent 2255d14 commit 558f5de

File tree

7 files changed

+62
-6
lines changed

7 files changed

+62
-6
lines changed

cmd/common.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,8 @@ func getProjectWithEnvDir(enabled bool) (*project.Project, error) {
8585
opts = append(opts, project.WithEnvFilesReadOrder(fEnvOrder))
8686
}
8787

88+
opts = append(opts, project.WithAllowUnsupportedGitExtensions(true))
89+
8890
var err error
8991
proj, err = project.NewDirProject(projDir, opts...)
9092
if err != nil {

internal/config/autoconfig/autoconfig.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -219,6 +219,8 @@ func getProject(c *config.Config, logger *zap.Logger) (*project.Project, error)
219219
opts = append(opts, project.WithFindRepoUpward())
220220
}
221221

222+
opts = append(opts, project.WithAllowUnsupportedGitExtensions(true))
223+
222224
return project.NewDirProject(projDir, opts...)
223225
}
224226

project/project.go

Lines changed: 31 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -127,6 +127,15 @@ func WithLogger(logger *zap.Logger) ProjectOption {
127127
}
128128
}
129129

130+
// WithAllowUnsupportedGitExtensions configures NewDirProject to continue in
131+
// plain directory mode when go-git can't open a repository due to unsupported
132+
// repository extensions.
133+
func WithAllowUnsupportedGitExtensions(value bool) ProjectOption {
134+
return func(p *Project) {
135+
p.allowUnsupportedGitExtensions = value
136+
}
137+
}
138+
130139
type Project struct {
131140
// filePath is used for file-based projects.
132141
filePath string
@@ -143,6 +152,9 @@ type Project struct {
143152
repo *git.Repository
144153
plainOpenOptions *git.PlainOpenOptions
145154
respectGitignore bool
155+
// allowUnsupportedGitExtensions keeps project initialization working even
156+
// if go-git cannot parse repository extensions.
157+
allowUnsupportedGitExtensions bool
146158

147159
// envFilesReadOrder is a list of paths to .env files
148160
// to read from.
@@ -174,6 +186,12 @@ func normalizeAndValidatePath(path string) (string, error) {
174186
return path, nil
175187
}
176188

189+
func isUnsupportedGitOpenError(err error) bool {
190+
return errors.Is(err, git.ErrUnsupportedExtensionRepositoryFormatVersion) ||
191+
errors.Is(err, git.ErrUnknownExtension) ||
192+
errors.Is(err, git.ErrUnsupportedRepositoryFormatVersion)
193+
}
194+
177195
func NewDirProject(
178196
dir string,
179197
opts ...ProjectOption,
@@ -184,6 +202,10 @@ func NewDirProject(
184202
opt(p)
185203
}
186204

205+
if p.logger == nil {
206+
p.logger = zap.NewNop()
207+
}
208+
187209
var err error
188210

189211
dir, err = normalizeAndValidatePath(dir)
@@ -204,7 +226,15 @@ func NewDirProject(
204226
openOptions,
205227
)
206228
if err != nil && !errors.Is(err, git.ErrRepositoryNotExists) {
207-
return nil, errors.Wrapf(err, "failed to open dir-based project %q", dir)
229+
if !p.allowUnsupportedGitExtensions || !isUnsupportedGitOpenError(err) {
230+
return nil, errors.Wrapf(err, "failed to open dir-based project %q", dir)
231+
}
232+
233+
p.logger.Info(
234+
"failed to open git repository due to unsupported extensions; continuing with directory project",
235+
zap.String("dir", dir),
236+
zap.Error(err),
237+
)
208238
}
209239

210240
if p.repo != nil {
@@ -215,10 +245,6 @@ func NewDirProject(
215245
p.fs = wt.Filesystem
216246
}
217247

218-
if p.logger == nil {
219-
p.logger = zap.NewNop()
220-
}
221-
222248
return p, nil
223249
}
224250

project/project_test.go

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import (
66
"path/filepath"
77
"testing"
88

9+
"github.com/go-git/go-git/v5"
910
"github.com/stretchr/testify/assert"
1011
"github.com/stretchr/testify/require"
1112

@@ -76,6 +77,27 @@ func TestNewDirProject(t *testing.T) {
7677
})
7778
}
7879

80+
func TestNewDirProject_FallbackOnUnsupportedGitExtensions(t *testing.T) {
81+
repoDir := t.TempDir()
82+
_, err := git.PlainInit(repoDir, false)
83+
require.NoError(t, err)
84+
85+
configPath := filepath.Join(repoDir, ".git", "config")
86+
f, err := os.OpenFile(configPath, os.O_APPEND|os.O_WRONLY, 0)
87+
require.NoError(t, err)
88+
_, err = f.WriteString("\n[extensions]\n\tworktreeConfig = true\n")
89+
require.NoError(t, err)
90+
require.NoError(t, f.Close())
91+
92+
_, err = NewDirProject(repoDir)
93+
require.Error(t, err)
94+
95+
p, err := NewDirProject(repoDir, WithAllowUnsupportedGitExtensions(true))
96+
require.NoError(t, err)
97+
require.Nil(t, p.repo)
98+
assert.Equal(t, repoDir, p.Root())
99+
}
100+
79101
func TestNewFileProject(t *testing.T) {
80102
temp := t.TempDir()
81103
testData := teststub.Setup(t, temp)

project/projectservice/project_service.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -103,6 +103,8 @@ func projectFromReq(req *projectv1.LoadRequest) (*project.Project, error) {
103103
opts = append(opts, project.WithFindRepoUpward())
104104
}
105105

106+
opts = append(opts, project.WithAllowUnsupportedGitExtensions(true))
107+
106108
return project.NewDirProject(v.Directory.Path, opts...)
107109
case *projectv1.LoadRequest_File:
108110
return project.NewFileProject(v.File.Path)

runner/service.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -202,6 +202,8 @@ func ConvertRunnerProject(runnerProj *runnerv1.Project) (*project.Project, error
202202
opts = append(opts, project.WithEnvFilesReadOrder(runnerProj.EnvLoadOrder))
203203
}
204204

205+
opts = append(opts, project.WithAllowUnsupportedGitExtensions(true))
206+
205207
proj, err := project.NewDirProject(runnerProj.Root, opts...)
206208
if err != nil {
207209
return nil, err

runnerv2service/convert.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ func convertProtoProjectToProject(runnerProj *runnerv2.Project) (*project.Projec
2020
return nil, nil
2121
}
2222

23-
opts := project.DefaultProjectOptions[:]
23+
opts := append(project.DefaultProjectOptions[:], project.WithAllowUnsupportedGitExtensions(true))
2424

2525
if runnerProj.EnvLoadOrder != nil {
2626
opts = append(opts, project.WithEnvFilesReadOrder(runnerProj.EnvLoadOrder))

0 commit comments

Comments
 (0)