134 lines
4.5 KiB
Go
134 lines
4.5 KiB
Go
package main
|
|
|
|
import (
|
|
"context"
|
|
"flag"
|
|
"fmt"
|
|
"os"
|
|
"strings"
|
|
|
|
"dagger.io/dagger"
|
|
"golang.org/x/sync/errgroup"
|
|
)
|
|
|
|
func main() {
|
|
osFlag := flag.String("os", "all", "OS to test (debian, arch, fedora, or all)")
|
|
flag.Parse()
|
|
|
|
ctx := context.Background()
|
|
|
|
// Initialize Dagger Client
|
|
client, err := dagger.Connect(ctx, dagger.WithLogOutput(os.Stderr))
|
|
if err != nil {
|
|
fmt.Fprintf(os.Stderr, "Failed to connect to Dagger: %v\n", err)
|
|
os.Exit(1)
|
|
}
|
|
defer client.Close()
|
|
|
|
// Get reference to the project source directory
|
|
src := client.Host().Directory(".")
|
|
|
|
// Build the bootstrapping binary inside Go container
|
|
fmt.Println("Building bootstrap_environment binary for Linux...")
|
|
builder := client.Container().
|
|
From("golang:1.25").
|
|
WithMountedDirectory("/src", src).
|
|
WithWorkdir("/src").
|
|
WithExec([]string{"go", "build", "-o", "bootstrap_environment", "."})
|
|
|
|
binaryFile := builder.File("bootstrap_environment")
|
|
|
|
// Target OS list
|
|
var targets []string
|
|
switch strings.ToLower(*osFlag) {
|
|
case "debian":
|
|
targets = []string{"debian:latest"}
|
|
case "arch":
|
|
targets = []string{"archlinux:latest"}
|
|
case "fedora":
|
|
targets = []string{"fedora:latest"}
|
|
case "all":
|
|
targets = []string{"debian:latest", "archlinux:latest", "fedora:latest"}
|
|
default:
|
|
fmt.Fprintf(os.Stderr, "Unsupported OS: %s. Supported: debian, arch, fedora, all\n", *osFlag)
|
|
os.Exit(1)
|
|
}
|
|
|
|
g, ctx := errgroup.WithContext(ctx)
|
|
|
|
for _, target := range targets {
|
|
target := target // capture loop variable
|
|
g.Go(func() error {
|
|
fmt.Printf("=== Starting integration test on target OS: %s ===\n", target)
|
|
|
|
// 1. Prepare target container base and setup script based on OS distro
|
|
var testContainer *dagger.Container
|
|
if strings.Contains(target, "debian") {
|
|
testContainer = client.Container().
|
|
From(target).
|
|
WithExec([]string{"apt-get", "update"}).
|
|
WithExec([]string{"apt-get", "install", "-y", "sudo", "curl", "git", "wget", "tar", "unzip", "xz-utils", "make", "python3", "which"})
|
|
} else if strings.Contains(target, "fedora") {
|
|
testContainer = client.Container().
|
|
From(target).
|
|
WithExec([]string{"dnf", "install", "-y", "sudo", "curl", "git", "wget", "tar", "unzip", "xz", "make", "python3", "which"})
|
|
} else if strings.Contains(target, "archlinux") {
|
|
testContainer = client.Container().
|
|
From(target).
|
|
WithExec([]string{"pacman", "-Sy", "--noconfirm", "sudo", "curl", "git", "wget", "tar", "unzip", "xz", "make", "python", "which"})
|
|
} else {
|
|
return fmt.Errorf("unsupported target OS: %s", target)
|
|
}
|
|
|
|
// 2. Pre-create the ~/.pyenv directory to skip python source compilation in integration test (saves ~10 minutes)
|
|
testContainer = testContainer.WithExec([]string{"mkdir", "-p", "/root/.pyenv"})
|
|
|
|
// 3. Mount the built binary
|
|
testContainer = testContainer.
|
|
WithFile("/usr/local/bin/bootstrap_environment", binaryFile).
|
|
WithWorkdir("/tmp")
|
|
|
|
// Forward GitHub token so API calls are authenticated (avoids 403 rate-limits)
|
|
if tok := os.Getenv("GITHUB_TOKEN"); tok != "" {
|
|
secret := client.SetSecret("github-token", tok)
|
|
testContainer = testContainer.
|
|
WithSecretVariable("GITHUB_TOKEN", secret).
|
|
WithSecretVariable("GH_TOKEN", secret)
|
|
}
|
|
|
|
// 4. Run bootstrap binary against the full package set (no scope flags).
|
|
// We pipe 'y' to satisfy the "Proceed? [y/N]" prompt.
|
|
fmt.Printf("[%s] Executing bootstrap_environment...\n", target)
|
|
testContainer = testContainer.WithExec([]string{"sh", "-c", "echo y | bootstrap_environment --gui"})
|
|
|
|
// 5. Verify all installed custom packages return a path and zero exit code from version command
|
|
fmt.Printf("[%s] Verifying package installations on PATH and running version checks...\n", target)
|
|
verifyCmd := []string{
|
|
"sh", "-c",
|
|
"export PATH=$PATH:/usr/local/go/bin; " +
|
|
"which go && go version && " +
|
|
"which nvim && nvim --version && " +
|
|
"which zig && zig version && " +
|
|
"which firecracker && firecracker --version",
|
|
}
|
|
verifyOutput, err := testContainer.WithExec(verifyCmd).Stdout(ctx)
|
|
if err != nil {
|
|
return fmt.Errorf("verification failed on %s: package not found on PATH or exited with error (%w)", target, err)
|
|
}
|
|
|
|
|
|
fmt.Printf("[%s] Verification Output:\n%s\n", target, verifyOutput)
|
|
fmt.Printf("--- PASS: Integration test on %s completed successfully ---\n", target)
|
|
return nil
|
|
|
|
})
|
|
}
|
|
|
|
if err := g.Wait(); err != nil {
|
|
fmt.Fprintf(os.Stderr, "One or more integration tests failed: %v\n", err)
|
|
os.Exit(1)
|
|
}
|
|
|
|
fmt.Println("\nAll parallel integration tests passed successfully!")
|
|
}
|