diff --git a/slug.go b/slug.go index 09d8fbe..df33063 100644 --- a/slug.go +++ b/slug.go @@ -158,6 +158,13 @@ func (p *Packer) Pack(src string, w io.Writer) (*Meta, error) { ignoreRules = parseIgnoreFile(src) } + if !filepath.IsAbs(src) { + src, err = filepath.Abs(src) + if err != nil { + return nil, fmt.Errorf("something went super wrong root") + } + } + // Walk the tree of files. err = filepath.Walk(src, p.packWalkFn(src, src, src, tarW, meta, ignoreRules)) if err != nil { @@ -183,6 +190,19 @@ func (p *Packer) packWalkFn(root, src, dst string, tarW *tar.Writer, meta *Meta, return err } + if !filepath.IsAbs(src) { + src, err = filepath.Abs(src) + if err != nil { + return fmt.Errorf("failed to get absolute path for src %q: %w", src, err) + } + } + + if !filepath.IsAbs(path) { + path, err = filepath.Abs(path) + if err != nil { + return fmt.Errorf("failed to get absolute path for file %q: %w", path, err) + } + } // Get the relative path from the current src directory. subpath, err := filepath.Rel(src, path) if err != nil { diff --git a/slug_test.go b/slug_test.go index 44b6878..6aa7a47 100644 --- a/slug_test.go +++ b/slug_test.go @@ -55,6 +55,40 @@ func TestPack_rootIsSymlink(t *testing.T) { } } +func TestPack_absoluteSrcRelativeSymlinks(t *testing.T) { + var path string + + // In instances we run within CI, we want to fetch + // the absolute path where our test is located + if workDir, ok := os.LookupEnv("GITHUB_WORKSPACE"); ok { + path = workDir + } else { + homeDir, err := os.UserHomeDir() + if err != nil { + t.Fatalf("Could not read home dir: %v", err) + } + // !! Ugly code alert: This tests assumes the repository + // lives in $HOME/hashicorp/go-slug. You may need to change + // this according to your needs + path = filepath.Join(homeDir, "hashicorp/go-slug") + } + + // One last check, if this variable is empty we'll error + // since we need the absolute path for the source + if path == "" { + t.Fatal("Home directory could not be determined") + } + + path = filepath.Join(path, "testdata/archive-dir-absolute/dev") + slug := bytes.NewBuffer(nil) + _, err := Pack(path, slug, true) + if err != nil { + // We simply want to ensure paths can be resolved while + // traversing the source directory + t.Fatalf("err: %v", err) + } +} + func TestPackWithoutIgnoring(t *testing.T) { slug := bytes.NewBuffer(nil) @@ -1088,8 +1122,8 @@ func assertArchiveFixture(t *testing.T, slug *bytes.Buffer, got *Meta) { } if hdr.Name == "example.tf" { - if hdr.Typeflag != tar.TypeSymlink { - t.Fatalf("expected symlink file 'example.tf'") + if hdr.Typeflag != tar.TypeReg { + t.Fatalf("expected symlink to be dereferenced 'example.tf'") } externalTargetFound = true } @@ -1100,9 +1134,9 @@ func assertArchiveFixture(t *testing.T, slug *bytes.Buffer, got *Meta) { t.Fatal("expected to find symlink") } - // Make sure we saw and handled a nested symlink + // Make sure we saw and handled a dereferenced symlink if !externalTargetFound { - t.Fatal("expected to find nested symlink") + t.Fatal("expected to find dereferenced symlink") } // Make sure the .git directory is ignored diff --git a/testdata/archive-dir-absolute/_common/extra-files/bar.sh b/testdata/archive-dir-absolute/_common/extra-files/bar.sh new file mode 100644 index 0000000..5b0e87e --- /dev/null +++ b/testdata/archive-dir-absolute/_common/extra-files/bar.sh @@ -0,0 +1,2 @@ +#!/usr/bin/env bash +echo "bar" diff --git a/testdata/archive-dir-absolute/_common/extra-files/foo.sh b/testdata/archive-dir-absolute/_common/extra-files/foo.sh new file mode 100644 index 0000000..af85c95 --- /dev/null +++ b/testdata/archive-dir-absolute/_common/extra-files/foo.sh @@ -0,0 +1,2 @@ +#!/usr/bin/env bash +echo "foo" diff --git a/testdata/archive-dir-absolute/_common/locals.tf b/testdata/archive-dir-absolute/_common/locals.tf new file mode 100644 index 0000000..7324c9d --- /dev/null +++ b/testdata/archive-dir-absolute/_common/locals.tf @@ -0,0 +1,3 @@ +locals { + app = "service-01" +} diff --git a/testdata/archive-dir-absolute/_common/output.tf b/testdata/archive-dir-absolute/_common/output.tf new file mode 100644 index 0000000..94e8f35 --- /dev/null +++ b/testdata/archive-dir-absolute/_common/output.tf @@ -0,0 +1,7 @@ +locals { + files = fileset("${path.module}/extra-files", "*.sh") +} + +output "scripts" { + value = local.files +} diff --git a/testdata/archive-dir-absolute/_common/versions.tf b/testdata/archive-dir-absolute/_common/versions.tf new file mode 100644 index 0000000..c509258 --- /dev/null +++ b/testdata/archive-dir-absolute/_common/versions.tf @@ -0,0 +1,3 @@ +terraform { + required_version = "~> 1.2" +} diff --git a/testdata/archive-dir-absolute/dev/backend.tf b/testdata/archive-dir-absolute/dev/backend.tf new file mode 100644 index 0000000..3e1c863 --- /dev/null +++ b/testdata/archive-dir-absolute/dev/backend.tf @@ -0,0 +1,10 @@ +terraform { + remote "backend" { + hostname = "foobar.terraform.io" + organization = "hashicorp" + + workspaces { + name = "dev-service-02" + } + } +} diff --git a/testdata/archive-dir-absolute/dev/extra-files b/testdata/archive-dir-absolute/dev/extra-files new file mode 120000 index 0000000..6773dc5 --- /dev/null +++ b/testdata/archive-dir-absolute/dev/extra-files @@ -0,0 +1 @@ +../_common/extra-files \ No newline at end of file diff --git a/testdata/archive-dir-absolute/dev/locals.tf b/testdata/archive-dir-absolute/dev/locals.tf new file mode 120000 index 0000000..173668c --- /dev/null +++ b/testdata/archive-dir-absolute/dev/locals.tf @@ -0,0 +1 @@ +../_common/locals.tf \ No newline at end of file diff --git a/testdata/archive-dir-absolute/dev/output.tf b/testdata/archive-dir-absolute/dev/output.tf new file mode 120000 index 0000000..d597fae --- /dev/null +++ b/testdata/archive-dir-absolute/dev/output.tf @@ -0,0 +1 @@ +../_common/output.tf \ No newline at end of file diff --git a/testdata/archive-dir-absolute/dev/variables.tf b/testdata/archive-dir-absolute/dev/variables.tf new file mode 100644 index 0000000..ec9ce9d --- /dev/null +++ b/testdata/archive-dir-absolute/dev/variables.tf @@ -0,0 +1,4 @@ +locals { + env = "dev" + region = "us-east-2" +} diff --git a/testdata/archive-dir-absolute/dev/versions.tf b/testdata/archive-dir-absolute/dev/versions.tf new file mode 120000 index 0000000..08a39e4 --- /dev/null +++ b/testdata/archive-dir-absolute/dev/versions.tf @@ -0,0 +1 @@ +../_common/versions.tf \ No newline at end of file