Skip to content
Open
Show file tree
Hide file tree
Changes from 7 commits
Commits
Show all changes
44 commits
Select commit Hold shift + click to select a range
75dae97
improve comments for Link struct and its fields in linkedfiles.go
teresaromero Sep 24, 2025
83e13ad
refactor: enhance newLinkedFile function for better error handling an…
teresaromero Sep 24, 2025
9139bb2
test: add unit test for newLinkedFile function to validate link file …
teresaromero Sep 24, 2025
60672b2
decoupled repoRoot from lint cmd and docs
teresaromero Sep 25, 2025
211c7c9
update repository root handling across multiple components
teresaromero Sep 25, 2025
0b61910
standardize repository root handling across build, lint, and links ma…
teresaromero Sep 25, 2025
ce07ec3
ensure repository root is properly closed in multiple command actions…
teresaromero Sep 25, 2025
0deae99
add repoRoot parameter to build command action
teresaromero Sep 29, 2025
1fc643a
update linked file handling to use absolute paths and improve clarity
teresaromero Sep 29, 2025
6820b49
add copyright notice to packages_test.go file
teresaromero Sep 29, 2025
2c16cab
refactor linkedfiles_test.go to use os.MkdirAll for directory creation
teresaromero Sep 29, 2025
403527e
implement repository root handling in benchmark and install commands,…
teresaromero Sep 29, 2025
96d5129
read repoRoot at test runner cmd
teresaromero Sep 29, 2025
90ba403
refactor linkedfiles_test.go to use filepath.Join for constructing li…
teresaromero Sep 29, 2025
aeeee55
inject repoRoot to needed test options
teresaromero Sep 29, 2025
385fc89
Update data stream tests to include repoRoot parameter
teresaromero Sep 29, 2025
9edca9b
Ensure repoRoot is closed in all data stream test cases
teresaromero Sep 30, 2025
c60b836
Remove unnecessary directory change in createAndCheckDataStream function
teresaromero Sep 30, 2025
679c566
Merge branch 'main' into 2797-detach-repo-root
teresaromero Oct 6, 2025
ef3497f
refactor at copyLicenceTextFile to ensure license inside reporoot, re…
teresaromero Oct 6, 2025
1f591bf
Merge branch 'main' into 2797-detach-repo-root
teresaromero Oct 8, 2025
ec2a7e1
refactor linkefiles management to use relative paths and root
teresaromero Oct 9, 2025
169777f
revert linksDefinitionsFilePath from public to private
teresaromero Oct 9, 2025
9229664
add validation for RepoRoot in Options
teresaromero Oct 9, 2025
0436a37
clarify variable name for included file path in newLinkedFile function
teresaromero Oct 9, 2025
9793ffd
simplify checksum comparison logic in newLinkedFile function
teresaromero Oct 9, 2025
5d6ef55
refactor findRepositoryLicensePath to use repoRoot
teresaromero Oct 9, 2025
ecfeb9b
refactor copyLicenseTextFile to use repoRoot.Stat
teresaromero Oct 9, 2025
4412b0b
refactor FindPackageRoot and handle error on FindPackageRootFrom calls
teresaromero Oct 9, 2025
9b7a721
remove repoRoot.Write and Read
teresaromero Oct 9, 2025
091d117
Merge branch 'main' into 2797-detach-repo-root
teresaromero Oct 15, 2025
66274da
rename repoRoot to repositoryRoot for clarity
teresaromero Oct 15, 2025
5429121
fix: correct grammar in comments for license file handling
teresaromero Oct 15, 2025
b3e73ac
update copyLicenseTextFile function to improve clarity and error hand…
teresaromero Oct 15, 2025
563522f
enhance findRepositoryLicensePath function to check for empty license…
teresaromero Oct 15, 2025
bfe509e
improve path handling in TestFindRepositoryLicense and TestCopyLicen…
teresaromero Oct 15, 2025
59436db
rename test function and update comment for clarity
teresaromero Oct 15, 2025
248a704
remove unnecessary blank lines in test files for improved readability
teresaromero Oct 15, 2025
c74c6c8
rename PackageRoot to PackageRootPath for consistency across builder …
teresaromero Oct 15, 2025
68ed0d8
add repository root handling in benchmark and test runner commands
teresaromero Oct 15, 2025
54d8502
rename newLinkMap to newEmptyLinkMap and revert related functions to …
teresaromero Oct 15, 2025
3b32fcc
update findRepositoryLicensePath to use os.ReadFile and improve error…
teresaromero Oct 15, 2025
8af2c99
remove RepositoryRoot references from FleetAgentPolicy, rename RootPa…
teresaromero Oct 16, 2025
d08ed58
refactor copyLicenseTextFile to enforce absolute target license path …
teresaromero Oct 16, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 12 additions & 1 deletion cmd/build.go
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,17 @@ func buildCommandAction(cmd *cobra.Command, args []string) error {
}
}

