-
Notifications
You must be signed in to change notification settings - Fork 0
/
build_ctx.go
131 lines (117 loc) · 3.23 KB
/
build_ctx.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
package main
import (
"archive/tar"
"bytes"
"embed"
"fmt"
"io"
"io/fs"
"os"
"path/filepath"
"strings"
)
// Embed your Dockerfile
//
//go:embed Dockerfile
//go:embed generate_makefile.py
var embeddedFiles embed.FS
// createBuildContext generates the build context including the current directory and the embedded Dockerfile.
func createBuildContext(baseDir string, dockerfile string) (io.Reader, error) {
buf := new(bytes.Buffer)
tw := tar.NewWriter(buf)
// Correctly handle paths by ensuring they use Unix-style separators
fixPathSeparator := func(path string) string {
return strings.ReplaceAll(path, `\`, `/`) // Replace Windows-style separators
}
err := filepath.Walk(baseDir, func(path string, info os.FileInfo, err error) error {
if err != nil {
return err
}
// Skip the root directory entry
if path == baseDir {
return nil
}
// Skip files or directories that start with an underscore
if strings.HasPrefix(filepath.Base(path), "_") {
if info.IsDir() {
return filepath.SkipDir // Skip entire directory if it starts with an underscore
}
return nil // Skip this file
}
// Ensure file paths use Unix-style separators
fixedPath := fixPathSeparator(path)
// Create header
header, err := tar.FileInfoHeader(info, fixedPath)
if err != nil {
return err
}
// Adjust header name to be relative to base directory and use correct path separators
header.Name, err = filepath.Rel(baseDir, path)
if err != nil {
return err
}
header.Name = fixPathSeparator(header.Name) // Ensure Unix-style separators in the tarball
if err := tw.WriteHeader(header); err != nil {
return err
}
if !info.IsDir() {
// Write file content
file, err := os.Open(path)
if err != nil {
return err
}
defer file.Close()
if _, err := io.Copy(tw, file); err != nil {
return err
}
}
return nil
})
if err != nil {
return nil, fmt.Errorf("error adding current directory to tar: %w", err)
}
var dockerfileData []byte
if dockerfile == "" {
dockerfileData, err = fs.ReadFile(embeddedFiles, "Dockerfile")
if err != nil {
return nil, fmt.Errorf("error reading embedded Dockerfile: %w", err)
}
} else {
dockerfileData, err = os.ReadFile(dockerfile)
if err != nil {
return nil, fmt.Errorf("error reading custom Dockerfile: %w", err)
}
fmt.Println("Using custom dockerfile: ", dockerfile)
}
// Add the embedded Dockerfile
if err := tw.WriteHeader(&tar.Header{
Name: "Dockerfile",
Mode: 0600,
Size: int64(len(dockerfileData)),
}); err != nil {
return nil, err
}
if _, err := tw.Write(dockerfileData); err != nil {
return nil, err
}
// Add the embedded generate_makefile.py
genMakeData, err := fs.ReadFile(embeddedFiles, "generate_makefile.py")
if err != nil {
return nil, fmt.Errorf("error reading embedded generate_makefile.py: %w", err)
}
if err := tw.WriteHeader(&tar.Header{
Name: "generate_makefile.py",
Mode: 0600,
Size: int64(len(genMakeData)),
}); err != nil {
return nil, err
}
if _, err := tw.Write(genMakeData); err != nil {
return nil, err
}
// Make sure to close the tar writer to flush buffers
if err := tw.Close(); err != nil {
return nil, fmt.Errorf("error finalizing tarball: %w", err)
}
return bytes.NewReader(buf.Bytes()), nil
}