Skip to content

Commit c22f128

Browse files
authored
Feat: customize console output with env variable (apple#952)
Fixes apple#915 Added a new feature to support the passing of buildkit colors for customizing console output.
1 parent 9b7cfd8 commit c22f128

2 files changed

Lines changed: 69 additions & 3 deletions

File tree

Sources/ContainerCommands/Builder/BuilderStart.swift

Lines changed: 22 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -88,10 +88,26 @@ extension Application {
8888

8989
let builderPlatform = ContainerizationOCI.Platform(arch: "arm64", os: "linux", variant: "v8")
9090

91+
var targetEnvVars: [String] = []
92+
if let buildkitColors = ProcessInfo.processInfo.environment["BUILDKIT_COLORS"] {
93+
targetEnvVars.append("BUILDKIT_COLORS=\(buildkitColors)")
94+
}
95+
if ProcessInfo.processInfo.environment["NO_COLOR"] != nil {
96+
targetEnvVars.append("NO_COLOR=true")
97+
}
98+
targetEnvVars.sort()
99+
91100
let existingContainer = try? await ClientContainer.get(id: "buildkit")
92101
if let existingContainer {
93102
let existingImage = existingContainer.configuration.image.reference
94103
let existingResources = existingContainer.configuration.resources
104+
let existingEnv = existingContainer.configuration.initProcess.environment
105+
106+
let existingManagedEnv = existingEnv.filter { envVar in
107+
envVar.hasPrefix("BUILDKIT_COLORS=") || envVar.hasPrefix("NO_COLOR=")
108+
}.sorted()
109+
110+
let envChanged = existingManagedEnv != targetEnvVars
95111

96112
// Check if we need to recreate the builder due to different image
97113
let imageChanged = existingImage != builderImage
@@ -115,7 +131,7 @@ extension Application {
115131

116132
switch existingContainer.status {
117133
case .running:
118-
guard imageChanged || cpuChanged || memChanged else {
134+
guard imageChanged || cpuChanged || memChanged || envChanged else {
119135
// If image, mem and cpu are the same, continue using the existing builder
120136
return
121137
}
@@ -125,7 +141,7 @@ extension Application {
125141
case .stopped:
126142
// If the builder is stopped and matches our requirements, start it
127143
// Otherwise, delete it and create a new one
128-
guard imageChanged || cpuChanged || memChanged else {
144+
guard imageChanged || cpuChanged || memChanged || envChanged else {
129145
try await existingContainer.startBuildKit(progressUpdate, nil)
130146
return
131147
}
@@ -173,10 +189,13 @@ extension Application {
173189
)
174190

175191
let imageConfig = try await image.config(for: builderPlatform).config
192+
var environment = imageConfig?.env ?? []
193+
environment.append(contentsOf: targetEnvVars)
194+
176195
let processConfig = ProcessConfiguration(
177196
executable: "/usr/local/bin/container-builder-shim",
178197
arguments: shimArguments,
179-
environment: imageConfig?.env ?? [],
198+
environment: environment,
180199
workingDirectory: "/",
181200
terminal: false,
182201
user: .id(uid: 0, gid: 0)

Tests/CLITests/Subcommands/Build/CLIBuilderLifecycleTest.swift

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,5 +33,52 @@ extension TestCLIBuildBase {
3333
#expect(status == "stopped", "BuildKit container is not stopped")
3434
}
3535
}
36+
37+
@Test func testBuilderEnvironmentColors() throws {
38+
let testColors = "run=green:warning=yellow:error=red:cancel=cyan"
39+
let testNoColor = "true"
40+
41+
let originalColors = ProcessInfo.processInfo.environment["BUILDKIT_COLORS"]
42+
let originalNoColor = ProcessInfo.processInfo.environment["NO_COLOR"]
43+
44+
defer {
45+
if let originalColors {
46+
setenv("BUILDKIT_COLORS", originalColors, 1)
47+
} else {
48+
unsetenv("BUILDKIT_COLORS")
49+
}
50+
if let originalNoColor {
51+
setenv("NO_COLOR", originalNoColor, 1)
52+
} else {
53+
unsetenv("NO_COLOR")
54+
}
55+
56+
try? builderStop()
57+
try? builderDelete(force: true)
58+
}
59+
60+
setenv("BUILDKIT_COLORS", testColors, 1)
61+
setenv("NO_COLOR", testNoColor, 1)
62+
63+
try? builderStop()
64+
try? builderDelete(force: true)
65+
66+
let (_, _, err, status) = try run(arguments: ["builder", "start"])
67+
try #require(status == 0, "builder start failed: \(err)")
68+
69+
try waitForBuilderRunning()
70+
71+
let container = try inspectContainer("buildkit")
72+
let envVars = container.configuration.initProcess.environment
73+
74+
#expect(
75+
envVars.contains("BUILDKIT_COLORS=\(testColors)"),
76+
"Expected BUILDKIT_COLORS to be passed to container, but it was missing from env: \(envVars)"
77+
)
78+
#expect(
79+
envVars.contains("NO_COLOR=\(testNoColor)"),
80+
"Expected NO_COLOR to be passed to container, but it was missing from env: \(envVars)"
81+
)
82+
}
3683
}
3784
}

0 commit comments

Comments
 (0)