Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions Package.resolved

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

9 changes: 5 additions & 4 deletions Package.swift
Original file line number Diff line number Diff line change
Expand Up @@ -25,10 +25,10 @@ let package = Package(
dependencies: [
.package(url: "https://github.com/JohnSundell/Files", from: "4.0.0"),
.package(url: "https://github.com/nikolainobadi/NnGitKit.git", from: "0.6.0"),
.package(url: "https://github.com/nikolainobadi/NnShellKit.git", from: "2.0.0"),
.package(url: "https://github.com/nikolainobadi/NnSwiftDataKit", from: "0.5.0"),
.package(url: "https://github.com/nikolainobadi/NnShellKit.git", from: "2.2.0"),
.package(url: "https://github.com/nikolainobadi/NnSwiftDataKit", exact: "0.5.0"),
.package(url: "https://github.com/apple/swift-argument-parser.git", from: "1.5.0"),
.package(url: "https://github.com/nikolainobadi/SwiftPickerKit.git", from: "0.5.0")
.package(url: "https://github.com/nikolainobadi/SwiftPickerKit.git", exact: "0.6.0")
],
targets: [
.executableTarget(
Expand Down Expand Up @@ -59,7 +59,8 @@ let package = Package(
.target(
name: "NnexSharedTestHelpers",
dependencies: [
"NnexKit"
"NnexKit",
.product(name: "NnShellTesting", package: "NnShellKit"),
]
),
.testTarget(
Expand Down
20 changes: 9 additions & 11 deletions Sources/NnexKit/Archive/BinaryArchiver.swift
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,11 @@
//

import Foundation
import NnShellKit

public struct BinaryArchiver {
private let shell: any Shell
private let shell: any NnexShell

public init(shell: any Shell) {
public init(shell: any NnexShell) {
self.shell = shell
}
}
Expand All @@ -37,7 +36,7 @@ public extension BinaryArchiver {

if fileName.hasSuffix(".tar.gz") {
let removeCmd = "rm -f \"\(archived.archivePath)\""
_ = try shell.bash(removeCmd)
try shell.runAndPrint(bash: removeCmd)
}
}
}
Expand All @@ -55,15 +54,11 @@ private extension BinaryArchiver {
let archivePath = "\(directory)/\(archiveName)"

let tarCmd = "cd \"\(directory)\" && tar -czf \"\(archiveName)\" \"\(fileName)\""
_ = try shell.bash(tarCmd)
try shell.runAndPrint(bash: tarCmd)

let sha256 = try calculateSHA256(for: archivePath)

return ArchivedBinary(
originalPath: binaryPath,
archivePath: archivePath,
sha256: sha256
)
return .init(originalPath: binaryPath, archivePath: archivePath, sha256: sha256)
}

func determineArchiveName(for binaryPath: String, fileName: String) -> String {
Expand All @@ -85,7 +80,10 @@ private extension BinaryArchiver {
let raw = try? shell.bash("shasum -a 256 \"\(filePath)\""),
let sha = raw.components(separatedBy: " ").first,
!sha.isEmpty
else { throw NnexError.missingSha256 }
else {
throw NnexError.missingSha256
}

return sha
}
}
9 changes: 4 additions & 5 deletions Sources/NnexKit/Building/BinaryCopyUtility.swift
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,11 @@
//

import Files
import NnShellKit

public struct BinaryCopyUtility {
private let shell: any Shell
private let shell: any NnexShell

public init(shell: any Shell) {
public init(shell: any NnexShell) {
self.shell = shell
}
}
Expand Down Expand Up @@ -42,14 +41,14 @@ private extension BinaryCopyUtility {
switch binaryOutput {
case .single(let binaryInfo):
let finalPath = destinationPath + "/" + executableName
_ = try shell.bash("cp \"\(binaryInfo.path)\" \"\(finalPath)\"")
try shell.runAndPrint(bash: "cp \"\(binaryInfo.path)\" \"\(finalPath)\"")
return .single(.init(path: finalPath))

case .multiple(let binaries):
var results: [ReleaseArchitecture: BinaryInfo] = [:]
for (arch, binaryInfo) in binaries {
let finalPath = destinationPath + "/" + executableName + "-\(arch.name)"
_ = try shell.bash("cp \"\(binaryInfo.path)\" \"\(finalPath)\"")
try shell.runAndPrint(bash: "cp \"\(binaryInfo.path)\" \"\(finalPath)\"")
results[arch] = .init(path: finalPath)
}
return .multiple(results)
Expand Down
5 changes: 0 additions & 5 deletions Sources/NnexKit/Building/BinaryInfo.swift
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,9 @@
// Created by Nikolai Nobadi on 3/20/25.
//

/// Represents information about a binary file.
public struct BinaryInfo {
/// The file path to the binary.
public let path: String

/// Initializes a new instance of BinaryInfo.
/// - Parameters:
/// - path: The file path to the binary.
public init(path: String) {
self.path = path
}
Expand Down
6 changes: 0 additions & 6 deletions Sources/NnexKit/Building/BuildConfig.swift
Original file line number Diff line number Diff line change
Expand Up @@ -5,17 +5,11 @@
// Created by Nikolai Nobadi on 3/25/25.
//

/// Represents the configuration for building a project.
public struct BuildConfig: Sendable {
/// The name of the project to build.
public let projectName: String
/// The file path to the project directory.
public let projectPath: String
/// The type of build to perform (e.g., universal, arm64, x86_64).
public let buildType: BuildType
/// Additional arguments to pass to the build command.
public let extraBuildArgs: [String]
/// Indicates whether the project should be cleaned before building.
public let skipClean: Bool
public let testCommand: TestCommand?

Expand Down
6 changes: 0 additions & 6 deletions Sources/NnexKit/Building/BuildType.swift
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,8 @@
// Created by Nikolai Nobadi on 3/22/25.
//

/// Represents the build type for a project, specifying the target architecture.
public enum BuildType: String, CaseIterable, Sendable {
/// Universal build, targeting both ARM and Intel architectures.
case universal

/// ARM64 architecture.
case arm64

/// x86_64 architecture.
case x86_64
}
40 changes: 25 additions & 15 deletions Sources/NnexKit/Building/ProjectBuilder.swift
Original file line number Diff line number Diff line change
@@ -1,12 +1,19 @@
import NnShellKit
//
// ProjectBuilder.swift
// nnex
//
// Created by Nikolai Nobadi on 3/21/25.
//

import Foundation
import NnShellKit

public struct ProjectBuilder {
private let shell: any Shell
private let shell: any NnexShell
private let config: BuildConfig
private let progressDelegate: (any BuildProgressDelegate)?

public init(shell: any Shell, config: BuildConfig, progressDelegate: (any BuildProgressDelegate)? = nil) {
public init(shell: any NnexShell, config: BuildConfig, progressDelegate: (any BuildProgressDelegate)? = nil) {
self.shell = shell
self.config = config
self.progressDelegate = progressDelegate
Expand Down Expand Up @@ -61,8 +68,7 @@ private extension ProjectBuilder {

func cleanProject() throws {
log("🧹 Cleaning the project...")
let output = try shell.bash("swift package clean --package-path \(config.projectPath)")
if !output.isEmpty { print(output) }
try shell.runAndPrint(bash: "swift package clean --package-path \(config.projectPath)")
log("✅ Project cleaned.")
}

Expand All @@ -86,8 +92,7 @@ private extension ProjectBuilder {
log("🧪 Running tests: \(testCommand)")

do {
let output = try shell.bash(testCommand)
if !output.isEmpty { print(output) }
try shell.runAndPrint(bash: testCommand)
log("✅ Tests completed successfully.")
} catch let shellError as ShellError {
// Extract test output from the shell error
Expand All @@ -113,9 +118,8 @@ private extension ProjectBuilder {
log("🔨 Building for \(arch.name)...")
let extra = config.extraBuildArgs.joined(separator: " ")
let cmd = "swift build -c release --arch \(arch.name) -Xswiftc -Osize -Xswiftc -wmo -Xswiftc -gnone -Xswiftc -cross-module-optimization -Xlinker -dead_strip_dylibs --package-path \(config.projectPath) \(extra)"
let output = try shell.bash(cmd)
if !output.isEmpty { print(output) }

try shell.runAndPrint(bash: cmd)
try stripBinary(for: arch)
}

Expand All @@ -127,13 +131,14 @@ private extension ProjectBuilder {
log("✂️ Stripping binary for \(arch.name)...")
let binaryPath = binaryPath(for: arch)
let stripCmd = "strip -x \"\(binaryPath)\""
let output = try shell.bash(stripCmd)
if !output.isEmpty { print(output) }

try shell.runAndPrint(bash: stripCmd)
log("✅ Binary stripped for \(arch.name).")
}

}


// MARK: - Dependencies
public enum BinaryOutput {
case single(BinaryInfo)
case multiple([ReleaseArchitecture: BinaryInfo])
Expand All @@ -156,12 +161,17 @@ public struct TestFailureError: Error, LocalizedError {
}
}


// MARK: - Extension Dependencies
private extension BuildType {
var archs: [ReleaseArchitecture] {
switch self {
case .arm64: return [.arm]
case .x86_64: return [.intel]
case .universal: return [.arm, .intel]
case .arm64:
return [.arm]
case .x86_64:
return [.intel]
case .universal:
return [.arm, .intel]
}
}
}
5 changes: 2 additions & 3 deletions Sources/NnexKit/Formula/PublishUtilities.swift
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@

import Files
import Foundation
import NnShellKit

public enum PublishUtilities {
/// Builds the binary for the given project and formula.
Expand All @@ -18,7 +17,7 @@ public enum PublishUtilities {
/// - shell: The shell instance to use for building.
/// - Returns: The binary output including path(s) and hash(es).
/// - Throws: An error if the build process fails.
public static func buildBinary(formula: SwiftDataFormula, buildType: BuildType, skipTesting: Bool, shell: any Shell) throws -> BinaryOutput {
public static func buildBinary(formula: SwiftDataFormula, buildType: BuildType, skipTesting: Bool, shell: any NnexShell) throws -> BinaryOutput {
let testCommand = skipTesting ? nil : formula.testCommand
let config = BuildConfig(projectName: formula.name, projectPath: formula.localProjectPath, buildType: buildType, extraBuildArgs: formula.extraBuildArgs, skipClean: false, testCommand: testCommand)
let builder = ProjectBuilder(shell: shell, config: config)
Expand All @@ -32,7 +31,7 @@ public enum PublishUtilities {
/// - shell: The shell instance to use for archiving.
/// - Returns: An array of archived binaries.
/// - Throws: An error if archive creation fails.
public static func createArchives(from binaryOutput: BinaryOutput, shell: any Shell) throws -> [ArchivedBinary] {
public static func createArchives(from binaryOutput: BinaryOutput, shell: any NnexShell) throws -> [ArchivedBinary] {
let archiver = BinaryArchiver(shell: shell)

switch binaryOutput {
Expand Down
24 changes: 9 additions & 15 deletions Sources/NnexKit/Git/DefaultGitHandler.swift
Original file line number Diff line number Diff line change
Expand Up @@ -7,18 +7,12 @@

import Foundation
import GitShellKit
import NnShellKit

/// Default implementation of the GitHandler protocol, providing Git-related operations.
public struct DefaultGitHandler {
private let shell: any Shell
private let gitShell: any GitShell
private let shell: any NnexShell

/// Initializes a new instance of DefaultGitHandler with the specified shell.
/// - Parameter shell: The shell used to execute commands.
public init(shell: any Shell) {
public init(shell: any NnexShell) {
self.shell = shell
self.gitShell = GitShellAdapter(shell: shell)
}
}

Expand All @@ -30,16 +24,16 @@ extension DefaultGitHandler: GitHandler {
/// - message: The commit message describing the changes.
/// - path: The file path of the repository.
public func commitAndPush(message: String, path: String) throws {
_ = try shell.bash(makeGitCommand(.addAll, path: path))
_ = try shell.bash(makeGitCommand(.commit(message: message), path: path))
_ = try shell.bash(makeGitCommand(.push, path: path))
try shell.runAndPrint(bash: makeGitCommand(.addAll, path: path))
try shell.runAndPrint(bash: makeGitCommand(.commit(message: message), path: path))
try shell.runAndPrint(bash: makeGitCommand(.push, path: path))
}

/// Retrieves the remote URL of the repository located at the given path.
/// - Parameter path: The file path of the repository.
/// - Returns: A string representing the remote URL.
public func getRemoteURL(path: String) throws -> String {
return try gitShell.getGitHubURL(at: path)
return try shell.getGitHubURL(at: path)
}

/// Retrieves the previous release version from the repository at the given path.
Expand All @@ -52,7 +46,7 @@ extension DefaultGitHandler: GitHandler {
/// Initializes a new Git repository at the given path.
/// - Parameter path: The file path where the repository should be initialized.
public func gitInit(path: String) throws {
try GitStarter(path: path, shell: gitShell).gitInit()
try GitStarter(path: path, shell: shell).gitInit()
}

/// Initializes a new remote repository on GitHub with specified details and returns the repository URL.
Expand All @@ -64,7 +58,7 @@ extension DefaultGitHandler: GitHandler {
/// - Returns: A string representing the repository URL.
public func remoteRepoInit(tapName: String, path: String, projectDetails: String, visibility: RepoVisibility) throws -> String {
let info = RepoInfo(name: tapName, details: projectDetails, visibility: visibility, canUploadFromNonMainBranch: false)
return try GitHubRepoStarter(path: path, shell: gitShell, repoInfo: info).repoInit()
return try GitHubRepoStarter(path: path, shell: shell, repoInfo: info).repoInit()
}

/// Creates a new release with one or more archived binaries and returns all asset URLs.
Expand Down Expand Up @@ -102,7 +96,7 @@ private extension DefaultGitHandler {
// Create the release and upload all archives at once
let quotedArchivePaths = archivedBinaries.map { "\"\($0.archivePath)\"" }.joined(separator: " ")
let createCmd = "cd \"\(path)\" && gh release create \(version) \(quotedArchivePaths) --title \"\(version)\" \(notesParam)"
_ = try shell.bash(createCmd)
try shell.runAndPrint(bash: createCmd)

// Clean up archive files after upload
let archiver = BinaryArchiver(shell: shell)
Expand Down
31 changes: 0 additions & 31 deletions Sources/NnexKit/Git/GitShellAdapter.swift

This file was deleted.

Loading