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-05-22 13:14:28 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/okteto (Old) and /work/SRC/openSUSE:Factory/.okteto.new.1533 (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "okteto" Mon May 22 13:14:28 2023 rev:49 rq:1088267 version:2.15.3 Changes: -------- --- /work/SRC/openSUSE:Factory/okteto/okteto.changes 2023-05-05 15:59:06.884714074 +0200 +++ /work/SRC/openSUSE:Factory/.okteto.new.1533/okteto.changes 2023-05-22 13:14:31.218865698 +0200 @@ -1,0 +2,9 @@ +Mon May 22 05:45:35 UTC 2023 - ka...@b1-systems.de + +- Update to version 2.15.3: + * fix(build): expand build args (#3633) (#3637) + * fix: release-2.15 (#3636) + * fix: endpoints command (#3630) + * doc: add more context on errors (#3591) (#3592) + +------------------------------------------------------------------- Old: ---- okteto-2.15.2.obscpio New: ---- okteto-2.15.3.obscpio ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ okteto.spec ++++++ --- /var/tmp/diff_new_pack.KEaNAi/_old 2023-05-22 13:14:32.422871707 +0200 +++ /var/tmp/diff_new_pack.KEaNAi/_new 2023-05-22 13:14:32.426871727 +0200 @@ -19,7 +19,7 @@ %define __arch_install_post export NO_BRP_STRIP_DEBUG=true Name: okteto -Version: 2.15.2 +Version: 2.15.3 Release: 0 Summary: Develop your applications directly in your Kubernetes Cluster License: Apache-2.0 ++++++ _service ++++++ --- /var/tmp/diff_new_pack.KEaNAi/_old 2023-05-22 13:14:32.466871927 +0200 +++ /var/tmp/diff_new_pack.KEaNAi/_new 2023-05-22 13:14:32.470871947 +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.15.2</param> + <param name="revision">2.15.3</param> <param name="versionformat">@PARENT_TAG@</param> <param name="changesgenerate">enable</param> - <param name="match-tag">2.15.2</param> + <param name="match-tag">2.15.3</param> </service> <service name="set_version" mode="disabled"> <param name="basename">okteto</param> ++++++ _servicedata ++++++ --- /var/tmp/diff_new_pack.KEaNAi/_old 2023-05-22 13:14:32.494872066 +0200 +++ /var/tmp/diff_new_pack.KEaNAi/_new 2023-05-22 13:14:32.494872066 +0200 @@ -1,6 +1,6 @@ <servicedata> <service name="tar_scm"> <param name="url">https://github.com/okteto/okteto</param> - <param name="changesrevision">274b41b8fe33f99d5e0773363c46a6ff7c16a6f8</param></service></servicedata> + <param name="changesrevision">a4587f1827b1933f700363317694e655c6efd74b</param></service></servicedata> (No newline at EOF) ++++++ okteto-2.15.2.obscpio -> okteto-2.15.3.obscpio ++++++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/okteto-2.15.2/cmd/deploy/command_configuration.go new/okteto-2.15.3/cmd/deploy/command_configuration.go --- old/okteto-2.15.2/cmd/deploy/command_configuration.go 2023-05-04 12:12:37.000000000 +0200 +++ new/okteto-2.15.3/cmd/deploy/command_configuration.go 2023-05-19 14:42:12.000000000 +0200 @@ -125,7 +125,7 @@ } } -func (dc *DeployCommand) addEnvVars(cwd string) { +func (dc *DeployCommand) addEnvVars(ctx context.Context, cwd string) { if os.Getenv(constants.OktetoGitBranchEnvVar) == "" { branch, err := utils.GetBranch(cwd) if err != nil { diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/okteto-2.15.2/cmd/deploy/deploy.go new/okteto-2.15.3/cmd/deploy/deploy.go --- old/okteto-2.15.2/cmd/deploy/deploy.go 2023-05-04 12:12:37.000000000 +0200 +++ new/okteto-2.15.3/cmd/deploy/deploy.go 2023-05-19 14:42:12.000000000 +0200 @@ -38,6 +38,7 @@ "github.com/okteto/okteto/pkg/types" "github.com/spf13/afero" "github.com/spf13/cobra" + "k8s.io/client-go/rest" ) const ( @@ -79,9 +80,10 @@ TempKubeconfigFile string K8sClientProvider okteto.K8sClientProvider Builder *buildv2.OktetoBuilder - GetExternalControl func(cp okteto.K8sClientProvider, filename string) (ExternalResourceInterface, error) + GetExternalControl func(cfg *rest.Config) ExternalResourceInterface GetDeployer func(context.Context, *model.Manifest, *Options, string, *buildv2.OktetoBuilder) (deployerInterface, error) - deployWaiter deployWaiter + EndpointGetter func() (EndpointGetter, error) + DeployWaiter DeployWaiter CfgMapHandler configMapHandler Fs afero.Fs DivertDriver divert.Driver @@ -101,6 +103,10 @@ cleanUp(context.Context, error) } +func NewDeployExternalK8sControl(cfg *rest.Config) ExternalResourceInterface { + return externalresource.NewExternalK8sControl(cfg) +} + // Deploy deploys the okteto manifest func Deploy(ctx context.Context) *cobra.Command { options := &Options{} @@ -177,11 +183,12 @@ c := &DeployCommand{ GetManifest: model.GetManifestV2, - GetExternalControl: getExternalControlFromCtx, + GetExternalControl: NewDeployExternalK8sControl, K8sClientProvider: k8sClientProvider, GetDeployer: GetDeployer, Builder: buildv2.NewBuilderFromScratch(), - deployWaiter: newDeployWaiter(k8sClientProvider), + DeployWaiter: NewDeployWaiter(k8sClientProvider), + EndpointGetter: NewEndpointGetter, isRemote: utils.LoadBoolean(constants.OKtetoDeployRemote), CfgMapHandler: NewConfigmapHandler(k8sClientProvider), Fs: afero.NewOsFs(), @@ -286,8 +293,10 @@ // We need to create a client that doesn't go through the proxy to create // the configmap without the deployedByLabel c, _, err := dc.K8sClientProvider.Provide(okteto.Context().Cfg) - - dc.addEnvVars(cwd) + if err != nil { + return err + } + dc.addEnvVars(ctx, cwd) if err := setDeployOptionsValuesFromManifest(ctx, deployOptions, cwd, c); err != nil { return err @@ -346,15 +355,14 @@ } if hasDeployed { if deployOptions.Wait { - if err := dc.deployWaiter.wait(ctx, deployOptions); err != nil { + if err := dc.DeployWaiter.wait(ctx, deployOptions); err != nil { return err } } if !utils.LoadBoolean(constants.OktetoWithinDeployCommandContextEnvVar) { - eg := &endpointGetter{ - K8sClientProvider: dc.K8sClientProvider, - GetExternalControl: dc.GetExternalControl, - TempKubeconfigFile: dc.TempKubeconfigFile, + eg, err := dc.EndpointGetter() + if err != nil { + oktetoLog.Infof("could not create endpoint getter: %s", err) } if err := eg.showEndpoints(ctx, &EndpointsOptions{Name: deployOptions.Name, Namespace: deployOptions.Manifest.Namespace}); err != nil { oktetoLog.Infof("could not retrieve endpoints: %s", err) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/okteto-2.15.2/cmd/deploy/deploy_test.go new/okteto-2.15.3/cmd/deploy/deploy_test.go --- old/okteto-2.15.2/cmd/deploy/deploy_test.go 2023-05-04 12:12:37.000000000 +0200 +++ new/okteto-2.15.3/cmd/deploy/deploy_test.go 2023-05-19 14:42:12.000000000 +0200 @@ -496,6 +496,7 @@ Contexts: map[string]*okteto.OktetoContext{ "test": { Namespace: "test", + Cfg: clientcmdapi.NewConfig(), }, }, CurrentContext: "test", @@ -518,6 +519,7 @@ }, GetExternalControl: cp.getFakeExternalControl, K8sClientProvider: clientProvider, + EndpointGetter: getFakeEndpoint, CfgMapHandler: newDefaultConfigMapHandler(clientProvider), Fs: afero.NewMemMapFs(), } @@ -579,6 +581,7 @@ c := &DeployCommand{ GetManifest: getFakeManifest, K8sClientProvider: clientProvider, + EndpointGetter: getFakeEndpoint, GetExternalControl: cp.getFakeExternalControl, Fs: afero.NewMemMapFs(), CfgMapHandler: newDefaultConfigMapHandler(clientProvider), @@ -787,8 +790,15 @@ return f.err } -func (f *fakeExternalControlProvider) getFakeExternalControl(cp okteto.K8sClientProvider, filename string) (ExternalResourceInterface, error) { - return f.control, f.err +func (f *fakeExternalControlProvider) getFakeExternalControl(_ *rest.Config) ExternalResourceInterface { + return f.control +} + +func getFakeEndpoint() (EndpointGetter, error) { + return EndpointGetter{ + K8sClientProvider: test.NewFakeK8sProvider(), + endpointControl: &fakeExternalControl{}, + }, nil } func TestDeployExternals(t *testing.T) { @@ -869,6 +879,7 @@ ld := localDeployer{ GetExternalControl: cp.getFakeExternalControl, Fs: afero.NewMemMapFs(), + K8sClientProvider: test.NewFakeK8sProvider(), } if tc.expectedErr { diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/okteto-2.15.2/cmd/deploy/endpoints.go new/okteto-2.15.3/cmd/deploy/endpoints.go --- old/okteto-2.15.2/cmd/deploy/endpoints.go 2023-05-04 12:12:37.000000000 +0200 +++ new/okteto-2.15.3/cmd/deploy/endpoints.go 2023-05-19 14:42:12.000000000 +0200 @@ -26,9 +26,7 @@ "github.com/okteto/okteto/pkg/devenvironment" oktetoErrors "github.com/okteto/okteto/pkg/errors" "github.com/okteto/okteto/pkg/externalresource" - k8sExternalResources "github.com/okteto/okteto/pkg/externalresource/k8s" "github.com/okteto/okteto/pkg/format" - kconfig "github.com/okteto/okteto/pkg/k8s/kubeconfig" oktetoLog "github.com/okteto/okteto/pkg/log" "github.com/okteto/okteto/pkg/model" "github.com/okteto/okteto/pkg/okteto" @@ -44,20 +42,30 @@ K8sContext string } -type endpointGetter struct { - GetManifest func(path string) (*model.Manifest, error) - K8sClientProvider okteto.K8sClientProvider - GetExternalControl func(cp okteto.K8sClientProvider, filename string) (ExternalResourceInterface, error) - TempKubeconfigFile string +type endpointGetterInterface interface { + List(ctx context.Context, ns string, labelSelector string) ([]externalresource.ExternalResource, error) } -func newEndpointGetter(tempKubeconfig string) endpointGetter { - return endpointGetter{ - GetManifest: model.GetManifestV2, - K8sClientProvider: okteto.NewK8sClientProvider(), - GetExternalControl: getExternalControlFromCtx, - TempKubeconfigFile: tempKubeconfig, +type EndpointGetter struct { + GetManifest func(path string) (*model.Manifest, error) + endpointControl endpointGetterInterface + K8sClientProvider okteto.K8sClientProvider +} + +func NewEndpointGetter() (EndpointGetter, error) { + k8sProvider := okteto.NewK8sClientProvider() + _, cfg, err := k8sProvider.Provide(okteto.Context().Cfg) + if err != nil { + return EndpointGetter{}, fmt.Errorf("error getting kubernetes client: %w", err) } + + ec := externalresource.NewExternalK8sControl(cfg) + return EndpointGetter{ + GetManifest: model.GetManifestV2, + endpointControl: ec, + K8sClientProvider: k8sProvider, + }, nil + } // Endpoints deploys the okteto manifest @@ -101,7 +109,10 @@ return err } - eg := newEndpointGetter("") + eg, err := NewEndpointGetter() + if err != nil { + return err + } cwd, err := os.Getwd() if err != nil { return fmt.Errorf("failed to get the current working directory: %w", err) @@ -155,7 +166,7 @@ } } -func (eg *endpointGetter) getEndpoints(ctx context.Context, opts *EndpointsOptions) ([]string, error) { +func (eg *EndpointGetter) getEndpoints(ctx context.Context, opts *EndpointsOptions) ([]string, error) { if opts.Output == "" { oktetoLog.Spinner("Retrieving endpoints...") oktetoLog.StartSpinner() @@ -173,11 +184,7 @@ return nil, err } - externalCtrl, err := eg.GetExternalControl(eg.K8sClientProvider, eg.TempKubeconfigFile) - if err != nil { - return nil, err - } - externalEps, err := externalCtrl.List(ctx, opts.Namespace, labelSelector) + externalEps, err := eg.endpointControl.List(ctx, opts.Namespace, labelSelector) if err != nil { return nil, err } @@ -196,7 +203,7 @@ return eps, nil } -func (dc *endpointGetter) showEndpoints(ctx context.Context, opts *EndpointsOptions) error { +func (dc *EndpointGetter) showEndpoints(ctx context.Context, opts *EndpointsOptions) error { eps, err := dc.getEndpoints(ctx, opts) if err != nil { return err @@ -228,15 +235,3 @@ } return nil } - -func getExternalControlFromCtx(cp okteto.K8sClientProvider, filename string) (ExternalResourceInterface, error) { - _, proxyConfig, err := cp.Provide(kconfig.Get([]string{filename})) - if err != nil { - return nil, err - } - - return &externalresource.K8sControl{ - ClientProvider: k8sExternalResources.GetExternalClient, - Cfg: proxyConfig, - }, nil -} diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/okteto-2.15.2/cmd/deploy/local.go new/okteto-2.15.3/cmd/deploy/local.go --- old/okteto-2.15.2/cmd/deploy/local.go 2023-05-04 12:12:37.000000000 +0200 +++ new/okteto-2.15.3/cmd/deploy/local.go 2023-05-19 14:42:12.000000000 +0200 @@ -27,8 +27,6 @@ "github.com/okteto/okteto/pkg/constants" "github.com/okteto/okteto/pkg/devenvironment" "github.com/okteto/okteto/pkg/divert" - "github.com/okteto/okteto/pkg/externalresource" - k8sExternalResources "github.com/okteto/okteto/pkg/externalresource/k8s" "github.com/okteto/okteto/pkg/format" "github.com/okteto/okteto/pkg/k8s/ingresses" kconfig "github.com/okteto/okteto/pkg/k8s/kubeconfig" @@ -36,6 +34,7 @@ "github.com/okteto/okteto/pkg/model" "github.com/okteto/okteto/pkg/okteto" "github.com/spf13/afero" + "k8s.io/client-go/rest" ) type localDeployer struct { @@ -45,10 +44,10 @@ TempKubeconfigFile string K8sClientProvider okteto.K8sClientProvider - GetExternalControl func(cp okteto.K8sClientProvider, filename string) (ExternalResourceInterface, error) + GetExternalControl func(cfg *rest.Config) ExternalResourceInterface cwd string - deployWaiter deployWaiter + deployWaiter DeployWaiter isRemote bool Fs afero.Fs DivertDriver divert.Driver @@ -88,8 +87,8 @@ Proxy: proxy, TempKubeconfigFile: GetTempKubeConfigFile(tempKubeconfigName), K8sClientProvider: clientProvider, - GetExternalControl: getExternalControlFromCtx, - deployWaiter: newDeployWaiter(clientProvider), + GetExternalControl: NewDeployExternalK8sControl, + deployWaiter: NewDeployWaiter(clientProvider), isRemote: true, Fs: afero.NewOsFs(), }, nil @@ -329,7 +328,12 @@ } func (ld *localDeployer) deployExternals(ctx context.Context, opts *Options, dynamicEnvs map[string]string) error { - control, err := ld.GetExternalControl(ld.K8sClientProvider, ld.TempKubeconfigFile) + + _, cfg, err := ld.K8sClientProvider.Provide(kconfig.Get([]string{ld.TempKubeconfigFile})) + if err != nil { + return fmt.Errorf("error getting kubernetes client: %w", err) + } + control := ld.GetExternalControl(cfg) if err != nil { return err } @@ -366,18 +370,6 @@ } } -func GetExternalControl(cp okteto.K8sClientProvider, filename string) (ExternalResourceInterface, error) { - _, proxyConfig, err := cp.Provide(kconfig.Get([]string{filename})) - if err != nil { - return nil, err - } - - return &externalresource.K8sControl{ - ClientProvider: k8sExternalResources.GetExternalClient, - Cfg: proxyConfig, - }, nil -} - func (ld *localDeployer) createTempOktetoEnvFile() (afero.File, error) { oktetoEnvFileDir, err := afero.TempDir(ld.Fs, "", "") if err != nil { diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/okteto-2.15.2/cmd/deploy/wait.go new/okteto-2.15.3/cmd/deploy/wait.go --- old/okteto-2.15.2/cmd/deploy/wait.go 2023-05-04 12:12:37.000000000 +0200 +++ new/okteto-2.15.3/cmd/deploy/wait.go 2023-05-19 14:42:12.000000000 +0200 @@ -28,17 +28,17 @@ "github.com/okteto/okteto/pkg/okteto" ) -type deployWaiter struct { +type DeployWaiter struct { K8sClientProvider okteto.K8sClientProvider } -func newDeployWaiter(k8sClientProvider okteto.K8sClientProvider) deployWaiter { - return deployWaiter{ +func NewDeployWaiter(k8sClientProvider okteto.K8sClientProvider) DeployWaiter { + return DeployWaiter{ K8sClientProvider: k8sClientProvider, } } -func (dw *deployWaiter) wait(ctx context.Context, opts *Options) error { +func (dw *DeployWaiter) wait(ctx context.Context, opts *Options) error { oktetoLog.Spinner(fmt.Sprintf("Waiting for %s to be deployed...", opts.Name)) oktetoLog.StartSpinner() defer oktetoLog.StopSpinner() @@ -63,7 +63,7 @@ return nil } -func (dw *deployWaiter) waitForResourcesToBeRunning(ctx context.Context, opts *Options) error { +func (dw *DeployWaiter) waitForResourcesToBeRunning(ctx context.Context, opts *Options) error { ticker := time.NewTicker(5 * time.Second) to := time.NewTicker(opts.Timeout) c, _, err := dw.K8sClientProvider.Provide(okteto.Context().Cfg) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/okteto-2.15.2/cmd/manifest/init-v2.go new/okteto-2.15.3/cmd/manifest/init-v2.go --- old/okteto-2.15.2/cmd/manifest/init-v2.go 2023-05-04 12:12:37.000000000 +0200 +++ new/okteto-2.15.3/cmd/manifest/init-v2.go 2023-05-19 14:42:12.000000000 +0200 @@ -278,10 +278,12 @@ TempKubeconfigFile: deploy.GetTempKubeConfigFile(mc.manifest.Name), K8sClientProvider: mc.K8sClientProvider, Builder: buildv2.NewBuilderFromScratch(), - GetExternalControl: deploy.GetExternalControl, + GetExternalControl: deploy.NewDeployExternalK8sControl, Fs: afero.NewOsFs(), CfgMapHandler: deploy.NewConfigmapHandler(mc.K8sClientProvider), PipelineCMD: pc, + DeployWaiter: deploy.NewDeployWaiter(mc.K8sClientProvider), + EndpointGetter: deploy.NewEndpointGetter, } err = c.RunDeploy(ctx, &deploy.Options{ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/okteto-2.15.2/cmd/pipeline/deploy.go new/okteto-2.15.3/cmd/pipeline/deploy.go --- old/okteto-2.15.2/cmd/pipeline/deploy.go 2023-05-04 12:12:37.000000000 +0200 +++ new/okteto-2.15.3/cmd/pipeline/deploy.go 2023-05-19 14:42:12.000000000 +0200 @@ -95,7 +95,11 @@ return err } opts := flags.toOptions() - return pipelineCmd.ExecuteDeployPipeline(ctx, opts) + err = pipelineCmd.ExecuteDeployPipeline(ctx, opts) + if err != nil { + return fmt.Errorf("pipeline deploy failed: %w", err) + } + return nil }, } @@ -132,7 +136,7 @@ cfg, err := configmaps.Get(ctx, cfgName, opts.Namespace, c) if err != nil && !oktetoErrors.IsNotFound(err) { - return err + return fmt.Errorf("failed to get pipeline '%s': %w", cfgName, err) } if err == nil { if cfg != nil && cfg.Data != nil { @@ -158,7 +162,7 @@ Name: cfg.Data["actionName"], } if err := pc.waitUntilRunning(ctx, opts.Name, opts.Namespace, existingAction, opts.Timeout); err != nil { - return err + return fmt.Errorf("wait for pipeline '%s' to finish failed: %w", opts.Name, err) } oktetoLog.Success("Repository '%s' successfully deployed", opts.Name) return nil @@ -187,7 +191,7 @@ resp, err := pc.deployPipeline(ctx, opts) if err != nil { - return err + return fmt.Errorf("failed to deploy pipeline '%s': %w", opts.Name, err) } if !opts.Wait { @@ -200,7 +204,7 @@ defer oktetoLog.StopSpinner() if err := pc.waitUntilRunning(ctx, opts.Name, opts.Namespace, resp.Action, opts.Timeout); err != nil { - return err + return fmt.Errorf("wait for pipeline '%s' to finish failed: %w", opts.Name, err) } oktetoLog.Success("Repository '%s' successfully deployed", opts.Name) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/okteto-2.15.2/cmd/up/up.go new/okteto-2.15.3/cmd/up/up.go --- old/okteto-2.15.2/cmd/up/up.go 2023-05-04 12:12:37.000000000 +0200 +++ new/okteto-2.15.3/cmd/up/up.go 2023-05-19 14:42:12.000000000 +0200 @@ -528,16 +528,19 @@ if err != nil { return err } + k8sClientProvider := okteto.NewK8sClientProvider() c := &deploy.DeployCommand{ GetManifest: up.getManifest, GetDeployer: deploy.GetDeployer, TempKubeconfigFile: deploy.GetTempKubeConfigFile(up.Manifest.Name), - K8sClientProvider: okteto.NewK8sClientProvider(), + K8sClientProvider: k8sClientProvider, Builder: buildv2.NewBuilderFromScratch(), - GetExternalControl: deploy.GetExternalControl, + GetExternalControl: deploy.NewDeployExternalK8sControl, Fs: afero.NewOsFs(), CfgMapHandler: deploy.NewConfigmapHandler(k8sProvider), PipelineCMD: pc, + DeployWaiter: deploy.NewDeployWaiter(k8sClientProvider), + EndpointGetter: deploy.NewEndpointGetter, } return c.RunDeploy(ctx, &deploy.Options{ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/okteto-2.15.2/integration/actions/preview_test.go new/okteto-2.15.3/integration/actions/preview_test.go --- old/okteto-2.15.2/integration/actions/preview_test.go 2023-05-04 12:12:37.000000000 +0200 +++ new/okteto-2.15.3/integration/actions/preview_test.go 2023-05-19 14:42:12.000000000 +0200 @@ -60,7 +60,7 @@ log.Printf("Deploying preview %s", namespace) command := oktetoPath - args := []string{"preview", "deploy", namespace, "--scope", "personal", "--branch", "master", "--repository", fmt.Sprintf("%s%s", githubHTTPSURL, pipelineRepo), "--wait"} + args := []string{"preview", "deploy", namespace, "--scope", "personal", "--branch", "cli-e2e", "--repository", fmt.Sprintf("%s%s", githubHTTPSURL, pipelineRepo), "--wait"} cmd := exec.Command(command, args...) cmd.Env = os.Environ() o, err := cmd.CombinedOutput() diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/okteto-2.15.2/integration/commands/deploy.go new/okteto-2.15.3/integration/commands/deploy.go --- old/okteto-2.15.2/integration/commands/deploy.go 2023-05-04 12:12:37.000000000 +0200 +++ new/okteto-2.15.3/integration/commands/deploy.go 2023-05-19 14:42:12.000000000 +0200 @@ -14,6 +14,7 @@ package commands import ( + "bufio" "fmt" "log" "os" @@ -52,13 +53,25 @@ func RunOktetoDeploy(oktetoPath string, deployOptions *DeployOptions) error { cmd := getDeployCmd(oktetoPath, deployOptions) log.Printf("Running '%s'", cmd.String()) - - o, err := cmd.CombinedOutput() + stdout, err := cmd.StdoutPipe() if err != nil { - return fmt.Errorf("okteto deploy failed: %s - %s", string(o), err) + log.Printf("error getting stdout pipe: %s", err) + return err + } + if err := cmd.Start(); err != nil { + return err } + go func() { + + scanner := bufio.NewScanner(stdout) + // optionally, resize scanner's capacity for lines over 64K, see next example + for scanner.Scan() { + log.Println(scanner.Text()) + } + }() + err = cmd.Wait() log.Printf("okteto deploy success") - return nil + return err } // RunOktetoDeployAndGetOutput runs an okteto deploy command and returns the output diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/okteto-2.15.2/integration/commands/endpoints.go new/okteto-2.15.3/integration/commands/endpoints.go --- old/okteto-2.15.2/integration/commands/endpoints.go 1970-01-01 01:00:00.000000000 +0100 +++ new/okteto-2.15.3/integration/commands/endpoints.go 2023-05-19 14:42:12.000000000 +0200 @@ -0,0 +1,53 @@ +// 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 commands + +import ( + "fmt" + "log" + "os/exec" +) + +// DeployOptions defines the options that can be added to a deploy command +type EndpointOptions struct { + Workdir string + Output string + Namespace string + OktetoHome string +} + +// RunOktetoDeploy runs an okteto deploy command +func RunOktetoEndpoints(oktetoPath string, endpointsOptions *EndpointOptions) ([]byte, error) { + cmd := exec.Command(oktetoPath, "endpoints") + if endpointsOptions.Workdir != "" { + cmd.Dir = endpointsOptions.Workdir + } + if endpointsOptions.Namespace != "" { + cmd.Args = append(cmd.Args, "--namespace", endpointsOptions.Namespace) + } + if endpointsOptions.OktetoHome != "" { + cmd.Env = append(cmd.Env, fmt.Sprintf("OKTETO_HOME=%s", endpointsOptions.OktetoHome)) + } + if endpointsOptions.Output != "" { + cmd.Args = append(cmd.Args, "--output", endpointsOptions.Output) + } + log.Printf("Running '%s'", cmd.String()) + + o, err := cmd.CombinedOutput() + if err != nil { + return o, fmt.Errorf("okteto deploy failed: %s - %s", string(o), err) + } + log.Printf("okteto deploy success") + return o, nil +} diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/okteto-2.15.2/integration/deploy/compose_test.go new/okteto-2.15.3/integration/deploy/compose_test.go --- old/okteto-2.15.2/integration/deploy/compose_test.go 2023-05-04 12:12:37.000000000 +0200 +++ new/okteto-2.15.3/integration/deploy/compose_test.go 2023-05-19 14:42:12.000000000 +0200 @@ -166,6 +166,7 @@ Namespace: testNamespace, OktetoHome: dir, Token: token, + LogOutput: "info", } require.NoError(t, commands.RunOktetoDeploy(oktetoPath, deployOptions)) @@ -245,6 +246,7 @@ Namespace: testNamespace, OktetoHome: dir, Token: token, + LogOutput: "info", } require.NoError(t, commands.RunOktetoDeploy(oktetoPath, deployOptions)) @@ -326,6 +328,7 @@ Namespace: testNamespace, OktetoHome: dir, Token: token, + LogOutput: "info", } require.NoError(t, commands.RunOktetoDeploy(oktetoPath, deployOptions)) @@ -385,6 +388,7 @@ Namespace: testNamespace, OktetoHome: dir, Token: token, + LogOutput: "info", } require.NoError(t, commands.RunOktetoDeploy(oktetoPath, deployOptions)) @@ -449,6 +453,7 @@ Namespace: testNamespace, OktetoHome: dir, Token: token, + LogOutput: "info", } require.NoError(t, commands.RunOktetoDeploy(oktetoPath, deployOptions)) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/okteto-2.15.2/integration/deploy/endpoints_test.go new/okteto-2.15.3/integration/deploy/endpoints_test.go --- old/okteto-2.15.2/integration/deploy/endpoints_test.go 2023-05-04 12:12:37.000000000 +0200 +++ new/okteto-2.15.3/integration/deploy/endpoints_test.go 2023-05-19 14:42:12.000000000 +0200 @@ -166,6 +166,7 @@ Namespace: testNamespace, OktetoHome: dir, Token: token, + LogOutput: "info", } require.NoError(t, commands.RunOktetoDeploy(oktetoPath, deployOptions)) @@ -226,6 +227,7 @@ Namespace: testNamespace, OktetoHome: dir, Token: token, + LogOutput: "info", } require.NoError(t, commands.RunOktetoDeploy(oktetoPath, deployOptions)) @@ -280,6 +282,7 @@ Namespace: testNamespace, OktetoHome: dir, Token: token, + LogOutput: "info", } require.NoError(t, commands.RunOktetoDeploy(oktetoPath, deployOptions)) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/okteto-2.15.2/integration/deploy/external_test.go new/okteto-2.15.3/integration/deploy/external_test.go --- old/okteto-2.15.2/integration/deploy/external_test.go 2023-05-04 12:12:37.000000000 +0200 +++ new/okteto-2.15.3/integration/deploy/external_test.go 2023-05-19 14:42:12.000000000 +0200 @@ -19,6 +19,7 @@ import ( "context" b64 "encoding/base64" + "encoding/json" "os" "path/filepath" "testing" @@ -26,6 +27,7 @@ "github.com/okteto/okteto/cmd/deploy" "github.com/okteto/okteto/integration" "github.com/okteto/okteto/integration/commands" + "github.com/okteto/okteto/pkg/k8s/kubeconfig" "github.com/okteto/okteto/pkg/okteto" "github.com/stretchr/testify/require" ) @@ -75,9 +77,11 @@ } require.NoError(t, commands.RunOktetoDeploy(oktetoPath, deployOptions)) - externalControl, err := deploy.GetExternalControl(okteto.NewK8sClientProvider(), filepath.Join(dir, ".kube", "config")) + _, cfg, err := okteto.NewK8sClientProvider().Provide(kubeconfig.Get([]string{filepath.Join(dir, ".kube", "config")})) require.NoError(t, err) + externalControl := deploy.NewDeployExternalK8sControl(cfg) + externals, err := externalControl.List(ctx, namespaceOpts.Namespace, "") require.NoError(t, err) @@ -88,6 +92,23 @@ require.Equal(t, string(decodedContent), notesContent) + // Check the endpoints command + opts := &commands.EndpointOptions{ + Workdir: dir, + Namespace: testNamespace, + OktetoHome: dir, + Output: "json", + } + + output, err := commands.RunOktetoEndpoints(oktetoPath, opts) + require.NoError(t, err) + + var endpoints []string + err = json.Unmarshal([]byte(output), &endpoints) + require.NoError(t, err) + + require.Greater(t, len(endpoints), 0) + destroyOptions := &commands.DestroyOptions{ Workdir: dir, Namespace: testNamespace, diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/okteto-2.15.2/pkg/externalresource/control.go new/okteto-2.15.3/pkg/externalresource/control.go --- old/okteto-2.15.2/pkg/externalresource/control.go 2023-05-04 12:12:37.000000000 +0200 +++ new/okteto-2.15.3/pkg/externalresource/control.go 2023-05-19 14:42:12.000000000 +0200 @@ -21,6 +21,13 @@ Cfg *rest.Config } +func NewExternalK8sControl(cfg *rest.Config) *K8sControl { + return &K8sControl{ + ClientProvider: k8s.GetExternalClient, + Cfg: cfg, + } +} + func (c *K8sControl) Deploy(ctx context.Context, name, ns string, er *ExternalResource) error { k8sclient, err := c.ClientProvider(c.Cfg) if err != nil { diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/okteto-2.15.2/pkg/model/serializer.go new/okteto-2.15.3/pkg/model/serializer.go --- old/okteto-2.15.2/pkg/model/serializer.go 2023-05-04 12:12:37.000000000 +0200 +++ new/okteto-2.15.3/pkg/model/serializer.go 2023-05-19 14:42:12.000000000 +0200 @@ -1279,7 +1279,11 @@ err := unmarshal(&rawList) if err == nil { for _, buildArg := range rawList { - result[buildArg.Name] = buildArg.Value + value, err := ExpandEnv(buildArg.Value, true) + if err != nil { + return nil, err + } + result[buildArg.Name] = value } return result, nil } diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/okteto-2.15.2/pkg/model/serializer_test.go new/okteto-2.15.3/pkg/model/serializer_test.go --- old/okteto-2.15.2/pkg/model/serializer_test.go 2023-05-04 12:12:37.000000000 +0200 +++ new/okteto-2.15.3/pkg/model/serializer_test.go 2023-05-19 14:42:12.000000000 +0200 @@ -2440,6 +2440,7 @@ name string data []byte expected BuildArgs + env map[string]string }{ { name: "list", @@ -2450,16 +2451,50 @@ Value: "VALUE", }, }, + env: map[string]string{}, }, { - name: "list with env var", + name: "list with env var set", + data: []byte("- KEY=${VALUE2}"), + expected: BuildArgs{ + { + Name: "KEY", + Value: "actual-value", + }, + }, + env: map[string]string{"VALUE2": "actual-value"}, + }, + { + name: "list with env var unset", data: []byte("- KEY=$VALUE"), expected: BuildArgs{ { Name: "KEY", - Value: "$VALUE", + Value: "", + }, + }, + env: map[string]string{}, + }, + { + name: "list with multiple env vars", + data: []byte(`- KEY=$VALUE +- KEY2=$VALUE2 +- KEY3=${VALUE3}`), + expected: BuildArgs{ + { + Name: "KEY", + Value: "", + }, + { + Name: "KEY2", + Value: "actual-value-2", + }, + { + Name: "KEY3", + Value: "actual-value-3", }, }, + env: map[string]string{"VALUE2": "actual-value-2", "VALUE3": "actual-value-3"}, }, { name: "map", @@ -2470,6 +2505,7 @@ Value: "VALUE", }, }, + env: map[string]string{}, }, { name: "map with env var", @@ -2480,11 +2516,16 @@ Value: "$VALUE", }, }, + env: map[string]string{}, }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { + for k, v := range tt.env { + t.Setenv(k, v) + } + var buildArgs BuildArgs if err := yaml.UnmarshalStrict(tt.data, &buildArgs); err != nil { t.Fatal(err) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/okteto-2.15.2/pkg/model/utils.go new/okteto-2.15.3/pkg/model/utils.go --- old/okteto-2.15.2/pkg/model/utils.go 2023-05-04 12:12:37.000000000 +0200 +++ new/okteto-2.15.3/pkg/model/utils.go 2023-05-19 14:42:12.000000000 +0200 @@ -203,3 +203,27 @@ } return added } + +// snapshotEnv takes a snapshot of the current environment variables +func snapshotEnv() map[string]string { + env := os.Environ() + snapshot := make(map[string]string, len(env)) + for _, e := range env { + pair := strings.SplitN(e, "=", 2) + snapshot[pair[0]] = pair[1] + } + return snapshot +} + +// restoreEnv restores the environment variables from a given snapshot +func restoreEnv(snapshot map[string]string) error { + os.Clearenv() + + for key, value := range snapshot { + err := os.Setenv(key, value) + if err != nil { + return err + } + } + return nil +} diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/okteto-2.15.2/pkg/model/utils_test.go new/okteto-2.15.3/pkg/model/utils_test.go --- old/okteto-2.15.2/pkg/model/utils_test.go 2023-05-04 12:12:37.000000000 +0200 +++ new/okteto-2.15.3/pkg/model/utils_test.go 2023-05-19 14:42:12.000000000 +0200 @@ -14,6 +14,7 @@ package model import ( + "os" "testing" "github.com/stretchr/testify/assert" @@ -126,3 +127,57 @@ } } + +func Test_snapshotEnv(t *testing.T) { + os.Clearenv() + + vars := map[string]string{ + "TEST_1": "1", + "TEST_2": "2", + } + for k, v := range vars { + assert.NoError(t, os.Setenv(k, v)) + } + + env := snapshotEnv() + + expected := map[string]string{ + "TEST_1": "1", + "TEST_2": "2", + } + assert.Equal(t, expected, env) +} + +func Test_restoreEnv(t *testing.T) { + os.Clearenv() + + vars := map[string]string{ + "TEST_1": "1", + "TEST_2": "2", + } + for k, v := range vars { + assert.NoError(t, os.Setenv(k, v)) + } + + env := snapshotEnv() + os.Clearenv() + + assert.Equal(t, os.Environ(), []string{}) + + assert.NoError(t, os.Setenv("TEST_3", "3")) + assert.NoError(t, restoreEnv(env)) + + checks := []struct { + key string + exists bool + }{ + {"TEST_1", true}, + {"TEST_2", true}, + {"TEST_3", false}, + } + + for _, c := range checks { + _, has := os.LookupEnv(c.key) + assert.Equal(t, has, c.exists) + } +} diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/okteto-2.15.2/pkg/okteto/action.go new/okteto-2.15.3/pkg/okteto/action.go --- old/okteto-2.15.2/pkg/okteto/action.go 2023-05-04 12:12:37.000000000 +0200 +++ new/okteto-2.15.3/pkg/okteto/action.go 2023-05-19 14:42:12.000000000 +0200 @@ -31,6 +31,7 @@ // GetAction gets a installer job given its name func (c *pipelineClient) GetAction(ctx context.Context, name, namespace string) (*types.Action, error) { + oktetoLog.Infof("getting action '%s' on %s", name, namespace) queryStruct := getActionQueryStruct{} variables := map[string]interface{}{ "name": graphql.String(name), @@ -39,7 +40,7 @@ err := query(ctx, &queryStruct, variables, c.client) if err != nil { - return nil, err + return nil, fmt.Errorf("failed to get action '%s': %w", name, err) } action := &types.Action{ ID: string(queryStruct.Action.Id), @@ -51,6 +52,7 @@ } func (c *pipelineClient) WaitForActionToFinish(ctx context.Context, pipelineName, namespace, actionName string, timeout time.Duration) error { + oktetoLog.Infof("waiting for action '%s' to finish", actionName) timeoutTimer := c.provideTimer(timeout) ticker := c.provideTicker(tickerInterval) for { @@ -85,6 +87,7 @@ } func (c *pipelineClient) WaitForActionProgressing(ctx context.Context, pipelineName, namespace, actionName string, timeout time.Duration) error { + oktetoLog.Infof("waiting for action '%s' to start", actionName) timeoutTimer := c.provideTimer(timeout) ticker := c.provideTicker(tickerInterval) for { diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/okteto-2.15.2/pkg/okteto/pipeline.go new/okteto-2.15.3/pkg/okteto/pipeline.go --- old/okteto-2.15.2/pkg/okteto/pipeline.go 2023-05-04 12:12:37.000000000 +0200 +++ new/okteto-2.15.3/pkg/okteto/pipeline.go 2023-05-19 14:42:12.000000000 +0200 @@ -103,6 +103,7 @@ // Deploy creates a pipeline func (c *pipelineClient) Deploy(ctx context.Context, opts types.PipelineDeployOptions) (*types.GitDeployResponse, error) { + oktetoLog.Infof("deploying pipeline '%s' mutation on %s", opts.Name, opts.Namespace) origin := config.GetDeployOrigin() gitDeployResponse := &types.GitDeployResponse{} @@ -192,13 +193,14 @@ // GetByName gets a pipeline given its name func (c *pipelineClient) GetByName(ctx context.Context, name, namespace string) (*types.GitDeploy, error) { + oktetoLog.Infof("getting pipeline '%s' in namespace '%s'", name, namespace) var queryStruct getPipelineByNameQuery variables := map[string]interface{}{ "id": graphql.String(namespace), } err := query(ctx, &queryStruct, variables, c.client) if err != nil { - return nil, err + return nil, fmt.Errorf("failed to get pipeline: %w", err) } for _, gitDeploy := range queryStruct.Response.GitDeploys { @@ -315,6 +317,7 @@ // GetResourcesStatus returns the status of deployments statefulsets and jobs func (c *pipelineClient) GetResourcesStatus(ctx context.Context, name, namespace string) (map[string]string, error) { + oktetoLog.Infof("get resource status started for pipeline: %s/%s", namespace, name) var queryStruct getPipelineResources variables := map[string]interface{}{ "id": graphql.String(namespace), @@ -328,7 +331,7 @@ } return okClient.Previews().GetResourcesStatus(ctx, namespace, name) } - return nil, err + return nil, fmt.Errorf("failed to get resources status: %w", err) } status := make(map[string]string) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/okteto-2.15.2/pkg/repository/git.go new/okteto-2.15.3/pkg/repository/git.go --- old/okteto-2.15.2/pkg/repository/git.go 2023-05-04 12:12:37.000000000 +0200 +++ new/okteto-2.15.3/pkg/repository/git.go 2023-05-19 14:42:12.000000000 +0200 @@ -14,7 +14,9 @@ package repository import ( + "context" "fmt" + "time" "github.com/go-git/go-git/v5" "github.com/go-git/go-git/v5/plumbing" @@ -32,27 +34,34 @@ } // 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) - } +func (r gitRepoController) isClean(ctx context.Context) (bool, error) { + ctxWithTimeout, cancel := context.WithTimeout(ctx, 1*time.Second) + defer cancel() + select { + case <-ctxWithTimeout.Done(): + return false, nil + default: + 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) + } - 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 status.IsClean(), nil } // GetSHA returns the last commit sha of the repository func (r gitRepoController) getSHA() (string, error) { - isClean, err := r.isClean() + isClean, err := r.isClean(context.TODO()) if err != nil { return "", fmt.Errorf("failed to check if repo is clean: %w", err) } diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/okteto-2.15.2/pkg/repository/remote.go new/okteto-2.15.3/pkg/repository/remote.go --- old/okteto-2.15.2/pkg/repository/remote.go 2023-05-04 12:12:37.000000000 +0200 +++ new/okteto-2.15.3/pkg/repository/remote.go 2023-05-19 14:42:12.000000000 +0200 @@ -13,6 +13,8 @@ package repository +import "context" + type oktetoRemoteRepoController struct { gitCommit string } @@ -23,7 +25,7 @@ } } -func (or oktetoRemoteRepoController) isClean() (bool, error) { +func (or oktetoRemoteRepoController) isClean(_ context.Context) (bool, error) { return or.gitCommit != "", nil } diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/okteto-2.15.2/pkg/repository/remote_test.go new/okteto-2.15.3/pkg/repository/remote_test.go --- old/okteto-2.15.2/pkg/repository/remote_test.go 2023-05-04 12:12:37.000000000 +0200 +++ new/okteto-2.15.3/pkg/repository/remote_test.go 2023-05-19 14:42:12.000000000 +0200 @@ -14,6 +14,7 @@ package repository import ( + "context" "testing" "github.com/stretchr/testify/assert" @@ -23,7 +24,7 @@ remote := oktetoRemoteRepoController{ gitCommit: "123", } - isClean, err := remote.isClean() + isClean, err := remote.isClean(context.Background()) assert.NoError(t, err) assert.True(t, isClean) } @@ -32,7 +33,7 @@ remote := oktetoRemoteRepoController{ gitCommit: "", } - isClean, err := remote.isClean() + isClean, err := remote.isClean(context.Background()) assert.NoError(t, err) assert.False(t, isClean) } diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/okteto-2.15.2/pkg/repository/repository.go new/okteto-2.15.3/pkg/repository/repository.go --- old/okteto-2.15.2/pkg/repository/repository.go 2023-05-04 12:12:37.000000000 +0200 +++ new/okteto-2.15.3/pkg/repository/repository.go 2023-05-19 14:42:12.000000000 +0200 @@ -14,6 +14,7 @@ package repository import ( + "context" "net/url" "os" "strings" @@ -33,7 +34,7 @@ } type repositoryInterface interface { - isClean() (bool, error) + isClean(ctx context.Context) (bool, error) getSHA() (string, error) } @@ -59,7 +60,7 @@ // IsClean checks if the repository have changes over the commit func (r Repository) IsClean() (bool, error) { - return r.control.isClean() + return r.control.isClean(context.TODO()) } // GetSHA returns the last commit sha of the repository ++++++ okteto.obsinfo ++++++ --- /var/tmp/diff_new_pack.KEaNAi/_old 2023-05-22 13:14:32.818873683 +0200 +++ /var/tmp/diff_new_pack.KEaNAi/_new 2023-05-22 13:14:32.818873683 +0200 @@ -1,5 +1,5 @@ name: okteto -version: 2.15.2 -mtime: 1683195157 -commit: 274b41b8fe33f99d5e0773363c46a6ff7c16a6f8 +version: 2.15.3 +mtime: 1684500132 +commit: a4587f1827b1933f700363317694e655c6efd74b ++++++ vendor.tar.gz ++++++ /work/SRC/openSUSE:Factory/okteto/vendor.tar.gz /work/SRC/openSUSE:Factory/.okteto.new.1533/vendor.tar.gz differ: char 5, line 1