Script 'mail_helper' called by obssrc Hello community, here is the log from the commit of package okteto for openSUSE:Factory checked in at 2023-04-06 15:56:11 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/okteto (Old) and /work/SRC/openSUSE:Factory/.okteto.new.19717 (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "okteto" Thu Apr 6 15:56:11 2023 rev:44 rq:1077621 version:2.14.2 Changes: -------- --- /work/SRC/openSUSE:Factory/okteto/okteto.changes 2023-04-03 17:47:04.287165533 +0200 +++ /work/SRC/openSUSE:Factory/.okteto.new.19717/okteto.changes 2023-04-06 15:56:12.748387534 +0200 @@ -1,0 +2,9 @@ +Thu Apr 06 03:26:17 UTC 2023 - ka...@b1-systems.de + +- Update to version 2.14.2: + * remove sensitive data in git url displayed (#3535) (#3537) + * fix: adding .git folder to the folder should propagate okteto + git commit (#3533) (#3538) + * fix .env removal locally (#3534) (#3536) + +------------------------------------------------------------------- Old: ---- okteto-2.14.1.obscpio New: ---- okteto-2.14.2.obscpio ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ okteto.spec ++++++ --- /var/tmp/diff_new_pack.tHlUXl/_old 2023-04-06 15:56:14.312396367 +0200 +++ /var/tmp/diff_new_pack.tHlUXl/_new 2023-04-06 15:56:14.344396548 +0200 @@ -19,7 +19,7 @@ %define __arch_install_post export NO_BRP_STRIP_DEBUG=true Name: okteto -Version: 2.14.1 +Version: 2.14.2 Release: 0 Summary: Develop your applications directly in your Kubernetes Cluster License: Apache-2.0 ++++++ _service ++++++ --- /var/tmp/diff_new_pack.tHlUXl/_old 2023-04-06 15:56:14.672398399 +0200 +++ /var/tmp/diff_new_pack.tHlUXl/_new 2023-04-06 15:56:14.716398648 +0200 @@ -3,10 +3,10 @@ <param name="url">https://github.com/okteto/okteto</param> <param name="scm">git</param> <param name="exclude">.git</param> - <param name="revision">2.14.1</param> + <param name="revision">2.14.2</param> <param name="versionformat">@PARENT_TAG@</param> <param name="changesgenerate">enable</param> - <param name="match-tag">2.14.1</param> + <param name="match-tag">2.14.2</param> </service> <service name="set_version" mode="disabled"> <param name="basename">okteto</param> ++++++ _servicedata ++++++ --- /var/tmp/diff_new_pack.tHlUXl/_old 2023-04-06 15:56:14.904399710 +0200 +++ /var/tmp/diff_new_pack.tHlUXl/_new 2023-04-06 15:56:14.928399845 +0200 @@ -1,6 +1,6 @@ <servicedata> <service name="tar_scm"> <param name="url">https://github.com/okteto/okteto</param> - <param name="changesrevision">14b577383d98920b1275fb86393566b93943876b</param></service></servicedata> + <param name="changesrevision">ac0f5a90199e4aac4f4b6fab478259dc3b879bda</param></service></servicedata> (No newline at EOF) ++++++ okteto-2.14.1.obscpio -> okteto-2.14.2.obscpio ++++++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/okteto-2.14.1/cmd/deploy/command_configuration.go new/okteto-2.14.2/cmd/deploy/command_configuration.go --- old/okteto-2.14.1/cmd/deploy/command_configuration.go 2023-03-31 21:11:44.000000000 +0200 +++ new/okteto-2.14.2/cmd/deploy/command_configuration.go 2023-04-05 18:55:26.000000000 +0200 @@ -126,12 +126,12 @@ } func (dc *DeployCommand) addEnvVars(cwd string) { - if os.Getenv(model.OktetoGitBranchEnvVar) == "" { + if os.Getenv(constants.OktetoGitBranchEnvVar) == "" { branch, err := utils.GetBranch(cwd) if err != nil { oktetoLog.Infof("could not retrieve branch name: %s", err) } - os.Setenv(model.OktetoGitBranchEnvVar, branch) + os.Setenv(constants.OktetoGitBranchEnvVar, branch) } if os.Getenv(model.GithubRepositoryEnvVar) == "" { @@ -152,7 +152,7 @@ os.Setenv(model.GithubRepositoryEnvVar, repo) } - if os.Getenv(model.OktetoGitCommitEnvVar) == "" { + if os.Getenv(constants.OktetoGitCommitEnvVar) == "" { sha, err := repository.NewRepository(cwd).GetSHA() if err != nil { oktetoLog.Infof("could not retrieve sha: %s", err) @@ -167,7 +167,7 @@ if !isClean { sha = utils.GetRandomSHA() } - os.Setenv(model.OktetoGitCommitEnvVar, sha) + os.Setenv(constants.OktetoGitCommitEnvVar, sha) } if os.Getenv(model.OktetoRegistryURLEnvVar) == "" { os.Setenv(model.OktetoRegistryURLEnvVar, okteto.Context().Registry) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/okteto-2.14.1/cmd/deploy/deploy.go new/okteto-2.14.2/cmd/deploy/deploy.go --- old/okteto-2.14.1/cmd/deploy/deploy.go 2023-03-31 21:11:44.000000000 +0200 +++ new/okteto-2.14.2/cmd/deploy/deploy.go 2023-04-05 18:55:26.000000000 +0200 @@ -297,7 +297,7 @@ Name: deployOptions.Name, Namespace: deployOptions.Manifest.Namespace, Repository: os.Getenv(model.GithubRepositoryEnvVar), - Branch: os.Getenv(model.OktetoGitBranchEnvVar), + Branch: os.Getenv(constants.OktetoGitBranchEnvVar), Filename: deployOptions.ManifestPathFlag, Status: pipeline.ProgressingStatus, Manifest: deployOptions.Manifest.Manifest, diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/okteto-2.14.1/cmd/deploy/local.go new/okteto-2.14.2/cmd/deploy/local.go --- old/okteto-2.14.1/cmd/deploy/local.go 2023-03-31 21:11:44.000000000 +0200 +++ new/okteto-2.14.2/cmd/deploy/local.go 2023-04-05 18:55:26.000000000 +0200 @@ -189,7 +189,7 @@ } defer func() { - if err := ld.Fs.RemoveAll(filepath.Base(oktetoEnvFile.Name())); err != nil { + if err := ld.Fs.RemoveAll(filepath.Dir(oktetoEnvFile.Name())); err != nil { oktetoLog.Infof("error removing okteto env file dir: %w", err) } }() diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/okteto-2.14.1/cmd/deploy/local_test.go new/okteto-2.14.2/cmd/deploy/local_test.go --- old/okteto-2.14.1/cmd/deploy/local_test.go 1970-01-01 01:00:00.000000000 +0100 +++ new/okteto-2.14.2/cmd/deploy/local_test.go 2023-04-05 18:55:26.000000000 +0200 @@ -0,0 +1,42 @@ +// Copyright 2023 The Okteto Authors +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package deploy + +import ( + "context" + "testing" + + "github.com/okteto/okteto/pkg/model" + "github.com/spf13/afero" + "github.com/stretchr/testify/require" +) + +func TestDeployNotRemovingEnvFile(t *testing.T) { + fs := afero.NewMemMapFs() + + _, err := fs.Create(".env") + require.NoError(t, err) + opts := &Options{ + Manifest: &model.Manifest{ + Deploy: &model.DeployInfo{}, + }, + } + localDeployer := localDeployer{ + Fs: fs, + } + localDeployer.runDeploySection(context.Background(), opts) + _, err = fs.Stat(".env") + require.NoError(t, err) + +} diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/okteto-2.14.1/cmd/deploy/remote.go new/okteto-2.14.2/cmd/deploy/remote.go --- old/okteto-2.14.1/cmd/deploy/remote.go 2023-03-31 21:11:44.000000000 +0200 +++ new/okteto-2.14.2/cmd/deploy/remote.go 2023-04-05 18:55:26.000000000 +0200 @@ -66,6 +66,9 @@ {{ if ne .ActionNameValue "" }} ENV {{ .ActionNameEnvVar }} {{ .ActionNameValue }} {{ end }} +{{ if ne .GitCommitValue "" }} +ENV {{ .GitCommitEnvVar }} {{ .GitCommitValue }} +{{ end }} COPY . /okteto/src WORKDIR /okteto/src @@ -87,6 +90,8 @@ TokenValue string ActionNameEnvVar string ActionNameValue string + GitCommitEnvVar string + GitCommitValue string RemoteDeployEnvVar string DeployFlags string RandomInt int @@ -200,6 +205,8 @@ TokenValue: okteto.Context().Token, ActionNameEnvVar: model.OktetoActionNameEnvVar, ActionNameValue: os.Getenv(model.OktetoActionNameEnvVar), + GitCommitEnvVar: constants.OktetoGitCommitEnvVar, + GitCommitValue: os.Getenv(constants.OktetoGitCommitEnvVar), RemoteDeployEnvVar: constants.OKtetoDeployRemote, RandomInt: int(randomNumber.Int64()), DeployFlags: strings.Join(getDeployFlags(opts), " "), diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/okteto-2.14.1/cmd/destroy/remote.go new/okteto-2.14.2/cmd/destroy/remote.go --- old/okteto-2.14.1/cmd/destroy/remote.go 2023-03-31 21:11:44.000000000 +0200 +++ new/okteto-2.14.2/cmd/destroy/remote.go 2023-04-05 18:55:26.000000000 +0200 @@ -53,6 +53,9 @@ {{ if ne .ActionNameValue "" }} ENV {{ .ActionNameEnvVar }} {{ .ActionNameValue }} {{ end }} +{{ if ne .GitCommitValue "" }} +ENV {{ .GitCommitEnvVar }} {{ .GitCommitValue }} +{{ end }} COPY . /okteto/src WORKDIR /okteto/src @@ -74,6 +77,8 @@ TokenValue string ActionNameEnvVar string ActionNameValue string + GitCommitEnvVar string + GitCommitValue string RemoteDeployEnvVar string DeployFlags string RandomInt int @@ -191,6 +196,8 @@ TokenValue: okteto.Context().Token, ActionNameEnvVar: model.OktetoActionNameEnvVar, ActionNameValue: os.Getenv(model.OktetoActionNameEnvVar), + GitCommitEnvVar: constants.OktetoGitCommitEnvVar, + GitCommitValue: os.Getenv(constants.OktetoGitCommitEnvVar), RemoteDeployEnvVar: constants.OKtetoDeployRemote, RandomInt: int(randomNumber.Int64()), DestroyFlags: strings.Join(getDestroyFlags(opts), " "), diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/okteto-2.14.1/pkg/cmd/pipeline/translate.go new/okteto-2.14.2/pkg/cmd/pipeline/translate.go --- old/okteto-2.14.1/pkg/cmd/pipeline/translate.go 2023-03-31 21:11:44.000000000 +0200 +++ new/okteto-2.14.2/pkg/cmd/pipeline/translate.go 2023-04-05 18:55:26.000000000 +0200 @@ -32,6 +32,7 @@ "github.com/okteto/okteto/pkg/k8s/configmaps" oktetoLog "github.com/okteto/okteto/pkg/log" "github.com/okteto/okteto/pkg/model" + giturls "github.com/whilp/git-urls" apiv1 "k8s.io/api/core/v1" k8sErrors "k8s.io/apimachinery/pkg/api/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" @@ -260,7 +261,7 @@ continue } if repo != "" { - app.ObjectMeta().Annotations[model.OktetoRepositoryAnnotation] = repo + app.ObjectMeta().Annotations[model.OktetoRepositoryAnnotation] = removeSensitiveDataFromGitURL(repo) } app.ObjectMeta().Annotations[model.OktetoDevNameAnnotation] = devName if err := app.PatchAnnotations(ctx, c); err != nil { @@ -268,3 +269,19 @@ } } } + +func removeSensitiveDataFromGitURL(gitURL string) string { + if gitURL == "" { + return gitURL + } + + parsedRepo, err := giturls.Parse(gitURL) + if err != nil { + return "" + } + + if parsedRepo.User.Username() != "" { + parsedRepo.User = nil + } + return parsedRepo.String() +} diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/okteto-2.14.1/pkg/cmd/pipeline/translate_test.go new/okteto-2.14.2/pkg/cmd/pipeline/translate_test.go --- old/okteto-2.14.1/pkg/cmd/pipeline/translate_test.go 2023-03-31 21:11:44.000000000 +0200 +++ new/okteto-2.14.2/pkg/cmd/pipeline/translate_test.go 2023-04-05 18:55:26.000000000 +0200 @@ -110,8 +110,49 @@ assert.Equal(t, d.Annotations, map[string]string{ - model.OktetoRepositoryAnnotation: "git-repo", + model.OktetoRepositoryAnnotation: "file://git-repo", model.OktetoDevNameAnnotation: "deployment", }, ) } + +func Test_removeSensitiveDataFromGitURL(t *testing.T) { + tests := []struct { + name string + gitURL string + expected string + }{ + { + name: "empty-url", + gitURL: "", + expected: "", + }, + { + name: "without-user-information", + gitURL: "https://github.com/okteto/movies", + expected: "https://github.com/okteto/movies", + }, + { + name: "with-user-and-password", + gitURL: "https://my-user:my-strong-p...@github.com:80/okteto/movies", + expected: "https://github.com:80/okteto/movies", + }, + { + name: "with-auth-token-long", + gitURL: "https://adsoifq9389qnjasd:x-oauth-ba...@github.com/okteto/movies", + expected: "https://github.com/okteto/movies", + }, + { + name: "with-auth-token-short", + gitURL: "https://adsoifq9389qnj...@github.com/okteto/movies", + expected: "https://github.com/okteto/movies", + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + result := removeSensitiveDataFromGitURL(tt.gitURL) + assert.Equal(t, tt.expected, result) + }) + } +} diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/okteto-2.14.1/pkg/constants/constants.go new/okteto-2.14.2/pkg/constants/constants.go --- old/okteto-2.14.1/pkg/constants/constants.go 2023-03-31 21:11:44.000000000 +0200 +++ new/okteto-2.14.2/pkg/constants/constants.go 2023-04-05 18:55:26.000000000 +0200 @@ -79,4 +79,10 @@ // DefaultGlobalNamespace namespace where okteto app is running DefaultGlobalNamespace = "okteto" + + // OktetoGitBranchEnvVar is the name of the Git branch currently being deployed. + OktetoGitBranchEnvVar = "OKTETO_GIT_BRANCH" + + // OktetoGitCommitEnvVar is the SHA1 hash of the last commit of the branch. + OktetoGitCommitEnvVar = "OKTETO_GIT_COMMIT" ) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/okteto-2.14.1/pkg/model/const.go new/okteto-2.14.2/pkg/model/const.go --- old/okteto-2.14.1/pkg/model/const.go 2023-03-31 21:11:44.000000000 +0200 +++ new/okteto-2.14.2/pkg/model/const.go 2023-04-05 18:55:26.000000000 +0200 @@ -168,12 +168,6 @@ // HelmSecretType indicates the type for secrets created by Helm HelmSecretType = "helm.sh/release.v1" - // OktetoGitBranchEnvVar is the name of the Git branch currently being deployed. - OktetoGitBranchEnvVar = "OKTETO_GIT_BRANCH" - - // OktetoGitCommitEnvVar is the SHA1 hash of the last commit of the branch. - OktetoGitCommitEnvVar = "OKTETO_GIT_COMMIT" - // OktetoRegistryURLEnvVar is the url of the Okteto Registry OktetoRegistryURLEnvVar = "OKTETO_REGISTRY_URL" diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/okteto-2.14.1/pkg/repository/git.go new/okteto-2.14.2/pkg/repository/git.go --- old/okteto-2.14.1/pkg/repository/git.go 1970-01-01 01:00:00.000000000 +0100 +++ new/okteto-2.14.2/pkg/repository/git.go 2023-04-05 18:55:26.000000000 +0200 @@ -0,0 +1,132 @@ +// Copyright 2023 The Okteto Authors +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package repository + +import ( + "fmt" + + "github.com/go-git/go-git/v5" + "github.com/go-git/go-git/v5/plumbing" +) + +type gitRepoController struct { + path string + repoGetter repositoryGetterInterface +} + +func newGitRepoController() gitRepoController { + return gitRepoController{ + repoGetter: gitRepositoryGetter{}, + } +} + +// IsClean checks if the repository have changes over the commit +func (r gitRepoController) isClean() (bool, error) { + repo, err := r.repoGetter.get(r.path) + if err != nil { + return false, fmt.Errorf("failed to analyze git repo: %w", err) + } + worktree, err := repo.Worktree() + if err != nil { + return false, fmt.Errorf("failed to infer the git repo's current branch: %w", err) + } + + status, err := worktree.Status() + if err != nil { + return false, fmt.Errorf("failed to infer the git repo's status: %w", err) + } + + return status.IsClean(), nil +} + +// GetSHA returns the last commit sha of the repository +func (r gitRepoController) getSHA() (string, error) { + isClean, err := r.isClean() + if err != nil { + return "", fmt.Errorf("failed to check if repo is clean: %w", err) + } + if !isClean { + return "", nil + } + repo, err := r.repoGetter.get(r.path) + if err != nil { + return "", fmt.Errorf("failed to analyze git repo: %w", err) + } + head, err := repo.Head() + if err != nil { + return "", fmt.Errorf("failed to analyze git repo: %w", err) + } + return head.Hash().String(), nil +} + +type repositoryGetterInterface interface { + get(path string) (gitRepositoryInterface, error) +} + +type gitRepositoryGetter struct{} + +func (gitRepositoryGetter) get(path string) (gitRepositoryInterface, error) { + repo, err := git.PlainOpen(path) + if err != nil { + return nil, err + } + return oktetoGitRepository{repo: repo}, nil +} + +type oktetoGitRepository struct { + repo *git.Repository +} + +func (ogr oktetoGitRepository) Worktree() (gitWorktreeInterface, error) { + worktree, err := ogr.repo.Worktree() + if err != nil { + return nil, err + } + return oktetoGitWorktree{worktree: worktree}, nil +} + +func (ogr oktetoGitRepository) Head() (*plumbing.Reference, error) { + return ogr.repo.Head() +} + +type oktetoGitWorktree struct { + worktree *git.Worktree +} + +func (ogr oktetoGitWorktree) Status() (gitStatusInterface, error) { + status, err := ogr.worktree.Status() + if err != nil { + return nil, err + } + return oktetoGitStatus{status: status}, nil +} + +type oktetoGitStatus struct { + status git.Status +} + +func (ogs oktetoGitStatus) IsClean() bool { + return ogs.status.IsClean() +} + +type gitRepositoryInterface interface { + Worktree() (gitWorktreeInterface, error) + Head() (*plumbing.Reference, error) +} +type gitWorktreeInterface interface { + Status() (gitStatusInterface, error) +} +type gitStatusInterface interface { + IsClean() bool +} diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/okteto-2.14.1/pkg/repository/git_test.go new/okteto-2.14.2/pkg/repository/git_test.go --- old/okteto-2.14.1/pkg/repository/git_test.go 1970-01-01 01:00:00.000000000 +0100 +++ new/okteto-2.14.2/pkg/repository/git_test.go 2023-04-05 18:55:26.000000000 +0200 @@ -0,0 +1,211 @@ +// Copyright 2023 The Okteto Authors +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package repository + +import ( + "testing" + + "github.com/go-git/go-git/v5" + "github.com/go-git/go-git/v5/plumbing" + "github.com/stretchr/testify/assert" +) + +func TestIsClean(t *testing.T) { + type config struct { + repositoryGetter fakeRepositoryGetter + } + type expected struct { + isClean bool + err error + } + var tests = []struct { + name string + config config + expected expected + }{ + { + name: "dir is not a repository", + config: config{ + repositoryGetter: fakeRepositoryGetter{ + repository: nil, + err: git.ErrRepositoryNotExists, + }, + }, + expected: expected{ + isClean: false, + err: git.ErrRepositoryNotExists, + }, + }, + { + name: "repository could not access worktree", + config: config{ + repositoryGetter: fakeRepositoryGetter{ + repository: &fakeRepository{ + worktree: nil, + err: assert.AnError, + }, + }, + }, + expected: expected{ + isClean: false, + err: assert.AnError, + }, + }, + { + name: "worktree could not access status", + config: config{ + repositoryGetter: fakeRepositoryGetter{ + repository: &fakeRepository{ + worktree: &fakeWorktree{ + status: nil, + err: assert.AnError, + }, + err: nil, + }, + }, + }, + expected: expected{ + isClean: false, + err: assert.AnError, + }, + }, + { + name: "repository is not clean", + config: config{ + repositoryGetter: fakeRepositoryGetter{ + repository: &fakeRepository{ + worktree: &fakeWorktree{ + status: &fakeStatus{ + isClean: false, + }, + err: nil, + }, + err: nil, + }, + }, + }, + expected: expected{ + isClean: false, + err: nil, + }, + }, + { + name: "repository is clean", + config: config{ + repositoryGetter: fakeRepositoryGetter{ + repository: &fakeRepository{ + worktree: &fakeWorktree{ + status: &fakeStatus{ + isClean: true, + }, + err: nil, + }, + err: nil, + }, + }, + }, + expected: expected{ + isClean: true, + err: nil, + }, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + repo := Repository{ + control: gitRepoController{ + repoGetter: tt.config.repositoryGetter, + }, + } + isClean, err := repo.IsClean() + assert.ErrorIs(t, err, tt.expected.err) + assert.Equal(t, tt.expected.isClean, isClean) + }) + } +} + +func TestGetSHA(t *testing.T) { + type config struct { + repositoryGetter fakeRepositoryGetter + } + type expected struct { + sha string + err error + } + var tests = []struct { + name string + config config + expected expected + }{ + { + name: "get sha without any problem", + config: config{ + repositoryGetter: fakeRepositoryGetter{ + repository: &fakeRepository{ + worktree: &fakeWorktree{ + status: &fakeStatus{ + isClean: true, + }, + }, + head: plumbing.NewHashReference("test", plumbing.NewHash("test")), + }, + }, + }, + expected: expected{ + sha: plumbing.NewHash("test").String(), + err: nil, + }, + }, + { + name: "error getting repository", + config: config{ + repositoryGetter: fakeRepositoryGetter{ + repository: nil, + err: assert.AnError, + }, + }, + expected: expected{ + sha: "", + err: assert.AnError, + }, + }, + { + name: "error getting Head", + config: config{ + repositoryGetter: fakeRepositoryGetter{ + repository: &fakeRepository{ + head: nil, + err: assert.AnError, + }, + }, + }, + expected: expected{ + sha: "", + err: assert.AnError, + }, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + repo := Repository{ + control: gitRepoController{ + repoGetter: tt.config.repositoryGetter, + }, + } + sha, err := repo.GetSHA() + assert.ErrorIs(t, err, tt.expected.err) + assert.Equal(t, tt.expected.sha, sha) + }) + } +} diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/okteto-2.14.1/pkg/repository/remote.go new/okteto-2.14.2/pkg/repository/remote.go --- old/okteto-2.14.1/pkg/repository/remote.go 1970-01-01 01:00:00.000000000 +0100 +++ new/okteto-2.14.2/pkg/repository/remote.go 2023-04-05 18:55:26.000000000 +0200 @@ -0,0 +1,32 @@ +// Copyright 2023 The Okteto Authors +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package repository + +type oktetoRemoteRepoController struct { + gitCommit string +} + +func newOktetoRemoteRepoController(localCommit string) oktetoRemoteRepoController { + return oktetoRemoteRepoController{ + gitCommit: localCommit, + } +} + +func (or oktetoRemoteRepoController) isClean() (bool, error) { + return or.gitCommit != "", nil +} + +func (or oktetoRemoteRepoController) getSHA() (string, error) { + return or.gitCommit, nil +} diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/okteto-2.14.1/pkg/repository/remote_test.go new/okteto-2.14.2/pkg/repository/remote_test.go --- old/okteto-2.14.1/pkg/repository/remote_test.go 1970-01-01 01:00:00.000000000 +0100 +++ new/okteto-2.14.2/pkg/repository/remote_test.go 2023-04-05 18:55:26.000000000 +0200 @@ -0,0 +1,47 @@ +// Copyright 2023 The Okteto Authors +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package repository + +import ( + "testing" + + "github.com/stretchr/testify/assert" +) + +func TestRemoteIsCleanTrue(t *testing.T) { + remote := oktetoRemoteRepoController{ + gitCommit: "123", + } + isClean, err := remote.isClean() + assert.NoError(t, err) + assert.True(t, isClean) +} + +func TestRemoteIsCleanFalse(t *testing.T) { + remote := oktetoRemoteRepoController{ + gitCommit: "", + } + isClean, err := remote.isClean() + assert.NoError(t, err) + assert.False(t, isClean) +} + +func TestRemoteGetSHA(t *testing.T) { + remote := oktetoRemoteRepoController{ + gitCommit: "123", + } + sha, err := remote.getSHA() + assert.NoError(t, err) + assert.Equal(t, remote.gitCommit, sha) +} diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/okteto-2.14.1/pkg/repository/repository.go new/okteto-2.14.2/pkg/repository/repository.go --- old/okteto-2.14.1/pkg/repository/repository.go 2023-03-31 21:11:44.000000000 +0200 +++ new/okteto-2.14.2/pkg/repository/repository.go 2023-04-05 18:55:26.000000000 +0200 @@ -14,115 +14,54 @@ package repository import ( - "fmt" + "net/url" + "os" - "github.com/go-git/go-git/v5" - "github.com/go-git/go-git/v5/plumbing" + "github.com/okteto/okteto/pkg/constants" + oktetoLog "github.com/okteto/okteto/pkg/log" + giturls "github.com/whilp/git-urls" ) // Repository is the struct to check everything related to Git Repo // like checking the commit or if the project has changes over it type Repository struct { path string + url *url.URL - repositoryGetter repositoryGetterInterface + control repositoryInterface } -type repositoryGetterInterface interface { - get(path string) (gitRepositoryInterface, error) -} - -type repositoryGetter struct{} -func (repositoryGetter) get(path string) (gitRepositoryInterface, error) { - repo, err := git.PlainOpen(path) - if err != nil { - return nil, err - } - return oktetoGitRepository{repo: repo}, nil +type repositoryInterface interface { + isClean() (bool, error) + getSHA() (string, error) } -type oktetoGitRepository struct { - repo *git.Repository -} - -func (ogr oktetoGitRepository) Worktree() (gitWorktreeInterface, error) { - worktree, err := ogr.repo.Worktree() +// NewRepository creates a repository controller +func NewRepository(path string) Repository { + url, err := giturls.Parse(path) if err != nil { - return nil, err + oktetoLog.Infof("could not parse url: %w", err) } - return oktetoGitWorktree{worktree: worktree}, nil -} - -func (ogr oktetoGitRepository) Head() (*plumbing.Reference, error) { - return ogr.repo.Head() -} - -type oktetoGitWorktree struct { - worktree *git.Worktree -} -func (ogr oktetoGitWorktree) Status() (gitStatusInterface, error) { - status, err := ogr.worktree.Status() - if err != nil { - return nil, err + var controller repositoryInterface = newGitRepoController() + // check if we are inside a remote deploy + if v := os.Getenv(constants.OKtetoDeployRemote); v != "" { + sha := os.Getenv(constants.OktetoGitCommitEnvVar) + controller = newOktetoRemoteRepoController(sha) } - return oktetoGitStatus{status: status}, nil -} - -type oktetoGitStatus struct { - status git.Status -} - -func (ogs oktetoGitStatus) IsClean() bool { - return ogs.status.IsClean() -} - -type gitRepositoryInterface interface { - Worktree() (gitWorktreeInterface, error) - Head() (*plumbing.Reference, error) -} -type gitWorktreeInterface interface { - Status() (gitStatusInterface, error) -} -type gitStatusInterface interface { - IsClean() bool -} - -func NewRepository(path string) Repository { return Repository{ - path: path, - repositoryGetter: repositoryGetter{}, + path: path, + url: url, + control: controller, } } // IsClean checks if the repository have changes over the commit func (r Repository) IsClean() (bool, error) { - repo, err := r.repositoryGetter.get(r.path) - if err != nil { - return false, fmt.Errorf("failed to analyze git repo: %w", err) - } - worktree, err := repo.Worktree() - if err != nil { - return false, fmt.Errorf("failed to infer the git repo's current branch: %w", err) - } - - status, err := worktree.Status() - if err != nil { - return false, fmt.Errorf("failed to infer the git repo's status: %w", err) - } - - return status.IsClean(), nil + return r.control.isClean() } // GetSHA returns the last commit sha of the repository func (r Repository) GetSHA() (string, error) { - repo, err := r.repositoryGetter.get(r.path) - if err != nil { - return "", fmt.Errorf("failed to analyze git repo: %w", err) - } - head, err := repo.Head() - if err != nil { - return "", fmt.Errorf("failed to analyze git repo: %w", err) - } - return head.Hash().String(), nil + return r.control.getSHA() } diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/okteto-2.14.1/pkg/repository/repository_test.go new/okteto-2.14.2/pkg/repository/repository_test.go --- old/okteto-2.14.1/pkg/repository/repository_test.go 2023-03-31 21:11:44.000000000 +0200 +++ new/okteto-2.14.2/pkg/repository/repository_test.go 2023-04-05 18:55:26.000000000 +0200 @@ -16,8 +16,8 @@ import ( "testing" - "github.com/go-git/go-git/v5" "github.com/go-git/go-git/v5/plumbing" + "github.com/okteto/okteto/pkg/constants" "github.com/stretchr/testify/assert" ) @@ -61,182 +61,43 @@ return fs.isClean } -func TestIsClean(t *testing.T) { - type config struct { - repositoryGetter fakeRepositoryGetter - } - type expected struct { - isClean bool - err error - } - var tests = []struct { - name string - config config - expected expected +func TestNewRepo(t *testing.T) { + tt := []struct { + name string + GitCommit string + remoteDeploy string + expectedControl repositoryInterface }{ { - name: "dir is not a repository", - config: config{ - repositoryGetter: fakeRepositoryGetter{ - repository: nil, - err: git.ErrRepositoryNotExists, - }, - }, - expected: expected{ - isClean: false, - err: git.ErrRepositoryNotExists, + name: "GitCommit is empty", + GitCommit: "", + expectedControl: gitRepoController{ + repoGetter: gitRepositoryGetter{}, }, }, { - name: "repository could not access worktree", - config: config{ - repositoryGetter: fakeRepositoryGetter{ - repository: &fakeRepository{ - worktree: nil, - err: assert.AnError, - }, - }, - }, - expected: expected{ - isClean: false, - err: assert.AnError, + name: "GitCommit is not empty", + GitCommit: "1234567890", + expectedControl: gitRepoController{ + repoGetter: gitRepositoryGetter{}, }, }, { - name: "worktree could not access status", - config: config{ - repositoryGetter: fakeRepositoryGetter{ - repository: &fakeRepository{ - worktree: &fakeWorktree{ - status: nil, - err: assert.AnError, - }, - err: nil, - }, - }, - }, - expected: expected{ - isClean: false, - err: assert.AnError, - }, - }, - { - name: "repository is not clean", - config: config{ - repositoryGetter: fakeRepositoryGetter{ - repository: &fakeRepository{ - worktree: &fakeWorktree{ - status: &fakeStatus{ - isClean: false, - }, - err: nil, - }, - err: nil, - }, - }, - }, - expected: expected{ - isClean: false, - err: nil, - }, - }, - { - name: "repository is clean", - config: config{ - repositoryGetter: fakeRepositoryGetter{ - repository: &fakeRepository{ - worktree: &fakeWorktree{ - status: &fakeStatus{ - isClean: true, - }, - err: nil, - }, - err: nil, - }, - }, - }, - expected: expected{ - isClean: true, - err: nil, - }, - }, - } - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - repo := Repository{ - repositoryGetter: tt.config.repositoryGetter, - } - isClean, err := repo.IsClean() - assert.ErrorIs(t, err, tt.expected.err) - assert.Equal(t, tt.expected.isClean, isClean) - }) - } -} - -func TestGetSHA(t *testing.T) { - type config struct { - repositoryGetter fakeRepositoryGetter - } - type expected struct { - sha string - err error - } - var tests = []struct { - name string - config config - expected expected - }{ - { - name: "get sha without any problem", - config: config{ - repositoryGetter: fakeRepositoryGetter{ - repository: &fakeRepository{ - head: plumbing.NewHashReference("test", plumbing.NewHash("test")), - }, - }, - }, - expected: expected{ - sha: plumbing.NewHash("test").String(), - err: nil, - }, - }, - { - name: "error getting repository", - config: config{ - repositoryGetter: fakeRepositoryGetter{ - repository: nil, - err: assert.AnError, - }, - }, - expected: expected{ - sha: "", - err: assert.AnError, - }, - }, - { - name: "error getting Head", - config: config{ - repositoryGetter: fakeRepositoryGetter{ - repository: &fakeRepository{ - head: nil, - err: assert.AnError, - }, - }, - }, - expected: expected{ - sha: "", - err: assert.AnError, + name: "GitCommit is not empty in remote deploy", + GitCommit: "1234567890", + remoteDeploy: "true", + expectedControl: oktetoRemoteRepoController{ + gitCommit: "1234567890", }, }, } - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - repo := Repository{ - repositoryGetter: tt.config.repositoryGetter, - } - sha, err := repo.GetSHA() - assert.ErrorIs(t, err, tt.expected.err) - assert.Equal(t, tt.expected.sha, sha) + for _, tc := range tt { + t.Run(tc.name, func(t *testing.T) { + t.Setenv(constants.OktetoGitCommitEnvVar, tc.GitCommit) + t.Setenv(constants.OKtetoDeployRemote, string(tc.remoteDeploy)) + r := NewRepository("https://my-repo/okteto/okteto") + assert.Equal(t, "/okteto/okteto", r.url.Path) + assert.IsType(t, tc.expectedControl, r.control) }) } } ++++++ okteto.obsinfo ++++++ --- /var/tmp/diff_new_pack.tHlUXl/_old 2023-04-06 15:56:15.932405515 +0200 +++ /var/tmp/diff_new_pack.tHlUXl/_new 2023-04-06 15:56:15.936405538 +0200 @@ -1,5 +1,5 @@ name: okteto -version: 2.14.1 -mtime: 1680289904 -commit: 14b577383d98920b1275fb86393566b93943876b +version: 2.14.2 +mtime: 1680713726 +commit: ac0f5a90199e4aac4f4b6fab478259dc3b879bda ++++++ vendor.tar.gz ++++++ /work/SRC/openSUSE:Factory/okteto/vendor.tar.gz /work/SRC/openSUSE:Factory/.okteto.new.19717/vendor.tar.gz differ: char 5, line 1