Skip to content

Commit 69c05b1

Browse files
authored
[runner] Chown repo dir (#3364)
Fixes: #3360
1 parent 6dc4008 commit 69c05b1

File tree

3 files changed

+73
-44
lines changed

3 files changed

+73
-44
lines changed

runner/internal/executor/files.go

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,8 +35,9 @@ func (ex *RunExecutor) AddFileArchive(id string, src io.Reader) error {
3535
}
3636

3737
// setupFiles must be called from Run
38-
// ex.jobWorkingDir must be already set
38+
// Must be called after setJobWorkingDir and setJobCredentials
3939
func (ex *RunExecutor) setupFiles(ctx context.Context) error {
40+
log.Trace(ctx, "Setting up files")
4041
if ex.jobWorkingDir == "" {
4142
return errors.New("setup files: working dir is not set")
4243
}

runner/internal/executor/repo.go

Lines changed: 68 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import (
44
"context"
55
"errors"
66
"fmt"
7+
"io/fs"
78
"os"
89
"os/exec"
910
"path/filepath"
@@ -17,9 +18,9 @@ import (
1718
)
1819

1920
// setupRepo must be called from Run
20-
// ex.jobWorkingDir must be already set
21-
// TODO: change ownership to uid:gid
21+
// Must be called after setJobWorkingDir and setJobCredentials
2222
func (ex *RunExecutor) setupRepo(ctx context.Context) error {
23+
log.Trace(ctx, "Setting up repo")
2324
if ex.jobWorkingDir == "" {
2425
return errors.New("setup repo: working dir is not set")
2526
}
@@ -37,7 +38,7 @@ func (ex *RunExecutor) setupRepo(ctx context.Context) error {
3738
}
3839
log.Trace(ctx, "Job repo dir", "path", ex.repoDir)
3940

40-
repoDirIsEmpty, err := ex.prepareRepoDir(ctx)
41+
repoDirIsEmpty, repoDirMustBeMoved, err := ex.checkRepoDir(ctx)
4142
if err != nil {
4243
return fmt.Errorf("prepare repo dir: %w", err)
4344
}
@@ -59,23 +60,27 @@ func (ex *RunExecutor) setupRepo(ctx context.Context) error {
5960
return fmt.Errorf("setup repo: unsupported action: %s", repoExistsAction)
6061
}
6162
}
62-
// Move existing repo files from the repo dir and back to be able to git clone.
63-
// Currently, only needed for volumes mounted inside repo with lost+found present.
64-
tmpRepoDir, err := os.MkdirTemp(ex.tempDir, "repo_dir_copy")
65-
if err != nil {
66-
return fmt.Errorf("create temp repo dir: %w", err)
67-
}
68-
defer func() { _ = os.RemoveAll(tmpRepoDir) }()
69-
err = ex.moveRepoDir(tmpRepoDir)
70-
if err != nil {
71-
return fmt.Errorf("move repo dir: %w", err)
72-
}
73-
defer func() {
74-
err_ := ex.restoreRepoDir(tmpRepoDir)
75-
if err == nil {
76-
err = fmt.Errorf("restore repo dir: %w", err_)
63+
64+
if repoDirMustBeMoved {
65+
// Move existing repo files from the repo dir and back to be able to git clone.
66+
// Currently, only needed for volumes mounted inside repo with lost+found present.
67+
tmpRepoDir, err := os.MkdirTemp(ex.tempDir, "repo_dir_copy")
68+
if err != nil {
69+
return fmt.Errorf("create temp repo dir: %w", err)
70+
}
71+
defer func() { _ = os.RemoveAll(tmpRepoDir) }()
72+
err = ex.moveRepoDir(ctx, tmpRepoDir)
73+
if err != nil {
74+
return fmt.Errorf("move repo dir: %w", err)
7775
}
78-
}()
76+
defer func() {
77+
err_ := ex.restoreRepoDir(ctx, tmpRepoDir)
78+
if err == nil {
79+
err = fmt.Errorf("restore repo dir: %w", err_)
80+
}
81+
}()
82+
}
83+
7984
switch ex.getRepoData().RepoType {
8085
case "remote":
8186
log.Trace(ctx, "Fetching git repository")
@@ -90,6 +95,11 @@ func (ex *RunExecutor) setupRepo(ctx context.Context) error {
9095
default:
9196
return fmt.Errorf("unknown RepoType: %s", ex.getRepoData().RepoType)
9297
}
98+
99+
if err := ex.chownRepoDir(ctx); err != nil {
100+
return fmt.Errorf("chown repo dir: %w", err)
101+
}
102+
93103
return err
94104
}
95105

@@ -125,7 +135,7 @@ func (ex *RunExecutor) prepareGit(ctx context.Context) error {
125135
}
126136

127137
log.Trace(ctx, "Checking out remote repo", "GIT URL", repoManager.URL())
128-
if err := repoManager.Checkout(); err != nil {
138+
if err := repoManager.Checkout(ctx); err != nil {
129139
return fmt.Errorf("checkout repo: %w", err)
130140
}
131141
if err := repoManager.SetConfig(ex.getRepoData().RepoConfigName, ex.getRepoData().RepoConfigEmail); err != nil {
@@ -158,56 +168,74 @@ func (ex *RunExecutor) prepareArchive(ctx context.Context) error {
158168
return nil
159169
}
160170

161-
func (ex *RunExecutor) prepareRepoDir(ctx context.Context) (bool, error) {
162-
log.Trace(ctx, "Preparing repo dir")
171+
func (ex *RunExecutor) checkRepoDir(ctx context.Context) (isEmpty bool, mustBeMoved bool, err error) {
172+
log.Trace(ctx, "Checking repo dir")
163173
info, err := os.Stat(ex.repoDir)
164174
if err != nil {
165175
if errors.Is(err, os.ErrNotExist) {
166-
if err = common.MkdirAll(ctx, ex.repoDir, ex.jobUid, ex.jobGid); err != nil {
167-
return false, fmt.Errorf("create repo dir: %w", err)
168-
}
169-
// No repo dir - created a new one
170-
return true, nil
176+
// No repo dir
177+
return true, false, nil
171178
}
172-
return false, fmt.Errorf("stat repo dir: %w", err)
179+
return false, false, fmt.Errorf("stat repo dir: %w", err)
173180
}
174181
if !info.IsDir() {
175-
return false, fmt.Errorf("stat repo dir: %s is not a dir", ex.repoDir)
182+
return false, false, fmt.Errorf("stat repo dir: %s is not a dir", ex.repoDir)
176183
}
177184
entries, err := os.ReadDir(ex.repoDir)
178185
if err != nil {
179-
return false, fmt.Errorf("read repo dir: %w", err)
186+
return false, false, fmt.Errorf("read repo dir: %w", err)
180187
}
181188
if len(entries) == 0 {
182189
// Repo dir is empty
183-
return true, nil
190+
return true, false, nil
184191
}
185192
if len(entries) == 1 && entries[0].Name() == "lost+found" {
186193
// lost+found may be present on a newly created volume
187-
// We (but not Git, see `{move,restore}RepoDir`) consider such a dir "empty"
188-
return true, nil
194+
// We (but not Git, thus mustBeMoved = true) consider such a dir "empty"
195+
return true, true, nil
189196
}
190197
// Repo dir is not empty
191-
return false, nil
198+
return false, false, nil
192199
}
193200

194-
func (ex *RunExecutor) moveRepoDir(tmpDir string) error {
195-
if err := moveDir(ex.repoDir, tmpDir); err != nil {
201+
func (ex *RunExecutor) moveRepoDir(ctx context.Context, tmpDir string) error {
202+
if err := moveDir(ctx, ex.repoDir, tmpDir); err != nil {
196203
return fmt.Errorf("move directory: %w", err)
197204
}
198205
return nil
199206
}
200207

201-
func (ex *RunExecutor) restoreRepoDir(tmpDir string) error {
202-
if err := moveDir(tmpDir, ex.repoDir); err != nil {
208+
func (ex *RunExecutor) restoreRepoDir(ctx context.Context, tmpDir string) error {
209+
if err := moveDir(ctx, tmpDir, ex.repoDir); err != nil {
203210
return fmt.Errorf("move directory: %w", err)
204211
}
205212
return nil
206213
}
207214

208-
func moveDir(srcDir, dstDir string) error {
215+
func (ex *RunExecutor) chownRepoDir(ctx context.Context) error {
216+
log.Trace(ctx, "Chowning repo dir")
217+
if ex.jobUid == -1 && ex.jobGid == -1 {
218+
return nil
219+
}
220+
return filepath.WalkDir(
221+
ex.repoDir,
222+
func(p string, d fs.DirEntry, err error) error {
223+
// We consider walk/chown errors non-fatal
224+
if err != nil {
225+
log.Debug(ctx, "Error while walking repo dir", "path", p, "err", err)
226+
return nil
227+
}
228+
if err := os.Chown(p, ex.jobUid, ex.jobGid); err != nil {
229+
log.Debug(ctx, "Error while chowning repo dir", "path", p, "err", err)
230+
}
231+
return nil
232+
},
233+
)
234+
}
235+
236+
func moveDir(ctx context.Context, srcDir, dstDir string) error {
209237
// We cannot just move/rename files because with volumes they'll be on different devices
210-
cmd := exec.CommandContext(context.TODO(), "cp", "-a", srcDir+"/.", dstDir)
238+
cmd := exec.CommandContext(ctx, "cp", "-a", srcDir+"/.", dstDir)
211239
if output, err := cmd.CombinedOutput(); err != nil {
212240
return fmt.Errorf("failed to cp: %w, output: %s", err, string(output))
213241
}

runner/internal/repo/manager.go

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -69,9 +69,9 @@ func (m *Manager) WithSSHAuth(pem, password string) *Manager {
6969
return m
7070
}
7171

72-
func (m *Manager) Checkout() error {
73-
log.Info(m.ctx, "git checkout", "auth", fmt.Sprintf("%T", (&m.clo).Auth))
74-
ref, err := git.PlainClone(m.localPath, false, &m.clo)
72+
func (m *Manager) Checkout(ctx context.Context) error {
73+
log.Info(m.ctx, "git checkout", "auth", fmt.Sprintf("%T", m.clo.Auth))
74+
ref, err := git.PlainCloneContext(ctx, m.localPath, false, &m.clo)
7575
if err != nil {
7676
return fmt.Errorf("clone repo: %w", err)
7777
}

0 commit comments

Comments
 (0)