Files
container/Sources/NativeBuilder/ContainerBuildReporting/BuildEvent.swift
T
Kathryn Baldauf 16f2630126 Add initial native builder code (#399)
We're working on making a pure swift container image build system that
leverages containerization. This PR represents our initial design and
initial work towards this goal.

The native builder is still in active development and most of the
implementation has not been started or completed. We will be opening a
series of issues that represent various (but not necessarily all) pieces
of work that need to be done here.

There are docs included in this PR that describe the overall design of
each component and outline some of our goals. The easiest way to view
the docs by themselves (since this is a massive PR) is to look at the
docs commit in the `Commits` tab.

We'd love any feedback! 

@wlan0

---------

Signed-off-by: Kathryn Baldauf <k_baldauf@apple.com>
2025-07-31 13:13:20 -07:00

190 lines
5.6 KiB
Swift

//===----------------------------------------------------------------------===//
// Copyright © 2025 Apple Inc. and the container project authors. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//===----------------------------------------------------------------------===//
import Foundation
/// Represents all types of events that can occur during a build.
///
/// Design rationale:
/// - Single enum to capture all build activity (operations, logs, progress)
/// - Each case carries relevant context and data
/// - Sendable and Codable for thread safety and serialization
/// - Extensible for future event types
public enum BuildEvent: Sendable, Codable {
// MARK: - Build Lifecycle Events
/// Build has started
case buildStarted(totalOperations: Int, stages: Int, timestamp: Date)
/// Build has completed
case buildCompleted(success: Bool, timestamp: Date)
// MARK: - Stage Events
/// A build stage has started
case stageStarted(stageName: String, timestamp: Date)
/// A build stage has completed
case stageCompleted(stageName: String, timestamp: Date)
// MARK: - Operation Events
/// An operation has started executing
case operationStarted(context: ReportContext)
/// An operation has finished successfully
case operationFinished(context: ReportContext, duration: TimeInterval)
/// An operation has failed
case operationFailed(context: ReportContext, error: BuildEventError)
/// An operation was satisfied from cache
case operationCacheHit(context: ReportContext)
/// Progress update for a long-running operation
case operationProgress(context: ReportContext, fraction: Double)
/// Log output from an operation
case operationLog(context: ReportContext, message: String)
// MARK: - IR Events
/// IR construction or analysis event
case irEvent(context: ReportContext, type: IREventType)
}
/// Context information for events.
///
/// Design rationale:
/// - Provides provenance for each event
/// - Enables grouping and correlation of events
/// - Rich context for UI/logging decisions
/// - Source mapping for precise error location
public struct ReportContext: Sendable, Codable {
/// Unique identifier for the node (if applicable)
public let nodeId: UUID?
/// Identifier for the build stage (if applicable)
public let stageId: String?
/// Human-readable description
public let description: String
/// Timestamp when the event was generated
public let timestamp: Date
/// Source location mapping (if available)
public let sourceMap: SourceMap?
public init(
nodeId: UUID? = nil,
stageId: String? = nil,
description: String,
timestamp: Date = Date(),
sourceMap: SourceMap? = nil
) {
self.nodeId = nodeId
self.stageId = stageId
self.description = description
self.timestamp = timestamp
self.sourceMap = sourceMap
}
/// Convenience init for operation events (backwards compatibility)
public init(
nodeId: UUID,
stageId: String,
operationDescription: String,
timestamp: Date = Date()
) {
self.init(
nodeId: nodeId,
stageId: stageId,
description: operationDescription,
timestamp: timestamp
)
}
}
/// Source location information for precise error reporting
public struct SourceMap: Sendable, Codable {
/// Source file path (e.g., Dockerfile path)
public let file: String?
/// Line number (1-based)
public let line: Int?
/// Column number (1-based)
public let column: Int?
/// Source text snippet for context
public let snippet: String?
public init(file: String? = nil, line: Int? = nil, column: Int? = nil, snippet: String? = nil) {
self.file = file
self.line = line
self.column = column
self.snippet = snippet
}
}
/// Types of IR events
public enum IREventType: String, Sendable, Codable {
case graphStarted = "graph_started"
case graphCompleted = "graph_completed"
case stageAdded = "stage_added"
case nodeAdded = "node_added"
case analyzing = "analyzing"
case validating = "validating"
case error = "error"
case warning = "warning"
}
/// Error information for build events.
///
/// Design rationale:
/// - Structured error representation for serialization
/// - Captures error type and description
/// - Extensible with diagnostics
public struct BuildEventError: Sendable, Codable {
/// The type of failure
public let type: FailureType
/// Human-readable error description
public let description: String
/// Additional diagnostic information
public let diagnostics: [String: String]?
public init(
type: FailureType,
description: String,
diagnostics: [String: String]? = nil
) {
self.type = type
self.description = description
self.diagnostics = diagnostics
}
public enum FailureType: String, Sendable, Codable {
case executionFailed
case cancelled
case invalidConfiguration
case timeout
case resourceExhausted
}
}