From 5a3ae01b636ae349aa97062a7e9cb40e8965eb62 Mon Sep 17 00:00:00 2001 From: Jaime Soriano Pastor Date: Tue, 11 Nov 2025 14:44:35 +0100 Subject: [PATCH 1/3] Stop using Chdir --- Makefile | 2 + cmd/benchmark.go | 36 ++++++++--- cmd/build.go | 14 +++-- cmd/changelog.go | 7 ++- cmd/clean.go | 11 +++- cmd/create_data_stream.go | 7 ++- cmd/edit.go | 7 ++- cmd/export_dashboards.go | 9 ++- cmd/export_ingest_pipelines.go | 7 ++- cmd/format.go | 6 +- cmd/install.go | 10 ++- cmd/links.go | 19 +++--- cmd/lint.go | 16 +++-- cmd/report.go | 12 +++- cmd/root.go | 14 ----- cmd/service.go | 6 +- cmd/status.go | 11 +++- cmd/testrunner.go | 61 +++++++++++++------ cmd/uninstall.go | 7 ++- go.mod | 1 + go.sum | 2 + internal/agentdeployer/agent.go | 9 ++- internal/agentdeployer/factory.go | 3 + internal/agentdeployer/logs.go | 8 +-- .../benchrunner/reporters/outputs/file.go | 2 +- internal/benchrunner/runners/rally/options.go | 7 +++ internal/benchrunner/runners/rally/runner.go | 1 + .../benchrunner/runners/system/options.go | 7 +++ internal/benchrunner/runners/system/runner.go | 1 + internal/builder/packages.go | 42 ++++++------- internal/cleanup/build.go | 6 +- internal/cleanup/service_logs.go | 4 +- internal/cleanup/stack.go | 4 +- internal/cobraext/cwd.go | 27 ++++++++ internal/docs/exported_fields.go | 4 +- internal/docs/readme.go | 28 ++++----- internal/docs/readme_test.go | 8 +-- internal/export/dashboards.go | 4 +- internal/fields/validate.go | 10 +-- internal/fields/validate_test.go | 32 +++++----- internal/files/linkedfiles_test.go | 6 +- internal/files/repository.go | 10 +-- .../packages/archetype/data_stream_test.go | 3 +- internal/packages/archetype/package_test.go | 14 +++-- internal/packages/installer/factory.go | 2 + internal/packages/packages.go | 10 +-- internal/resources/fleetpackage.go | 4 ++ internal/resources/fleetpackage_test.go | 19 +++++- internal/resources/fleetpolicy_test.go | 23 ++++--- internal/servicedeployer/compose.go | 17 ++++-- internal/servicedeployer/custom_agent.go | 6 +- internal/servicedeployer/factory.go | 4 ++ internal/servicedeployer/terraform.go | 6 +- internal/stack/boot.go | 2 +- internal/stack/options.go | 1 + internal/testrunner/coverage.go | 12 ++-- internal/testrunner/coveragereport.go | 22 +++---- internal/testrunner/coveragereport_test.go | 2 +- internal/testrunner/report_output.go | 6 +- internal/testrunner/reporters/outputs/file.go | 8 +-- .../testrunner/reporters/outputs/stdout.go | 2 +- internal/testrunner/runners/asset/runner.go | 4 ++ internal/testrunner/runners/asset/tester.go | 6 +- .../testrunner/runners/pipeline/coverage.go | 2 +- .../testrunner/runners/pipeline/runner.go | 4 ++ .../testrunner/runners/pipeline/tester.go | 5 +- internal/testrunner/runners/policy/runner.go | 5 ++ internal/testrunner/runners/policy/tester.go | 9 ++- internal/testrunner/runners/static/runner.go | 4 ++ internal/testrunner/runners/static/tester.go | 7 ++- internal/testrunner/runners/system/runner.go | 5 ++ internal/testrunner/runners/system/tester.go | 10 ++- tools/tools.go | 1 + 73 files changed, 478 insertions(+), 235 deletions(-) create mode 100644 internal/cobraext/cwd.go diff --git a/Makefile b/Makefile index 34b5c1a70b..c93e207bb4 100644 --- a/Makefile +++ b/Makefile @@ -30,7 +30,9 @@ install: go install -ldflags "$(VERSION_LDFLAGS)" github.com/elastic/elastic-package lint: + # TODO: Migrate to golangci-lint go run honnef.co/go/tools/cmd/staticcheck ./... + go run github.com/ashanbrown/forbidigo/v2 -tests=false "^os.(Getwd|Chdir)$$" -- ./... licenser: go run github.com/elastic/go-licenser -license Elastic diff --git a/cmd/benchmark.go b/cmd/benchmark.go index cb7588ffbe..831622c323 100644 --- a/cmd/benchmark.go +++ b/cmd/benchmark.go @@ -137,12 +137,17 @@ func pipelineCommandAction(cmd *cobra.Command, args []string) error { return cobraext.FlagParsingError(err, cobraext.BenchNumTopProcsFlagName) } - repositoryRoot, err := files.FindRepositoryRoot() + cwd, err := cobraext.Getwd(cmd) + if err != nil { + return err + } + + repositoryRoot, err := files.FindRepositoryRoot(cwd) if err != nil { return fmt.Errorf("locating repository root failed: %w", err) } - packageRootPath, err := packages.FindPackageRoot() + packageRootPath, err := packages.FindPackageRoot(cwd) if err != nil { return fmt.Errorf("locating package root failed: %w", err) } @@ -294,15 +299,20 @@ func rallyCommandAction(cmd *cobra.Command, args []string) error { return fmt.Errorf("getting package name and version failed, expected format: -: %w", err) } + cwd, err := cobraext.Getwd(cmd) + if err != nil { + return err + } + var packageRootPath string if len(packageName) == 0 { - packageRootPath, err = packages.FindPackageRoot() + packageRootPath, err = packages.FindPackageRoot(cwd) if err != nil { return fmt.Errorf("locating package root failed: %w", err) } } - repositoryRoot, err := files.FindRepositoryRoot() + repositoryRoot, err := files.FindRepositoryRoot(cwd) if err != nil { return fmt.Errorf("locating repository root failed: %w", err) } @@ -333,6 +343,7 @@ func rallyCommandAction(cmd *cobra.Command, args []string) error { rally.WithVariant(variant), rally.WithBenchmarkName(benchName), rally.WithDataReindexing(dataReindex), + rally.WithWorkDir(cwd), rally.WithPackageRootPath(packageRootPath), rally.WithESAPI(esClient.API), rally.WithKibanaClient(kc), @@ -471,12 +482,17 @@ func streamCommandAction(cmd *cobra.Command, args []string) error { return cobraext.FlagParsingError(err, cobraext.BenchStreamTimestampFieldFlagName) } - packageRootPath, err := packages.FindPackageRoot() + cwd, err := cobraext.Getwd(cmd) + if err != nil { + return err + } + + packageRootPath, err := packages.FindPackageRoot(cwd) if err != nil { return fmt.Errorf("locating package root failed: %w", err) } - repositoryRoot, err := files.FindRepositoryRoot() + repositoryRoot, err := files.FindRepositoryRoot(cwd) if err != nil { return fmt.Errorf("locating repository root failed: %w", err) } @@ -581,7 +597,12 @@ func systemCommandAction(cmd *cobra.Command, args []string) error { return cobraext.FlagParsingError(err, cobraext.BenchReindexToMetricstoreFlagName) } - packageRootPath, err := packages.FindPackageRoot() + cwd, err := cobraext.Getwd(cmd) + if err != nil { + return err + } + + packageRootPath, err := packages.FindPackageRoot(cwd) if err != nil { return fmt.Errorf("locating package root failed: %w", err) } @@ -609,6 +630,7 @@ func systemCommandAction(cmd *cobra.Command, args []string) error { } withOpts := []system.OptionFunc{ + system.WithWorkDir(cwd), system.WithVariant(variant), system.WithBenchmarkPath(benchPath), system.WithBenchmarkName(benchName), diff --git a/cmd/build.go b/cmd/build.go index e56c8a3da8..d8992f4178 100644 --- a/cmd/build.go +++ b/cmd/build.go @@ -61,26 +61,32 @@ func buildCommandAction(cmd *cobra.Command, args []string) error { } } - repositoryRoot, err := files.FindRepositoryRoot() + cwd, err := cobraext.Getwd(cmd) + if err != nil { + return err + } + + repositoryRoot, err := files.FindRepositoryRoot(cwd) if err != nil { return fmt.Errorf("locating repository root failed: %w", err) } defer repositoryRoot.Close() - packageRoot, err := packages.MustFindPackageRoot() + packageRoot, err := packages.MustFindPackageRoot(cwd) if err != nil { return fmt.Errorf("locating package root failed: %w", err) } // Currently the build directory is placed inside the repository build/ folder. // In the future we might want to make this configurable. - buildDir, err := builder.BuildDirectory() + buildDir, err := builder.BuildDirectory(cwd) if err != nil { return fmt.Errorf("can't prepare build directory: %w", err) } logger.Debugf("Use build directory: %s", buildDir) target, err := builder.BuildPackage(cmd.Context(), builder.BuildOptions{ + WorkDir: cwd, PackageRootPath: packageRoot, BuildDir: buildDir, CreateZip: createZip, @@ -92,7 +98,7 @@ func buildCommandAction(cmd *cobra.Command, args []string) error { return fmt.Errorf("building package failed: %w", err) } - targets, err := docs.UpdateReadmes(repositoryRoot, packageRoot, buildDir) + targets, err := docs.UpdateReadmes(repositoryRoot, cwd, packageRoot, buildDir) if err != nil { return fmt.Errorf("updating files failed: %w", err) } diff --git a/cmd/changelog.go b/cmd/changelog.go index bfdf5599b6..f790d2662d 100644 --- a/cmd/changelog.go +++ b/cmd/changelog.go @@ -60,7 +60,12 @@ func setupChangelogCommand() *cobraext.Command { } func changelogAddCmd(cmd *cobra.Command, args []string) error { - packageRoot, err := packages.MustFindPackageRoot() + cwd, err := cobraext.Getwd(cmd) + if err != nil { + return err + } + + packageRoot, err := packages.MustFindPackageRoot(cwd) if err != nil { return fmt.Errorf("locating package root failed: %w", err) } diff --git a/cmd/clean.go b/cmd/clean.go index c88faba5f5..fd58e4d1ab 100644 --- a/cmd/clean.go +++ b/cmd/clean.go @@ -39,7 +39,12 @@ func cleanCommandAction(cmd *cobra.Command, args []string) error { return err } - target, err := cleanup.Build() + cwd, err := cobraext.Getwd(cmd) + if err != nil { + return err + } + + target, err := cleanup.Build(cwd) if err != nil { return fmt.Errorf("can't clean build resources: %w", err) } @@ -48,7 +53,7 @@ func cleanCommandAction(cmd *cobra.Command, args []string) error { cmd.Printf("Build resources removed: %s\n", target) } - target, err = cleanup.Stack() + target, err = cleanup.Stack(cwd) if err != nil { return fmt.Errorf("can't clean the development stack: %w", err) } @@ -64,7 +69,7 @@ func cleanCommandAction(cmd *cobra.Command, args []string) error { cmd.Printf("Temporary service logs removed: %s\n", target) } - target, err = cleanup.ServiceLogsIndependentAgents(profile) + target, err = cleanup.ServiceLogsIndependentAgents(profile, cwd) if err != nil { return fmt.Errorf("can't clean temporary service logs: %w", err) } diff --git a/cmd/create_data_stream.go b/cmd/create_data_stream.go index 102b7475a4..25ff4ad5f2 100644 --- a/cmd/create_data_stream.go +++ b/cmd/create_data_stream.go @@ -13,6 +13,7 @@ import ( "github.com/Masterminds/semver/v3" "github.com/spf13/cobra" + "github.com/elastic/elastic-package/internal/cobraext" "github.com/elastic/elastic-package/internal/packages" "github.com/elastic/elastic-package/internal/packages/archetype" "github.com/elastic/elastic-package/internal/tui" @@ -36,8 +37,12 @@ type newDataStreamAnswers struct { func createDataStreamCommandAction(cmd *cobra.Command, args []string) error { cmd.Println("Create a new data stream") + cwd, err := cobraext.Getwd(cmd) + if err != nil { + return err + } - packageRoot, err := packages.FindPackageRoot() + packageRoot, err := packages.FindPackageRoot(cwd) if err != nil { if errors.Is(err, packages.ErrPackageRootNotFound) { return errors.New("package root not found, you can only create new data stream in the package context") diff --git a/cmd/edit.go b/cmd/edit.go index 5ea57b152b..edd9dbd67d 100644 --- a/cmd/edit.go +++ b/cmd/edit.go @@ -96,11 +96,16 @@ func editDashboardsCmd(cmd *cobra.Command, args []string) error { fmt.Printf("Warning: %s\n", message) } + cwd, err := cobraext.Getwd(cmd) + if err != nil { + return err + } + if len(dashboardIDs) == 0 { // Not mandatory to get the package name here, but it would be helpful for users // to select by default the package where they are located if any. defaultPackage := "" - packageRoot, err := packages.MustFindPackageRoot() + packageRoot, err := packages.MustFindPackageRoot(cwd) if err == nil { m, err := packages.ReadPackageManifestFromPackageRoot(packageRoot) if err != nil { diff --git a/cmd/export_dashboards.go b/cmd/export_dashboards.go index a5405cadfe..a82a94cce5 100644 --- a/cmd/export_dashboards.go +++ b/cmd/export_dashboards.go @@ -78,9 +78,14 @@ func exportDashboardsCmd(cmd *cobra.Command, args []string) error { fmt.Printf("Warning: %s\n", message) } + cwd, err := cobraext.Getwd(cmd) + if err != nil { + return err + } + // Just query for dashboards if none were provided as flags if len(dashboardIDs) == 0 { - packageRoot, err := packages.MustFindPackageRoot() + packageRoot, err := packages.MustFindPackageRoot(cwd) if err != nil { return fmt.Errorf("locating package root failed: %w", err) } @@ -106,7 +111,7 @@ func exportDashboardsCmd(cmd *cobra.Command, args []string) error { } } - err = export.Dashboards(cmd.Context(), kibanaClient, dashboardIDs) + err = export.Dashboards(cmd.Context(), kibanaClient, cwd, dashboardIDs) if err != nil { return fmt.Errorf("dashboards export failed: %w", err) } diff --git a/cmd/export_ingest_pipelines.go b/cmd/export_ingest_pipelines.go index e71f76c765..97882fceb9 100644 --- a/cmd/export_ingest_pipelines.go +++ b/cmd/export_ingest_pipelines.go @@ -70,7 +70,12 @@ func exportIngestPipelinesCmd(cmd *cobra.Command, args []string) error { } } - packageRoot, err := packages.MustFindPackageRoot() + cwd, err := cobraext.Getwd(cmd) + if err != nil { + return err + } + + packageRoot, err := packages.MustFindPackageRoot(cwd) if err != nil { return fmt.Errorf("locating package root failed: %w", err) } diff --git a/cmd/format.go b/cmd/format.go index 8976ac6bb0..25c99abbc1 100644 --- a/cmd/format.go +++ b/cmd/format.go @@ -33,8 +33,12 @@ func setupFormatCommand() *cobraext.Command { func formatCommandAction(cmd *cobra.Command, args []string) error { cmd.Println("Format the package") + cwd, err := cobraext.Getwd(cmd) + if err != nil { + return err + } - packageRoot, err := packages.FindPackageRoot() + packageRoot, err := packages.FindPackageRoot(cwd) if err != nil { return fmt.Errorf("locating package root failed: %w", err) } diff --git a/cmd/install.go b/cmd/install.go index adabd025fe..6b88f51ba7 100644 --- a/cmd/install.go +++ b/cmd/install.go @@ -73,21 +73,27 @@ func installCommandAction(cmd *cobra.Command, _ []string) error { return fmt.Errorf("could not create kibana client: %w", err) } + cwd, err := cobraext.Getwd(cmd) + if err != nil { + return err + } + if zipPathFile == "" && packageRootPath == "" { var err error - packageRootPath, err = packages.FindPackageRoot() + packageRootPath, err = packages.FindPackageRoot(cwd) if err != nil { return fmt.Errorf("locating package root failed: %w", err) } } - repositoryRoot, err := files.FindRepositoryRoot() + repositoryRoot, err := files.FindRepositoryRoot(cwd) if err != nil { return fmt.Errorf("locating repository root failed: %w", err) } installer, err := installer.NewForPackage(cmd.Context(), installer.Options{ Kibana: kibanaClient, + WorkDir: cwd, PackageRootPath: packageRootPath, SkipValidation: skipValidation, ZipPath: zipPathFile, diff --git a/cmd/links.go b/cmd/links.go index 4315c8ba22..d88255d57e 100644 --- a/cmd/links.go +++ b/cmd/links.go @@ -6,7 +6,6 @@ package cmd import ( "fmt" - "os" "github.com/spf13/cobra" @@ -51,18 +50,18 @@ func getLinksCheckCommand() *cobra.Command { func linksCheckCommandAction(cmd *cobra.Command, args []string) error { cmd.Printf("Check for linked files changes\n") - pwd, err := os.Getwd() + cwd, err := cobraext.Getwd(cmd) if err != nil { return fmt.Errorf("reading current working directory failed: %w", err) } // Find the repository root to create the links filesystem reference tied to the repository root - repositoryRoot, err := files.FindRepositoryRoot() + repositoryRoot, err := files.FindRepositoryRoot(cwd) if err != nil { return fmt.Errorf("finding repository root: %w", err) } defer repositoryRoot.Close() - linksFS, err := files.CreateLinksFSFromPath(repositoryRoot, pwd) + linksFS, err := files.CreateLinksFSFromPath(repositoryRoot, cwd) if err != nil { return fmt.Errorf("creating links filesystem failed: %w", err) } @@ -95,19 +94,19 @@ func getLinksUpdateCommand() *cobra.Command { func linksUpdateCommandAction(cmd *cobra.Command, args []string) error { cmd.Printf("Update linked files checksums if needed.\n") - pwd, err := os.Getwd() + cwd, err := cobraext.Getwd(cmd) if err != nil { return fmt.Errorf("reading current working directory failed: %w", err) } // Find the repository root to create the links filesystem reference tied to the repository root - repositoryRoot, err := files.FindRepositoryRoot() + repositoryRoot, err := files.FindRepositoryRoot(cwd) if err != nil { return fmt.Errorf("finding repository root: %w", err) } defer repositoryRoot.Close() - linksFS, err := files.CreateLinksFSFromPath(repositoryRoot, pwd) + linksFS, err := files.CreateLinksFSFromPath(repositoryRoot, cwd) if err != nil { return fmt.Errorf("creating links filesystem failed: %w", err) } @@ -142,19 +141,19 @@ func linksListCommandAction(cmd *cobra.Command, args []string) error { return cobraext.FlagParsingError(err, cobraext.PackagesFlagName) } - pwd, err := os.Getwd() + cwd, err := cobraext.Getwd(cmd) if err != nil { return fmt.Errorf("reading current working directory failed: %w", err) } // Find the repository root to create the links filesystem reference tied to the repository root - repositoryRoot, err := files.FindRepositoryRoot() + repositoryRoot, err := files.FindRepositoryRoot(cwd) if err != nil { return fmt.Errorf("finding repository root: %w", err) } defer repositoryRoot.Close() - linksFS, err := files.CreateLinksFSFromPath(repositoryRoot, pwd) + linksFS, err := files.CreateLinksFSFromPath(repositoryRoot, cwd) if err != nil { return fmt.Errorf("creating links filesystem failed: %w", err) } diff --git a/cmd/lint.go b/cmd/lint.go index a0759752f7..bbb48483fa 100644 --- a/cmd/lint.go +++ b/cmd/lint.go @@ -45,19 +45,23 @@ func setupLintCommand() *cobraext.Command { func lintCommandAction(cmd *cobra.Command, args []string) error { cmd.Println("Lint the package") + cwd, err := cobraext.Getwd(cmd) + if err != nil { + return err + } - repositoryRoot, err := files.FindRepositoryRoot() + repositoryRoot, err := files.FindRepositoryRoot(cwd) if err != nil { return fmt.Errorf("locating repository root failed: %w", err) } defer repositoryRoot.Close() - packageRoot, err := packages.MustFindPackageRoot() + packageRoot, err := packages.MustFindPackageRoot(cwd) if err != nil { return fmt.Errorf("package root not found: %w", err) } - readmeFiles, err := docs.AreReadmesUpToDate(repositoryRoot, packageRoot) + readmeFiles, err := docs.AreReadmesUpToDate(repositoryRoot, cwd, packageRoot) if err != nil { for _, f := range readmeFiles { if !f.UpToDate { @@ -73,7 +77,11 @@ func lintCommandAction(cmd *cobra.Command, args []string) error { } func validateSourceCommandAction(cmd *cobra.Command, args []string) error { - packageRootPath, err := packages.FindPackageRoot() + cwd, err := cobraext.Getwd(cmd) + if err != nil { + return err + } + packageRootPath, err := packages.FindPackageRoot(cwd) if err != nil { return fmt.Errorf("locating package root failed: %w", err) } diff --git a/cmd/report.go b/cmd/report.go index fed90f09c3..60ecba6d63 100644 --- a/cmd/report.go +++ b/cmd/report.go @@ -83,8 +83,14 @@ func getBenchReportCommand() *cobra.Command { if err != nil { return cobraext.FlagParsingError(err, cobraext.ReportOutputPathFlagName) } + + cwd, err := cobraext.Getwd(cmd) + if err != nil { + return err + } + if reportOutputPath == "" { - dest, err := resultsDir() + dest, err := resultsDir(cwd) if err != nil { return fmt.Errorf("could not determine benchmark reports folder: %w", err) } @@ -160,8 +166,8 @@ func getBenchReportCommand() *cobra.Command { } // resultsDir returns the location of the directory to store reports. -func resultsDir() (string, error) { - buildDir, err := builder.BuildDirectory() +func resultsDir(workDir string) (string, error) { + buildDir, err := builder.BuildDirectory(workDir) if err != nil { return "", fmt.Errorf("locating build directory failed: %w", err) } diff --git a/cmd/root.go b/cmd/root.go index e449ff5169..05b98b406d 100644 --- a/cmd/root.go +++ b/cmd/root.go @@ -5,8 +5,6 @@ package cmd import ( - "fmt" - "os" "sort" "github.com/spf13/cobra" @@ -82,18 +80,6 @@ func processPersistentFlags(cmd *cobra.Command, args []string) error { logger.EnableTraceMode() } - changeDirectory, err := cmd.Flags().GetString(cobraext.ChangeDirectoryFlagName) - if err != nil { - return cobraext.FlagParsingError(err, cobraext.ChangeDirectoryFlagName) - } - if changeDirectory != "" { - err := os.Chdir(changeDirectory) - if err != nil { - return fmt.Errorf("failed to change directory: %w", err) - } - logger.Debugf("Running command in directory \"%s\"", changeDirectory) - } - return nil } diff --git a/cmd/service.go b/cmd/service.go index 76c4ee7723..eb8f98e343 100644 --- a/cmd/service.go +++ b/cmd/service.go @@ -45,8 +45,12 @@ func setupServiceCommand() *cobraext.Command { func upCommandAction(cmd *cobra.Command, args []string) error { cmd.Println("Boot up the service stack") + cwd, err := cobraext.Getwd(cmd) + if err != nil { + return err + } - packageRoot, err := packages.FindPackageRoot() + packageRoot, err := packages.FindPackageRoot(cwd) if err != nil { return fmt.Errorf("locating package root failed: %w", err) } diff --git a/cmd/status.go b/cmd/status.go index 1d4c7cf8ba..103cead554 100644 --- a/cmd/status.go +++ b/cmd/status.go @@ -110,6 +110,10 @@ func statusCommandAction(cmd *cobra.Command, args []string) error { return fmt.Errorf("validating info paramaters failed: %w", err) } + cwd, err := cobraext.Getwd(cmd) + if err != nil { + return err + } options := registry.SearchOptions{ All: showAll, KibanaVersion: kibanaVersion, @@ -118,7 +122,7 @@ func statusCommandAction(cmd *cobra.Command, args []string) error { // Deprecated, keeping for compatibility with older versions of the registry. Experimental: true, } - packageStatus, err := getPackageStatus(packageName, options) + packageStatus, err := getPackageStatus(cwd, packageName, options) if err != nil { return err } @@ -159,11 +163,12 @@ func validateExtraInfoParameters(extraParameters []string) error { return nil } -func getPackageStatus(packageName string, options registry.SearchOptions) (*status.PackageStatus, error) { +func getPackageStatus(workDir string, packageName string, options registry.SearchOptions) (*status.PackageStatus, error) { if packageName != "" { return status.RemotePackage(packageName, options) } - packageRootPath, err := packages.FindPackageRoot() + + packageRootPath, err := packages.FindPackageRoot(workDir) if err != nil { if errors.Is(err, packages.ErrPackageRootNotFound) { return nil, errors.New("no package specified and package root not found") diff --git a/cmd/testrunner.go b/cmd/testrunner.go index f06a33045c..a468e53fe0 100644 --- a/cmd/testrunner.go +++ b/cmd/testrunner.go @@ -146,12 +146,16 @@ func testRunnerAssetCommandAction(cmd *cobra.Command, args []string) error { return cobraext.FlagParsingError(fmt.Errorf("coverage format not available: %s", testCoverageFormat), cobraext.TestCoverageFormatFlagName) } - packageRootPath, err := packages.FindPackageRoot() + cwd, err := cobraext.Getwd(cmd) + if err != nil { + return err + } + packageRootPath, err := packages.FindPackageRoot(cwd) if err != nil { return fmt.Errorf("locating package root failed: %w", err) } - repositoryRoot, err := files.FindRepositoryRoot() + repositoryRoot, err := files.FindRepositoryRoot(cwd) if err != nil { return fmt.Errorf("locating repository root failed: %w", err) } @@ -175,6 +179,7 @@ func testRunnerAssetCommandAction(cmd *cobra.Command, args []string) error { } runner := asset.NewAssetTestRunner(asset.AssetTestRunnerOptions{ + WorkDir: cwd, PackageRootPath: packageRootPath, KibanaClient: kibanaClient, GlobalTestConfig: globalTestConfig.Asset, @@ -188,7 +193,7 @@ func testRunnerAssetCommandAction(cmd *cobra.Command, args []string) error { return fmt.Errorf("error running package %s tests: %w", testType, err) } - return processResults(results, testType, reportFormat, reportOutput, packageRootPath, manifest.Name, manifest.Type, testCoverageFormat, testCoverage) + return processResults(results, testType, reportFormat, reportOutput, cwd, packageRootPath, manifest.Name, manifest.Type, testCoverageFormat, testCoverage) } func getTestRunnerStaticCommand() *cobra.Command { @@ -239,7 +244,11 @@ func testRunnerStaticCommandAction(cmd *cobra.Command, args []string) error { return cobraext.FlagParsingError(fmt.Errorf("coverage format not available: %s", testCoverageFormat), cobraext.TestCoverageFormatFlagName) } - packageRootPath, err := packages.FindPackageRoot() + cwd, err := cobraext.Getwd(cmd) + if err != nil { + return err + } + packageRootPath, err := packages.FindPackageRoot(cwd) if err != nil { return fmt.Errorf("locating package root failed: %w", err) } @@ -263,6 +272,7 @@ func testRunnerStaticCommandAction(cmd *cobra.Command, args []string) error { } runner := static.NewStaticTestRunner(static.StaticTestRunnerOptions{ + WorkDir: cwd, PackageRootPath: packageRootPath, DataStreams: dataStreams, FailOnMissingTests: failOnMissing, @@ -276,7 +286,7 @@ func testRunnerStaticCommandAction(cmd *cobra.Command, args []string) error { return err } - return processResults(results, testType, reportFormat, reportOutput, packageRootPath, manifest.Name, manifest.Type, testCoverageFormat, testCoverage) + return processResults(results, testType, reportFormat, reportOutput, cwd, packageRootPath, manifest.Name, manifest.Type, testCoverageFormat, testCoverage) } func getTestRunnerPipelineCommand() *cobra.Command { @@ -343,12 +353,16 @@ func testRunnerPipelineCommandAction(cmd *cobra.Command, args []string) error { return cobraext.FlagParsingError(err, cobraext.DeferCleanupFlagName) } - repositoryRoot, err := files.FindRepositoryRoot() + cwd, err := cobraext.Getwd(cmd) + if err != nil { + return err + } + repositoryRoot, err := files.FindRepositoryRoot(cwd) if err != nil { return fmt.Errorf("locating repository root failed: %w", err) } - packageRootPath, err := packages.FindPackageRoot() + packageRootPath, err := packages.FindPackageRoot(cwd) if err != nil { return fmt.Errorf("locating package root failed: %w", err) } @@ -382,6 +396,7 @@ func testRunnerPipelineCommandAction(cmd *cobra.Command, args []string) error { runner := pipeline.NewPipelineTestRunner(pipeline.PipelineTestRunnerOptions{ Profile: profile, + WorkDir: cwd, PackageRootPath: packageRootPath, API: esClient.API, DataStreams: dataStreams, @@ -399,7 +414,7 @@ func testRunnerPipelineCommandAction(cmd *cobra.Command, args []string) error { return err } - return processResults(results, testType, reportFormat, reportOutput, packageRootPath, manifest.Name, manifest.Type, testCoverageFormat, testCoverage) + return processResults(results, testType, reportFormat, reportOutput, cwd, packageRootPath, manifest.Name, manifest.Type, testCoverageFormat, testCoverage) } func getTestRunnerSystemCommand() *cobra.Command { @@ -490,12 +505,17 @@ func testRunnerSystemCommandAction(cmd *cobra.Command, args []string) error { return cobraext.FlagParsingError(err, cobraext.VariantFlagName) } - packageRootPath, err := packages.FindPackageRoot() + cwd, err := cobraext.Getwd(cmd) + if err != nil { + return err + } + + packageRootPath, err := packages.FindPackageRoot(cwd) if err != nil { return fmt.Errorf("locating package root failed: %w", err) } - repositoryRoot, err := files.FindRepositoryRoot() + repositoryRoot, err := files.FindRepositoryRoot(cwd) if err != nil { return fmt.Errorf("locating repository root failed: %w", err) } @@ -568,6 +588,7 @@ func testRunnerSystemCommandAction(cmd *cobra.Command, args []string) error { runner := system.NewSystemTestRunner(system.SystemTestRunnerOptions{ Profile: profile, + WorkDir: cwd, PackageRootPath: packageRootPath, KibanaClient: kibanaClient, API: esClient.API, @@ -593,7 +614,7 @@ func testRunnerSystemCommandAction(cmd *cobra.Command, args []string) error { return err } - err = processResults(results, runner.Type(), reportFormat, reportOutput, packageRootPath, manifest.Name, manifest.Type, testCoverageFormat, testCoverage) + err = processResults(results, runner.Type(), reportFormat, reportOutput, cwd, packageRootPath, manifest.Name, manifest.Type, testCoverageFormat, testCoverage) if err != nil { return fmt.Errorf("failed to process results: %w", err) } @@ -658,12 +679,17 @@ func testRunnerPolicyCommandAction(cmd *cobra.Command, args []string) error { return cobraext.FlagParsingError(fmt.Errorf("coverage format not available: %s", testCoverageFormat), cobraext.TestCoverageFormatFlagName) } - packageRootPath, err := packages.FindPackageRoot() + cwd, err := cobraext.Getwd(cmd) + if err != nil { + return err + } + + packageRootPath, err := packages.FindPackageRoot(cwd) if err != nil { return fmt.Errorf("locating package root failed: %w", err) } - repositoryRoot, err := files.FindRepositoryRoot() + repositoryRoot, err := files.FindRepositoryRoot(cwd) if err != nil { return fmt.Errorf("locating repository root failed: %w", err) } @@ -692,6 +718,7 @@ func testRunnerPolicyCommandAction(cmd *cobra.Command, args []string) error { } runner := policy.NewPolicyTestRunner(policy.PolicyTestRunnerOptions{ + WorkDir: cwd, PackageRootPath: packageRootPath, KibanaClient: kibanaClient, DataStreams: dataStreams, @@ -708,10 +735,10 @@ func testRunnerPolicyCommandAction(cmd *cobra.Command, args []string) error { return err } - return processResults(results, testType, reportFormat, reportOutput, packageRootPath, manifest.Name, manifest.Type, testCoverageFormat, testCoverage) + return processResults(results, testType, reportFormat, reportOutput, cwd, packageRootPath, manifest.Name, manifest.Type, testCoverageFormat, testCoverage) } -func processResults(results []testrunner.TestResult, testType testrunner.TestType, reportFormat, reportOutput, packageRootPath, packageName, packageType, testCoverageFormat string, testCoverage bool) error { +func processResults(results []testrunner.TestResult, testType testrunner.TestType, reportFormat, reportOutput, workDir, packageRootPath, packageName, packageType, testCoverageFormat string, testCoverage bool) error { sort.Slice(results, func(i, j int) bool { if results[i].Package != results[j].Package { return results[i].Package < results[j].Package @@ -730,12 +757,12 @@ func processResults(results []testrunner.TestResult, testType testrunner.TestTyp return fmt.Errorf("error formatting test report: %w", err) } - if err := testrunner.WriteReport(packageName, testType, testrunner.TestReportOutput(reportOutput), report, format); err != nil { + if err := testrunner.WriteReport(packageName, workDir, testType, testrunner.TestReportOutput(reportOutput), report, format); err != nil { return fmt.Errorf("error writing test report: %w", err) } if testCoverage { - err := testrunner.WriteCoverage(packageRootPath, packageName, packageType, testType, results, testCoverageFormat) + err := testrunner.WriteCoverage(workDir, packageRootPath, packageName, packageType, testType, results, testCoverageFormat) if err != nil { return fmt.Errorf("error writing test coverage: %w", err) } diff --git a/cmd/uninstall.go b/cmd/uninstall.go index 01075d3922..e7fc5b8ff1 100644 --- a/cmd/uninstall.go +++ b/cmd/uninstall.go @@ -34,7 +34,12 @@ func setupUninstallCommand() *cobraext.Command { } func uninstallCommandAction(cmd *cobra.Command, args []string) error { - packageRootPath, err := packages.FindPackageRoot() + cwd, err := cobraext.Getwd(cmd) + if err != nil { + return err + } + + packageRootPath, err := packages.FindPackageRoot(cwd) if err != nil { return fmt.Errorf("locating package root failed: %w", err) } diff --git a/go.mod b/go.mod index 6bd714eb5a..8a4cf74984 100644 --- a/go.mod +++ b/go.mod @@ -5,6 +5,7 @@ go 1.25.3 require ( github.com/Masterminds/semver/v3 v3.4.0 github.com/ProtonMail/gopenpgp/v2 v2.9.0 + github.com/ashanbrown/forbidigo/v2 v2.3.0 github.com/aymerick/raymond v2.0.2+incompatible github.com/boumenot/gocover-cobertura v1.4.0 github.com/cbroglie/mustache v1.4.0 diff --git a/go.sum b/go.sum index 67885662c4..15c624b654 100644 --- a/go.sum +++ b/go.sum @@ -54,6 +54,8 @@ github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5/go.mod h1:wHh0iHkY github.com/asaskevich/govalidator v0.0.0-20200907205600-7a23bdc65eef/go.mod h1:WaHUgvxTVq04UNunO+XhnAqY/wQc+bxr74GqbsZ/Jqw= github.com/asaskevich/govalidator v0.0.0-20230301143203-a9d515a09cc2 h1:DklsrG3dyBCFEj5IhUbnKptjxatkF07cF2ak3yi77so= github.com/asaskevich/govalidator v0.0.0-20230301143203-a9d515a09cc2/go.mod h1:WaHUgvxTVq04UNunO+XhnAqY/wQc+bxr74GqbsZ/Jqw= +github.com/ashanbrown/forbidigo/v2 v2.3.0 h1:OZZDOchCgsX5gvToVtEBoV2UWbFfI6RKQTir2UZzSxo= +github.com/ashanbrown/forbidigo/v2 v2.3.0/go.mod h1:5p6VmsG5/1xx3E785W9fouMxIOkvY2rRV9nMdWadd6c= github.com/atotto/clipboard v0.1.4 h1:EH0zSVneZPSuFR11BlR9YppQTVDbh5+16AmcJi4g1z4= github.com/atotto/clipboard v0.1.4/go.mod h1:ZY9tmq7sm5xIbd9bOK4onWV4S6X0u6GY7Vn0Yu86PYI= github.com/aymanbagabas/go-osc52/v2 v2.0.1 h1:HwpRHbFMcZLEVr42D4p7XBqjyuxQH5SMiErDT4WkJ2k= diff --git a/internal/agentdeployer/agent.go b/internal/agentdeployer/agent.go index c8fd2abcdd..acc07726bd 100644 --- a/internal/agentdeployer/agent.go +++ b/internal/agentdeployer/agent.go @@ -45,6 +45,7 @@ var staticSource = resource.NewSourceFS(static) // a Docker Compose file. type DockerComposeAgentDeployer struct { profile *profile.Profile + workDir string stackVersion string policyName string @@ -60,6 +61,7 @@ type DockerComposeAgentDeployer struct { type DockerComposeAgentDeployerOptions struct { Profile *profile.Profile + WorkDir string StackVersion string PolicyName string @@ -79,6 +81,7 @@ type dockerComposeDeployedAgent struct { project string env []string configDir string + workDir string } var _ DeployedAgent = new(dockerComposeDeployedAgent) @@ -87,6 +90,7 @@ var _ DeployedAgent = new(dockerComposeDeployedAgent) func NewCustomAgentDeployer(options DockerComposeAgentDeployerOptions) (*DockerComposeAgentDeployer, error) { return &DockerComposeAgentDeployer{ profile: options.Profile, + workDir: options.WorkDir, stackVersion: options.StackVersion, packageName: options.PackageName, dataStream: options.DataStream, @@ -131,6 +135,7 @@ func (d *DockerComposeAgentDeployer) SetUp(ctx context.Context, agentInfo AgentI project: composeProjectName, env: env, configDir: configDir, + workDir: d.workDir, } agentInfo.NetworkName = fmt.Sprintf("%s_default", composeProjectName) @@ -185,7 +190,7 @@ func (d *DockerComposeAgentDeployer) SetUp(ctx context.Context, agentInfo AgentI // requires to be connected the service to the stack network err = p.WaitForHealthy(ctx, opts) if err != nil { - processAgentContainerLogs(ctx, p, compose.CommandOptions{ + processAgentContainerLogs(ctx, d.workDir, p, compose.CommandOptions{ Env: opts.Env, }, agentName) return nil, fmt.Errorf("service is unhealthy: %w", err) @@ -426,7 +431,7 @@ func (s *dockerComposeDeployedAgent) TearDown(ctx context.Context) error { } opts := compose.CommandOptions{Env: s.env} - processAgentContainerLogs(ctx, p, opts, s.agentInfo.Name) + processAgentContainerLogs(ctx, s.workDir, p, opts, s.agentInfo.Name) if err := p.Down(ctx, compose.CommandOptions{ Env: opts.Env, diff --git a/internal/agentdeployer/factory.go b/internal/agentdeployer/factory.go index 5f3362c3c4..f3b91fb660 100644 --- a/internal/agentdeployer/factory.go +++ b/internal/agentdeployer/factory.go @@ -23,6 +23,7 @@ const ( // FactoryOptions defines options used to create an instance of a service deployer. type FactoryOptions struct { Profile *profile.Profile + WorkDir string PackageRootPath string DataStreamRootPath string @@ -56,6 +57,7 @@ func Factory(options FactoryOptions) (AgentDeployer, error) { } opts := DockerComposeAgentDeployerOptions{ Profile: options.Profile, + WorkDir: options.WorkDir, StackVersion: options.StackVersion, PackageName: options.PackageName, PolicyName: options.PolicyName, @@ -85,6 +87,7 @@ func Factory(options FactoryOptions) (AgentDeployer, error) { func selectAgentDeployerType(options FactoryOptions) (string, error) { devDeployPath, err := servicedeployer.FindDevDeployPath(servicedeployer.FactoryOptions{ + WorkDir: options.WorkDir, DataStreamRootPath: options.DataStreamRootPath, DevDeployDir: options.DevDeployDir, PackageRootPath: options.PackageRootPath, diff --git a/internal/agentdeployer/logs.go b/internal/agentdeployer/logs.go index 3d23f6219f..0144bc0733 100644 --- a/internal/agentdeployer/logs.go +++ b/internal/agentdeployer/logs.go @@ -15,7 +15,7 @@ import ( "github.com/elastic/elastic-package/internal/logger" ) -func processAgentContainerLogs(ctx context.Context, p *compose.Project, opts compose.CommandOptions, agentName string) { +func processAgentContainerLogs(ctx context.Context, workDir string, p *compose.Project, opts compose.CommandOptions, agentName string) { content, err := p.Logs(ctx, opts) if err != nil { logger.Errorf("can't export service logs: %v", err) @@ -27,14 +27,14 @@ func processAgentContainerLogs(ctx context.Context, p *compose.Project, opts com return } - err = writeAgentContainerLogs(agentName, content) + err = writeAgentContainerLogs(workDir, agentName, content) if err != nil { logger.Errorf("can't write service container logs: %v", err) } } -func writeAgentContainerLogs(agentName string, content []byte) error { - buildDir, err := builder.BuildDirectory() +func writeAgentContainerLogs(workDir string, agentName string, content []byte) error { + buildDir, err := builder.BuildDirectory(workDir) if err != nil { return fmt.Errorf("locating build directory failed: %w", err) } diff --git a/internal/benchrunner/reporters/outputs/file.go b/internal/benchrunner/reporters/outputs/file.go index 1bb827fed7..7495c10fff 100644 --- a/internal/benchrunner/reporters/outputs/file.go +++ b/internal/benchrunner/reporters/outputs/file.go @@ -85,7 +85,7 @@ func reportSingle(report reporters.Reportable) error { // reportsDir returns the location of the directory to store reports. func reportsDir() (string, error) { - buildDir, err := builder.BuildDirectory() + buildDir, err := builder.BuildDirectory(".") if err != nil { return "", fmt.Errorf("locating build directory failed: %w", err) } diff --git a/internal/benchrunner/runners/rally/options.go b/internal/benchrunner/runners/rally/options.go index 769730e844..b684d79afa 100644 --- a/internal/benchrunner/runners/rally/options.go +++ b/internal/benchrunner/runners/rally/options.go @@ -22,6 +22,7 @@ type Options struct { ReindexData bool ESMetricsAPI *elasticsearch.API BenchName string + WorkDir string PackageRootPath string Variant string Profile *profile.Profile @@ -60,6 +61,12 @@ func WithKibanaClient(c *kibana.Client) OptionFunc { } } +func WithWorkDir(workDir string) OptionFunc { + return func(opts *Options) { + opts.WorkDir = workDir + } +} + func WithPackageRootPath(path string) OptionFunc { return func(opts *Options) { opts.PackageRootPath = path diff --git a/internal/benchrunner/runners/rally/runner.go b/internal/benchrunner/runners/rally/runner.go index 99840ba683..8bba4e1f2e 100644 --- a/internal/benchrunner/runners/rally/runner.go +++ b/internal/benchrunner/runners/rally/runner.go @@ -487,6 +487,7 @@ func (r *runner) installPackageFromPackageRoot(ctx context.Context) error { logger.Debug("Installing package...") installer, err := installer.NewForPackage(ctx, installer.Options{ Kibana: r.options.KibanaClient, + WorkDir: r.options.WorkDir, PackageRootPath: r.options.PackageRootPath, SkipValidation: true, RepositoryRoot: r.options.RepositoryRoot, diff --git a/internal/benchrunner/runners/system/options.go b/internal/benchrunner/runners/system/options.go index 7fe2d34d54..83f1221a7d 100644 --- a/internal/benchrunner/runners/system/options.go +++ b/internal/benchrunner/runners/system/options.go @@ -14,6 +14,7 @@ import ( // Options contains benchmark runner options. type Options struct { + WorkDir string ESAPI *elasticsearch.API KibanaClient *kibana.Client DeferCleanup time.Duration @@ -37,6 +38,12 @@ func NewOptions(fns ...OptionFunc) Options { return opts } +func WithWorkDir(workDir string) OptionFunc { + return func(opts *Options) { + opts.WorkDir = workDir + } +} + func WithESAPI(api *elasticsearch.API) OptionFunc { return func(opts *Options) { opts.ESAPI = api diff --git a/internal/benchrunner/runners/system/runner.go b/internal/benchrunner/runners/system/runner.go index b34efab3a2..aedcd45b89 100644 --- a/internal/benchrunner/runners/system/runner.go +++ b/internal/benchrunner/runners/system/runner.go @@ -307,6 +307,7 @@ func (r *runner) setupService(ctx context.Context) (servicedeployer.DeployedServ logger.Debug("Setting up service...") devDeployDir := filepath.Clean(filepath.Join(r.options.BenchPath, "deploy")) opts := servicedeployer.FactoryOptions{ + WorkDir: r.options.WorkDir, PackageRootPath: r.options.PackageRootPath, DevDeployDir: devDeployDir, Variant: r.options.Variant, diff --git a/internal/builder/packages.go b/internal/builder/packages.go index 9244970367..e2b29b6025 100644 --- a/internal/builder/packages.go +++ b/internal/builder/packages.go @@ -26,6 +26,7 @@ const licenseTextFileName = "LICENSE.txt" var repositoryLicenseEnv = environment.WithElasticPackagePrefix("REPOSITORY_LICENSE") type BuildOptions struct { + WorkDir string // current working directory PackageRootPath string // path to the package source content BuildDir string // directory where all the built packages are placed and zipped packages are stored RepositoryRoot *os.Root @@ -36,13 +37,13 @@ type BuildOptions struct { } // BuildDirectory function locates the target build directory. If the directory doesn't exist, it will create it. -func BuildDirectory() (string, error) { - buildDir, found, err := findBuildDirectory() +func BuildDirectory(workDir string) (string, error) { + buildDir, found, err := findBuildDirectory(workDir) if err != nil { return "", fmt.Errorf("can't locate build directory: %w", err) } if !found { - buildDir, err = createBuildDirectory() + buildDir, err = createBuildDirectory(workDir) if err != nil { return "", fmt.Errorf("can't create new build directory: %w", err) } @@ -50,13 +51,7 @@ func BuildDirectory() (string, error) { return buildDir, nil } -func findBuildDirectory() (string, bool, error) { - workDir, err := os.Getwd() - if err != nil { - return "", false, fmt.Errorf("can't locate build directory: %w", err) - } - - dir := workDir +func findBuildDirectory(dir string) (string, bool, error) { // required for multi platform support root := fmt.Sprintf("%s%c", filepath.VolumeName(dir), os.PathSeparator) for dir != "." { @@ -76,9 +71,12 @@ func findBuildDirectory() (string, bool, error) { // BuildPackagesDirectory function locates the target build directory for the package. // It is in the form /packages//. -func BuildPackagesDirectory(packageRoot string, buildDir string) (string, error) { +func BuildPackagesDirectory(workDir string, packageRoot string, buildDir string) (string, error) { if buildDir == "" { - d, err := buildPackagesRootDirectory() + if workDir == "" { + return "", fmt.Errorf("working directory required to find build directory") + } + d, err := buildPackagesRootDirectory(workDir) if err != nil { return "", fmt.Errorf("can't locate build packages root directory: %w", err) } @@ -106,8 +104,8 @@ func BuildPackagesDirectory(packageRoot string, buildDir string) (string, error) } // buildPackagesZipPath function returns the path to zipped built package. -func buildPackagesZipPath(packageRoot string) (string, error) { - buildPackagesDir, err := buildPackagesRootDirectory() +func buildPackagesZipPath(packageRoot string, workDir string) (string, error) { + buildPackagesDir, err := buildPackagesRootDirectory(workDir) if err != nil { return "", fmt.Errorf("can't locate build packages root directory: %w", err) } @@ -123,8 +121,8 @@ func ZippedBuiltPackagePath(buildDir string, m packages.PackageManifest) string return filepath.Join(buildDir, fmt.Sprintf("%s-%s.zip", m.Name, m.Version)) } -func buildPackagesRootDirectory() (string, error) { - buildDir, found, err := FindBuildPackagesDirectory() +func buildPackagesRootDirectory(workDir string) (string, error) { + buildDir, found, err := FindBuildPackagesDirectory(workDir) if err != nil { return "", fmt.Errorf("can't locate build directory: %w", err) } @@ -138,8 +136,8 @@ func buildPackagesRootDirectory() (string, error) { } // FindBuildPackagesDirectory function locates the target build directory for packages. -func FindBuildPackagesDirectory() (string, bool, error) { - buildDir, found, err := findBuildDirectory() +func FindBuildPackagesDirectory(workDir string) (string, bool, error) { + buildDir, found, err := findBuildDirectory(workDir) if err != nil { return "", false, err } @@ -166,7 +164,7 @@ func FindBuildPackagesDirectory() (string, bool, error) { func BuildPackage(ctx context.Context, options BuildOptions) (string, error) { // builtPackageDir is the directory where the built package content is placed // eg. /packages// - builtPackageDir, err := BuildPackagesDirectory(options.PackageRootPath, options.BuildDir) + builtPackageDir, err := BuildPackagesDirectory(options.WorkDir, options.PackageRootPath, options.BuildDir) if err != nil { return "", fmt.Errorf("can't locate build directory: %w", err) } @@ -252,7 +250,7 @@ func BuildPackage(ctx context.Context, options BuildOptions) (string, error) { // buildZippedPackage function builds the zipped package from the builtPackageDir and stores it in buildPackagesDir. func buildZippedPackage(ctx context.Context, options BuildOptions, builtPackageDir string) (string, error) { logger.Debug("Build zipped package") - zippedPackagePath, err := buildPackagesZipPath(options.PackageRootPath) + zippedPackagePath, err := buildPackagesZipPath(options.PackageRootPath, options.WorkDir) if err != nil { return "", fmt.Errorf("can't evaluate path for the zipped package: %w", err) } @@ -352,8 +350,8 @@ func copyLicenseTextFile(repositoryRoot *os.Root, targetLicensePath string) erro return nil } -func createBuildDirectory(dirs ...string) (string, error) { - dir, err := files.FindRepositoryRootDirectory() +func createBuildDirectory(workDir string, dirs ...string) (string, error) { + dir, err := files.FindRepositoryRootDirectory(workDir) if errors.Is(err, os.ErrNotExist) { return "", errors.New("package can be only built inside of a Git repository (.git folder is used as reference point)") } diff --git a/internal/cleanup/build.go b/internal/cleanup/build.go index 8a55642a9e..58de898849 100644 --- a/internal/cleanup/build.go +++ b/internal/cleanup/build.go @@ -16,10 +16,10 @@ import ( ) // Build function removes package resources from build/. -func Build() (string, error) { +func Build(workDir string) (string, error) { logger.Debug("Clean build resources") - packageRoot, err := packages.MustFindPackageRoot() + packageRoot, err := packages.MustFindPackageRoot(workDir) if err != nil { return "", fmt.Errorf("locating package root failed: %w", err) } @@ -29,7 +29,7 @@ func Build() (string, error) { return "", fmt.Errorf("reading package manifest failed (path: %s): %w", packageRoot, err) } - buildDir, found, err := builder.FindBuildPackagesDirectory() + buildDir, found, err := builder.FindBuildPackagesDirectory(workDir) if err != nil { return "", fmt.Errorf("locating build directory failed: %w", err) } diff --git a/internal/cleanup/service_logs.go b/internal/cleanup/service_logs.go index 44ce3e32c2..4074e9f03b 100644 --- a/internal/cleanup/service_logs.go +++ b/internal/cleanup/service_logs.go @@ -36,10 +36,10 @@ func ServiceLogs() (string, error) { } // ServiceLogsIndependentAgent function removes service logs from temporary directory for independent agents in `~/.elastic-package`. -func ServiceLogsIndependentAgents(profile *profile.Profile) (string, error) { +func ServiceLogsIndependentAgents(profile *profile.Profile, workDir string) (string, error) { logger.Debug("Clean all service logs from independent Elastic Agents") - packageRootPath, err := packages.MustFindPackageRoot() + packageRootPath, err := packages.MustFindPackageRoot(workDir) if err != nil { return "", fmt.Errorf("locating package root failed: %w", err) } diff --git a/internal/cleanup/stack.go b/internal/cleanup/stack.go index f4844f71cd..35ce29441a 100644 --- a/internal/cleanup/stack.go +++ b/internal/cleanup/stack.go @@ -17,10 +17,10 @@ import ( ) // Stack function removes built package used by the Package Registry image. -func Stack() (string, error) { +func Stack(workDir string) (string, error) { logger.Debug("Clean built packages from the development stack") - packageRoot, err := packages.MustFindPackageRoot() + packageRoot, err := packages.MustFindPackageRoot(workDir) if err != nil { return "", fmt.Errorf("locating package root failed: %w", err) } diff --git a/internal/cobraext/cwd.go b/internal/cobraext/cwd.go new file mode 100644 index 0000000000..07b4b91fdd --- /dev/null +++ b/internal/cobraext/cwd.go @@ -0,0 +1,27 @@ +// Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one +// or more contributor license agreements. Licensed under the Elastic License; +// you may not use this file except in compliance with the Elastic License. + +package cobraext + +import ( + "os" + "path/filepath" + + "github.com/spf13/cobra" +) + +func Getwd(cmd *cobra.Command) (string, error) { + cwd, err := cmd.Flags().GetString(ChangeDirectoryFlagName) + if err != nil { + return "", FlagParsingError(err, ChangeDirectoryFlagName) + } + if cwd == "" { + return os.Getwd() //permit:os.Getwd // This should be the only place where this is needed. + } + abs, err := filepath.Abs(cwd) + if err != nil { + return "", FlagParsingError(err, ChangeDirectoryFlagName) + } + return abs, nil +} diff --git a/internal/docs/exported_fields.go b/internal/docs/exported_fields.go index 2f45a1a39d..6af8b7813f 100644 --- a/internal/docs/exported_fields.go +++ b/internal/docs/exported_fields.go @@ -23,7 +23,7 @@ type fieldsTableRecord struct { var escaper = strings.NewReplacer("*", "\\*", "{", "\\{", "}", "\\}", "<", "\\<", ">", "\\>") -func renderExportedFields(fieldsParentDir string) (string, error) { +func renderExportedFields(workDir string, fieldsParentDir string) (string, error) { injectOptions := fields.InjectFieldsOptions{ // Keep External parameter when rendering fields, so we can render // documentation for empty groups imported from ECS, for backwards compatibility. @@ -33,7 +33,7 @@ func renderExportedFields(fieldsParentDir string) (string, error) { // keep them to accept them for validation. SkipEmptyFields: true, } - validator, err := fields.CreateValidatorForDirectory(fieldsParentDir, fields.WithInjectFieldsOptions(injectOptions)) + validator, err := fields.CreateValidatorForDirectory(workDir, fieldsParentDir, fields.WithInjectFieldsOptions(injectOptions)) if err != nil { return "", fmt.Errorf("can't create fields validator instance (path: %s): %w", fieldsParentDir, err) } diff --git a/internal/docs/readme.go b/internal/docs/readme.go index 39791172ee..ca70838d5a 100644 --- a/internal/docs/readme.go +++ b/internal/docs/readme.go @@ -32,7 +32,7 @@ const ( ) // AreReadmesUpToDate function checks if all the .md readme files are up-to-date. -func AreReadmesUpToDate(repositoryRoot *os.Root, packageRoot string) ([]ReadmeFile, error) { +func AreReadmesUpToDate(repositoryRoot *os.Root, workDir, packageRoot string) ([]ReadmeFile, error) { linksFilePath, err := linksDefinitionsFilePath(repositoryRoot) if err != nil { return nil, fmt.Errorf("locating links file failed: %w", err) @@ -46,7 +46,7 @@ func AreReadmesUpToDate(repositoryRoot *os.Root, packageRoot string) ([]ReadmeFi var readmeFiles []ReadmeFile for _, filePath := range files { fileName := filepath.Base(filePath) - ok, diff, err := isReadmeUpToDate(fileName, linksFilePath, packageRoot) + ok, diff, err := isReadmeUpToDate(fileName, linksFilePath, workDir, packageRoot) if !ok || err != nil { readmeFile := ReadmeFile{ FileName: fileName, @@ -65,11 +65,11 @@ func AreReadmesUpToDate(repositoryRoot *os.Root, packageRoot string) ([]ReadmeFi } // isReadmeUpToDate function checks if a single readme file is up-to-date. -func isReadmeUpToDate(fileName, linksFilePath, packageRoot string) (bool, string, error) { +func isReadmeUpToDate(fileName, linksFilePath, workDir, packageRoot string) (bool, string, error) { logger.Debugf("Check if %s is up-to-date", fileName) // the readme is generated within the package root, so source should be the packageRoot files too - rendered, shouldBeRendered, err := generateReadme(fileName, linksFilePath, packageRoot, packageRoot) + rendered, shouldBeRendered, err := generateReadme(fileName, linksFilePath, workDir, packageRoot, packageRoot) if err != nil { return false, "", fmt.Errorf("generating readme file failed: %w", err) } @@ -100,7 +100,7 @@ func isReadmeUpToDate(fileName, linksFilePath, packageRoot string) (bool, string // UpdateReadmes function updates all .md readme files using a defined template // files. The function doesn't perform any action if the template file is not present. -func UpdateReadmes(repositoryRoot *os.Root, packageRoot, buildDir string) ([]string, error) { +func UpdateReadmes(repositoryRoot *os.Root, workDir, packageRoot, buildDir string) ([]string, error) { linksFilePath, err := linksDefinitionsFilePath(repositoryRoot) if err != nil { return nil, fmt.Errorf("locating links file failed: %w", err) @@ -114,7 +114,7 @@ func UpdateReadmes(repositoryRoot *os.Root, packageRoot, buildDir string) ([]str var targets []string for _, filePath := range readmeFiles { fileName := filepath.Base(filePath) - target, err := updateReadme(fileName, linksFilePath, packageRoot, buildDir) + target, err := updateReadme(fileName, linksFilePath, workDir, packageRoot, buildDir) if err != nil { return nil, fmt.Errorf("updating readme file %s failed: %w", fileName, err) } @@ -128,15 +128,15 @@ func UpdateReadmes(repositoryRoot *os.Root, packageRoot, buildDir string) ([]str // updateReadme function updates a single readme file using a defined template file. // It writes the rendered file to both the package directory and the package build directory. -func updateReadme(fileName, linksFilePath, packageRoot, buildDir string) (string, error) { +func updateReadme(fileName, linksFilePath, workDir, packageRoot, buildDir string) (string, error) { logger.Debugf("Update the %s file", fileName) - packageBuildRoot, err := builder.BuildPackagesDirectory(packageRoot, buildDir) + packageBuildRoot, err := builder.BuildPackagesDirectory(workDir, packageRoot, buildDir) if err != nil { return "", fmt.Errorf("package build root not found: %w", err) } - rendered, shouldBeRendered, err := generateReadme(fileName, linksFilePath, packageRoot, packageBuildRoot) + rendered, shouldBeRendered, err := generateReadme(fileName, linksFilePath, workDir, packageRoot, packageBuildRoot) if err != nil { return "", err } @@ -161,7 +161,7 @@ func updateReadme(fileName, linksFilePath, packageRoot, buildDir string) (string // the readme template reads data from the sourceFilesRoot directory. // sourceFilesRoot is usually the package root when generating readme for checking up-to-dateness, // and the built package root when generating readme for the built package. -func generateReadme(fileName, linksFilePath, packageRoot, sourceFilesRoot string) ([]byte, bool, error) { +func generateReadme(fileName, linksFilePath, workDir, packageRoot, sourceFilesRoot string) ([]byte, bool, error) { logger.Debugf("Generate %s file (package: %s)", fileName, packageRoot) templatePath, found, err := findReadmeTemplatePath(fileName, packageRoot) if err != nil { @@ -180,7 +180,7 @@ func generateReadme(fileName, linksFilePath, packageRoot, sourceFilesRoot string // templatePath lives under the _dev/build/docs directory at the package root. // builtPackageRoot is the root directory of the built package. - rendered, err := renderReadme(fileName, sourceFilesRoot, templatePath, linksMap) + rendered, err := renderReadme(fileName, workDir, sourceFilesRoot, templatePath, linksMap) if err != nil { return nil, true, fmt.Errorf("rendering Readme failed: %w", err) } @@ -201,7 +201,7 @@ func findReadmeTemplatePath(fileName, packageRoot string) (string, bool, error) } // renderReadme function renders the readme file reading from -func renderReadme(fileName, sourceFilesRoot, templatePath string, linksMap linkMap) ([]byte, error) { +func renderReadme(fileName, workDir, sourceFilesRoot, templatePath string, linksMap linkMap) ([]byte, error) { logger.Debugf("Render %s file (package: %s, templatePath: %s)", fileName, sourceFilesRoot, templatePath) t := template.New(fileName) @@ -215,9 +215,9 @@ func renderReadme(fileName, sourceFilesRoot, templatePath string, linksMap linkM "fields": func(args ...string) (string, error) { if len(args) > 0 { dataStreamPath := filepath.Join(sourceFilesRoot, "data_stream", args[0]) - return renderExportedFields(dataStreamPath) + return renderExportedFields(workDir, dataStreamPath) } - return renderExportedFields(sourceFilesRoot) + return renderExportedFields(workDir, sourceFilesRoot) }, "url": func(args ...string) (string, error) { options := linkOptions{} diff --git a/internal/docs/readme_test.go b/internal/docs/readme_test.go index a06be43071..22de7c1261 100644 --- a/internal/docs/readme_test.go +++ b/internal/docs/readme_test.go @@ -58,7 +58,7 @@ Introduction to the package`, err := createReadmeFile(dir, c.readmeTemplateContents) require.NoError(t, err) - rendered, isTemplate, err := generateReadme(c.filename, "", dir, dir) + rendered, isTemplate, err := generateReadme(c.filename, "", ".", dir, dir) require.NoError(t, err) if c.readmeTemplateContents != "" { @@ -115,7 +115,7 @@ http://www.example.com/bar err := createReadmeFile(c.packageRoot, c.readmeTemplateContents) require.NoError(t, err) - rendered, err := renderReadme(filename, c.packageRoot, templatePath, c.linksMap) + rendered, err := renderReadme(filename, ".", c.packageRoot, templatePath, c.linksMap) require.NoError(t, err) renderedString := string(rendered) @@ -174,7 +174,7 @@ An example event for ` + "`example`" + ` looks as following: err = createManifestFile(c.packageRoot) require.NoError(t, err) - rendered, err := renderReadme(filename, c.packageRoot, templatePath, linksMap) + rendered, err := renderReadme(filename, ".", c.packageRoot, templatePath, linksMap) require.NoError(t, err) renderedString := string(rendered) @@ -276,7 +276,7 @@ Introduction to the package err = createFieldsFile(c.packageRoot, c.dataStreamName, c.fieldsContents) require.NoError(t, err) - rendered, err := renderReadme(filename, c.packageRoot, templatePath, linksMap) + rendered, err := renderReadme(filename, ".", c.packageRoot, templatePath, linksMap) require.NoError(t, err) renderedString := string(rendered) diff --git a/internal/export/dashboards.go b/internal/export/dashboards.go index df57b85ac4..2cff65d473 100644 --- a/internal/export/dashboards.go +++ b/internal/export/dashboards.go @@ -21,8 +21,8 @@ import ( // Dashboards method exports selected dashboards with references objects. All Kibana objects are saved to local files // in appropriate directories. -func Dashboards(ctx context.Context, kibanaClient *kibana.Client, dashboardsIDs []string) error { - packageRoot, err := packages.MustFindPackageRoot() +func Dashboards(ctx context.Context, kibanaClient *kibana.Client, workDir string, dashboardsIDs []string) error { + packageRoot, err := packages.MustFindPackageRoot(workDir) if err != nil { return fmt.Errorf("locating package root failed: %w", err) } diff --git a/internal/fields/validate.go b/internal/fields/validate.go index 26527a40e6..f1f9149a01 100644 --- a/internal/fields/validate.go +++ b/internal/fields/validate.go @@ -260,15 +260,17 @@ type packageRootFinder interface { FindPackageRoot() (string, error) } -type packageRoot struct{} +type packageRoot struct { + Cwd string +} func (p packageRoot) FindPackageRoot() (string, error) { - return packages.FindPackageRoot() + return packages.FindPackageRoot(p.Cwd) } // CreateValidatorForDirectory function creates a validator for the directory. -func CreateValidatorForDirectory(fieldsParentDir string, opts ...ValidatorOption) (v *Validator, err error) { - p := packageRoot{} +func CreateValidatorForDirectory(workDir string, fieldsParentDir string, opts ...ValidatorOption) (v *Validator, err error) { + p := packageRoot{Cwd: workDir} return createValidatorForDirectoryAndPackageRoot(fieldsParentDir, p, opts...) } diff --git a/internal/fields/validate_test.go b/internal/fields/validate_test.go index dcbf5c5e77..ac4a159630 100644 --- a/internal/fields/validate_test.go +++ b/internal/fields/validate_test.go @@ -33,7 +33,7 @@ func (p packageRootTestFinder) FindPackageRoot() (string, error) { } func TestValidate_NoWildcardFields(t *testing.T) { - validator, err := CreateValidatorForDirectory("../../test/packages/parallel/aws/data_stream/elb_logs", WithDisabledDependencyManagement()) + validator, err := CreateValidatorForDirectory(".", "../../test/packages/parallel/aws/data_stream/elb_logs", WithDisabledDependencyManagement()) require.NoError(t, err) require.NotNil(t, validator) @@ -45,7 +45,7 @@ func TestValidate_NoWildcardFields(t *testing.T) { } func TestValidate_WithWildcardFields(t *testing.T) { - validator, err := CreateValidatorForDirectory("../../test/packages/parallel/aws/data_stream/sns", WithDisabledDependencyManagement()) + validator, err := CreateValidatorForDirectory(".", "../../test/packages/parallel/aws/data_stream/sns", WithDisabledDependencyManagement()) require.NoError(t, err) require.NotNil(t, validator) @@ -55,7 +55,7 @@ func TestValidate_WithWildcardFields(t *testing.T) { } func TestValidate_WithFlattenedFields(t *testing.T) { - validator, err := CreateValidatorForDirectory("testdata", + validator, err := CreateValidatorForDirectory(".", "testdata", WithDisabledDependencyManagement()) require.NoError(t, err) require.NotNil(t, validator) @@ -66,7 +66,7 @@ func TestValidate_WithFlattenedFields(t *testing.T) { } func TestValidate_ObjectTypeWithoutWildcard(t *testing.T) { - validator, err := CreateValidatorForDirectory("testdata", + validator, err := CreateValidatorForDirectory(".", "testdata", WithDisabledDependencyManagement()) require.NoError(t, err) require.NotNil(t, validator) @@ -85,7 +85,7 @@ func TestValidate_ObjectTypeWithoutWildcard(t *testing.T) { } func TestValidate_DisabledParent(t *testing.T) { - validator, err := CreateValidatorForDirectory("testdata", + validator, err := CreateValidatorForDirectory(".", "testdata", WithDisabledDependencyManagement()) require.NoError(t, err) require.NotNil(t, validator) @@ -98,7 +98,7 @@ func TestValidate_DisabledParent(t *testing.T) { } func TestValidate_EnabledNotMappedError(t *testing.T) { - validator, err := CreateValidatorForDirectory("testdata", + validator, err := CreateValidatorForDirectory(".", "testdata", WithDisabledDependencyManagement()) require.NoError(t, err) require.NotNil(t, validator) @@ -115,7 +115,7 @@ func TestValidate_EnabledNotMappedError(t *testing.T) { } func TestValidate_WithNumericKeywordFields(t *testing.T) { - validator, err := CreateValidatorForDirectory("testdata", + validator, err := CreateValidatorForDirectory(".", "testdata", WithNumericKeywordFields([]string{ "foo.code", // Contains a number. "foo.pid", // Contains an array of numbers. @@ -133,7 +133,7 @@ func TestValidate_WithNumericKeywordFields(t *testing.T) { } func TestValidate_WithStringNumberFields(t *testing.T) { - validator, err := CreateValidatorForDirectory("testdata", + validator, err := CreateValidatorForDirectory(".", "testdata", WithStringNumberFields([]string{ "foo.count", // Contains a number as string. "foo.metric", // Contains a floating number as string. @@ -186,7 +186,7 @@ func TestValidate_WithDisabledImportAllECSSchema(t *testing.T) { } func TestValidate_constantKeyword(t *testing.T) { - validator, err := CreateValidatorForDirectory("testdata", WithDisabledDependencyManagement()) + validator, err := CreateValidatorForDirectory(".", "testdata", WithDisabledDependencyManagement()) require.NoError(t, err) require.NotNil(t, validator) @@ -200,7 +200,7 @@ func TestValidate_constantKeyword(t *testing.T) { } func TestValidate_ipAddress(t *testing.T) { - validator, err := CreateValidatorForDirectory("testdata", WithEnabledAllowedIPCheck(), WithDisabledDependencyManagement()) + validator, err := CreateValidatorForDirectory(".", "testdata", WithEnabledAllowedIPCheck(), WithDisabledDependencyManagement()) require.NoError(t, err) require.NotNil(t, validator) @@ -215,7 +215,7 @@ func TestValidate_ipAddress(t *testing.T) { } func TestValidate_undefinedArrayOfObjects(t *testing.T) { - validator, err := CreateValidatorForDirectory("testdata", WithSpecVersion("2.0.0"), WithDisabledDependencyManagement()) + validator, err := CreateValidatorForDirectory(".", "testdata", WithSpecVersion("2.0.0"), WithDisabledDependencyManagement()) require.NoError(t, err) require.NotNil(t, validator) @@ -226,7 +226,7 @@ func TestValidate_undefinedArrayOfObjects(t *testing.T) { } func TestValidate_WithSpecVersion(t *testing.T) { - validator, err := CreateValidatorForDirectory("testdata", WithSpecVersion("2.0.0"), WithDisabledDependencyManagement()) + validator, err := CreateValidatorForDirectory(".", "testdata", WithSpecVersion("2.0.0"), WithDisabledDependencyManagement()) require.NoError(t, err) e := readSampleEvent(t, "testdata/invalid-array-normalization.json") @@ -239,7 +239,7 @@ func TestValidate_WithSpecVersion(t *testing.T) { require.Empty(t, errs) // Check now that this validation was only enabled for 2.0.0. - validator, err = CreateValidatorForDirectory("testdata", WithSpecVersion("1.99.99"), WithDisabledDependencyManagement()) + validator, err = CreateValidatorForDirectory(".", "testdata", WithSpecVersion("1.99.99"), WithDisabledDependencyManagement()) require.NoError(t, err) e = readSampleEvent(t, "testdata/invalid-array-normalization.json") @@ -248,7 +248,7 @@ func TestValidate_WithSpecVersion(t *testing.T) { } func TestValidate_ExpectedEventType(t *testing.T) { - validator, err := CreateValidatorForDirectory("testdata", WithSpecVersion("2.0.0"), WithDisabledDependencyManagement()) + validator, err := CreateValidatorForDirectory(".", "testdata", WithSpecVersion("2.0.0"), WithDisabledDependencyManagement()) require.NoError(t, err) require.NotNil(t, validator) @@ -337,7 +337,7 @@ func TestValidate_ExpectedEventType(t *testing.T) { } func TestValidate_ExpectedDatasets(t *testing.T) { - validator, err := CreateValidatorForDirectory("testdata", + validator, err := CreateValidatorForDirectory(".", "testdata", WithSpecVersion("2.0.0"), WithExpectedDatasets([]string{"apache.status"}), WithDisabledDependencyManagement(), @@ -992,7 +992,7 @@ func TestCompareKeys(t *testing.T) { } func TestValidateGeoPoint(t *testing.T) { - validator, err := CreateValidatorForDirectory("../../test/packages/other/fields_tests/data_stream/first", WithDisabledDependencyManagement()) + validator, err := CreateValidatorForDirectory(".", "../../test/packages/other/fields_tests/data_stream/first", WithDisabledDependencyManagement()) require.NoError(t, err) require.NotNil(t, validator) diff --git a/internal/files/linkedfiles_test.go b/internal/files/linkedfiles_test.go index 3900a425ab..f4fa89a8d8 100644 --- a/internal/files/linkedfiles_test.go +++ b/internal/files/linkedfiles_test.go @@ -86,7 +86,7 @@ func TestListLinkedFiles(t *testing.T) { basePath := filepath.Join(wd, "testdata", "links") // Find the repository root to create a secure os.Root context - root, err := FindRepositoryRoot() + root, err := FindRepositoryRoot(wd) require.NoError(t, err) t.Cleanup(func() { _ = root.Close() }) @@ -159,7 +159,7 @@ func TestAreLinkedFilesUpToDate(t *testing.T) { basePath := filepath.Join(wd, filepath.FromSlash("testdata/links")) // Find the repository root to create a secure os.Root context - root, err := FindRepositoryRoot() + root, err := FindRepositoryRoot(wd) require.NoError(t, err) t.Cleanup(func() { _ = root.Close() }) @@ -234,7 +234,7 @@ func TestLinkedFilesByPackageFrom(t *testing.T) { basePath := filepath.Join(wd, "testdata", "links") // Find the repository root to create a secure os.Root context - root, err := FindRepositoryRoot() + root, err := FindRepositoryRoot(wd) require.NoError(t, err) t.Cleanup(func() { _ = root.Close() }) diff --git a/internal/files/repository.go b/internal/files/repository.go index d7ae0bf68d..7395de34b3 100644 --- a/internal/files/repository.go +++ b/internal/files/repository.go @@ -13,8 +13,8 @@ import ( "gopkg.in/yaml.v3" ) -func FindRepositoryRoot() (*os.Root, error) { - rootPath, err := FindRepositoryRootDirectory() +func FindRepositoryRoot(workDir string) (*os.Root, error) { + rootPath, err := FindRepositoryRootDirectory(workDir) if err != nil { return nil, fmt.Errorf("root not found: %w", err) } @@ -28,11 +28,7 @@ func FindRepositoryRoot() (*os.Root, error) { return dirRoot, nil } -func FindRepositoryRootDirectory() (string, error) { - workDir, err := os.Getwd() - if err != nil { - return "", fmt.Errorf("locating working directory failed: %w", err) - } +func FindRepositoryRootDirectory(workDir string) (string, error) { return findRepositoryRootDirectory(workDir) } diff --git a/internal/packages/archetype/data_stream_test.go b/internal/packages/archetype/data_stream_test.go index d6e2deaa25..278fed9be5 100644 --- a/internal/packages/archetype/data_stream_test.go +++ b/internal/packages/archetype/data_stream_test.go @@ -77,7 +77,6 @@ func createDataStreamDescriptorForTest() DataStreamDescriptor { } func createAndCheckDataStream(t *testing.T, pd PackageDescriptor, dd DataStreamDescriptor, valid bool, repositoryRoot *os.Root) { - packagesDir := filepath.Join(repositoryRoot.Name(), "packages") err := os.MkdirAll(packagesDir, 0o755) require.NoError(t, err) @@ -91,5 +90,5 @@ func createAndCheckDataStream(t *testing.T, pd PackageDescriptor, dd DataStreamD err = CreateDataStream(dd) require.NoError(t, err) - checkPackage(t, repositoryRoot, packageRoot, valid) + checkPackage(t, repositoryRoot, ".", packageRoot, valid) } diff --git a/internal/packages/archetype/package_test.go b/internal/packages/archetype/package_test.go index 5f739d91ac..fe834c6dd1 100644 --- a/internal/packages/archetype/package_test.go +++ b/internal/packages/archetype/package_test.go @@ -46,7 +46,7 @@ func createAndCheckPackage(t *testing.T, pd PackageDescriptor, valid bool) { err = createPackageInDir(pd, packagesDir) require.NoError(t, err) - checkPackage(t, repositoryRoot, filepath.Join(packagesDir, pd.Manifest.Name), valid) + checkPackage(t, repositoryRoot, ".", filepath.Join(packagesDir, pd.Manifest.Name), valid) } func createPackageDescriptorForTest(packageType, kibanaVersion string) PackageDescriptor { @@ -96,16 +96,20 @@ func createPackageDescriptorForTest(packageType, kibanaVersion string) PackageDe } } -func buildPackage(t *testing.T, repositoryRoot *os.Root, packageRootPath string) error { +func buildPackage(t *testing.T, repositoryRoot *os.Root, workDir, packageRootPath string) error { buildDir := filepath.Join(repositoryRoot.Name(), "build") err := os.MkdirAll(buildDir, 0o755) require.NoError(t, err) - _, err = docs.UpdateReadmes(repositoryRoot, packageRootPath, buildDir) + _, err = docs.UpdateReadmes(repositoryRoot, workDir, packageRootPath, buildDir) if err != nil { return err } + cwd, err := os.Getwd() + require.NoError(t, err) + _, err = builder.BuildPackage(t.Context(), builder.BuildOptions{ + WorkDir: cwd, PackageRootPath: packageRootPath, BuildDir: buildDir, RepositoryRoot: repositoryRoot, @@ -113,8 +117,8 @@ func buildPackage(t *testing.T, repositoryRoot *os.Root, packageRootPath string) return err } -func checkPackage(t *testing.T, repositoryRoot *os.Root, packageRootPath string, valid bool) { - err := buildPackage(t, repositoryRoot, packageRootPath) +func checkPackage(t *testing.T, repositoryRoot *os.Root, workDir, packageRootPath string, valid bool) { + err := buildPackage(t, repositoryRoot, workDir, packageRootPath) if !valid { assert.Error(t, err) return diff --git a/internal/packages/installer/factory.go b/internal/packages/installer/factory.go index ec278e6c57..2930170e5c 100644 --- a/internal/packages/installer/factory.go +++ b/internal/packages/installer/factory.go @@ -35,6 +35,7 @@ type Installer interface { // Options are the parameters used to build an installer. type Options struct { Kibana *kibana.Client + WorkDir string PackageRootPath string // Root path of the package to be installed. ZipPath string SkipValidation bool @@ -86,6 +87,7 @@ func NewForPackage(ctx context.Context, options Options) (Installer, error) { } target, err := builder.BuildPackage(ctx, builder.BuildOptions{ + WorkDir: options.WorkDir, PackageRootPath: options.PackageRootPath, CreateZip: supportsUploadZip, SignPackage: false, diff --git a/internal/packages/packages.go b/internal/packages/packages.go index 1cdd157104..150652900a 100644 --- a/internal/packages/packages.go +++ b/internal/packages/packages.go @@ -285,8 +285,8 @@ func (t *Transform) HasSource(name string) (bool, error) { // MustFindPackageRoot finds and returns the path to the root folder of a package. // It fails with an error if the package root can't be found. -func MustFindPackageRoot() (string, error) { - root, err := FindPackageRoot() +func MustFindPackageRoot(workDir string) (string, error) { + root, err := FindPackageRoot(workDir) if err != nil { return "", fmt.Errorf("locating package root failed: %w", err) } @@ -294,11 +294,7 @@ func MustFindPackageRoot() (string, error) { } // FindPackageRoot finds and returns the path to the root folder of a package from the working directory. -func FindPackageRoot() (string, error) { - workDir, err := os.Getwd() - if err != nil { - return "", fmt.Errorf("locating working directory failed: %w", err) - } +func FindPackageRoot(workDir string) (string, error) { return FindPackageRootFrom(workDir) } diff --git a/internal/resources/fleetpackage.go b/internal/resources/fleetpackage.go index 7fab894ae2..89618148eb 100644 --- a/internal/resources/fleetpackage.go +++ b/internal/resources/fleetpackage.go @@ -22,6 +22,9 @@ type FleetPackage struct { // Provider is the name of the provider to use, defaults to "kibana". Provider string + // WorkDir is the current working directory. + WorkDir string + // PackageRootPath is the root of the package source to install. PackageRootPath string @@ -61,6 +64,7 @@ func (f *FleetPackage) installer(ctx resource.Context) (installer.Installer, err return installer.NewForPackage(ctx, installer.Options{ Kibana: provider.Client, + WorkDir: f.WorkDir, PackageRootPath: f.PackageRootPath, SkipValidation: true, RepositoryRoot: f.RepositoryRoot, diff --git a/internal/resources/fleetpackage_test.go b/internal/resources/fleetpackage_test.go index 7749ad20e6..b57824b5f0 100644 --- a/internal/resources/fleetpackage_test.go +++ b/internal/resources/fleetpackage_test.go @@ -7,6 +7,7 @@ package resources import ( "errors" "fmt" + "os" "path/filepath" "testing" @@ -22,12 +23,16 @@ import ( func TestRequiredProvider(t *testing.T) { manager := resource.NewManager() - repositoryRoot, err := files.FindRepositoryRoot() + cwd, err := os.Getwd() + require.NoError(t, err) + + repositoryRoot, err := files.FindRepositoryRoot(cwd) require.NoError(t, err) t.Cleanup(func() { _ = repositoryRoot.Close() }) _, err = manager.Apply(resource.Resources{ &FleetPackage{ + WorkDir: cwd, PackageRootPath: "../../test/packages/parallel/nginx", RepositoryRoot: repositoryRoot, }, @@ -46,6 +51,9 @@ func TestPackageLifecycle(t *testing.T) { {title: "package not found", name: "sql_input"}, } + cwd, err := os.Getwd() + require.NoError(t, err) + for _, c := range cases { t.Run(c.title, func(t *testing.T) { recordPath := filepath.Join("testdata", "kibana-8-mock-package-lifecycle-"+c.name) @@ -54,13 +62,14 @@ func TestPackageLifecycle(t *testing.T) { t.FailNow() } - repositoryRoot, err := files.FindRepositoryRoot() + repositoryRoot, err := files.FindRepositoryRoot(cwd) require.NoError(t, err) defer repositoryRoot.Close() packageRootPath := filepath.Join(repositoryRoot.Name(), "test", "packages", "parallel", c.name) fleetPackage := FleetPackage{ + WorkDir: cwd, PackageRootPath: packageRootPath, RepositoryRoot: repositoryRoot, } @@ -84,11 +93,15 @@ func TestSystemPackageIsNotRemoved(t *testing.T) { t.FailNow() } - repositoryRoot, err := files.FindRepositoryRoot() + cwd, err := os.Getwd() + require.NoError(t, err) + + repositoryRoot, err := files.FindRepositoryRoot(cwd) require.NoError(t, err) t.Cleanup(func() { _ = repositoryRoot.Close() }) fleetPackage := FleetPackage{ + WorkDir: cwd, PackageRootPath: "../../test/packages/parallel/system", Absent: true, RepositoryRoot: repositoryRoot, diff --git a/internal/resources/fleetpolicy_test.go b/internal/resources/fleetpolicy_test.go index 4d6c547159..e7d8aa559a 100644 --- a/internal/resources/fleetpolicy_test.go +++ b/internal/resources/fleetpolicy_test.go @@ -21,7 +21,10 @@ import ( ) func TestRequiredProviderFleetPolicy(t *testing.T) { - repositoryRoot, err := files.FindRepositoryRoot() + cwd, err := os.Getwd() + require.NoError(t, err) + + repositoryRoot, err := files.FindRepositoryRoot(cwd) require.NoError(t, err) t.Cleanup(func() { _ = repositoryRoot.Close() }) @@ -37,7 +40,10 @@ func TestRequiredProviderFleetPolicy(t *testing.T) { } func TestPolicyLifecycle(t *testing.T) { - repositoryRoot, err := files.FindRepositoryRoot() + cwd, err := os.Getwd() + require.NoError(t, err) + + repositoryRoot, err := files.FindRepositoryRoot(cwd) require.NoError(t, err) t.Cleanup(func() { _ = repositoryRoot.Close() }) @@ -100,14 +106,14 @@ func TestPolicyLifecycle(t *testing.T) { Namespace: "eptest", PackagePolicies: c.packagePolicies, } - t.Cleanup(func() { deletePolicy(t, manager, agentPolicy, repositoryRoot) }) + t.Cleanup(func() { deletePolicy(t, manager, agentPolicy, repositoryRoot, cwd) }) - _, err := manager.Apply(withPackageResources(&agentPolicy, repositoryRoot)) + _, err := manager.Apply(withPackageResources(&agentPolicy, repositoryRoot, cwd)) assert.NoError(t, err) assertPolicyPresent(t, kibanaClient, true, agentPolicy.ID) agentPolicy.Absent = true - _, err = manager.Apply(withPackageResources(&agentPolicy, repositoryRoot)) + _, err = manager.Apply(withPackageResources(&agentPolicy, repositoryRoot, cwd)) assert.NoError(t, err) assertPolicyPresent(t, kibanaClient, false, agentPolicy.ID) }) @@ -116,10 +122,11 @@ func TestPolicyLifecycle(t *testing.T) { // withPackageResources prepares a list of resources that ensures that all required packages are installed // before creating the policy. -func withPackageResources(agentPolicy *FleetAgentPolicy, repostoryRoot *os.Root) resource.Resources { +func withPackageResources(agentPolicy *FleetAgentPolicy, repostoryRoot *os.Root, workDir string) resource.Resources { var resources resource.Resources for _, policy := range agentPolicy.PackagePolicies { resources = append(resources, &FleetPackage{ + WorkDir: workDir, PackageRootPath: policy.PackageRootPath, Absent: agentPolicy.Absent, RepositoryRoot: repostoryRoot, @@ -143,10 +150,10 @@ func assertPolicyPresent(t *testing.T, client *kibana.Client, expected bool, pol return false } -func deletePolicy(t *testing.T, manager *resource.Manager, agentPolicy FleetAgentPolicy, repositoryRoot *os.Root) { +func deletePolicy(t *testing.T, manager *resource.Manager, agentPolicy FleetAgentPolicy, repositoryRoot *os.Root, workDir string) { t.Helper() agentPolicy.Absent = true - _, err := manager.Apply(withPackageResources(&agentPolicy, repositoryRoot)) + _, err := manager.Apply(withPackageResources(&agentPolicy, repositoryRoot, workDir)) assert.NoError(t, err, "cleanup execution") } diff --git a/internal/servicedeployer/compose.go b/internal/servicedeployer/compose.go index d15c0a6954..00b69bd557 100644 --- a/internal/servicedeployer/compose.go +++ b/internal/servicedeployer/compose.go @@ -24,6 +24,7 @@ import ( // DockerComposeServiceDeployer knows how to deploy a service defined via // a Docker Compose file. type DockerComposeServiceDeployer struct { + workDir string profile *profile.Profile ymlPaths []string variant ServiceVariant @@ -35,6 +36,7 @@ type DockerComposeServiceDeployer struct { } type DockerComposeServiceDeployerOptions struct { + WorkDir string Profile *profile.Profile YmlPaths []string Variant ServiceVariant @@ -55,6 +57,7 @@ type dockerComposeDeployedService struct { variant ServiceVariant env []string configDir string + workDir string } var _ ServiceDeployer = new(DockerComposeServiceDeployer) @@ -62,6 +65,7 @@ var _ ServiceDeployer = new(DockerComposeServiceDeployer) // NewDockerComposeServiceDeployer returns a new instance of a DockerComposeServiceDeployer. func NewDockerComposeServiceDeployer(options DockerComposeServiceDeployerOptions) (*DockerComposeServiceDeployer, error) { return &DockerComposeServiceDeployer{ + workDir: options.WorkDir, profile: options.Profile, ymlPaths: options.YmlPaths, variant: options.Variant, @@ -75,6 +79,7 @@ func NewDockerComposeServiceDeployer(options DockerComposeServiceDeployerOptions func (d *DockerComposeServiceDeployer) SetUp(ctx context.Context, svcInfo ServiceInfo) (DeployedService, error) { logger.Debug("setting up service using Docker Compose service deployer") service := dockerComposeDeployedService{ + workDir: d.workDir, ymlPaths: d.ymlPaths, project: svcInfo.ProjectName(), variant: d.variant, @@ -132,7 +137,7 @@ func (d *DockerComposeServiceDeployer) SetUp(ctx context.Context, svcInfo Servic if err != nil { processServiceContainerLogs(context.WithoutCancel(ctx), p, compose.CommandOptions{ Env: opts.Env, - }, svcInfo.Name) + }, d.workDir, svcInfo.Name) return nil, fmt.Errorf("service is unhealthy: %w", err) } @@ -285,7 +290,7 @@ func (s *dockerComposeDeployedService) TearDown(ctx context.Context) error { return fmt.Errorf("could not stop service using Docker Compose: %w", err) } - processServiceContainerLogs(ctx, p, opts, s.svcInfo.Name) + processServiceContainerLogs(ctx, p, opts, s.workDir, s.svcInfo.Name) if err := p.Down(ctx, compose.CommandOptions{ Env: opts.Env, @@ -307,7 +312,7 @@ func (s *dockerComposeDeployedService) SetInfo(ctxt ServiceInfo) error { return nil } -func processServiceContainerLogs(ctx context.Context, p *compose.Project, opts compose.CommandOptions, serviceName string) { +func processServiceContainerLogs(ctx context.Context, p *compose.Project, opts compose.CommandOptions, workDir, serviceName string) { content, err := p.Logs(ctx, opts) if err != nil { logger.Errorf("can't export service logs: %v", err) @@ -319,14 +324,14 @@ func processServiceContainerLogs(ctx context.Context, p *compose.Project, opts c return } - err = writeServiceContainerLogs(serviceName, content) + err = writeServiceContainerLogs(workDir, serviceName, content) if err != nil { logger.Errorf("can't write service container logs: %v", err) } } -func writeServiceContainerLogs(serviceName string, content []byte) error { - buildDir, err := builder.BuildDirectory() +func writeServiceContainerLogs(workDir, serviceName string, content []byte) error { + buildDir, err := builder.BuildDirectory(workDir) if err != nil { return fmt.Errorf("locating build directory failed: %w", err) } diff --git a/internal/servicedeployer/custom_agent.go b/internal/servicedeployer/custom_agent.go index 360477f3fa..19ca40bd88 100644 --- a/internal/servicedeployer/custom_agent.go +++ b/internal/servicedeployer/custom_agent.go @@ -35,6 +35,7 @@ var dockerCustomAgentDockerfileContent []byte // CustomAgentDeployer knows how to deploy a custom elastic-agent defined via // a Docker Compose file. type CustomAgentDeployer struct { + workDir string profile *profile.Profile dockerComposeFile string stackVersion string @@ -45,6 +46,7 @@ type CustomAgentDeployer struct { } type CustomAgentDeployerOptions struct { + WorkDir string Profile *profile.Profile DockerComposeFile string StackVersion string @@ -59,6 +61,7 @@ var _ ServiceDeployer = new(CustomAgentDeployer) // NewCustomAgentDeployer returns a new instance of a deployedCustomAgent. func NewCustomAgentDeployer(options CustomAgentDeployerOptions) (*CustomAgentDeployer, error) { return &CustomAgentDeployer{ + workDir: options.WorkDir, profile: options.Profile, dockerComposeFile: options.DockerComposeFile, stackVersion: options.StackVersion, @@ -114,6 +117,7 @@ func (d *CustomAgentDeployer) SetUp(ctx context.Context, svcInfo ServiceInfo) (D Env: env, }, configDir: configDir, + workDir: d.workDir, } p, err := compose.NewProject(service.project, service.ymlPaths...) @@ -171,7 +175,7 @@ func (d *CustomAgentDeployer) SetUp(ctx context.Context, svcInfo ServiceInfo) (D if err != nil { processServiceContainerLogs(ctx, p, compose.CommandOptions{ Env: opts.Env, - }, svcInfo.Name) + }, d.workDir, svcInfo.Name) return nil, fmt.Errorf("service is unhealthy: %w", err) } diff --git a/internal/servicedeployer/factory.go b/internal/servicedeployer/factory.go index d21f62e57e..d1f09c977c 100644 --- a/internal/servicedeployer/factory.go +++ b/internal/servicedeployer/factory.go @@ -21,6 +21,7 @@ const ( // FactoryOptions defines options used to create an instance of a service deployer. type FactoryOptions struct { + WorkDir string Profile *profile.Profile PackageRootPath string @@ -84,6 +85,7 @@ func Factory(options FactoryOptions) (ServiceDeployer, error) { return nil, fmt.Errorf("can't use service variant: %w", err) } opts := DockerComposeServiceDeployerOptions{ + WorkDir: options.WorkDir, Profile: options.Profile, YmlPaths: []string{dockerComposeYMLPath}, Variant: sv, @@ -105,6 +107,7 @@ func Factory(options FactoryOptions) (ServiceDeployer, error) { policyName := getTokenPolicyName(options.StackVersion, options.PolicyName) opts := CustomAgentDeployerOptions{ + WorkDir: options.WorkDir, Profile: options.Profile, DockerComposeFile: customAgentCfgYMLPath, StackVersion: options.StackVersion, @@ -120,6 +123,7 @@ func Factory(options FactoryOptions) (ServiceDeployer, error) { } if _, err := os.Stat(serviceDeployerPath); err == nil { opts := TerraformServiceDeployerOptions{ + WorkDir: options.WorkDir, DefinitionsDir: serviceDeployerPath, } return NewTerraformServiceDeployer(opts) diff --git a/internal/servicedeployer/terraform.go b/internal/servicedeployer/terraform.go index 54b62154d6..f504e793d3 100644 --- a/internal/servicedeployer/terraform.go +++ b/internal/servicedeployer/terraform.go @@ -42,10 +42,12 @@ var terraformDeployerDockerfileContent string // TerraformServiceDeployer is responsible for deploying infrastructure described with Terraform definitions. type TerraformServiceDeployer struct { + workDir string definitionsDir string } type TerraformServiceDeployerOptions struct { + WorkDir string DefinitionsDir string } @@ -89,6 +91,7 @@ func addTerraformOutputs(svcInfo *ServiceInfo) error { // NewTerraformServiceDeployer creates an instance of TerraformServiceDeployer. func NewTerraformServiceDeployer(opts TerraformServiceDeployerOptions) (*TerraformServiceDeployer, error) { return &TerraformServiceDeployer{ + workDir: opts.WorkDir, definitionsDir: opts.DefinitionsDir, }, nil } @@ -117,6 +120,7 @@ func (tsd TerraformServiceDeployer) SetUp(ctx context.Context, svcInfo ServiceIn env: tfEnvironment, shutdownTimeout: 300 * time.Second, configDir: configDir, + workDir: tsd.workDir, } p, err := compose.NewProject(service.project, service.ymlPaths...) @@ -157,7 +161,7 @@ func (tsd TerraformServiceDeployer) SetUp(ctx context.Context, svcInfo ServiceIn if err != nil { processServiceContainerLogs(ctx, p, compose.CommandOptions{ Env: opts.Env, - }, svcInfo.Name) + }, tsd.workDir, svcInfo.Name) //lint:ignore ST1005 error starting with product name can be capitalized return nil, fmt.Errorf("Terraform deployer is unhealthy: %w", err) } diff --git a/internal/stack/boot.go b/internal/stack/boot.go index d076bce74d..b5dcdc68d6 100644 --- a/internal/stack/boot.go +++ b/internal/stack/boot.go @@ -45,7 +45,7 @@ func BootUp(ctx context.Context, options Options) error { } printUserConfig(options.Printer, config) - buildPackagesPath, found, err := builder.FindBuildPackagesDirectory() + buildPackagesPath, found, err := builder.FindBuildPackagesDirectory(options.WorkDir) if err != nil { return fmt.Errorf("finding build packages directory failed: %w", err) } diff --git a/internal/stack/options.go b/internal/stack/options.go index 1c8f2827d6..c3c59956bd 100644 --- a/internal/stack/options.go +++ b/internal/stack/options.go @@ -10,6 +10,7 @@ import ( // Options defines available image booting options. type Options struct { + WorkDir string DaemonMode bool StackVersion string diff --git a/internal/testrunner/coverage.go b/internal/testrunner/coverage.go index c4badce219..80bf50eddb 100644 --- a/internal/testrunner/coverage.go +++ b/internal/testrunner/coverage.go @@ -20,8 +20,8 @@ import ( // GenerateBasePackageCoverageReport generates a coverage report where all files under the root path are // marked as not covered. It ignores files under _dev directories. -func GenerateBasePackageCoverageReport(pkgName, rootPath, format string) (CoverageReport, error) { - repoPath, err := files.FindRepositoryRootDirectory() +func GenerateBasePackageCoverageReport(pkgName, workDir, rootPath, format string) (CoverageReport, error) { + repoPath, err := files.FindRepositoryRootDirectory(workDir) if err != nil { return nil, fmt.Errorf("failed to find repository root directory: %w", err) } @@ -68,8 +68,8 @@ func GenerateBasePackageCoverageReport(pkgName, rootPath, format string) (Covera } // GenerateBaseFileCoverageReport generates a coverage report for a given file, where all the file is marked as covered or uncovered. -func GenerateBaseFileCoverageReport(pkgName, path, format string, covered bool) (CoverageReport, error) { - repoPath, err := files.FindRepositoryRootDirectory() +func GenerateBaseFileCoverageReport(pkgName, workDir, path, format string, covered bool) (CoverageReport, error) { + repoPath, err := files.FindRepositoryRootDirectory(workDir) if err != nil { return nil, fmt.Errorf("failed to find repository root directory: %w", err) } @@ -79,8 +79,8 @@ func GenerateBaseFileCoverageReport(pkgName, path, format string, covered bool) // GenerateBaseFileCoverageReport generates a coverage report for all the files matching any of the given patterns. The complete // files are marked as fully covered or uncovered depending on the given value. -func GenerateBaseFileCoverageReportGlob(pkgName string, patterns []string, format string, covered bool) (CoverageReport, error) { - repoPath, err := files.FindRepositoryRootDirectory() +func GenerateBaseFileCoverageReportGlob(workDir string, pkgName string, patterns []string, format string, covered bool) (CoverageReport, error) { + repoPath, err := files.FindRepositoryRootDirectory(workDir) if err != nil { return nil, fmt.Errorf("failed to find repository root directory: %w", err) } diff --git a/internal/testrunner/coveragereport.go b/internal/testrunner/coveragereport.go index 71f1a26e04..a8f7dabdd6 100644 --- a/internal/testrunner/coveragereport.go +++ b/internal/testrunner/coveragereport.go @@ -75,8 +75,8 @@ func (tcd *testCoverageDetails) withTestResults(results []TestResult) *testCover // WriteCoverage function calculates test coverage for the given package. // It requires to execute tests for all data streams (same test type), so the coverage can be calculated properly. -func WriteCoverage(packageRootPath, packageName, packageType string, testType TestType, results []TestResult, format string) error { - report, err := createCoverageReport(packageRootPath, packageName, packageType, testType, results, format) +func WriteCoverage(workDir, packageRootPath, packageName, packageType string, testType TestType, results []TestResult, format string) error { + report, err := createCoverageReport(packageRootPath, workDir, packageName, packageType, testType, results, format) if err != nil { return fmt.Errorf("can't create coverage report: %w", err) } @@ -84,15 +84,15 @@ func WriteCoverage(packageRootPath, packageName, packageType string, testType Te return fmt.Errorf("coverage not found for test type %s", testType) } - err = writeCoverageReportFile(report, packageName, string(testType)) + err = writeCoverageReportFile(workDir, report, packageName, string(testType)) if err != nil { return fmt.Errorf("can't write test coverage report file: %w", err) } return nil } -func createCoverageReport(packageRootPath, packageName, packageType string, testType TestType, results []TestResult, format string) (CoverageReport, error) { - details, err := collectTestCoverageDetails(packageRootPath, packageName, packageType, testType, results, format) +func createCoverageReport(packageRootPath, workDir, packageName, packageType string, testType TestType, results []TestResult, format string) (CoverageReport, error) { + details, err := collectTestCoverageDetails(packageRootPath, workDir, packageName, packageType, testType, results, format) if err != nil { return nil, fmt.Errorf("can't collect test coverage details: %w", err) } @@ -101,13 +101,13 @@ func createCoverageReport(packageRootPath, packageName, packageType string, test return details.coverage, nil } -func collectTestCoverageDetails(packageRootPath, packageName, packageType string, testType TestType, results []TestResult, format string) (*testCoverageDetails, error) { +func collectTestCoverageDetails(packageRootPath, workDir, packageName, packageType string, testType TestType, results []TestResult, format string) (*testCoverageDetails, error) { withoutTests, err := findDataStreamsWithoutTests(packageRootPath, testType) if err != nil { return nil, fmt.Errorf("can't find data streams without tests: %w", err) } - emptyCoverage, err := GenerateBasePackageCoverageReport(packageName, packageRootPath, format) + emptyCoverage, err := GenerateBasePackageCoverageReport(packageName, workDir, packageRootPath, format) if err != nil { return nil, fmt.Errorf("can't generate initial base coverage report: %w", err) } @@ -177,8 +177,8 @@ func verifyTestExpected(packageRootPath string, dataStreamName string, testType return true, nil } -func writeCoverageReportFile(report CoverageReport, packageName, testType string) error { - dest, err := testCoverageReportsDir() +func writeCoverageReportFile(workDir string, report CoverageReport, packageName, testType string) error { + dest, err := testCoverageReportsDir(workDir) if err != nil { return fmt.Errorf("could not determine test coverage reports folder: %w", err) } @@ -205,8 +205,8 @@ func writeCoverageReportFile(report CoverageReport, packageName, testType string return nil } -func testCoverageReportsDir() (string, error) { - buildDir, err := builder.BuildDirectory() +func testCoverageReportsDir(workDir string) (string, error) { + buildDir, err := builder.BuildDirectory(workDir) if err != nil { return "", fmt.Errorf("locating build directory failed: %w", err) } diff --git a/internal/testrunner/coveragereport_test.go b/internal/testrunner/coveragereport_test.go index 6c70c225ca..4d35a794f7 100644 --- a/internal/testrunner/coveragereport_test.go +++ b/internal/testrunner/coveragereport_test.go @@ -86,7 +86,7 @@ func TestCreateCoverageReport(t *testing.T) { for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - report, err := createCoverageReport(tt.rootPath, tt.packageName, tt.packageType, tt.testType, tt.results, tt.coverageFormat) + report, err := createCoverageReport(tt.rootPath, workDir, tt.packageName, tt.packageType, tt.testType, tt.results, tt.coverageFormat) require.NoError(t, err) assert.Equal(t, tt.expected, report) }) diff --git a/internal/testrunner/report_output.go b/internal/testrunner/report_output.go index 7af7468a55..1eb0ae495d 100644 --- a/internal/testrunner/report_output.go +++ b/internal/testrunner/report_output.go @@ -12,7 +12,7 @@ import ( type TestReportOutput string // ReportOutputFunc defines the report writer function. -type ReportOutputFunc func(pkg, report string, testType TestType, format TestReportFormat) error +type ReportOutputFunc func(pkg, workDir, report string, testType TestType, format TestReportFormat) error var reportOutputs = map[TestReportOutput]ReportOutputFunc{} @@ -22,11 +22,11 @@ func RegisterReporterOutput(name TestReportOutput, outputFunc ReportOutputFunc) } // WriteReport delegates writing of test results to the registered test report output -func WriteReport(pkg string, testType TestType, name TestReportOutput, report string, format TestReportFormat) error { +func WriteReport(pkg string, workDir string, testType TestType, name TestReportOutput, report string, format TestReportFormat) error { outputFunc, defined := reportOutputs[name] if !defined { return fmt.Errorf("unregistered test report output: %s", name) } - return outputFunc(pkg, report, testType, format) + return outputFunc(pkg, workDir, report, testType, format) } diff --git a/internal/testrunner/reporters/outputs/file.go b/internal/testrunner/reporters/outputs/file.go index 4588357e56..4af0eee0a8 100644 --- a/internal/testrunner/reporters/outputs/file.go +++ b/internal/testrunner/reporters/outputs/file.go @@ -25,8 +25,8 @@ const ( ReportOutputFile testrunner.TestReportOutput = "file" ) -func reportToFile(pkg, report string, testType testrunner.TestType, format testrunner.TestReportFormat) error { - dest, err := testReportsDir() +func reportToFile(pkg, workDir string, report string, testType testrunner.TestType, format testrunner.TestReportFormat) error { + dest, err := testReportsDir(workDir) if err != nil { return fmt.Errorf("could not determine test reports folder: %w", err) } @@ -54,8 +54,8 @@ func reportToFile(pkg, report string, testType testrunner.TestType, format testr } // testReportsDir returns the location of the directory to store test reports. -func testReportsDir() (string, error) { - buildDir, err := builder.BuildDirectory() +func testReportsDir(workDir string) (string, error) { + buildDir, err := builder.BuildDirectory(workDir) if err != nil { return "", fmt.Errorf("locating build directory failed: %w", err) } diff --git a/internal/testrunner/reporters/outputs/stdout.go b/internal/testrunner/reporters/outputs/stdout.go index 4cb3d11d75..a0f01f16ee 100644 --- a/internal/testrunner/reporters/outputs/stdout.go +++ b/internal/testrunner/reporters/outputs/stdout.go @@ -19,7 +19,7 @@ const ( ReportOutputSTDOUT testrunner.TestReportOutput = "stdout" ) -func reportToSTDOUT(pkg, report string, _ testrunner.TestType, _ testrunner.TestReportFormat) error { +func reportToSTDOUT(pkg, _, report string, _ testrunner.TestType, _ testrunner.TestReportFormat) error { fmt.Printf("--- Test results for package: %s - START ---\n", pkg) fmt.Println(report) fmt.Printf("--- Test results for package: %s - END ---\n", pkg) diff --git a/internal/testrunner/runners/asset/runner.go b/internal/testrunner/runners/asset/runner.go index 93f90c3508..179d19d94d 100644 --- a/internal/testrunner/runners/asset/runner.go +++ b/internal/testrunner/runners/asset/runner.go @@ -19,6 +19,7 @@ const ( ) type runner struct { + workDir string packageRootPath string kibanaClient *kibana.Client globalTestConfig testrunner.GlobalRunnerTestConfig @@ -28,6 +29,7 @@ type runner struct { } type AssetTestRunnerOptions struct { + WorkDir string PackageRootPath string KibanaClient *kibana.Client GlobalTestConfig testrunner.GlobalRunnerTestConfig @@ -38,6 +40,7 @@ type AssetTestRunnerOptions struct { func NewAssetTestRunner(options AssetTestRunnerOptions) *runner { runner := runner{ + workDir: options.WorkDir, packageRootPath: options.PackageRootPath, kibanaClient: options.KibanaClient, globalTestConfig: options.GlobalTestConfig, @@ -68,6 +71,7 @@ func (r *runner) GetTests(ctx context.Context) ([]testrunner.Tester, error) { _, pkg := filepath.Split(r.packageRootPath) testers := []testrunner.Tester{ NewAssetTester(AssetTesterOptions{ + WorkDir: r.workDir, PackageRootPath: r.packageRootPath, KibanaClient: r.kibanaClient, TestFolder: testrunner.TestFolder{Package: pkg}, diff --git a/internal/testrunner/runners/asset/tester.go b/internal/testrunner/runners/asset/tester.go index b0eabb811a..a5b1eea55d 100644 --- a/internal/testrunner/runners/asset/tester.go +++ b/internal/testrunner/runners/asset/tester.go @@ -20,6 +20,7 @@ import ( type tester struct { testFolder testrunner.TestFolder + workDir string packageRootPath string kibanaClient *kibana.Client resourcesManager *resources.Manager @@ -31,6 +32,7 @@ type tester struct { type AssetTesterOptions struct { TestFolder testrunner.TestFolder + WorkDir string PackageRootPath string KibanaClient *kibana.Client GlobalTestConfig testrunner.GlobalRunnerTestConfig @@ -42,6 +44,7 @@ type AssetTesterOptions struct { func NewAssetTester(options AssetTesterOptions) *tester { tester := tester{ testFolder: options.TestFolder, + workDir: options.WorkDir, packageRootPath: options.PackageRootPath, kibanaClient: options.KibanaClient, globalTestConfig: options.GlobalTestConfig, @@ -84,6 +87,7 @@ func (r *tester) Run(ctx context.Context) ([]testrunner.TestResult, error) { func (r *tester) resources(installedPackage bool) resources.Resources { return resources.Resources{ &resources.FleetPackage{ + WorkDir: r.workDir, PackageRootPath: r.packageRootPath, Absent: !installedPackage, Force: installedPackage, // Force re-installation, in case there are code changes in the same package version. @@ -167,7 +171,7 @@ func (r *tester) run(ctx context.Context) ([]testrunner.TestResult, error) { } result := tr[0] if r.withCoverage && e.SourcePath != "" { - result.Coverage, err = testrunner.GenerateBaseFileCoverageReport(rc.CoveragePackageName(), e.SourcePath, r.coverageType, true) + result.Coverage, err = testrunner.GenerateBaseFileCoverageReport(rc.CoveragePackageName(), r.workDir, e.SourcePath, r.coverageType, true) if err != nil { tr, _ = rc.WithError(testrunner.ErrTestCaseFailed{ Reason: "could not generate test coverage", diff --git a/internal/testrunner/runners/pipeline/coverage.go b/internal/testrunner/runners/pipeline/coverage.go index f72f8c5715..92602ff42f 100644 --- a/internal/testrunner/runners/pipeline/coverage.go +++ b/internal/testrunner/runners/pipeline/coverage.go @@ -40,7 +40,7 @@ func getPipelineCoverage(pkgName string, options PipelineTesterOptions, pipeline // and a default.yml pipeline). basePath := filepath.Dir(options.PackageRootPath) - repositoryRootDir, err := files.FindRepositoryRootDirectory() + repositoryRootDir, err := files.FindRepositoryRootDirectory(options.WorkDir) if err != nil { return nil, err } diff --git a/internal/testrunner/runners/pipeline/runner.go b/internal/testrunner/runners/pipeline/runner.go index f556f67323..3e67464483 100644 --- a/internal/testrunner/runners/pipeline/runner.go +++ b/internal/testrunner/runners/pipeline/runner.go @@ -23,6 +23,7 @@ const ( ) type runner struct { + workDir string packageRootPath string profile *profile.Profile esAPI *elasticsearch.API @@ -40,6 +41,7 @@ type runner struct { } type PipelineTestRunnerOptions struct { + WorkDir string Profile *profile.Profile PackageRootPath string API *elasticsearch.API @@ -66,6 +68,7 @@ func NewPipelineTestRunner(options PipelineTestRunnerOptions) *runner { deferCleanup: options.DeferCleanup, globalTestConfig: options.GlobalTestConfig, repositoryRoot: options.RepositoryRoot, + workDir: options.WorkDir, } return &runner } @@ -133,6 +136,7 @@ func (r *runner) GetTests(ctx context.Context) ([]testrunner.Tester, error) { for _, caseFile := range testCaseFiles { t, err := NewPipelineTester(PipelineTesterOptions{ TestFolder: folder, + WorkDir: r.workDir, PackageRootPath: r.packageRootPath, GenerateTestResult: r.generateTestResult, WithCoverage: r.withCoverage, diff --git a/internal/testrunner/runners/pipeline/tester.go b/internal/testrunner/runners/pipeline/tester.go index ea96741609..6cad312940 100644 --- a/internal/testrunner/runners/pipeline/tester.go +++ b/internal/testrunner/runners/pipeline/tester.go @@ -37,6 +37,7 @@ import ( var serverlessDisableCompareResults = environment.WithElasticPackagePrefix("SERVERLESS_PIPELINE_TEST_DISABLE_COMPARE_RESULTS") type tester struct { + workDir string profile *profile.Profile deferCleanup time.Duration esAPI *elasticsearch.API @@ -58,6 +59,7 @@ type tester struct { } type PipelineTesterOptions struct { + WorkDir string Profile *profile.Profile DeferCleanup time.Duration API *elasticsearch.API @@ -77,6 +79,7 @@ func NewPipelineTester(options PipelineTesterOptions) (*tester, error) { } r := tester{ + workDir: options.WorkDir, profile: options.Profile, packageRootPath: options.PackageRootPath, esAPI: options.API, @@ -347,7 +350,7 @@ func (r *tester) runTestCase(ctx context.Context, testCaseFile string, dsPath st fields.WithNumericKeywordFields(tc.config.NumericKeywordFields), fields.WithStringNumberFields(tc.config.StringNumberFields), ) - fieldsValidator, err := fields.CreateValidatorForDirectory(dsPath, validatorOptions...) + fieldsValidator, err := fields.CreateValidatorForDirectory(r.workDir, dsPath, validatorOptions...) if err != nil { return rc.WithErrorf("creating fields validator for data stream failed (path: %s, test case file: %s): %w", dsPath, testCaseFile, err) } diff --git a/internal/testrunner/runners/policy/runner.go b/internal/testrunner/runners/policy/runner.go index 0f8166981f..f869735de9 100644 --- a/internal/testrunner/runners/policy/runner.go +++ b/internal/testrunner/runners/policy/runner.go @@ -23,6 +23,7 @@ const ( ) type runner struct { + workDir string packageRootPath string kibanaClient *kibana.Client @@ -43,6 +44,7 @@ type runner struct { var _ testrunner.TestRunner = new(runner) type PolicyTestRunnerOptions struct { + WorkDir string KibanaClient *kibana.Client PackageRootPath string DataStreams []string @@ -56,6 +58,7 @@ type PolicyTestRunnerOptions struct { func NewPolicyTestRunner(options PolicyTestRunnerOptions) *runner { runner := runner{ + workDir: options.WorkDir, packageRootPath: options.PackageRootPath, kibanaClient: options.KibanaClient, dataStreams: options.DataStreams, @@ -140,6 +143,7 @@ func (r *runner) GetTests(ctx context.Context) ([]testrunner.Tester, error) { } for _, test := range tests { testers = append(testers, NewPolicyTester(PolicyTesterOptions{ + WorkDir: r.workDir, PackageRootPath: r.packageRootPath, TestFolder: folder, KibanaClient: r.kibanaClient, @@ -161,6 +165,7 @@ func (r *runner) Type() testrunner.TestType { func (r *runner) setupSuite(ctx context.Context, manager *resources.Manager) (cleanup func(ctx context.Context) error, err error) { packageResource := resources.FleetPackage{ + WorkDir: r.workDir, PackageRootPath: r.packageRootPath, RepositoryRoot: r.repositoryRoot, } diff --git a/internal/testrunner/runners/policy/tester.go b/internal/testrunner/runners/policy/tester.go index 40f93c0894..1885d58abb 100644 --- a/internal/testrunner/runners/policy/tester.go +++ b/internal/testrunner/runners/policy/tester.go @@ -19,6 +19,7 @@ import ( type tester struct { testFolder testrunner.TestFolder + workDir string packageRootPath string kibanaClient *kibana.Client testPath string @@ -34,6 +35,7 @@ type tester struct { var _ testrunner.Tester = new(tester) type PolicyTesterOptions struct { + WorkDir string TestFolder testrunner.TestFolder TestPath string KibanaClient *kibana.Client @@ -46,6 +48,7 @@ type PolicyTesterOptions struct { func NewPolicyTester(options PolicyTesterOptions) *tester { tester := tester{ + workDir: options.WorkDir, kibanaClient: options.KibanaClient, testFolder: options.TestFolder, packageRootPath: options.PackageRootPath, @@ -143,7 +146,7 @@ func (r *tester) runTest(ctx context.Context, manager *resources.Manager, testPa } if r.withCoverage { - coverage, err := generateCoverageReport(result.CoveragePackageName(), r.packageRootPath, r.testFolder.DataStream, r.coverageType) + coverage, err := generateCoverageReport(result.CoveragePackageName(), r.workDir, r.packageRootPath, r.testFolder.DataStream, r.coverageType) if err != nil { return result.WithErrorf("coverage report generation failed: %w", err) } @@ -159,7 +162,7 @@ func (r *tester) runTest(ctx context.Context, manager *resources.Manager, testPa // generateCoverageReport generates a coverage report that includes the manifests and template files in the package or data stream. // TODO: For manifests, mark as covered only the variables used. // TODO: For templates, mark as covered only the parts used, but this requires introspection in handlebars. -func generateCoverageReport(pkgName, rootPath, dataStream, coverageType string) (testrunner.CoverageReport, error) { +func generateCoverageReport(pkgName, workDir, rootPath, dataStream, coverageType string) (testrunner.CoverageReport, error) { dsPattern := "*" if dataStream != "" { dsPattern = dataStream @@ -173,7 +176,7 @@ func generateCoverageReport(pkgName, rootPath, dataStream, coverageType string) filepath.Join(rootPath, "data_stream", dsPattern, "agent", "stream", "*.yml.hbs"), } - return testrunner.GenerateBaseFileCoverageReportGlob(pkgName, patterns, coverageType, true) + return testrunner.GenerateBaseFileCoverageReportGlob(pkgName, workDir, patterns, coverageType, true) } func testNameFromPath(path string) string { diff --git a/internal/testrunner/runners/static/runner.go b/internal/testrunner/runners/static/runner.go index 6c15670e79..e8b8c4237d 100644 --- a/internal/testrunner/runners/static/runner.go +++ b/internal/testrunner/runners/static/runner.go @@ -22,6 +22,7 @@ const ( ) type runner struct { + workDir string packageRootPath string failOnMissingTests bool dataStreams []string @@ -31,6 +32,7 @@ type runner struct { } type StaticTestRunnerOptions struct { + WorkDir string PackageRootPath string FailOnMissingTests bool DataStreams []string @@ -41,6 +43,7 @@ type StaticTestRunnerOptions struct { func NewStaticTestRunner(options StaticTestRunnerOptions) *runner { runner := runner{ + workDir: options.WorkDir, packageRootPath: options.PackageRootPath, failOnMissingTests: options.FailOnMissingTests, dataStreams: options.DataStreams, @@ -98,6 +101,7 @@ func (r *runner) GetTests(ctx context.Context) ([]testrunner.Tester, error) { var testers []testrunner.Tester for _, t := range tests { testers = append(testers, NewStaticTester(StaticTesterOptions{ + WorkDir: r.workDir, PackageRootPath: r.packageRootPath, TestFolder: t, GlobalTestConfig: r.globalTestConfig, diff --git a/internal/testrunner/runners/static/tester.go b/internal/testrunner/runners/static/tester.go index 4e23d87274..6125838390 100644 --- a/internal/testrunner/runners/static/tester.go +++ b/internal/testrunner/runners/static/tester.go @@ -22,6 +22,7 @@ import ( type tester struct { testFolder testrunner.TestFolder + workDir string packageRootPath string globalTestConfig testrunner.GlobalRunnerTestConfig withCoverage bool @@ -29,6 +30,7 @@ type tester struct { } type StaticTesterOptions struct { + WorkDir string TestFolder testrunner.TestFolder PackageRootPath string GlobalTestConfig testrunner.GlobalRunnerTestConfig @@ -39,6 +41,7 @@ type StaticTesterOptions struct { func NewStaticTester(options StaticTesterOptions) *tester { runner := tester{ testFolder: options.TestFolder, + workDir: options.WorkDir, packageRootPath: options.PackageRootPath, globalTestConfig: options.GlobalTestConfig, withCoverage: options.WithCoverage, @@ -149,7 +152,7 @@ func (r tester) verifySampleEvent(pkgManifest *packages.PackageManifest) []testr } if r.withCoverage { - coverage, err := testrunner.GenerateBaseFileCoverageReport(resultComposer.CoveragePackageName(), sampleEventPath, r.coverageType, true) + coverage, err := testrunner.GenerateBaseFileCoverageReport(resultComposer.CoveragePackageName(), r.workDir, sampleEventPath, r.coverageType, true) if err != nil { results, _ := resultComposer.WithErrorf("coverage report generation failed: %w", err) return results @@ -162,7 +165,7 @@ func (r tester) verifySampleEvent(pkgManifest *packages.PackageManifest) []testr results, _ := resultComposer.WithError(err) return results } - fieldsValidator, err := fields.CreateValidatorForDirectory(filepath.Dir(sampleEventPath), + fieldsValidator, err := fields.CreateValidatorForDirectory(r.workDir, filepath.Dir(sampleEventPath), fields.WithSpecVersion(pkgManifest.SpecVersion), fields.WithDefaultNumericConversion(), fields.WithExpectedDatasets(expectedDatasets), diff --git a/internal/testrunner/runners/system/runner.go b/internal/testrunner/runners/system/runner.go index 669089f125..b55d1742ea 100644 --- a/internal/testrunner/runners/system/runner.go +++ b/internal/testrunner/runners/system/runner.go @@ -25,6 +25,7 @@ import ( type runner struct { profile *profile.Profile + workDir string repositoryRoot *os.Root packageRootPath string kibanaClient *kibana.Client @@ -55,6 +56,7 @@ var _ testrunner.TestRunner = new(runner) type SystemTestRunnerOptions struct { Profile *profile.Profile + WorkDir string PackageRootPath string RepositoryRoot *os.Root KibanaClient *kibana.Client @@ -82,6 +84,7 @@ type SystemTestRunnerOptions struct { func NewSystemTestRunner(options SystemTestRunnerOptions) *runner { r := runner{ + workDir: options.WorkDir, packageRootPath: options.PackageRootPath, kibanaClient: options.KibanaClient, esAPI: options.API, @@ -250,6 +253,7 @@ func (r *runner) GetTests(ctx context.Context) ([]testrunner.Tester, error) { logger.Debugf("System runner: data stream %q config file %q variant %q", t.DataStream, config, variant) tester, err := NewSystemTester(SystemTesterOptions{ Profile: r.profile, + WorkDir: r.workDir, PackageRootPath: r.packageRootPath, KibanaClient: r.kibanaClient, API: r.esAPI, @@ -286,6 +290,7 @@ func (r *runner) Type() testrunner.TestType { func (r *runner) resources(opts resourcesOptions) resources.Resources { return resources.Resources{ &resources.FleetPackage{ + WorkDir: r.workDir, PackageRootPath: r.packageRootPath, Absent: !opts.installedPackage, Force: opts.installedPackage, // Force re-installation, in case there are code changes in the same package version. diff --git a/internal/testrunner/runners/system/tester.go b/internal/testrunner/runners/system/tester.go index e8c4028885..53f974bcc1 100644 --- a/internal/testrunner/runners/system/tester.go +++ b/internal/testrunner/runners/system/tester.go @@ -195,6 +195,7 @@ var validationMethods = map[string]fieldValidationMethod{ type tester struct { profile *profile.Profile + workDir string testFolder testrunner.TestFolder packageRootPath string generateTestResult bool @@ -241,6 +242,7 @@ type tester struct { type SystemTesterOptions struct { Profile *profile.Profile + WorkDir string TestFolder testrunner.TestFolder PackageRootPath string GenerateTestResult bool @@ -265,6 +267,7 @@ type SystemTesterOptions struct { func NewSystemTester(options SystemTesterOptions) (*tester, error) { r := tester{ profile: options.Profile, + workDir: options.WorkDir, testFolder: options.TestFolder, packageRootPath: options.PackageRootPath, generateTestResult: options.GenerateTestResult, @@ -454,6 +457,7 @@ type resourcesOptions struct { func (r *tester) createAgentOptions(policyName, deployerName string) agentdeployer.FactoryOptions { return agentdeployer.FactoryOptions{ Profile: r.profile, + WorkDir: r.workDir, PackageRootPath: r.packageRootPath, DataStreamRootPath: r.dataStreamPath, DevDeployDir: DevDeployDir, @@ -1633,7 +1637,7 @@ func (r *tester) validateTestScenario(ctx context.Context, result *testrunner.Re logger.Warn("Validation for packages using OpenTelemetry Collector input is experimental") } - fieldsValidator, err := fields.CreateValidatorForDirectory(r.dataStreamPath, + fieldsValidator, err := fields.CreateValidatorForDirectory(r.workDir, r.dataStreamPath, fields.WithSpecVersion(r.pkgManifest.SpecVersion), fields.WithNumericKeywordFields(config.NumericKeywordFields), fields.WithStringNumberFields(config.StringNumberFields), @@ -2227,7 +2231,7 @@ func (r *tester) checkTransforms(ctx context.Context, config *testConfig, pkgMan } transformRootPath := filepath.Dir(transform.Path) - fieldsValidator, err := fields.CreateValidatorForDirectory(transformRootPath, + fieldsValidator, err := fields.CreateValidatorForDirectory(r.workDir, transformRootPath, fields.WithSpecVersion(pkgManifest.SpecVersion), fields.WithNumericKeywordFields(config.NumericKeywordFields), fields.WithEnabledImportAllECSSChema(true), @@ -2623,5 +2627,5 @@ func (r *tester) generateCoverageReport(pkgName string) (testrunner.CoverageRepo filepath.Join(r.packageRootPath, "data_stream", dsPattern, "fields", "*.yml"), } - return testrunner.GenerateBaseFileCoverageReportGlob(pkgName, patterns, r.coverageType, true) + return testrunner.GenerateBaseFileCoverageReportGlob(r.workDir, pkgName, patterns, r.coverageType, true) } diff --git a/tools/tools.go b/tools/tools.go index 0e68450929..162756e2dd 100644 --- a/tools/tools.go +++ b/tools/tools.go @@ -9,6 +9,7 @@ package tools // Add dependencies on tools. // https://github.com/golang/go/wiki/Modules#how-can-i-track-tool-dependencies-for-a-module import ( + _ "github.com/ashanbrown/forbidigo/v2" _ "github.com/boumenot/gocover-cobertura" _ "golang.org/x/tools/cmd/goimports" _ "gotest.tools/gotestsum" From 6ee051b81843f1fdb7299d54d0b705622eb53802 Mon Sep 17 00:00:00 2001 From: Jaime Soriano Pastor Date: Tue, 11 Nov 2025 15:08:28 +0100 Subject: [PATCH 2/3] Fix creation of build directory when it doesn't exist --- internal/builder/packages.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/internal/builder/packages.go b/internal/builder/packages.go index e2b29b6025..1ef639a95d 100644 --- a/internal/builder/packages.go +++ b/internal/builder/packages.go @@ -127,7 +127,7 @@ func buildPackagesRootDirectory(workDir string) (string, error) { return "", fmt.Errorf("can't locate build directory: %w", err) } if !found { - buildDir, err = createBuildDirectory(builtPackagesDir) + buildDir, err = createBuildDirectory(workDir, builtPackagesDir) if err != nil { return "", fmt.Errorf("can't create new build directory: %w", err) } From 88a986ce0d33aa8c5f96a08cd5b4b5421125d07d Mon Sep 17 00:00:00 2001 From: Jaime Soriano Pastor Date: Tue, 11 Nov 2025 17:35:14 +0100 Subject: [PATCH 3/3] Compose actions instead of commands --- cmd/check.go | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/cmd/check.go b/cmd/check.go index d1b20c1d4a..45a12722f5 100644 --- a/cmd/check.go +++ b/cmd/check.go @@ -23,9 +23,10 @@ func setupCheckCommand() *cobraext.Command { Long: checkLongDescription, Args: cobra.NoArgs, RunE: func(cmd *cobra.Command, args []string) error { - err := cobraext.ComposeCommands(cmd, args, - setupLintCommand(), - setupBuildCommand(), + err := cobraext.ComposeCommandActions(cmd, args, + lintCommandAction, + validateSourceCommandAction, + buildCommandAction, ) if err != nil { return fmt.Errorf("checking package failed: %w", err)