Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Cherry-pick #5412 #5419

Merged
merged 1 commit into from
Dec 13, 2024
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
11 changes: 10 additions & 1 deletion pkg/app/piped/deploysource/deploysource.go
Original file line number Diff line number Diff line change
Expand Up @@ -203,8 +203,17 @@
func (p *provider) copy(lw io.Writer) (*DeploySource, error) {
p.copyNum++

src := p.source.RepoDir

Check warning on line 206 in pkg/app/piped/deploysource/deploysource.go

View check run for this annotation

Codecov / codecov/patch

pkg/app/piped/deploysource/deploysource.go#L206

Added line #L206 was not covered by tests
dest := fmt.Sprintf("%s-%d", p.source.RepoDir, p.copyNum)
cmd := exec.Command("cp", "-rf", p.source.RepoDir, dest)

// use tar to exclude the .git directory
// the tar command does not create the destination directory if it does not exist.
// so we need to create it before running the command.
if err := os.MkdirAll(dest, 0700); err != nil {
fmt.Fprintf(lw, "Unable to create the directory to store the copied deploy source (%v)\n", err)
return nil, err
}
cmd := exec.Command("sh", "-c", fmt.Sprintf("tar c -f - -C '%s' --exclude='.git' . | tar x -f - -C '%s'", src, dest))

Check warning on line 216 in pkg/app/piped/deploysource/deploysource.go

View check run for this annotation

Codecov / codecov/patch

pkg/app/piped/deploysource/deploysource.go#L208-L216

Added lines #L208 - L216 were not covered by tests
out, err := cmd.CombinedOutput()
if err != nil {
fmt.Fprintf(lw, "Unable to copy deploy source data (%v, %s)\n", err, string(out))
Expand Down
4 changes: 3 additions & 1 deletion pkg/app/piped/driftdetector/cloudrun/detector.go
Original file line number Diff line number Diff line change
Expand Up @@ -221,7 +221,7 @@
return d.reporter.ReportApplicationSyncState(ctx, app.Id, state)
}

func (d *detector) loadHeadServiceManifest(app *model.Application, repo git.Repo, headCommit git.Commit) (provider.ServiceManifest, error) {
func (d *detector) loadHeadServiceManifest(app *model.Application, repo git.Worktree, headCommit git.Commit) (provider.ServiceManifest, error) {

Check warning on line 224 in pkg/app/piped/driftdetector/cloudrun/detector.go

View check run for this annotation

Codecov / codecov/patch

pkg/app/piped/driftdetector/cloudrun/detector.go#L224

Added line #L224 was not covered by tests
var (
manifestCache = provider.ServiceManifestCache{
AppID: app.Id,
Expand Down Expand Up @@ -263,6 +263,8 @@
if err != nil {
return provider.ServiceManifest{}, fmt.Errorf("failed to copy the cloned git repository (%w)", err)
}
defer repo.Clean()

Check warning on line 267 in pkg/app/piped/driftdetector/cloudrun/detector.go

View check run for this annotation

Codecov / codecov/patch

pkg/app/piped/driftdetector/cloudrun/detector.go#L266-L267

Added lines #L266 - L267 were not covered by tests
repoDir := repo.GetPath()
appDir = filepath.Join(repoDir, app.GitPath.Path)
}
Expand Down
4 changes: 3 additions & 1 deletion pkg/app/piped/driftdetector/ecs/detector.go
Original file line number Diff line number Diff line change
Expand Up @@ -343,7 +343,7 @@
return live, head
}

func (d *detector) loadConfigs(app *model.Application, repo git.Repo, headCommit git.Commit) (provider.ECSManifests, error) {
func (d *detector) loadConfigs(app *model.Application, repo git.Worktree, headCommit git.Commit) (provider.ECSManifests, error) {

Check warning on line 346 in pkg/app/piped/driftdetector/ecs/detector.go

View check run for this annotation

Codecov / codecov/patch

pkg/app/piped/driftdetector/ecs/detector.go#L346

Added line #L346 was not covered by tests
var (
manifestCache = provider.ECSManifestsCache{
AppID: app.Id,
Expand Down Expand Up @@ -387,6 +387,8 @@
if err != nil {
return provider.ECSManifests{}, fmt.Errorf("failed to copy the cloned git repository (%w)", err)
}
defer repo.Clean()

Check warning on line 391 in pkg/app/piped/driftdetector/ecs/detector.go

View check run for this annotation

Codecov / codecov/patch

pkg/app/piped/driftdetector/ecs/detector.go#L390-L391

Added lines #L390 - L391 were not covered by tests
repoDir := repo.GetPath()
appDir = filepath.Join(repoDir, app.GitPath.Path)
}
Expand Down
4 changes: 3 additions & 1 deletion pkg/app/piped/driftdetector/kubernetes/detector.go
Original file line number Diff line number Diff line change
Expand Up @@ -236,7 +236,7 @@
return d.reporter.ReportApplicationSyncState(ctx, app.Id, state)
}

func (d *detector) loadHeadManifests(ctx context.Context, app *model.Application, repo git.Repo, headCommit git.Commit, watchingResourceKinds []provider.APIVersionKind) ([]provider.Manifest, error) {
func (d *detector) loadHeadManifests(ctx context.Context, app *model.Application, repo git.Worktree, headCommit git.Commit, watchingResourceKinds []provider.APIVersionKind) ([]provider.Manifest, error) {

Check warning on line 239 in pkg/app/piped/driftdetector/kubernetes/detector.go

View check run for this annotation

Codecov / codecov/patch

pkg/app/piped/driftdetector/kubernetes/detector.go#L239

Added line #L239 was not covered by tests
var (
manifestCache = provider.AppManifestsCache{
AppID: app.Id,
Expand Down Expand Up @@ -278,6 +278,8 @@
if err != nil {
return nil, fmt.Errorf("failed to copy the cloned git repository (%w)", err)
}
defer repo.Clean()

Check warning on line 282 in pkg/app/piped/driftdetector/kubernetes/detector.go

View check run for this annotation

Codecov / codecov/patch

pkg/app/piped/driftdetector/kubernetes/detector.go#L281-L282

Added lines #L281 - L282 were not covered by tests
repoDir = repo.GetPath()
appDir = filepath.Join(repoDir, app.GitPath.Path)
}
Expand Down
4 changes: 3 additions & 1 deletion pkg/app/piped/driftdetector/lambda/detector.go
Original file line number Diff line number Diff line change
Expand Up @@ -270,7 +270,7 @@
return cloneSpec
}

func (d *detector) loadHeadFunctionManifest(app *model.Application, repo git.Repo, headCommit git.Commit) (provider.FunctionManifest, error) {
func (d *detector) loadHeadFunctionManifest(app *model.Application, repo git.Worktree, headCommit git.Commit) (provider.FunctionManifest, error) {

Check warning on line 273 in pkg/app/piped/driftdetector/lambda/detector.go

View check run for this annotation

Codecov / codecov/patch

pkg/app/piped/driftdetector/lambda/detector.go#L273

Added line #L273 was not covered by tests
var (
manifestCache = provider.FunctionManifestCache{
AppID: app.Id,
Expand Down Expand Up @@ -312,6 +312,8 @@
if err != nil {
return provider.FunctionManifest{}, fmt.Errorf("failed to copy the cloned git repository (%w)", err)
}
defer repo.Clean()

Check warning on line 316 in pkg/app/piped/driftdetector/lambda/detector.go

View check run for this annotation

Codecov / codecov/patch

pkg/app/piped/driftdetector/lambda/detector.go#L315-L316

Added lines #L315 - L316 were not covered by tests
repoDir := repo.GetPath()
appDir = filepath.Join(repoDir, app.GitPath.Path)
}
Expand Down
4 changes: 3 additions & 1 deletion pkg/app/piped/driftdetector/terraform/detector.go
Original file line number Diff line number Diff line change
Expand Up @@ -169,7 +169,7 @@
}
}

func (d *detector) checkApplication(ctx context.Context, app *model.Application, repo git.Repo, headCommit git.Commit) error {
func (d *detector) checkApplication(ctx context.Context, app *model.Application, repo git.Worktree, headCommit git.Commit) error {

Check warning on line 172 in pkg/app/piped/driftdetector/terraform/detector.go

View check run for this annotation

Codecov / codecov/patch

pkg/app/piped/driftdetector/terraform/detector.go#L172

Added line #L172 was not covered by tests
var (
repoDir = repo.GetPath()
appDir = filepath.Join(repoDir, app.GitPath.Path)
Expand Down Expand Up @@ -206,6 +206,8 @@
if err != nil {
return fmt.Errorf("failed to copy the cloned git repository (%w)", err)
}
defer repo.Clean()

Check warning on line 210 in pkg/app/piped/driftdetector/terraform/detector.go

View check run for this annotation

Codecov / codecov/patch

pkg/app/piped/driftdetector/terraform/detector.go#L209-L210

Added lines #L209 - L210 were not covered by tests
repoDir = repo.GetPath()
appDir = filepath.Join(repoDir, app.GitPath.Path)
}
Expand Down
4 changes: 2 additions & 2 deletions pkg/app/piped/eventwatcher/eventwatcher.go
Original file line number Diff line number Diff line change
Expand Up @@ -319,7 +319,7 @@
if err != nil {
return fmt.Errorf("failed to create a new temporary directory: %w", err)
}
tmpRepo, err := repo.Copy(filepath.Join(tmpDir, "tmp-repo"))
tmpRepo, err := repo.CopyToModify(filepath.Join(tmpDir, "tmp-repo"))

Check warning on line 322 in pkg/app/piped/eventwatcher/eventwatcher.go

View check run for this annotation

Codecov / codecov/patch

pkg/app/piped/eventwatcher/eventwatcher.go#L322

Added line #L322 was not covered by tests
if err != nil {
return fmt.Errorf("failed to copy the repository to the temporary directory: %w", err)
}
Expand Down Expand Up @@ -495,7 +495,7 @@
if err != nil {
return fmt.Errorf("failed to create a new temporary directory: %w", err)
}
tmpRepo, err := repo.Copy(filepath.Join(tmpDir, "tmp-repo"))
tmpRepo, err := repo.CopyToModify(filepath.Join(tmpDir, "tmp-repo"))

Check warning on line 498 in pkg/app/piped/eventwatcher/eventwatcher.go

View check run for this annotation

Codecov / codecov/patch

pkg/app/piped/eventwatcher/eventwatcher.go#L498

Added line #L498 was not covered by tests
if err != nil {
return fmt.Errorf("failed to copy the repository to the temporary directory: %w", err)
}
Expand Down
11 changes: 10 additions & 1 deletion pkg/app/pipedv1/deploysource/deploysource.go
Original file line number Diff line number Diff line change
Expand Up @@ -183,8 +183,17 @@
func (p *provider) copy(lw io.Writer) (*DeploySource, error) {
p.copyNum++

src := p.source.RepoDir

Check warning on line 186 in pkg/app/pipedv1/deploysource/deploysource.go

View check run for this annotation

Codecov / codecov/patch

pkg/app/pipedv1/deploysource/deploysource.go#L186

Added line #L186 was not covered by tests
dest := fmt.Sprintf("%s-%d", p.source.RepoDir, p.copyNum)
cmd := exec.Command("cp", "-rf", p.source.RepoDir, dest)

// use tar to exclude the .git directory
// the tar command does not create the destination directory if it does not exist.
// so we need to create it before running the command.
if err := os.MkdirAll(dest, 0700); err != nil {
fmt.Fprintf(lw, "Unable to create the directory to store the copied deploy source (%v)\n", err)
return nil, err
}
cmd := exec.Command("sh", "-c", fmt.Sprintf("tar c -f - -C '%s' --exclude='.git' . | tar x -f - -C '%s'", src, dest))

Check warning on line 196 in pkg/app/pipedv1/deploysource/deploysource.go

View check run for this annotation

Codecov / codecov/patch

pkg/app/pipedv1/deploysource/deploysource.go#L188-L196

Added lines #L188 - L196 were not covered by tests
out, err := cmd.CombinedOutput()
if err != nil {
fmt.Fprintf(lw, "Unable to copy deploy source data (%v, %s)\n", err, string(out))
Expand Down
4 changes: 2 additions & 2 deletions pkg/app/pipedv1/eventwatcher/eventwatcher.go
Original file line number Diff line number Diff line change
Expand Up @@ -317,7 +317,7 @@
if err != nil {
return fmt.Errorf("failed to create a new temporary directory: %w", err)
}
tmpRepo, err := repo.Copy(filepath.Join(tmpDir, "tmp-repo"))
tmpRepo, err := repo.CopyToModify(filepath.Join(tmpDir, "tmp-repo"))

Check warning on line 320 in pkg/app/pipedv1/eventwatcher/eventwatcher.go

View check run for this annotation

Codecov / codecov/patch

pkg/app/pipedv1/eventwatcher/eventwatcher.go#L320

Added line #L320 was not covered by tests
if err != nil {
return fmt.Errorf("failed to copy the repository to the temporary directory: %w", err)
}
Expand Down Expand Up @@ -478,7 +478,7 @@
if err != nil {
return fmt.Errorf("failed to create a new temporary directory: %w", err)
}
tmpRepo, err := repo.Copy(filepath.Join(tmpDir, "tmp-repo"))
tmpRepo, err := repo.CopyToModify(filepath.Join(tmpDir, "tmp-repo"))

Check warning on line 481 in pkg/app/pipedv1/eventwatcher/eventwatcher.go

View check run for this annotation

Codecov / codecov/patch

pkg/app/pipedv1/eventwatcher/eventwatcher.go#L481

Added line #L481 was not covered by tests
if err != nil {
return fmt.Errorf("failed to copy the repository to the temporary directory: %w", err)
}
Expand Down
9 changes: 5 additions & 4 deletions pkg/git/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -166,7 +166,7 @@ func (c *client) Clone(ctx context.Context, repoID, remote, branch, destination
return nil, err
}
out, err := retryCommand(3, time.Second, logger, func() ([]byte, error) {
args := []string{"clone", "--mirror", remote, repoCachePath}
args := []string{"clone", "--mirror", "--filter=blob:none", remote, repoCachePath}
args = append(authArgs, args...)
return runGitCommand(ctx, c.gitPath, "", c.envsForRepo(remote), args...)
})
Expand Down Expand Up @@ -214,11 +214,12 @@ func (c *client) Clone(ctx context.Context, repoID, remote, branch, destination
}
}

args := []string{"clone"}
// git worktree add [-f] [--detach] [--checkout] [--lock [--reason <string>]]
// [--orphan] [(-b | -B) <new-branch>] <path> [<commit-ish>]
args := []string{"-C", repoCachePath, "worktree", "add", "--detach", destination}
if branch != "" {
args = append(args, "-b", branch)
args = append(args, branch)
}
args = append(args, repoCachePath, destination)

logger.Info("cloning a repo from cached one in local",
zap.String("src", repoCachePath),
Expand Down
19 changes: 17 additions & 2 deletions pkg/git/gittest/git.mock.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

112 changes: 103 additions & 9 deletions pkg/git/repo.go
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,8 @@
type Repo interface {
GetPath() string
GetClonedBranch() string
Copy(dest string) (Repo, error)
Copy(dest string) (Worktree, error)
CopyToModify(dest string) (Repo, error)

ListCommits(ctx context.Context, visionRange string) ([]Commit, error)
GetLatestCommit(ctx context.Context) (Commit, error)
Expand All @@ -52,6 +53,17 @@
CommitChanges(ctx context.Context, branch, message string, newBranch bool, changes map[string][]byte, trailers map[string]string) error
}

// Worktree provides functions to get and handle git worktree.
// It is a separate checkout of the repository.
// It is used to make changes to the repository without affecting the main repository.
// Worktree always does checkout with the detached HEAD, so it doesn't affect the main repository.
type Worktree interface {
GetPath() string
Clean() error
Copy(dest string) (Worktree, error)
Checkout(ctx context.Context, commitish string) error
}

type repo struct {
dir string
gitPath string
Expand All @@ -60,6 +72,55 @@
gitEnvs []string
}

// worktree is a git worktree.
// It is a separate checkout of the repository.
type worktree struct {
base *repo
worktreePath string
}

func (r *worktree) runGitCommand(ctx context.Context, args ...string) ([]byte, error) {
cmd := exec.CommandContext(ctx, r.base.gitPath, args...)
cmd.Dir = r.worktreePath
cmd.Env = append(os.Environ(), r.base.gitEnvs...)
return cmd.CombinedOutput()

Check warning on line 86 in pkg/git/repo.go

View check run for this annotation

Codecov / codecov/patch

pkg/git/repo.go#L82-L86

Added lines #L82 - L86 were not covered by tests
}

func (r *worktree) Copy(dest string) (Worktree, error) {
// garbage collecting worktrees
if _, err := r.runGitCommand(context.Background(), "worktree", "prune"); err != nil {
// ignore the error
}

Check warning on line 93 in pkg/git/repo.go

View check run for this annotation

Codecov / codecov/patch

pkg/git/repo.go#L89-L93

Added lines #L89 - L93 were not covered by tests

if out, err := r.runGitCommand(context.Background(), "worktree", "add", "--detach", dest); err != nil {
return nil, formatCommandError(err, out)
}

Check warning on line 97 in pkg/git/repo.go

View check run for this annotation

Codecov / codecov/patch

pkg/git/repo.go#L95-L97

Added lines #L95 - L97 were not covered by tests

return &worktree{
base: r.base,
worktreePath: dest,
}, nil

Check warning on line 102 in pkg/git/repo.go

View check run for this annotation

Codecov / codecov/patch

pkg/git/repo.go#L99-L102

Added lines #L99 - L102 were not covered by tests
}

func (r *worktree) GetPath() string {
return r.worktreePath

Check warning on line 106 in pkg/git/repo.go

View check run for this annotation

Codecov / codecov/patch

pkg/git/repo.go#L105-L106

Added lines #L105 - L106 were not covered by tests
}

func (r *worktree) Clean() error {
if out, err := r.base.runGitCommand(context.Background(), "worktree", "remove", r.worktreePath); err != nil {
return formatCommandError(err, out)
}

Check warning on line 112 in pkg/git/repo.go

View check run for this annotation

Codecov / codecov/patch

pkg/git/repo.go#L111-L112

Added lines #L111 - L112 were not covered by tests
return nil
}

func (r *worktree) Checkout(ctx context.Context, commitish string) error {
out, err := r.runGitCommand(ctx, "checkout", "--detach", commitish)
if err != nil {
return formatCommandError(err, out)
}
return nil

Check warning on line 121 in pkg/git/repo.go

View check run for this annotation

Codecov / codecov/patch

pkg/git/repo.go#L116-L121

Added lines #L116 - L121 were not covered by tests
}

// NewRepo creates a new Repo instance.
func NewRepo(dir, gitPath, remote, clonedBranch string, gitEnvs []string) *repo {
return &repo{
Expand All @@ -81,22 +142,55 @@
return r.clonedBranch
}

// Copy does copying the repository to the given destination.
// Copy does copying the repository to the given destination using git worktree.
// The repository is cloned to the given destination with the detached HEAD.
// NOTE: the given “dest” must be a path that doesn’t exist yet.
// If you don't, it copies the repo root itself to the given dest as a subdirectory.
func (r *repo) Copy(dest string) (Repo, error) {
cmd := exec.Command("cp", "-rf", r.dir, dest)
out, err := cmd.CombinedOutput()
if err != nil {
// If you don't, you will get an error.
func (r *repo) Copy(dest string) (Worktree, error) {
// garbage collecting worktrees
if _, err := r.runGitCommand(context.Background(), "worktree", "prune"); err != nil {
// ignore the error
}

Check warning on line 153 in pkg/git/repo.go

View check run for this annotation

Codecov / codecov/patch

pkg/git/repo.go#L152-L153

Added lines #L152 - L153 were not covered by tests

if out, err := r.runGitCommand(context.Background(), "worktree", "add", "--detach", dest); err != nil {
return nil, formatCommandError(err, out)
}

return &repo{
return &worktree{
base: r,
worktreePath: dest,
}, nil
}

// CopyToModify does cloning the repository to the given destination.
// The repository is cloned to the given destination with the .
// NOTE: the given “dest” must be a path that doesn’t exist yet.
// If you don't, you will get an error.
func (r *repo) CopyToModify(dest string) (Repo, error) {
cmd := exec.Command(r.gitPath, "clone", r.dir, dest)
if out, err := cmd.CombinedOutput(); err != nil {
return nil, formatCommandError(err, out)
}

Check warning on line 173 in pkg/git/repo.go

View check run for this annotation

Codecov / codecov/patch

pkg/git/repo.go#L172-L173

Added lines #L172 - L173 were not covered by tests

cloned := &repo{
dir: dest,
gitPath: r.gitPath,
remote: r.remote,
clonedBranch: r.clonedBranch,
}, nil
gitEnvs: r.gitEnvs,
}

// because we did a local cloning so set the remote url of origin
if err := cloned.setRemote(context.Background(), r.remote); err != nil {
return nil, err
}

Check warning on line 186 in pkg/git/repo.go

View check run for this annotation

Codecov / codecov/patch

pkg/git/repo.go#L185-L186

Added lines #L185 - L186 were not covered by tests

// fetch the latest changes which doesn't exist in the local repository
if out, err := cloned.runGitCommand(context.Background(), "fetch"); err != nil {
return nil, formatCommandError(err, out)
}

Check warning on line 191 in pkg/git/repo.go

View check run for this annotation

Codecov / codecov/patch

pkg/git/repo.go#L190-L191

Added lines #L190 - L191 were not covered by tests

return cloned, nil
}

// ListCommits returns a list of commits in a given revision range.
Expand Down
Loading
Loading