repoRoot, err := files.FindRepositoryRoot()
if err != nil {
return fmt.Errorf("locating repository root failed: %w", err)
}
defer repoRoot.Close()

linksFilePath, err := docs.LinksDefinitionsFilePath(repoRoot)
if err != nil {
return fmt.Errorf("locating links file failed: %w", err)
}

packageRoot, err := packages.MustFindPackageRoot()
if err != nil {
return fmt.Errorf("locating package root failed: %w", err)
Expand All @@ -72,7 +83,7 @@ func buildCommandAction(cmd *cobra.Command, args []string) error {
}
logger.Debugf("Use build directory: %s", buildDir)

targets, err := docs.UpdateReadmes(packageRoot, buildDir)
targets, err := docs.UpdateReadmes(linksFilePath, packageRoot, buildDir)
if err != nil {
return fmt.Errorf("updating files failed: %w", err)
}
Expand Down
26 changes: 23 additions & 3 deletions cmd/links.go
Original file line number Diff line number Diff line change
Expand Up @@ -56,8 +56,14 @@ func linksCheckCommandAction(cmd *cobra.Command, args []string) error {
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
repoRoot, err := files.FindRepositoryRoot()
if err != nil {
return fmt.Errorf("finding repository root: %w", err)
}
defer repoRoot.Close()

linksFS, err := files.CreateLinksFSFromPath(pwd)
linksFS, err := files.CreateLinksFSFromPath(repoRoot, pwd)
if err != nil {
return fmt.Errorf("creating links filesystem failed: %w", err)
}
Expand Down Expand Up @@ -95,7 +101,14 @@ func linksUpdateCommandAction(cmd *cobra.Command, args []string) error {
return fmt.Errorf("reading current working directory failed: %w", err)
}

linksFS, err := files.CreateLinksFSFromPath(pwd)
// Find the repository root to create the links filesystem reference tied to the repository root
repoRoot, err := files.FindRepositoryRoot()
if err != nil {
return fmt.Errorf("finding repository root: %w", err)
}
defer repoRoot.Close()

linksFS, err := files.CreateLinksFSFromPath(repoRoot, pwd)
if err != nil {
return fmt.Errorf("creating links filesystem failed: %w", err)
}
Expand Down Expand Up @@ -135,7 +148,14 @@ func linksListCommandAction(cmd *cobra.Command, args []string) error {
return fmt.Errorf("reading current working directory failed: %w", err)
}

linksFS, err := files.CreateLinksFSFromPath(pwd)
// Find the repository root to create the links filesystem reference tied to the repository root
repoRoot, err := files.FindRepositoryRoot()
if err != nil {
return fmt.Errorf("finding repository root: %w", err)
}
defer repoRoot.Close()

linksFS, err := files.CreateLinksFSFromPath(repoRoot, pwd)
if err != nil {
return fmt.Errorf("creating links filesystem failed: %w", err)
}
Expand Down
15 changes: 14 additions & 1 deletion cmd/lint.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import (

"github.com/elastic/elastic-package/internal/cobraext"
"github.com/elastic/elastic-package/internal/docs"
"github.com/elastic/elastic-package/internal/files"
"github.com/elastic/elastic-package/internal/logger"
"github.com/elastic/elastic-package/internal/packages"
"github.com/elastic/elastic-package/internal/validation"
Expand Down Expand Up @@ -45,7 +46,19 @@ func setupLintCommand() *cobraext.Command {

func lintCommandAction(cmd *cobra.Command, args []string) error {
cmd.Println("Lint the package")
readmeFiles, err := docs.AreReadmesUpToDate()

repoRoot, err := files.FindRepositoryRoot()
if err != nil {
return fmt.Errorf("locating repository root failed: %w", err)
}
defer repoRoot.Close()

linksFilePath, err := docs.LinksDefinitionsFilePath(repoRoot)
if err != nil {
return fmt.Errorf("locating links file failed: %w", err)
}

readmeFiles, err := docs.AreReadmesUpToDate(linksFilePath)
if err != nil {
for _, f := range readmeFiles {
if !f.UpToDate {
Expand Down
43 changes: 27 additions & 16 deletions internal/builder/packages.go
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I have tried to link a fields file that includes fields with external: ecs and elastic-package fails to resolve these fields when building the package, with errors like:

Error: building package failed: invalid content found in built zip package: found 7 validation errors:
   1. file ".../github.com/elastic/integrations/build/packages/system-2.6.1.zip/data_stream/cpu/fields/agent.yml" is invalid: field cloud.account.id with external key defined ("ecs") but no _dev/build/build.yml found

I guess it is trying to read the build.yml file from the target directory instead of from the source directory. It only happens with linked files.

Not sure if the issue is introduced with the current PR, so we can handle this in a follow up, as you prefer.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

could you walk me through this test? i am not sure i understood correctly the operation here.

Create a .link file for ecs.yml of one package ?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This can be reproduced with the following commands, from the integrations repository:

mkdir packages/system/_dev/shared
mv packages/system/data_stream/cpu/fields/agent.yml packages/system/_dev/shared/agent.yml
echo ../../../_dev/shared/agent.yml > packages/system/data_stream/cpu/fields/agent.yml.link
elastic-package links update
elastic-package build -C packages/system

Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ var repositoryLicenseEnv = environment.WithElasticPackagePrefix("REPOSITORY_LICE
type BuildOptions struct {
PackageRoot string
BuildDir string
RepoRoot *os.Root

CreateZip bool
SignPackage bool
Expand Down Expand Up @@ -182,7 +183,8 @@ func BuildPackage(ctx context.Context, options BuildOptions) (string, error) {
}

logger.Debug("Copy license file if needed")
err = copyLicenseTextFile(filepath.Join(destinationDir, licenseTextFileName))
destinationLicenseFilePath := filepath.Join(destinationDir, licenseTextFileName)
err = copyLicenseTextFile(options.RepoRoot, destinationLicenseFilePath)
if err != nil {
return "", fmt.Errorf("copying license text file: %w", err)
}
Expand All @@ -205,7 +207,7 @@ func BuildPackage(ctx context.Context, options BuildOptions) (string, error) {
}

logger.Debug("Include linked files")
linksFS, err := files.CreateLinksFSFromPath(options.PackageRoot)
linksFS, err := files.CreateLinksFSFromPath(options.RepoRoot, options.PackageRoot)
if err != nil {
return "", fmt.Errorf("creating links filesystem failed: %w", err)
}
Expand Down Expand Up @@ -290,19 +292,23 @@ func signZippedPackage(options BuildOptions, zippedPackagePath string) error {
return nil
}

func copyLicenseTextFile(licensePath string) error {
_, err := os.Stat(licensePath)
if err == nil {
func copyLicenseTextFile(repoRoot *os.Root, licensePath string) error {
// if the given path exist, skip copying
if info, err := os.Stat(licensePath); err == nil && !info.IsDir() {
logger.Debug("License file in the package will be used")
return nil
}

// lookup for the license file in the repository
// default license name can be overridden by the user
repositoryLicenseTextFileName, userDefined := os.LookupEnv(repositoryLicenseEnv)
if !userDefined {
repositoryLicenseTextFileName = licenseTextFileName
}

sourceLicensePath, err := findRepositoryLicense(repositoryLicenseTextFileName)
path := filepath.Join(repoRoot.Name(), repositoryLicenseTextFileName)

sourceLicensePath, err := findRepositoryLicense(path)
if !userDefined && errors.Is(err, os.ErrNotExist) {
logger.Debug("No license text file is included in package")
return nil
Expand Down Expand Up @@ -341,17 +347,22 @@ func createBuildDirectory(dirs ...string) (string, error) {
return buildDir, nil
}

func findRepositoryLicense(licenseTextFileName string) (string, error) {
dir, err := files.FindRepositoryRootDirectory()
if err != nil {
return "", err
}

sourceFileName := filepath.Join(dir, licenseTextFileName)
_, err = os.Stat(sourceFileName)
if err != nil {
// findRepositoryLicense checks if a license file exists at the specified path.
// If the file exists, it returns the path; otherwise, it returns an error indicating
// that the repository license could not be found.
//
// Parameters:
//
// licensePath - the path to the license file.
//
// Returns:
//
// string - the license file path if found.
// error - an error if the license file does not exist.
func findRepositoryLicense(licensePath string) (string, error) {
if _, err := os.Stat(licensePath); err != nil {
return "", fmt.Errorf("failed to find repository license: %w", err)
}

return sourceFileName, nil
return licensePath, nil
}
122 changes: 122 additions & 0 deletions internal/builder/packages_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,122 @@
package builder

import (
"os"
"path/filepath"
"testing"

"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)

func TestFindRepositoryLicense_FileExists(t *testing.T) {
dir := t.TempDir()
licensePath := filepath.Join(dir, "LICENSE.txt")
err := os.WriteFile(licensePath, []byte("license content"), 0644)
require.NoError(t, err)

path, err := findRepositoryLicense(licensePath)
require.NoError(t, err)
assert.Equal(t, licensePath, path)
}

func TestFindRepositoryLicense_FileDoesNotExist(t *testing.T) {
dir := t.TempDir()
licensePath := filepath.Join(dir, "NON_EXISTENT_LICENSE.txt")

path, err := findRepositoryLicense(licensePath)
require.Error(t, err)
assert.Empty(t, path)
}
func TestCopyLicenseTextFile_UsesExistingLicenseFile(t *testing.T) {
dir := t.TempDir()
licensePath := filepath.Join(dir, "LICENSE.txt")
err := os.WriteFile(licensePath, []byte("existing license"), 0644)
require.NoError(t, err)

repoRoot, err := os.OpenRoot(t.TempDir())
require.NoError(t, err)
defer repoRoot.Close()

// Should not attempt to copy, just return nil
err = copyLicenseTextFile(repoRoot, licensePath)
assert.NoError(t, err)

// License file should remain unchanged
content, err := os.ReadFile(licensePath)
require.NoError(t, err)
assert.Equal(t, "existing license", string(content))
}

func TestCopyLicenseTextFile_CopiesFromRepo(t *testing.T) {
repoRoot, err := os.OpenRoot(t.TempDir())
require.NoError(t, err)
defer repoRoot.Close()

licensePath := filepath.Join(repoRoot.Name(), "LICENSE.txt")
err = os.WriteFile(licensePath, []byte("repo license"), 0644)
require.NoError(t, err)

destDir := t.TempDir()
destLicensePath := filepath.Join(destDir, "LICENSE.txt")

err = copyLicenseTextFile(repoRoot, destLicensePath)
assert.NoError(t, err)

content, err := os.ReadFile(destLicensePath)
require.NoError(t, err)
assert.Equal(t, "repo license", string(content))
}

func TestCopyLicenseTextFile_NoRepoLicense_ReturnsNil(t *testing.T) {
repoRoot, err := os.OpenRoot(t.TempDir())
require.NoError(t, err)
defer repoRoot.Close()

destDir := t.TempDir()
destLicensePath := filepath.Join(destDir, "LICENSE.txt")

err = copyLicenseTextFile(repoRoot, destLicensePath)
assert.NoError(t, err)

_, err = os.Stat(destLicensePath)
assert.True(t, os.IsNotExist(err))
}

func TestCopyLicenseTextFile_EnvOverridesLicenseName(t *testing.T) {
repoRoot, err := os.OpenRoot(t.TempDir())
require.NoError(t, err)
defer repoRoot.Close()

customLicenseName := "CUSTOM_LICENSE.txt"
customLicensePath := filepath.Join(repoRoot.Name(), customLicenseName)
err = os.WriteFile(customLicensePath, []byte("custom license"), 0644)
require.NoError(t, err)

destDir := t.TempDir()
destLicensePath := filepath.Join(destDir, "LICENSE.txt")

t.Setenv(repositoryLicenseEnv, customLicenseName)
err = copyLicenseTextFile(repoRoot, destLicensePath)
assert.NoError(t, err)

content, err := os.ReadFile(destLicensePath)
require.NoError(t, err)
assert.Equal(t, "custom license", string(content))
}

func TestCopyLicenseTextFile_ErrorCopyingFile(t *testing.T) {
repoRoot, err := os.OpenRoot(t.TempDir())
require.NoError(t, err)
defer repoRoot.Close()

licensePath := filepath.Join(repoRoot.Name(), "LICENSE.txt")
err = os.WriteFile(licensePath, []byte("repo license"), 0644)
require.NoError(t, err)

// Use a destination path that is a directory, so sh.Copy should fail
destDir := t.TempDir()

err = copyLicenseTextFile(repoRoot, destDir)
assert.Error(t, err)
}
Loading