Skip to content

Commit 8d38e50

Browse files
authored
Merge pull request #141 from Keyruu/main
feat: add submodule support
2 parents 269ef43 + fa37079 commit 8d38e50

File tree

17 files changed

+244
-31
lines changed

17 files changed

+244
-31
lines changed

cmd/run.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -109,7 +109,7 @@ var runCmd = &cobra.Command{
109109
sched := scheduler.New()
110110
sched.FetchRemotes(fetcher, cfg.Remotes)
111111

112-
builder := builder.New(store, executor, gitConfig.Path, gitConfig.Dir, cfg.SystemAttr, cfg.Hostname, 30*time.Minute, 30*time.Minute)
112+
builder := builder.New(store, executor, gitConfig.Path, gitConfig.Dir, cfg.SystemAttr, cfg.Hostname, gitConfig.Submodules, 30*time.Minute, 30*time.Minute)
113113
deployer := deployer.New(store, executor.Deploy, lastDeployment, cfg.PostDeploymentCommand)
114114

115115
mode, err := manager.ParseMode(cfg.BuildConfirmer.Mode)

docs/generated-module-options.md

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -801,6 +801,28 @@ one of “flake”, “nix”
801801

802802

803803

804+
## services\.comin\.submodules
805+
806+
807+
808+
Whether to fetch and include Git submodules when cloning the repository\.
809+
When enabled, this adds ?submodules=1 to the flake URL\.
810+
811+
812+
813+
*Type:*
814+
boolean
815+
816+
817+
818+
*Default:*
819+
820+
```nix
821+
false
822+
```
823+
824+
825+
804826
## services\.comin\.systemAttr
805827

806828

internal/builder/builder.go

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ type Builder struct {
3535
repositoryPath string
3636
repositoryDir string
3737
systemAttr string
38+
submodules bool
3839
evalTimeout time.Duration
3940
buildTimeout time.Duration
4041

@@ -62,15 +63,16 @@ type Builder struct {
6263
isSuspended bool
6364
}
6465

65-
func New(store *store.Store, executor executor.Executor, repositoryPath, repositoryDir, systemAttr, hostname string, evalTimeout time.Duration, buildTimeout time.Duration) *Builder {
66-
logrus.Infof("builder: initialization with repositoryPath=%s, repositoryDir=%s, systemAttr=%s, hostname=%s, evalTimeout=%fs, buildTimeout=%fs, )",
67-
repositoryPath, repositoryDir, systemAttr, hostname, evalTimeout.Seconds(), buildTimeout.Seconds())
66+
func New(store *store.Store, executor executor.Executor, repositoryPath, repositoryDir, systemAttr, hostname string, submodules bool, evalTimeout time.Duration, buildTimeout time.Duration) *Builder {
67+
logrus.Infof("builder: initialization with repositoryPath=%s, repositoryDir=%s, systemAttr=%s, hostname=%s, submodules=%v, evalTimeout=%fs, buildTimeout=%fs, )",
68+
repositoryPath, repositoryDir, systemAttr, hostname, submodules, evalTimeout.Seconds(), buildTimeout.Seconds())
6869
return &Builder{
6970
store: store,
7071
executor: executor,
7172
repositoryPath: repositoryPath,
7273
repositoryDir: repositoryDir,
7374
systemAttr: systemAttr,
75+
submodules: submodules,
7476
hostname: hostname,
7577
evalTimeout: evalTimeout,
7678
buildTimeout: buildTimeout,
@@ -146,6 +148,7 @@ type Evaluator struct {
146148
systemAttr string
147149
commitId string
148150
hostname string
151+
submodules bool
149152

150153
evalFunc executor.EvalFunc
151154

@@ -155,7 +158,7 @@ type Evaluator struct {
155158
}
156159

157160
func (r *Evaluator) Run(ctx context.Context) (err error) {
158-
r.drvPath, r.outPath, r.machineId, err = r.evalFunc(ctx, r.repositoryPath, r.repostorySubdir, r.commitId, r.systemAttr, r.hostname)
161+
r.drvPath, r.outPath, r.machineId, err = r.evalFunc(ctx, r.repositoryPath, r.repostorySubdir, r.commitId, r.systemAttr, r.hostname, r.submodules)
159162
return err
160163
}
161164

@@ -194,6 +197,7 @@ func (b *Builder) Eval(ctx context.Context, rs *protobuf.RepositoryStatus) error
194197
repositoryPath: g.RepositoryPath,
195198
repostorySubdir: g.RepositorySubdir,
196199
systemAttr: g.SystemAttr,
200+
submodules: b.submodules,
197201

198202
commitId: g.SelectedCommitId,
199203
evalFunc: b.executor.Eval,

internal/builder/builder_test.go

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ func (n ExecutorMock) IsStorePathExist(storePath string) bool {
3333
func (n ExecutorMock) Deploy(ctx context.Context, outPath, operation string) (needToRestartComin bool, profilePath string, err error) {
3434
return false, "", nil
3535
}
36-
func (n ExecutorMock) Eval(ctx context.Context, repositoryPath, repositorySubdir, commitId, systemAttr, hostname string) (drvPath string, outPath string, machineId string, err error) {
36+
func (n ExecutorMock) Eval(ctx context.Context, repositoryPath, repositorySubdir, commitId, systemAttr, hostname string, submodules bool) (drvPath string, outPath string, machineId string, err error) {
3737
select {
3838
case <-ctx.Done():
3939
return "", "", "", ctx.Err()
@@ -69,7 +69,7 @@ func TestBuilderBuild(t *testing.T) {
6969
s, err := store.New(bk, tmp+"/state.json", tmp+"/gcroots", 1, 1)
7070
assert.Nil(t, err)
7171
eMock := NewExecutorMock(false)
72-
b := New(s, eMock, "", "", "", "my-machine", 2*time.Second, 2*time.Second)
72+
b := New(s, eMock, "", "", "", "my-machine", false, 2*time.Second, 2*time.Second)
7373
ctx := t.Context()
7474

7575
// Run the evaluator
@@ -133,7 +133,7 @@ func TestEval(t *testing.T) {
133133
s, err := store.New(bk, tmp+"/state.json", tmp+"/gcroots", 1, 1)
134134
assert.Nil(t, err)
135135
eMock := NewExecutorMock(false)
136-
b := New(s, eMock, "", "", "", "", 5*time.Second, 5*time.Second)
136+
b := New(s, eMock, "", "", "", "", false, 5*time.Second, 5*time.Second)
137137
_ = b.Eval(t.Context(), &protobuf.RepositoryStatus{})
138138
assert.True(t, b.isEvaluating.Load())
139139
eMock.evalDone <- struct{}{}
@@ -155,7 +155,7 @@ func TestEvalAlreadyBuilt(t *testing.T) {
155155
s, err := store.New(bk, tmp+"/state.json", tmp+"/gcroots", 1, 1)
156156
assert.Nil(t, err)
157157
eMock := NewExecutorMock(true)
158-
b := New(s, eMock, "", "", "", "", 5*time.Second, 5*time.Second)
158+
b := New(s, eMock, "", "", "", "", false, 5*time.Second, 5*time.Second)
159159
_ = b.Eval(t.Context(), &protobuf.RepositoryStatus{})
160160
assert.True(t, b.IsEvaluating())
161161

@@ -179,7 +179,7 @@ func TestBuilderPreemption(t *testing.T) {
179179
s, err := store.New(bk, tmp+"/state.json", tmp+"/gcroots", 1, 1)
180180
assert.Nil(t, err)
181181
eMock := NewExecutorMock(false)
182-
b := New(s, eMock, "", "", "", "", 5*time.Second, 5*time.Second)
182+
b := New(s, eMock, "", "", "", "", false, 5*time.Second, 5*time.Second)
183183
_ = b.Eval(t.Context(), &protobuf.RepositoryStatus{SelectedCommitId: "commit-1"})
184184
assert.True(t, b.isEvaluating.Load())
185185
assert.EventuallyWithT(t, func(c *assert.CollectT) {
@@ -202,7 +202,7 @@ func TestBuilderStop(t *testing.T) {
202202
s, err := store.New(bk, tmp+"/state.json", tmp+"/gcroots", 1, 1)
203203
assert.Nil(t, err)
204204
eMock := NewExecutorMock(false)
205-
b := New(s, eMock, "", "", "", "", 5*time.Second, 5*time.Second)
205+
b := New(s, eMock, "", "", "", "", false, 5*time.Second, 5*time.Second)
206206
_ = b.Eval(t.Context(), &protobuf.RepositoryStatus{})
207207
assert.True(t, b.isEvaluating.Load())
208208
b.Stop()
@@ -220,7 +220,7 @@ func TestBuilderTimeout(t *testing.T) {
220220
s, err := store.New(bk, tmp+"/state.json", tmp+"/gcroots", 1, 1)
221221
assert.Nil(t, err)
222222
eMock := NewExecutorMock(false)
223-
b := New(s, eMock, "", "", "", "", 1*time.Second, 5*time.Second)
223+
b := New(s, eMock, "", "", "", "", false, 1*time.Second, 5*time.Second)
224224
_ = b.Eval(t.Context(), &protobuf.RepositoryStatus{})
225225
assert.True(t, b.isEvaluating.Load())
226226
assert.EventuallyWithT(t, func(c *assert.CollectT) {
@@ -237,7 +237,7 @@ func TestBuilderSuspend(t *testing.T) {
237237
s, err := store.New(bk, tmp+"/state.json", tmp+"/gcroots", 1, 1)
238238
assert.Nil(t, err)
239239
eMock := NewExecutorMock(false)
240-
b := New(s, eMock, "", "", "", "", 1*time.Second, 5*time.Second)
240+
b := New(s, eMock, "", "", "", "", false, 1*time.Second, 5*time.Second)
241241
_ = b.Suspend()
242242
assert.True(t, b.isSuspended)
243243
_ = b.Eval(t.Context(), &protobuf.RepositoryStatus{})

internal/config/config.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -82,5 +82,6 @@ func MkGitConfig(config types.Configuration) types.GitConfig {
8282
Dir: config.RepositorySubdir,
8383
Remotes: config.Remotes,
8484
GpgPublicKeyPaths: config.GpgPublicKeyPaths,
85+
Submodules: config.Submodules,
8586
}
8687
}

internal/executor/executor.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ import (
66
"github.com/sirupsen/logrus"
77
)
88

9-
type EvalFunc func(ctx context.Context, repositoryPath, repositorySubdir, commitId, systemAttr, hostname string) (drvPath string, outPath string, machineId string, err error)
9+
type EvalFunc func(ctx context.Context, repositoryPath, repositorySubdir, commitId, systemAttr, hostname string, submodules bool) (drvPath string, outPath string, machineId string, err error)
1010
type BuildFunc func(ctx context.Context, drvPath string) error
1111

1212
// Executor contains the function used by comin to actually do actions
@@ -15,7 +15,7 @@ type BuildFunc func(ctx context.Context, drvPath string) error
1515
// Garnix implementation (such as proposed in
1616
// https://github.com/nlewo/comin/pull/74)
1717
type Executor interface {
18-
Eval(ctx context.Context, repositoryPath, repositorySubdir, commitId, systemAttr, hostname string) (drvPath string, outPath string, machineId string, err error)
18+
Eval(ctx context.Context, repositoryPath, repositorySubdir, commitId, systemAttr, hostname string, submodules bool) (drvPath string, outPath string, machineId string, err error)
1919
Build(ctx context.Context, drvPath string) (err error)
2020
Deploy(ctx context.Context, outPath, operation string) (needToRestartComin bool, profilePath string, err error)
2121
NeedToReboot(outPath, operation string) bool

internal/executor/executor_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,7 @@ func TestNixExecutorEval(t *testing.T) {
6060
// Test that Eval doesn't panic and handles parameters correctly
6161
// This will error in test environment since nix commands will fail,
6262
// but we're testing the code path and parameter handling
63-
_, _, _, err = executor.Eval(ctx, tt.repositoryPath, tt.repositorySubdir, tt.commitId, tt.systemAttr, tt.hostname)
63+
_, _, _, err = executor.Eval(ctx, tt.repositoryPath, tt.repositorySubdir, tt.commitId, tt.systemAttr, tt.hostname, false)
6464
t.Logf("Eval with %s returned error: %v (expected in test environment)", tt.systemAttr, err)
6565
})
6666
}

internal/executor/nix.go

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -30,8 +30,8 @@ func (n *NixLocal) NeedToReboot(outPath, operation string) bool {
3030
return utils.NeedToRebootLinux(outPath, operation)
3131
}
3232

33-
func (n *NixLocal) Eval(ctx context.Context, repositoryPath, repositorySubdir, commitId, systemAttr, hostname string) (drvPath string, outPath string, machineId string, err error) {
34-
tempDir, err := cloneRepoToTemp(repositoryPath, commitId)
33+
func (n *NixLocal) Eval(ctx context.Context, repositoryPath, repositorySubdir, commitId, systemAttr, hostname string, submodules bool) (drvPath string, outPath string, machineId string, err error) {
34+
tempDir, err := cloneRepoToTemp(repositoryPath, commitId, submodules)
3535
defer os.RemoveAll(tempDir) // nolint: errcheck
3636
if err != nil {
3737
return
@@ -49,7 +49,7 @@ func (n *NixLocal) Deploy(ctx context.Context, outPath, operation string) (needT
4949
return deployLinux(ctx, outPath, operation)
5050
}
5151

52-
func cloneRepoToTemp(remoteDir string, commitId string) (string, error) {
52+
func cloneRepoToTemp(remoteDir string, commitId string, submodules bool) (string, error) {
5353
dir, err := os.MkdirTemp("", "comin-git-clone-*")
5454
if err != nil {
5555
return "", err
@@ -68,9 +68,13 @@ func cloneRepoToTemp(remoteDir string, commitId string) (string, error) {
6868
return "", fmt.Errorf("nix: failed to set reference 'archive' to '%s' in %s: %s", commitId, remoteDir, err)
6969
}
7070

71-
r, err := git.PlainClone(dir, false, &git.CloneOptions{
71+
cloneOpts := &git.CloneOptions{
7272
URL: remoteDir,
73-
})
73+
}
74+
if submodules {
75+
cloneOpts.RecurseSubmodules = git.DefaultSubmoduleRecursionDepth
76+
}
77+
r, err := git.PlainClone(dir, false, cloneOpts)
7478
if err != nil {
7579
return "", fmt.Errorf("nix: failed to clone '%s': %s", dir, err)
7680
}

internal/executor/nix_flake.go

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,8 +45,11 @@ func (n *NixFlakeLocal) ShowDerivation(ctx context.Context, flakeUrl, hostname s
4545
return showDerivationWithFlake(ctx, flakeUrl, hostname, n.systemAttr)
4646
}
4747

48-
func (n *NixFlakeLocal) Eval(ctx context.Context, repositoryPath, repositorySubdir, commitId, systemAttr, hostname string) (drvPath string, outPath string, machineId string, err error) {
48+
func (n *NixFlakeLocal) Eval(ctx context.Context, repositoryPath, repositorySubdir, commitId, systemAttr, hostname string, submodules bool) (drvPath string, outPath string, machineId string, err error) {
4949
flakeUrl := fmt.Sprintf("git+file://%s?dir=%s&rev=%s", repositoryPath, repositorySubdir, commitId)
50+
if submodules {
51+
flakeUrl += "&submodules=1"
52+
}
5053
drvPath, outPath, err = showDerivationWithFlake(ctx, flakeUrl, hostname, n.systemAttr)
5154
if err != nil {
5255
return

internal/manager/manager_test.go

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,7 @@ func (n ExecutorMock) IsStorePathExist(storePath string) bool {
5353
func (n ExecutorMock) Deploy(ctx context.Context, outPath, operation string) (needToRestartComin bool, profilePath string, err error) {
5454
return false, "", nil
5555
}
56-
func (n ExecutorMock) Eval(ctx context.Context, repositoryPath, repositorySubdir, commitId, systemAttr, hostname string) (drvPath string, outPath string, machineId string, err error) {
56+
func (n ExecutorMock) Eval(ctx context.Context, repositoryPath, repositorySubdir, commitId, systemAttr, hostname string, submodules bool) (drvPath string, outPath string, machineId string, err error) {
5757
ok := <-n.evalOk
5858
if ok {
5959
return "drv-path", "out-path", n.machineId, nil
@@ -90,7 +90,7 @@ func TestBuild(t *testing.T) {
9090
s, _ := store.New(bk, tmp+"/state.json", tmp+"/gcroots", 1, 1)
9191
f.Start(t.Context())
9292
eMock := NewExecutorMock("")
93-
b := builder.New(s, eMock, "repoPath", "", "", "my-machine", 2*time.Second, 2*time.Second)
93+
b := builder.New(s, eMock, "repoPath", "", "", "my-machine", false, 2*time.Second, 2*time.Second)
9494
var deployFunc = func(context.Context, string, string) (bool, string, error) {
9595
return false, "profile-path", nil
9696
}
@@ -204,7 +204,7 @@ func TestDeploy(t *testing.T) {
204204
eMock := NewExecutorMock("")
205205
eMock.evalOk <- true
206206
eMock.buildOk <- true
207-
b := builder.New(s, eMock, "repoPath", "", "", "my-machine", 2*time.Second, 2*time.Second)
207+
b := builder.New(s, eMock, "repoPath", "", "", "my-machine", false, 2*time.Second, 2*time.Second)
208208
var deployFunc = func(context.Context, string, string) (bool, string, error) {
209209
return false, "profile-path", nil
210210
}
@@ -237,7 +237,7 @@ func TestIncorrectMachineId(t *testing.T) {
237237

238238
s, _ := store.New(bk, tmp+"/state.json", tmp+"/gcroots", 1, 1)
239239
eMock := NewExecutorMock("invalid-machine-id")
240-
b := builder.New(s, eMock, "repoPath", "", "", "my-machine", 2*time.Second, 2*time.Second)
240+
b := builder.New(s, eMock, "repoPath", "", "", "my-machine", false, 2*time.Second, 2*time.Second)
241241
d := mkDeployerMock(t)
242242
e, _ := executor.NewNixOSFlake()
243243
bc := NewConfirmer(bk, Without, 0, "")
@@ -269,7 +269,7 @@ func TestCorrectMachineId(t *testing.T) {
269269
s, _ := store.New(bk, tmp+"/state.json", tmp+"/gcroots", 1, 1)
270270
eMock := NewExecutorMock("the-test-machine-id")
271271
eMock.evalOk <- true
272-
b := builder.New(s, eMock, "repoPath", "", "", "my-machine", 2*time.Second, 2*time.Second)
272+
b := builder.New(s, eMock, "repoPath", "", "", "my-machine", false, 2*time.Second, 2*time.Second)
273273
d := mkDeployerMock(t)
274274
e, _ := executor.NewNixOSFlake()
275275
bc := NewConfirmer(bk, Without, 0, "")
@@ -299,7 +299,7 @@ func TestManagerWithDarwinConfiguration(t *testing.T) {
299299
bk.Start()
300300

301301
s, _ := store.New(bk, tmp+"/state.json", tmp+"/gcroots", 1, 1)
302-
b := builder.New(s, eMock, "repoPath", "", "", "my-machine", 2*time.Second, 2*time.Second)
302+
b := builder.New(s, eMock, "repoPath", "", "", "my-machine", false, 2*time.Second, 2*time.Second)
303303
d := mkDeployerMock(t)
304304

305305
// Test with Darwin configuration

0 commit comments

Comments
 (0)