11package main
22
33import (
4+ "builder/installer"
5+ "encoding/json"
6+ "fmt"
47 "os"
8+ "os/exec"
9+ "path"
10+ "path/filepath"
511
612 "github.com/roemer/gotaskr"
13+ "github.com/roemer/gotaskr/execr"
14+ "github.com/roemer/gotaskr/gttools"
15+ "github.com/roemer/gotaskr/log"
716)
817
18+ ////////////////////////////////////////////////////////////
19+ // Variables
20+ ////////////////////////////////////////////////////////////
21+
22+ var featureList = []string {
23+ "go" ,
24+ }
25+
926////////////////////////////////////////////////////////////
1027// Main
1128////////////////////////////////////////////////////////////
@@ -19,7 +36,230 @@ func main() {
1936////////////////////////////////////////////////////////////
2037
2138func init () {
22- gotaskr .Task ("Build" , func () error {
39+ gotaskr .Task ("Update-Readme-Files" , func () error {
40+ for _ , feature := range featureList {
41+ if err := BuildReadmeForFeature (fmt .Sprintf ("features/src/%s" , feature )); err != nil {
42+ return err
43+ }
44+ }
2345 return nil
2446 })
47+
48+ gotaskr .Task ("Feature:go:Package" , func () error {
49+ return packageFeature ("go" )
50+ })
51+ gotaskr .Task ("Feature:go:Test" , func () error {
52+ return testFeature ("go" )
53+ })
54+ gotaskr .Task ("Feature:go:Publish" , func () error {
55+ return publishFeature ("go" )
56+ })
57+ }
58+
59+ ////////////////////////////////////////////////////////////
60+ // Helpers
61+ ////////////////////////////////////////////////////////////
62+
63+ func buildGo (workingDirectory string , binaryName string ) error {
64+ // Check if a go installer exists and only compile it then
65+ if _ , err := os .Stat (filepath .Join (workingDirectory , "installer.go" )); err != nil {
66+ if os .IsNotExist (err ) {
67+ log .Information ("No go installer found, skip compiling" )
68+ return nil
69+ } else {
70+ return err
71+ }
72+ }
73+
74+ // Force static linking
75+ os .Setenv ("CGO_ENABLED" , "0" )
76+ // Compile the go installer
77+ cmd := exec .Command ("go" , "build" , "-o" , binaryName , "-ldflags" , "-w" , "." )
78+ cmd .Env = os .Environ ()
79+ cmd .Env = append (cmd .Env , "GOOS=linux" )
80+ cmd .Env = append (cmd .Env , "GOARCH=amd64" )
81+ cmd .Dir = workingDirectory
82+ if err := execr .RunCommand (true , cmd ); err != nil {
83+ return err
84+ }
85+ fullPath := filepath .Join (workingDirectory , binaryName )
86+ fi , err := os .Stat (fullPath )
87+ if err != nil {
88+ return err
89+ }
90+ log .Informationf ("Built %s with a size of %s" , fullPath , installer .HumanizeBytes (fi .Size (), false ))
91+ return nil
92+ }
93+
94+ func packageFeature (featureName string ) error {
95+ featurePath := path .Join ("features/src" , featureName )
96+
97+ // Build the installer
98+ if err := buildGo (featurePath , "installer" ); err != nil {
99+ return err
100+ }
101+ defer os .Remove (filepath .Join (featurePath , "installer" ))
102+
103+ // Package the feature
104+ settings := & gttools.DevContainerCliFeaturesPackageSettings {
105+ Target : featurePath ,
106+ ForceCleanOutputFolder : gttools .True ,
107+ }
108+ settings .OutputToConsole = true
109+ return gotaskr .Tools .DevContainerCli .FeaturesPackage (settings )
110+ }
111+
112+ func testFeature (featureName string ) error {
113+ // Prepare the temporary folder for the devcontainer spec
114+ testPath := ".scenario-test"
115+ os .RemoveAll (testPath )
116+ os .MkdirAll (testPath , os .ModePerm )
117+
118+ // Read the images that should be used for testing
119+ testImagesFile := path .Join ("features/test" , featureName , "test-images.json" )
120+ testImagesContent , err := os .ReadFile (testImagesFile )
121+ if err != nil {
122+ return err
123+ }
124+ var testImages []string
125+ if err := json .Unmarshal (testImagesContent , & testImages ); err != nil {
126+ return err
127+ }
128+
129+ // Read and parse the scenario file
130+ scenariosFile := path .Join ("features/test" , featureName , "scenarios.json" )
131+ fileContent , err := os .ReadFile (scenariosFile )
132+ if err != nil {
133+ return err
134+ }
135+ var jsonData map [string ]json.RawMessage
136+ if err := json .Unmarshal (fileContent , & jsonData ); err != nil {
137+ return err
138+ }
139+ // Loop thru the scenarios
140+ for scenarioName , scenarioContent := range jsonData {
141+ log .Informationf ("Processing scenario '%s'" , scenarioName )
142+
143+ // Loop thru the base images
144+ for _ , testImage := range testImages {
145+ log .Informationf ("Testing with image '%s'" , testImage )
146+
147+ // Clear and prepare the devcontainer path
148+ devcontainerPath := path .Join (testPath , ".devcontainer" )
149+ os .RemoveAll (devcontainerPath )
150+ os .MkdirAll (devcontainerPath , os .ModePerm )
151+
152+ // Write the devcontainer spec file
153+ devcontainerSpecPath := path .Join (devcontainerPath , "devcontainer.json" )
154+ if err := os .WriteFile (devcontainerSpecPath , scenarioContent , os .ModePerm ); err != nil {
155+ return err
156+ }
157+
158+ // Copy the verify-script
159+ data , err := os .ReadFile (path .Join ("features/test" , featureName , scenarioName + ".sh" ))
160+ if err != nil {
161+ return err
162+ }
163+ if err := os .WriteFile (path .Join (devcontainerPath , "check.sh" ), data , os .ModePerm ); err != nil {
164+ return err
165+ }
166+
167+ // Copy the functions.sh file
168+ data , err = os .ReadFile (path .Join ("features/test/functions.sh" ))
169+ if err != nil {
170+ return err
171+ }
172+ if err := os .WriteFile (path .Join (devcontainerPath , "functions.sh" ), data , os .ModePerm ); err != nil {
173+ return err
174+ }
175+
176+ // Write the Dockerfile
177+ if err := os .WriteFile (path .Join (devcontainerPath , "Dockerfile" ), []byte (fmt .Sprintf (`
178+ FROM %s
179+ ADD check.sh /tmp/check.sh
180+ ADD functions.sh /tmp/functions.sh
181+ ` , testImage )), os .ModePerm ); err != nil {
182+ return err
183+ }
184+
185+ // Copy the required feature
186+ originalFeaturePath := path .Join ("features/src" , featureName )
187+ copiedFeaturePath := path .Join (devcontainerPath , featureName )
188+ if err := os .CopyFS (copiedFeaturePath , os .DirFS (originalFeaturePath )); err != nil {
189+ return err
190+ }
191+
192+ // Build the go installer inside the feature
193+ if err := buildGo (copiedFeaturePath , "installer" ); err != nil {
194+ return err
195+ }
196+
197+ // Build the devcontainer
198+ imageName := fmt .Sprintf ("dev-container-feature-%s-scenario-%s-test" , featureName , scenarioName )
199+ if err := gotaskr .Tools .DevContainerCli .Build (& gttools.DevContainerCliBuildSettings {
200+ ToolSettingsBase : gttools.ToolSettingsBase {OutputToConsole : true },
201+ WorkspaceFolder : testPath ,
202+ ImageNames : []string {imageName },
203+ }); err != nil {
204+ return err
205+ }
206+ defer execr .Run (false , "docker" , "image" , "rm" , imageName )
207+
208+ // Run the check in the container
209+ checkError := execr .Run (true , "docker" , "run" , "-t" , "--rm" , "-v" , "/var/run/docker.sock:/var/run/docker.sock" , imageName , "sh" , "-c" , "/tmp/check.sh" )
210+ if checkError != nil {
211+ return fmt .Errorf ("check failed: %w" , checkError )
212+ }
213+ fmt .Println ("Check was successfull" )
214+ }
215+ }
216+
217+ return nil
218+
219+ // TODO: Somewhen in the future this can be done with the devcontainer cli
220+ /*featurePath := path.Join("features/src", featureName)
221+ // Build the installer
222+ if err := buildGo(featurePath, "installer"); err != nil {
223+ return err
224+ }
225+ defer os.Remove(filepath.Join(featurePath, "installer"))
226+
227+ if err := gotaskr.Tools.DevContainerCli.FeaturesTest(>tools.DevContainerCliFeaturesTestSettings{
228+ ToolSettingsBase: gttools.ToolSettingsBase{OutputToConsole: true},
229+ ProjectFolder: "./features",
230+ Features: []string{featureName},
231+ LogLevel: gttools.DEV_CONTAINER_CLI_LOG_LEVEL_DEBUG,
232+ SkipAutogenerated: gttools.True,
233+ SkipDuplicated: gttools.True,
234+ }); err != nil {
235+ return err
236+ }*/
237+ }
238+
239+ func publishFeature (featureName string ) error {
240+ // TODO
241+ return nil
242+
243+ /*
244+ featurePath := path.Join("features/src", featureName)
245+
246+ // Build the installer
247+ if err := buildGo(featurePath, "installer"); err != nil {
248+ return err
249+ }
250+ defer os.Remove(filepath.Join(featurePath, "installer"))
251+
252+ // Set OCI authentication
253+ if err := setOCIAuth(); err != nil {
254+ return err
255+ }
256+ // Build and publish the feature
257+ settings := >tools.DevContainerCliFeaturesPublishSettings{
258+ Target: featurePath,
259+ Registry: registry,
260+ Namespace: namespace,
261+ }
262+ settings.OutputToConsole = true
263+ return gotaskr.Tools.DevContainerCli.FeaturesPublish(settings)
264+ */
25265}
0 commit comments