Files
Peter Steinberger 234df15a6d chore: refresh dependencies after seven-day cooldown (#128414)
* build(deps): refresh dependencies after cooldown

Apply dependency, toolchain, action, image, and exact tool updates released by the inclusive 2026-08-16 seven-day cutoff. Adapt owner boundaries for the resulting CUA, logging, Teams, Markdown, native, and test-harness contract changes while retaining versions blocked by upstream compatibility constraints.

* fix(ui): align markdown renderer env typing

* fix(deps): align postcss and mistral peer contracts

* fix(deps): repair refreshed dependency contracts

* fix(deps): retain tslog startup budget

* fix(ci): verify Android tools with SHA-256

* fix(ci): fence Android SDK cache version
2026-08-24 03:01:54 -07:00

68 lines
2.4 KiB
Swift

import Foundation
import Subprocess
enum BoundedCommand {
private static let defaultOutputLimit = 8 * 1024 * 1024
static func run(
path: String,
arguments: [String],
environment: [String: String]? = nil,
timeout: TimeInterval,
outputLimit: Int = defaultOutputLimit) async -> String?
{
guard timeout > 0, outputLimit > 0 else { return nil }
let executable: Executable = path.contains("/")
? .path(.init(path))
: .name(path)
let subprocessEnvironment = environment.map(self.environment(from:)) ?? .inherit
do {
return try await withThrowingTaskGroup(
of: String?.self,
returning: String?.self)
{ group in
group.addTask {
let result = try await Subprocess.run(
executable,
arguments: Arguments(arguments),
environment: subprocessEnvironment,
output: .string(limit: outputLimit))
let output = result.standardOutput.trimmingCharacters(in: .whitespacesAndNewlines)
guard result.terminationStatus.isSuccess,
!output.isEmpty
else {
return nil
}
return output
}
group.addTask {
try await Task.sleep(nanoseconds: UInt64(timeout * 1_000_000_000))
return nil
}
// Keep timeout structured so swift-subprocess kills and reaps a canceled
// child before callers can start the next discovery probe.
defer { group.cancelAll() }
guard let result = try await group.next() else {
return nil
}
return result
}
} catch {
return nil
}
}
private static func environment(from values: [String: String]) -> Environment {
var converted: [Environment.Key: String] = [:]
converted.reserveCapacity(values.count)
for (key, value) in values {
guard let environmentKey = Environment.Key(rawValue: key) else { continue }
converted[environmentKey] = value
}
return .custom(converted)
}
}