-
Notifications
You must be signed in to change notification settings - Fork 49
Merge installation logic into swiftly as an init subcommand #127
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
Conversation
Instead of relying on a separate shell script with certain issues swiftly can perform its own user initialization with many of the features of the script, including prompts, flags, and options. It also prepares swiftly for possible delivery through system package managers. Provide a design for the new installation system in the DESIGN.md. Change SwiftlyVersion to make it more conformant to the semantic version specification (https://semver.org) with respect to pre releases. Add test cases that cover typical scenarios. Update the swiftly version to a "dev" pre-release.
DESIGN.md
Outdated
- Amazon Linux 2 | ||
We'll need an initialization mode which, detects information about the OS and distribution in the case of Linux. The initialization mode is also responsible for setting up the directory structure for the toolchains (if necessary), setting up the shell environment for the user, and determining any operating system level dependencies that are required, but missing. Swiftly can perform these tasks itself with the capabilities provided by the Swift language and libraries, such as rich argument parsing, and launching system processes provided that the binary is somehow delivered to the user. | ||
|
||
The delivery of the binary onto the user's system can be accomplished in a number of ways, such as direct download from a trusted website with some guidance for the user to pick the right one for their OS and architecture. There might also be a copy/paste of a simple shell command-line for some more automation. Swiftly might be provided as a system-level package (e.g. homebrew, apt, yum, macOS pkg, etc). In some cases delivery might come from manual compilation from this git repository and the "swift build" command, useful for swiftly development and testing. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Delivery of the binary is where this falls down to some degree (at least on Linux). Previously this was all done automatically by the script. macOS has pkg which avoids this issue, but unless we are using some package management system it will up to the user to copy the binary into a folder in their path which isn't an ideal situation. Or are you expecting swiftly-init
to do this for the user?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
All of the path/environment management, creating the swiftly configuration, detection of missing required system packages, and most of what the shell script does today would be incorporated into swiftly's new init subcommand in this design. It's up to the delivery mechanisms to help the user to get to that entry point. I think that with some of the conventions described here those mechanisms have some mechanisms to provide optimal user experiences. For example, I think that swift.org can provide a copy-able command-line that would be equivalent to what is there today, but a little more complex.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think it would be good to breakdown the assumed different responsibilities of the different delivery methods to ensure that we're covering all bases and don't have any missing features or regressions in behaviours. This would help us hash out what needs to be done for different platforms, what needs to be be done for security etc
…r entirely Describe in more detail the anticipated delivery methods
@adam-fowler @patrickfreed how does this new revision of the design look? I've enumerated the expected delivery methods, simplified things, and fixed up some of the wording. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think I'm pretty happy with this
DESIGN.md
Outdated
- CentOS 7 | ||
- CentOS 8 | ||
- Amazon Linux 2 | ||
Initialization also covers creating symbolic links for various toolchain commands (e.g. swift, swiftc, clang, clang++, etc.) so that swiftly can configure the targets. These need to be installed into a user controlled directory so that swiftly can operate on the without super user permissions. Also, the swiftly binary itself is copied into this location if it is not run from a system location, managed by a system package manager. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If the binary is copied we should message the user that they can delete the version they have in their current directory. Or at least message that it has been copied so the user understands they can delete that copy.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks, I've reworked this paragraph to notify the user about the case where swiftly is copied into the swiftly bin directory so that they are aware.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
sorry for the late review, mostly looks good just have a few minor suggestions
@swift-ci test macOS |
@swift-ci test macOS |
@swift-ci test macOS |
@swift-ci test macOS |
@swift-ci test macOS |
… shell environment
@swift-ci test macOS |
Automate the installing of the swift gpg signatures into the user keyring
@swift-ci test macOS |
Fix error message if swiftly is run outside of an installation
@swift-ci test macOS |
@swift-ci test macOS |
@adam-fowler @patrickfreed this should be ready for review now. The macOS tests all pass, but there's some kind of CI system problem that throws errors at the end. Thank you. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Some minor change requests, but in general looks good.
Sources/Swiftly/Swiftly.swift
Outdated
@@ -45,8 +53,22 @@ public struct Swiftly: SwiftlyCommand { | |||
|
|||
public protocol SwiftlyCommand: AsyncParsableCommand {} | |||
|
|||
extension Data { | |||
func append(file: URL) throws { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It isn't very clear what this function is doing from its name
func append(file: URL) throws { | |
func append(to file: URL) throws { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Also where is this used, might be better to move this to nearer its usage
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I've added this change to the signature.
Sources/Swiftly/Init.swift
Outdated
|
||
if let config = config, !overwrite && config.version != SwiftlyCore.version { | ||
// We don't support downgrades, and we don't yet support upgrades | ||
throw Error(message: "An existing swiftly installation was detected. You can try overwriting it.") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What is expected of the user here?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ah I understand, you need to add --overwrite
. Maybe make the error more explicit. Also when running with --overwrite
on Linux it returns a different error
Error: The operation could not be completed. A file with the same name already exists.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I've made the message more explicit about the --overwrite
flag since it's in the init subcommand and the error can directly reference the subcommand's flag.
} catch { | ||
let msg = """ | ||
Could not load swiftly's configuration file at \(Swiftly.currentPlatform.swiftlyConfigFile.path) due to | ||
error: \"\(error)\". | ||
To use swiftly, modify the configuration file to fix the issue or perform a clean installation. | ||
To begin using swiftly you can install it by running 'swiftly init'. | ||
""" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The error messages you get when a config is not there includes a lot of extraneous info.
error: "Error Domain=NSCocoaErrorDomain Code=260 "The file “config.json” couldn’t be opened because there is no such file." UserInfo={NSFilePath=/Users/adamfowler/Library/Application Support/swiftly/config.json, NSUnderlyingError=0x133207dc0 {Error Domain=NSPOSIXErrorDomain Code=2 "No such file or directory"}}"
Can we translate some of these into more user friendly strings
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I've pulled out this inner error since it's likely to cause more confusion. The focus should be on the instruction to run the init.
} | ||
|
||
guard let id = id, let idlike = idlike else { | ||
let message = "Unable to find release information from file \(releaseFile)" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
let message = "Unable to find release information from file \(releaseFile)" | |
let message = "Unable to find OS release information from file \(releaseFile)" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks, this is much clearer.
Sources/LinuxPlatform/Linux.swift
Outdated
|
||
let data = FileManager.default.contents(atPath: releaseFile) | ||
guard let data = data else { | ||
let message = "Unable to read release information from file \(releaseFile)" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
let message = "Unable to read release information from file \(releaseFile)" | |
let message = "Unable to read OS release information from file \(releaseFile)" |
Sources/Swiftly/Init.swift
Outdated
Note that the locations can be changed with SWIFTLY_HOME and SWIFTLY_BIN environment variables and run | ||
this again. | ||
|
||
Proceed with the installation? |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can we change this to a [Y/n]?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I've changed the prompt to a yes or no instead of numbered options.
@@ -11,6 +11,11 @@ To download swiftly and install Swift, run the following in your terminal, then | |||
curl -L https://swiftlang.github.io/swiftly/swiftly-install.sh | bash |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We either need to edit this script to download the correct version of swiftly (Linux or mac) and run swiftly init
or get rid of this line in the docs.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is tricky since this README is one of the places where people see how to install swiftly, but it's a few commits newer than the last release. Also, it's unclear if we are going to cut a release or not that still makes use of the shell script, which will still technically work.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think we should stick to one installation method. If we add swiftly init
then the install script should become history, or at least be reduced to copy the correct version of swiftly off the internet.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
reduced to copy the correct version of swiftly off the internet.
Yeah that's probably a good idea ... i think the maximum installation complexity i'd expect is "choose macOS or linux". Even that can probably be avoided in the script. Hopefully no manual architecture detection "are you on arm64 or amd64?!". manually choosing the arch is not the end of the world, but it can be harder than it looks, to beginners.
``` | ||
To begin using installed swiftly from your current shell, first run the following command: | ||
|
||
. "/root/.local/share/swiftly/env.sh" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Need to make it clear this is for Linux, maybe provide macOS version as well
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
env.sh
is not accurate, for fish
, it'll be env.fish
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
env.sh
is not accurate, forfish
, it'll beenv.fish
.
Right, I'm hoping to make this an illustrative example of something that an integrator would look for from the swiftly output so that they can automate it. I'll see if I can make the description above highlight that this is just an example and can be different depending on the environment (e.g. Windows or Fish)
@@ -6,6 +6,12 @@ To download swiftly and install Swift, run the following in your terminal, then | |||
curl -L https://swiftlang.github.io/swiftly/swiftly-install.sh | bash |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We either need to edit this script to download the correct version of swiftly (Linux or mac) and run swiftly init or get rid of this line in the docs.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's the same kind of problem with the readme. People might be reading this from the main branch of swiftpackageindex.com and want the latest release, which is using the shell script installer. We'll need to sweep all of the documentation when we release to switch over to the new method.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ok we should create a separate PR with documentation changes
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I've added a suggested fix for an issue on Linux when downloading gpg keys
|
||
try process.run() | ||
// Attach this process to our process group so that Ctrl-C and other signals work | ||
let pgid = tcgetpgrp(STDOUT_FILENO) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can we add the same process group support to runProgram
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I've added this functionality to the runProgram too.
Sources/Swiftly/Init.swift
Outdated
|
||
if swiftlyBin.fileExists() { | ||
if !overwrite { | ||
throw Error(message: "Swiftly binary already exists. You can try again with overwrite to replace it.") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
throw Error(message: "Swiftly binary already exists. You can try again with overwrite to replace it.") | |
throw Error(message: "Swiftly binary already exists. You can try again with `--overwrite` to replace it.") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I've fixed the wording here. Thank you.
@swift-ci test macOS |
1 similar comment
@swift-ci test macOS |
@adam-fowler @patrickfreed although the macOS platform check is failing, that is happening after the tests due to some kind of problem with the CI system itself. The tests are all reporting as successful there. |
Instead of relying on a separate shell script with certain issues swiftly can perform its own user initialization with many of the features of the script, including prompts, flags, and options. It also prepares swiftly for possible delivery through system package managers.
Provide a design for the new installation system in the DESIGN.md.
Add an implementation, tests and documentation of an init subcommand that is capable of finishing the installation of swiftly (after the download step) into the user's environment, including swiftly home, toolchains directory, the swiftly binary (if it's user downloaded), and symbolic links.
Contribute documentation describing how to install swiftly and toolchains automatically in the context of a build/CI system.