From caa5c6651b394e2e7382f57c8f08820d83b7cf93 Mon Sep 17 00:00:00 2001 From: laosb Date: Sun, 5 Oct 2025 17:37:39 +0800 Subject: [PATCH] fix: expand triple for bundle info.json too. --- ...rtifactBundleBuilder+File Operations.swift | 41 +++++++++++++++++ ...rtifactBundleBuilder+computeChecksum.swift | 46 +++++++++++++++++++ ...rtifactBundleBuilder+expandingTriple.swift | 29 ++++++++++++ .../ArtifactBundleBuilder.swift | 2 +- .../ArtifactBundleError.swift | 18 ++++++++ 5 files changed, 135 insertions(+), 1 deletion(-) create mode 100644 Sources/TailwindCSSCLIArtifactBundler/ArtifactBundleBuilder+File Operations.swift create mode 100644 Sources/TailwindCSSCLIArtifactBundler/ArtifactBundleBuilder+computeChecksum.swift create mode 100644 Sources/TailwindCSSCLIArtifactBundler/ArtifactBundleBuilder+expandingTriple.swift create mode 100644 Sources/TailwindCSSCLIArtifactBundler/ArtifactBundleError.swift diff --git a/Sources/TailwindCSSCLIArtifactBundler/ArtifactBundleBuilder+File Operations.swift b/Sources/TailwindCSSCLIArtifactBundler/ArtifactBundleBuilder+File Operations.swift new file mode 100644 index 0000000..19f43fd --- /dev/null +++ b/Sources/TailwindCSSCLIArtifactBundler/ArtifactBundleBuilder+File Operations.swift @@ -0,0 +1,41 @@ +import Foundation + +extension ArtifactBundleBuilder { + func downloadFile(from urlString: String, to destination: String) throws { + guard let url = URL(string: urlString) else { + throw ArtifactBundleError.invalidURL(urlString) + } + + let data = try Data(contentsOf: url) + try data.write(to: URL(fileURLWithPath: destination)) + } + + func makeExecutable(path: String) throws { + let attributes = [FileAttributeKey.posixPermissions: 0o755] + try fileManager.setAttributes(attributes, ofItemAtPath: path) + } + + func createZipFile(bundleDir: String, zipPath: String) throws { + // Remove existing ZIP file if it exists + if fileManager.fileExists(atPath: zipPath) { + try fileManager.removeItem(atPath: zipPath) + } + + let bundleDirURL = URL(fileURLWithPath: bundleDir) + let workDirURL = bundleDirURL.deletingLastPathComponent() + let bundleName = bundleDirURL.lastPathComponent + + let process = Process() + process.executableURL = URL(fileURLWithPath: "/usr/bin/zip") + process.arguments = ["-r", zipPath, bundleName] + process.currentDirectoryURL = workDirURL + + try process.run() + process.waitUntilExit() + + guard process.terminationStatus == 0 else { + throw ArtifactBundleError.zipCreationFailed + } + } + +} diff --git a/Sources/TailwindCSSCLIArtifactBundler/ArtifactBundleBuilder+computeChecksum.swift b/Sources/TailwindCSSCLIArtifactBundler/ArtifactBundleBuilder+computeChecksum.swift new file mode 100644 index 0000000..7a5f906 --- /dev/null +++ b/Sources/TailwindCSSCLIArtifactBundler/ArtifactBundleBuilder+computeChecksum.swift @@ -0,0 +1,46 @@ +import Crypto +import Foundation + +extension ArtifactBundleBuilder { + /// Computes the SHA256 checksum of a file. + /// + /// If `usingSHA256Directly` is true, it uses Swift Crypto's SHA256 implementation. + /// This is to workaround https://github.com/swiftlang/swift-package-manager/issues/9219. + func computeChecksum( + filePath: String, + usingSHA256Directly: Bool = false + ) throws -> String { + if usingSHA256Directly { + // Use swift-crypto's SHA256 implementation + let fileURL = URL(fileURLWithPath: filePath) + let data = try Data(contentsOf: fileURL) + let hash = SHA256.hash(data: data) + return hash.compactMap { String(format: "%02x", $0) }.joined() + } else { + // Use swift package compute-checksum command + let process = Process() + process.executableURL = URL(fileURLWithPath: "/usr/bin/swift") + process.arguments = ["package", "compute-checksum", filePath] + + let pipe = Pipe() + process.standardOutput = pipe + + try process.run() + process.waitUntilExit() + + guard process.terminationStatus == 0 else { + throw ArtifactBundleError.checksumComputationFailed + } + + let data = pipe.fileHandleForReading.readDataToEndOfFile() + let output = String(data: data, encoding: .utf8)?.trimmingCharacters( + in: .whitespacesAndNewlines) + + guard let checksum = output, !checksum.isEmpty else { + throw ArtifactBundleError.checksumComputationFailed + } + + return checksum + } + } +} diff --git a/Sources/TailwindCSSCLIArtifactBundler/ArtifactBundleBuilder+expandingTriple.swift b/Sources/TailwindCSSCLIArtifactBundler/ArtifactBundleBuilder+expandingTriple.swift new file mode 100644 index 0000000..77146b1 --- /dev/null +++ b/Sources/TailwindCSSCLIArtifactBundler/ArtifactBundleBuilder+expandingTriple.swift @@ -0,0 +1,29 @@ +extension ArtifactBundleBuilder { + /// Expands a list of triples into a stricter list of triples. + /// + /// To workaround https://github.com/swiftlang/swift-package-manager/issues/7362. + func expandingTriple(_ triple: String) -> [String] { + switch triple { + case "aarch64-apple-darwin": + [ + "aarch64-apple-darwin", + "arm64-apple-macosx12.0", + "arm64-apple-macosx13.0", + "arm64-apple-macosx14.0", + "arm64-apple-macosx15.0", + "arm64-apple-macosx26.0", + ] + case "x86_64-apple-darwin": + [ + "x86_64-apple-darwin", + "x86_64-apple-macosx12.0", + "x86_64-apple-macosx13.0", + "x86_64-apple-macosx14.0", + "x86_64-apple-macosx15.0", + "x86_64-apple-macosx26.0", + ] + // TODO: Does linux need more detailed triple variants? + default: [triple] + } + } +} diff --git a/Sources/TailwindCSSCLIArtifactBundler/ArtifactBundleBuilder.swift b/Sources/TailwindCSSCLIArtifactBundler/ArtifactBundleBuilder.swift index 043eae6..eef4027 100644 --- a/Sources/TailwindCSSCLIArtifactBundler/ArtifactBundleBuilder.swift +++ b/Sources/TailwindCSSCLIArtifactBundler/ArtifactBundleBuilder.swift @@ -110,7 +110,7 @@ class ArtifactBundleBuilder { version: version, type: "executable", variants: [ - ArtifactVariant(path: binaryPath, supportedTriples: [triple]) + ArtifactVariant(path: binaryPath, supportedTriples: expandingTriple(triple)) ] ) diff --git a/Sources/TailwindCSSCLIArtifactBundler/ArtifactBundleError.swift b/Sources/TailwindCSSCLIArtifactBundler/ArtifactBundleError.swift new file mode 100644 index 0000000..4bb59e2 --- /dev/null +++ b/Sources/TailwindCSSCLIArtifactBundler/ArtifactBundleError.swift @@ -0,0 +1,18 @@ +import Foundation + +enum ArtifactBundleError: Error, LocalizedError { + case invalidURL(String) + case zipCreationFailed + case checksumComputationFailed + + var errorDescription: String? { + switch self { + case .invalidURL(let url): + return "Invalid URL: \(url)" + case .zipCreationFailed: + return "Failed to create ZIP file" + case .checksumComputationFailed: + return "Failed to compute checksum" + } + } +}