//===----------------------------------------------------------------------===// // 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 ContainerBuildIR import ContainerizationOCI /// DockerInstruction represents a single docker instruction with its given options /// and arguments. Instructions are "visited" to add to a build graph. protocol DockerInstruction: Sendable, Equatable { func accept(_ visitor: DockerInstructionVisitor) throws } enum FromOptions: String { case platform = "--platform" } struct FromInstruction: DockerInstruction { let image: String let platform: Platform? let stageName: String? init(image: String, platform: String? = nil, stageName: String? = nil) throws { self.image = image var platformSpec = Platform.current if let platform = platform { platformSpec = try Platform(from: platform) } self.platform = platformSpec self.stageName = stageName } func accept(_ visitor: DockerInstructionVisitor) throws { try visitor.visit(self) } } /// DockerInstructionName defines a dockerfile instruction such as FROM, RUN, etc. enum DockerInstructionName: String { case FROM = "from" case RUN = "run" case COPY = "copy" case CMD = "cmd" case LABEL = "label" case EXPOSE = "expose" case ARG = "arg" } /// DockerKeyword defines words that are used as keywords within a line of a dockerfile /// to provide additional instruction enum DockerKeyword: String { case AS = "as" } struct CMDInstruction: DockerInstruction { let command: Command func accept(_ visitor: DockerInstructionVisitor) throws { try visitor.visit(self) } } struct LabelInstruction: DockerInstruction { let labels: [String: String] func accept(_ visitor: DockerInstructionVisitor) throws { try visitor.visit(self) } }