Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
2 changes: 1 addition & 1 deletion builder/build/apppacktoml.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,8 @@ import (
"os"
"strings"

"github.com/apppackio/codebuild-image/builder/filesystem"
"github.com/BurntSushi/toml"
"github.com/apppackio/codebuild-image/builder/filesystem"
"github.com/rs/zerolog/log"
)

Expand Down
6 changes: 6 additions & 0 deletions builder/build/build.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import (
"sync"

"github.com/apppackio/codebuild-image/builder/containers"
"github.com/apppackio/codebuild-image/builder/filesystem"
"github.com/docker/docker/api/types/container"
"github.com/google/go-containerregistry/pkg/crane"
cp "github.com/otiai10/copy"
Expand Down Expand Up @@ -121,6 +122,11 @@ func (b *Build) RunBuild() error {
if err = cp.Copy(logFile.Name(), "build.log"); err != nil {
return err
}
// Copy the apppack.toml file to the default location if it was read from a custom location
if err = filesystem.CopyAppPackTomlToDefault(); err != nil {
b.Log().Warn().Err(err).Msg("Failed to copy apppack.toml to default location for artifact archival")
// Don't fail the build if we can't copy the file, just warn
}
return b.state.WriteCommitTxt()
}

Expand Down
24 changes: 22 additions & 2 deletions builder/filesystem/filesystem.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,10 @@ import (
"github.com/spf13/afero"
)

const envFileFilename = "env.json"
const (
envFileFilename = "env.json"
DefaultAppPackTomlFilename = "apppack.toml"
)

type State interface {
CreateIfNotExists() error
Expand Down Expand Up @@ -181,9 +184,26 @@ func (f *FileState) WriteJsonToFile(filename string, v interface{}) error {
}

func GetAppPackTomlFilename() string {
filename := "apppack.toml"
filename := DefaultAppPackTomlFilename
if envFile := os.Getenv("APPPACK_TOML"); envFile != "" {
filename = envFile
}
return filename
}

// CopyAppPackTomlToDefault copies the apppack.toml file from a custom location to the default location
// This is needed for artifact archival when APPPACK_TOML env var is used to specify a custom location
// Returns nil if the file is already at the default location or if copy succeeds
func CopyAppPackTomlToDefault() error {
apppackTomlPath := GetAppPackTomlFilename()
if apppackTomlPath == DefaultAppPackTomlFilename {
// File is already at the default location, nothing to do
return nil
}

log.Debug().Msgf("Copying %s to %s for artifact archival", apppackTomlPath, DefaultAppPackTomlFilename)
if err := cp.Copy(apppackTomlPath, DefaultAppPackTomlFilename); err != nil {
return fmt.Errorf("failed to copy %s to %s: %w", apppackTomlPath, DefaultAppPackTomlFilename, err)
}
return nil
}
89 changes: 88 additions & 1 deletion builder/filesystem/filesystem_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@ import (
"fmt"
"io"
"os"
"path/filepath"
"strings"
"testing"

"github.com/rs/zerolog"
Expand Down Expand Up @@ -117,7 +119,7 @@ func TestGetFilename(t *testing.T) {
// Call GetAppPackTomlFilename and check the default value

filename := GetAppPackTomlFilename()
if filename != "apppack.toml" {
if filename != DefaultAppPackTomlFilename {
t.Errorf("expected apppack.toml, got %s", filename)
}

Expand All @@ -130,6 +132,91 @@ func TestGetFilename(t *testing.T) {
}
}

func TestCopyAppPackTomlToDefault(t *testing.T) {
tests := []struct {
name string
envValue string
setupFiles map[string]string
expectCopy bool
expectError bool
errorContains string
}{
{
name: "no copy needed when using default location",
envValue: "",
expectCopy: false,
},
{
name: "copies from custom location",
envValue: "config/custom.toml",
setupFiles: map[string]string{
"config/custom.toml": "[build]\ntest = true\n",
},
expectCopy: true,
},
{
name: "error when custom file doesn't exist",
envValue: "nonexistent.toml",
expectCopy: false,
expectError: true,
errorContains: "failed to copy nonexistent.toml",
},
}

for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
// Set up environment
if tt.envValue != "" {
os.Setenv("APPPACK_TOML", tt.envValue)
defer os.Unsetenv("APPPACK_TOML")
}

// Create temp directory for test
tempDir := t.TempDir()
originalDir, _ := os.Getwd()
os.Chdir(tempDir)
defer os.Chdir(originalDir)

// Set up test files
for path, content := range tt.setupFiles {
dir := filepath.Dir(path)
if dir != "." {
os.MkdirAll(dir, 0o755)
}
os.WriteFile(path, []byte(content), 0o644)
}

// Run the function
err := CopyAppPackTomlToDefault()

// Check error
if tt.expectError {
if err == nil {
t.Errorf("expected error, got nil")
} else if tt.errorContains != "" && !strings.Contains(err.Error(), tt.errorContains) {
t.Errorf("expected error to contain %q, got %q", tt.errorContains, err.Error())
}
} else if err != nil {
t.Errorf("unexpected error: %v", err)
}

// Check if file was copied
if tt.expectCopy {
if _, err := os.Stat(DefaultAppPackTomlFilename); os.IsNotExist(err) {
t.Errorf("expected %s to exist after copy", DefaultAppPackTomlFilename)
} else {
// Verify content matches
expected := tt.setupFiles[tt.envValue]
actual, _ := os.ReadFile(DefaultAppPackTomlFilename)
if string(actual) != expected {
t.Errorf("copied content mismatch: got %q, want %q", actual, expected)
}
}
}
})
}
}

func dummyTarBuffer() (*io.Reader, error) {
var buf bytes.Buffer
tw := tar.NewWriter(&buf)
Expand Down