Skip to content

Build swiftly release cleanup #335

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 9 commits into from
May 2, 2025
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
2 changes: 1 addition & 1 deletion Sources/SwiftlyCore/Commands.swift
Original file line number Diff line number Diff line change
Expand Up @@ -922,7 +922,7 @@ extension SystemCommand {
case arch(String)
case configuration(String)
case packagePath(FilePath)
case pkgConfigPath(String)
case pkgConfigPath(FilePath)
case product(String)
case swiftSdk(String)
case staticSwiftStdlib
Expand Down
6 changes: 6 additions & 0 deletions Sources/SwiftlyCore/ModeledCommandLine.swift
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,12 @@ public struct Configuration: Sendable {
public var arguments: Arguments
/// The environment to use when running the executable.
public var environment: Environment

public init(executable: Executable, arguments: Arguments, environment: Environment) {
self.executable = executable
self.arguments = arguments
self.environment = environment
}
}

public struct Executable: Sendable, Hashable {
Expand Down
3 changes: 3 additions & 0 deletions Sources/SwiftlyWebsiteAPI/openapi.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -284,6 +284,9 @@ components:
items:
$ref: '#/components/schemas/Architecture'
description: List of supported architectures.
checksum:
type: string
description: SHA-256 Checksum of the static SDK, if this platform is the static SDK.
required:
- name
- platform
Expand Down
82 changes: 69 additions & 13 deletions Sources/TestSwiftly/TestSwiftly.swift
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,60 @@ let currentPlatform: Platform = MacOS.currentPlatform
#error("Unsupported platform")
#endif

typealias sys = SwiftlyCore.SystemCommand
typealias fs = SwiftlyCore.FileSystem

func sh(executable: Executable = ShCommand.defaultExecutable, _ options: ShCommand.Option...) -> ShCommand {
sh(executable: executable, options)
}

func sh(executable: Executable = ShCommand.defaultExecutable, _ options: [ShCommand.Option]) -> ShCommand {
ShCommand(executable: executable, options)
}

struct ShCommand {
static var defaultExecutable: Executable { .name("sh") }

var executable: Executable

var options: [Option]

enum Option {
case login
case command(String)

func args() -> [String] {
switch self {
case .login:
["-l"]
case let .command(command):
["-c", command]
}
}
}

init(executable: Executable, _ options: [Option]) {
self.executable = executable
self.options = options
}

func config() -> Configuration {
var args: [String] = []

for opt in self.options {
args.append(contentsOf: opt.args())
}

return Configuration(
executable: self.executable,
arguments: Arguments(args),
environment: .inherit
)
}
}

extension ShCommand: Runnable {}

@main
struct TestSwiftly: AsyncParsableCommand {
@Flag(name: [.customShort("y"), .long], help: "Disable confirmation prompts by assuming 'yes'")
Expand All @@ -40,11 +92,13 @@ struct TestSwiftly: AsyncParsableCommand {
Foundation.exit(2)
}

guard case let swiftlyArchive = FilePath(swiftlyArchive) else { fatalError("") }

print("Extracting swiftly release")
#if os(Linux)
try currentPlatform.runProgram("tar", "-zxvf", swiftlyArchive, quiet: false)
try await sys.tar().extract(.verbose, .compressed, .archive(swiftlyArchive)).run(currentPlatform, quiet: false)
#elseif os(macOS)
try currentPlatform.runProgram("installer", "-pkg", swiftlyArchive, "-target", "CurrentUserHomeDirectory", quiet: false)
try await sys.installer(.verbose, pkg: swiftlyArchive, target: "CurrentUserHomeDirectory").run(currentPlatform, quiet: false)
#endif

#if os(Linux)
Expand All @@ -54,7 +108,7 @@ struct TestSwiftly: AsyncParsableCommand {
#endif

var env = ProcessInfo.processInfo.environment
let shell = try await currentPlatform.getShell()
let shell = FilePath(try await currentPlatform.getShell())
var customLoc: FilePath?

if self.customLocation {
Expand All @@ -66,37 +120,39 @@ struct TestSwiftly: AsyncParsableCommand {
env["SWIFTLY_TOOLCHAINS_DIR"] = (customLoc! / "toolchains").string

try currentPlatform.runProgram(extractedSwiftly.string, "init", "--assume-yes", "--no-modify-profile", "--skip-install", quiet: false, env: env)
try currentPlatform.runProgram(shell, "-l", "-c", ". \"\(customLoc! / "env.sh")\" && swiftly install --assume-yes latest --post-install-file=./post-install.sh", quiet: false, env: env)
try await sh(executable: .path(shell), .login, .command(". \"\(customLoc! / "env.sh")\" && swiftly install --assume-yes latest --post-install-file=./post-install.sh")).run(currentPlatform, env: env, quiet: false)
} else {
print("Installing swiftly to the default location.")
// Setting this environment helps to ensure that the profile gets sourced with bash, even if it is not in an interactive shell
if shell.hasSuffix("bash") {
if shell.ends(with: "bash") {
env["BASH_ENV"] = (fs.home / ".profile").string
} else if shell.hasSuffix("zsh") {
} else if shell.ends(with: "zsh") {
env["ZDOTDIR"] = fs.home.string
} else if shell.hasSuffix("fish") {
} else if shell.ends(with: "fish") {
env["XDG_CONFIG_HOME"] = (fs.home / ".config").string
}

try currentPlatform.runProgram(extractedSwiftly.string, "init", "--assume-yes", "--skip-install", quiet: false, env: env)
try currentPlatform.runProgram(shell, "-l", "-c", "swiftly install --assume-yes latest --post-install-file=./post-install.sh", quiet: false, env: env)
try await sh(executable: .path(shell), .login, .command("swiftly install --assume-yes latest --post-install-file=./post-install.sh")).run(currentPlatform, env: env, quiet: false)
}

var swiftReady = false

if NSUserName() == "root" && FileManager.default.fileExists(atPath: "./post-install.sh") {
try currentPlatform.runProgram(shell, "./post-install.sh", quiet: false)
if NSUserName() == "root" {
if try await fs.exists(atPath: "./post-install.sh") {
try currentPlatform.runProgram(shell.string, "./post-install.sh", quiet: false)
}
swiftReady = true
} else if FileManager.default.fileExists(atPath: "./post-install.sh") {
} else if try await fs.exists(atPath: "./post-install.sh") {
print("WARNING: not running as root, so skipping the post installation steps and final swift verification.")
} else {
swiftReady = true
}

if let customLoc = customLoc, swiftReady {
try currentPlatform.runProgram(shell, "-l", "-c", ". \"\(customLoc / "env.sh")\" && swift --version", quiet: false, env: env)
try await sh(executable: .path(shell), .login, .command(". \"\(customLoc / "env.sh")\" && swift --version")).run(currentPlatform, env: env, quiet: false)
} else if swiftReady {
try currentPlatform.runProgram(shell, "-l", "-c", "swift --version", quiet: false, env: env)
try await sh(executable: .path(shell), .login, .command("swift --version")).run(currentPlatform, env: env, quiet: false)
}
}
}
Loading