Skip to content

Commit 2794056

Browse files
authored
Streamline the swiftly init process (#177)
The init process just installs swiftly itself at the moment. Most users will immediately install a swift toolchain, most likely the latest available one. On Linux, there's confusing gpg messages that most users don't need to be aware. The init process will provide a summary of things that are going to happen to the user's system, including the addition of GnuPG keys on Linux, and the installation of the latest swift toolchain so that they can agree, or abort the entire process. When the process runs the user is given line-level and high level processes, not internal details. Add a verbose mode for more details, such as the messages that come from GnuPG on Linux. Add an option to the init subcommand to allow swiftly to be installed without the latest available swift toolchain so that advanced users can decide how to install a toolchain themselves after the swiftly installation. Update the documentation with the more automated workflow. Add more detail to the getting started guide. Rework the getting started guide to have a platform selector for linux/macOS and hide platform-specific details Permit bare swiftly command to start the init workflow when not installed. Quiet the macOS installer messages behind the verbose flag. Provide more verbose untarring messages in Linux behind the verbose flag.
1 parent 4c5911a commit 2794056

File tree

17 files changed

+313
-121
lines changed

17 files changed

+313
-121
lines changed

Documentation/SwiftlyDocs.docc/automated-install.md

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,18 +4,26 @@ Swiftly can be installed automatically in places like build/CI systems.
44

55
This guide will help you to script to the installation of swiftly and toolchains so that it can be unattended. We assume that you have working understanding of your build system. The examples are based on a typical Unix environment.
66

7-
First, download a swiftly binary from a trusted source, such as your artifact repository, or a well-known website for the operating system (e.g. Linux) and processor architecture (e.g. arm64, or x86_64). Here's an example using the popular curl command.
7+
First, download the swiftly binary from swift.org for your operating system (e.g. Linux) and processor architecture (e.g. arm64, or x86_64). Here's an example using the popular curl command.
88

99
```
10-
curl -L <trusted_location_of_swiftly> > swiftly
10+
curl -L <location_of_swiftly_swift_org> > swiftly.tar.gz
11+
tar zxf swiftly.tar.gz
12+
```
13+
14+
On macOS you can download the pkg file and extract it like this from the command-line:
15+
16+
```
17+
curl -L <location_of_swiftly_swift_org> > swiftly.pkg
18+
installer -pkg swiftly.pkg -target CurrentUserHomeDirectory
1119
```
1220

1321
> Tip: If you are using Linux you will need the "ca-certificates" package for the root certificate authorities that will establish the trust that swiftly needs to make API requests that it needs. This package is frequently pre-installed on end-user environments, but may not be present in more minimal installations.
1422
15-
Once swiftly is downloaded you can run the init subcommand to finish the installation. This command will use the default initialization options and proceed without prompting.
23+
Once swiftly is downloaded you can run the init subcommand to finish the installation. This command will print verbose outputs, assume yes for all prompts, and skip the automatic installation of the latest swift toolchain:
1624

1725
```
18-
./swiftly init --assume-yes
26+
./swiftly init --verbose --assume-yes --skip-install # the swiftly binary is extracted to ~/local/bin/swiftly on macOS
1927
```
2028

2129
Swiftly is installed, but the current shell may not yet be updated with the new environment variables, such as the PATH. The init command prints instructions on how to update the current shell environment without opening a new shell. This is an example of the output taken from Linux, but the details might be different for other OSes, username, or shell.

Documentation/SwiftlyDocs.docc/getting-started.md

Lines changed: 32 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,31 +1,46 @@
11
# Getting Started with Swiftly
22

3-
To download swiftly and install Swift, run the following in your terminal, then follow the on-screen instructions:
3+
Start using swiftly and swift.
44

5-
```
6-
curl -L https://swiftlang.github.io/swiftly/swiftly-install.sh | bash
7-
```
5+
To get started with swiftly you can download it from [swift.org](https://swift.org/download), and extract the package.
86

9-
Alternatively, you can download the swiftly binary and install itself like this:
7+
@TabNavigator {
8+
@Tab("Linux") {
9+
If you are using Linux then you can verify and extract the archive like this:
1010

11-
```
12-
swiftly init
13-
```
11+
```
12+
sha256sum swiftly-x.y.z.tar.gz # Check that the hash matches what's reported on swift.org
13+
tar zxf swiftly-x.y.z.tar.gz
14+
```
1415

15-
Once swiftly is installed you can use it to install the latest available swift toolchain like this:
16+
Now run swiftly init to finish the installation:
1617

17-
```
18-
$ swiftly install latest
18+
```
19+
./swiftly init
20+
```
21+
}
1922

20-
Fetching the latest stable Swift release...
21-
Installing Swift 5.8.1
22-
Downloaded 488.5 MiB of 488.5 MiB
23-
Extracting toolchain...
24-
Swift 5.8.1 installed successfully!
23+
@Tab("macOS") {
24+
On macOS you can either run the pkg installer from the command-line like this or just run the package by double-clicking on it (not recommended):
2525

26+
```
27+
installer -pkg swift-x.y.z.pkg -target CurrentUserHomeDirectory
28+
```
29+
30+
Now run swiftly init to finish the installation:
31+
32+
```
33+
$HOME/usr/local/bin/swiftly init
34+
```
35+
}
36+
}
37+
38+
Swiftly will install itself and download the latest available Swift toolchain. Follow the prompts for any additional steps. Once everything is done you can begin using swift.
39+
40+
```
2641
$ swift --version
2742
28-
Swift version 5.8.1 (swift-5.8.1-RELEASE)
43+
Swift version 6.0.1 (swift-6.0.1-RELEASE)
2944
Target: x86_64-unknown-linux-gnu
3045
3146
$ swift build # Build with the latest (5.8.1) toolchain

Documentation/SwiftlyDocs.docc/swiftly-cli-reference.md

Lines changed: 47 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ swiftly [--version] [--help]
2323
Install a new toolchain.
2424

2525
```
26-
swiftly install [<version>] [--use] [--verify|no-verify] [--post-install-file=<post-install-file>] [--assume-yes] [--version] [--help]
26+
swiftly install [<version>] [--use] [--verify|no-verify] [--post-install-file=<post-install-file>] [--assume-yes] [--verbose] [--version] [--help]
2727
```
2828

2929
**version:**
@@ -81,6 +81,11 @@ written to this file as commands that can be run after the installation.
8181
*Disable confirmation prompts by assuming 'yes'*
8282

8383

84+
**--verbose:**
85+
86+
*Enable verbose reporting from swiftly*
87+
88+
8489
**--version:**
8590

8691
*Show the version.*
@@ -143,7 +148,7 @@ Note that listing available snapshots before the latest release (major and minor
143148
Set the in-use toolchain. If no toolchain is provided, print the currently in-use toolchain, if any.
144149

145150
```
146-
swiftly use [--print-location] [--global-default] [--assume-yes] [<toolchain>] [--version] [--help]
151+
swiftly use [--print-location] [--global-default] [--assume-yes] [--verbose] [<toolchain>] [--version] [--help]
147152
```
148153

149154
**--print-location:**
@@ -161,6 +166,11 @@ swiftly use [--print-location] [--global-default] [--assume-yes] [<toolchain>] [
161166
*Disable confirmation prompts by assuming 'yes'*
162167

163168

169+
**--verbose:**
170+
171+
*Enable verbose reporting from swiftly*
172+
173+
164174
**toolchain:**
165175

166176
*The toolchain to use.*
@@ -210,7 +220,7 @@ Likewise, the latest snapshot associated with a given development branch can be
210220
Remove an installed toolchain.
211221

212222
```
213-
swiftly uninstall <toolchain> [--assume-yes] [--version] [--help]
223+
swiftly uninstall <toolchain> [--assume-yes] [--verbose] [--version] [--help]
214224
```
215225

216226
**toolchain:**
@@ -249,6 +259,11 @@ Finally, all installed toolchains can be uninstalled by specifying 'all':
249259
*Disable confirmation prompts by assuming 'yes'*
250260

251261

262+
**--verbose:**
263+
264+
*Enable verbose reporting from swiftly*
265+
266+
252267
**--version:**
253268

254269
*Show the version.*
@@ -309,7 +324,7 @@ The installed snapshots for a given devlopment branch can be listed by specifyin
309324
Update an installed toolchain to a newer version.
310325

311326
```
312-
swiftly update [<toolchain>] [--assume-yes] [--verify|no-verify] [--post-install-file=<post-install-file>] [--version] [--help]
327+
swiftly update [<toolchain>] [--assume-yes] [--verbose] [--verify|no-verify] [--post-install-file=<post-install-file>] [--version] [--help]
313328
```
314329

315330
**toolchain:**
@@ -355,6 +370,11 @@ A specific snapshot toolchain can be updated by including the date:
355370
*Disable confirmation prompts by assuming 'yes'*
356371

357372

373+
**--verbose:**
374+
375+
*Enable verbose reporting from swiftly*
376+
377+
358378
**--verify|no-verify:**
359379

360380
*Verify the toolchain's PGP signature before proceeding with installation.*
@@ -385,7 +405,7 @@ written to this file as commands that can be run after the installation.
385405
Perform swiftly initialization into your user account.
386406

387407
```
388-
swiftly init [--no-modify-profile] [--overwrite] [--platform=<platform>] [--assume-yes] [--version] [--help]
408+
swiftly init [--no-modify-profile] [--overwrite] [--platform=<platform>] [--skip-install] [--assume-yes] [--verbose] [--version] [--help]
389409
```
390410

391411
**--no-modify-profile:**
@@ -400,14 +420,24 @@ swiftly init [--no-modify-profile] [--overwrite] [--platform=<platform>] [--assu
400420

401421
**--platform=\<platform\>:**
402422

403-
*Specify the current Linux platform for swiftly.*
423+
*Specify the current Linux platform for swiftly*
424+
425+
426+
**--skip-install:**
427+
428+
*Skip installing the latest toolchain*
404429

405430

406431
**--assume-yes:**
407432

408433
*Disable confirmation prompts by assuming 'yes'*
409434

410435

436+
**--verbose:**
437+
438+
*Enable verbose reporting from swiftly*
439+
440+
411441
**--version:**
412442

413443
*Show the version.*
@@ -425,9 +455,19 @@ swiftly init [--no-modify-profile] [--overwrite] [--platform=<platform>] [--assu
425455
Update the version of swiftly itself.
426456

427457
```
428-
swiftly self-update [--version] [--help]
458+
swiftly self-update [--assume-yes] [--verbose] [--version] [--help]
429459
```
430460

461+
**--assume-yes:**
462+
463+
*Disable confirmation prompts by assuming 'yes'*
464+
465+
466+
**--verbose:**
467+
468+
*Enable verbose reporting from swiftly*
469+
470+
431471
**--version:**
432472

433473
*Show the version.*

README.md

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -6,12 +6,8 @@ Ongoing maintenance and stewardship of this project is led by the [SSWG](https:/
66

77
### Installation
88

9-
To download swiftly and install Swift, run the following in your terminal, then follow the on-screen instructions.
10-
```
11-
curl -L https://swiftlang.github.io/swiftly/swiftly-install.sh | bash
12-
```
9+
Download the swiftly package from [swift.org](https://swift.org/download) and it can install itself with init:
1310

14-
Alternatively, you can download the swiftly binary and it can install itself:
1511
```
1612
swiftly init
1713
```

Sources/LinuxPlatform/Linux.swift

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -327,7 +327,7 @@ public struct Linux: Platform {
327327
}
328328
}
329329

330-
public func install(from tmpFile: URL, version: ToolchainVersion) throws {
330+
public func install(from tmpFile: URL, version: ToolchainVersion, verbose: Bool) throws {
331331
guard tmpFile.fileExists() else {
332332
throw Error(message: "\(tmpFile) doesn't exist")
333333
}
@@ -348,7 +348,14 @@ public struct Linux: Platform {
348348
let relativePath = name.drop { c in c != "/" }.dropFirst()
349349

350350
// prepend /path/to/swiftlyHomeDir/toolchains/<toolchain> to each file name
351-
return toolchainDir.appendingPathComponent(String(relativePath))
351+
let destination = toolchainDir.appendingPathComponent(String(relativePath))
352+
353+
if verbose {
354+
SwiftlyCore.print("\(destination.path)")
355+
}
356+
357+
// prepend /path/to/swiftlyHomeDir/toolchains/<toolchain> to each file name
358+
return destination
352359
}
353360
}
354361

@@ -390,7 +397,7 @@ public struct Linux: Platform {
390397
FileManager.default.temporaryDirectory.appendingPathComponent("swiftly-\(UUID())")
391398
}
392399

393-
public func verifySignature(httpClient: SwiftlyHTTPClient, archiveDownloadURL: URL, archive: URL) async throws {
400+
public func verifySignature(httpClient: SwiftlyHTTPClient, archiveDownloadURL: URL, archive: URL, verbose: Bool) async throws {
394401
SwiftlyCore.print("Downloading toolchain signature...")
395402
let sigFile = self.getTempFilePath()
396403
let _ = FileManager.default.createFile(atPath: sigFile.path, contents: nil)
@@ -405,7 +412,7 @@ public struct Linux: Platform {
405412

406413
SwiftlyCore.print("Verifying toolchain signature...")
407414
do {
408-
try self.runProgram("gpg", "--verify", sigFile.path, archive.path)
415+
try self.runProgram("gpg", "--verify", sigFile.path, archive.path, quiet: !verbose)
409416
} catch {
410417
throw Error(message: "Signature verification failed: \(error).")
411418
}

Sources/MacOSPlatform/MacOS.swift

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@ public struct MacOS: Platform {
4949
nil
5050
}
5151

52-
public func install(from tmpFile: URL, version: ToolchainVersion) throws {
52+
public func install(from tmpFile: URL, version: ToolchainVersion, verbose: Bool) throws {
5353
guard tmpFile.fileExists() else {
5454
throw Error(message: "\(tmpFile) doesn't exist")
5555
}
@@ -60,23 +60,26 @@ public struct MacOS: Platform {
6060

6161
if SwiftlyCore.mockedHomeDir == nil {
6262
SwiftlyCore.print("Installing package in user home directory...")
63-
try runProgram("installer", "-pkg", tmpFile.path, "-target", "CurrentUserHomeDirectory")
63+
try runProgram("installer", "-verbose", "-pkg", tmpFile.path, "-target", "CurrentUserHomeDirectory", quiet: !verbose)
6464
} else {
6565
// In the case of a mock for testing purposes we won't use the installer, perferring a manual process because
6666
// the installer will not install to an arbitrary path, only a volume or user home directory.
67+
SwiftlyCore.print("Expanding pkg...")
6768
let tmpDir = self.getTempFilePath()
6869
let toolchainDir = self.swiftlyToolchainsDir.appendingPathComponent("\(version.identifier).xctoolchain", isDirectory: true)
6970
if !toolchainDir.fileExists() {
7071
try FileManager.default.createDirectory(at: toolchainDir, withIntermediateDirectories: false)
7172
}
72-
try runProgram("pkgutil", "--expand", tmpFile.path, tmpDir.path)
73+
try runProgram("pkgutil", "--verbose", "--expand", tmpFile.path, tmpDir.path, quiet: !verbose)
7374
// There's a slight difference in the location of the special Payload file between official swift packages
7475
// and the ones that are mocked here in the test framework.
7576
var payload = tmpDir.appendingPathComponent("Payload")
7677
if !payload.fileExists() {
7778
payload = tmpDir.appendingPathComponent("\(version.identifier)-osx-package.pkg/Payload")
7879
}
79-
try runProgram("tar", "-C", toolchainDir.path, "-xf", payload.path)
80+
81+
SwiftlyCore.print("Untarring pkg Payload...")
82+
try runProgram("tar", "-C", toolchainDir.path, "-xvf", payload.path, quiet: !verbose)
8083
}
8184
}
8285

@@ -146,7 +149,7 @@ public struct MacOS: Platform {
146149
FileManager.default.temporaryDirectory.appendingPathComponent("swiftly-\(UUID()).pkg")
147150
}
148151

149-
public func verifySignature(httpClient _: SwiftlyHTTPClient, archiveDownloadURL _: URL, archive _: URL) async throws {
152+
public func verifySignature(httpClient _: SwiftlyHTTPClient, archiveDownloadURL _: URL, archive _: URL, verbose _: Bool) async throws {
150153
// No signature verification is required on macOS since the pkg files have their own signing
151154
// mechanism and the swift.org downloadables are trusted by stock macOS installations.
152155
}

0 commit comments

Comments
 (0)