Skip to content
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

[action] add xcodes action, deprecating xcversion and xcode-install #20672

Merged
merged 29 commits into from Nov 12, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
29 commits
Select commit Hold shift + click to select a range
7c1de15
Move helpers to a separate and centralized file.
rogerluan Sep 18, 2022
676e3ee
Deprecate 'xcode-install' gem (the project has been sunset), adding '…
rogerluan Sep 18, 2022
8c5c733
Add 'select_only' option to 'xcodes', deprecating 'xcversion' action.
rogerluan Sep 18, 2022
eb583d5
Update documentation to state it also supports .xcode-version file.
rogerluan Sep 18, 2022
54786b0
Add TODO for a future improvement.
rogerluan Sep 18, 2022
b8d6090
Lint.
rogerluan Sep 18, 2022
766c53b
Fix link.
rogerluan Sep 19, 2022
6d6ff1f
Remove TODO comment.
rogerluan Sep 19, 2022
c9670be
Lint.
rogerluan Sep 19, 2022
97dff12
Fix typo in error being raised.
rogerluan Sep 19, 2022
c1c32ee
Add ability to select Xcode just for current build, without sudo perm…
rogerluan Sep 21, 2022
c2dafb7
Update documentation to point to 'xcodes' instead.
rogerluan Sep 21, 2022
7e84283
Update xcodes link.
rogerluan Sep 21, 2022
5675137
Apply suggestions from code review.
rogerluan Oct 14, 2022
4b5d083
Change "#" by "." in spec descriptions, to indicate class methods.
rogerluan Oct 14, 2022
083af9f
Apply suggestion from code review.
rogerluan Oct 14, 2022
5f9b24e
Improve documentation around requirements to run xcodes.
rogerluan Oct 14, 2022
23b33e8
Remove necessity to authenticate with Apple servers since xcodes v1.0.0.
rogerluan Nov 1, 2022
d66a490
Use new --update and --selected arguments, which require xcodes v1.1.0.
rogerluan Nov 1, 2022
9fc0824
Fix comparing Gem::Version with String error
revolter Nov 1, 2022
ccf5ec6
Remove unused local variable
revolter Nov 1, 2022
594d707
Split long lines
revolter Nov 1, 2022
30cd166
Fix lint issues
revolter Nov 1, 2022
136b664
Address style comments.
rogerluan Nov 2, 2022
7d0caea
Remove superfluous trailing slash
revolter Nov 2, 2022
317296b
Fix unsafe paths concatenation
revolter Nov 2, 2022
11bd750
Fix some WWDR certificates test failure
revolter Nov 2, 2022
1a27157
Replace `Actions.sh` call with a native one
revolter Nov 3, 2022
58a0ed9
Fix error-prone shell command status check
revolter Nov 3, 2022
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
10 changes: 5 additions & 5 deletions fastlane/lib/fastlane/actions/docs/build_app.md
Expand Up @@ -74,7 +74,7 @@ That's all you need to build your application. If you want more control, here ar
fastlane gym --workspace "Example.xcworkspace" --scheme "AppName" --clean
```

If you need to use a different Xcode installation, use `xcode-select` or define `DEVELOPER_DIR`:
If you need to use a different Xcode installation, use `[xcodes](https://docs.fastlane.tools/actions/xcodes)` or define `DEVELOPER_DIR`:

```no-highlight
DEVELOPER_DIR="/Applications/Xcode6.2.app" fastlane gym
Expand Down Expand Up @@ -150,7 +150,7 @@ build_app(
scheme: "Release",
export_method: "app-store",
export_options: {
provisioningProfiles: {
provisioningProfiles: {
"com.example.bundleid" => "Provisioning Profile Name",
"com.example.bundleid2" => "Provisioning Profile Name 2"
}
Expand Down Expand Up @@ -184,10 +184,10 @@ end
error do |lane, exception|
slack(
# message with short human friendly message
message: exception.to_s,
success: false,
message: exception.to_s,
success: false,
# Output containing extended log output
payload: { "Output" => exception.error_info.to_s }
payload: { "Output" => exception.error_info.to_s }
)
end
```
Expand Down
2 changes: 1 addition & 1 deletion fastlane/lib/fastlane/actions/docs/run_tests.md
Expand Up @@ -100,7 +100,7 @@ That's all you need to run your tests. If you want more control, here are some a
fastlane scan --workspace "Example.xcworkspace" --scheme "AppName" --device "iPhone 6" --clean
```

If you need to use a different Xcode install, use `xcode-select` or define `DEVELOPER_DIR`:
If you need to use a different Xcode install, use `[xcodes](https://docs.fastlane.tools/actions/xcodes)` or define `DEVELOPER_DIR`:

```no-highlight
DEVELOPER_DIR="/Applications/Xcode6.2.app" scan
Expand Down
6 changes: 5 additions & 1 deletion fastlane/lib/fastlane/actions/xcode_install.rb
Expand Up @@ -101,7 +101,11 @@ def self.example_code
end

def self.category
:building
:deprecated
end

def self.deprecated_notes
"The xcode-install gem, which this action depends on, has been sunset. Please migrate to [xcodes](https://docs.fastlane.tools/actions/xcodes). You can find a migration guide here: [xcpretty/xcode-install/MIGRATION.md](https://github.com/xcpretty/xcode-install/blob/master/MIGRATION.md)"
end
end
end
Expand Down
2 changes: 1 addition & 1 deletion fastlane/lib/fastlane/actions/xcode_select.rb
Expand Up @@ -40,7 +40,7 @@ def self.description
def self.details
[
"Select and build with the Xcode installed at the provided path.",
"Use the `xcversion` action if you want to select an Xcode:",
"Use the `xcodes` action if you want to select an Xcode:",
"- Based on a version specifier or",
"- You don't have known, stable paths, as may happen in a CI environment."
].join("\n")
Expand Down
137 changes: 137 additions & 0 deletions fastlane/lib/fastlane/actions/xcodes.rb
@@ -0,0 +1,137 @@
module Fastlane
module Actions
module SharedValues
XCODES_XCODE_PATH = :XCODES_XCODE_PATH
end

class XcodesAction < Action
def self.run(params)
binary = params[:binary_path]
xcodes_raw_version = Actions.sh("#{binary} version", log: false)
xcodes_version = Gem::Version.new(xcodes_raw_version)
UI.message("Running xcodes version #{xcodes_version}")
if xcodes_version < Gem::Version.new("1.1.0")
UI.user_error!([
"xcodes action requires the minimum version of xcodes binary to be v1.1.0.",
"Please update xcodes. If you installed it via Homebrew, this can be done via 'brew upgrade xcodes'"
].join(" "))
end

version = params[:version]
command = []
command << binary

if (xcodes_args = params[:xcodes_args])
command << xcodes_args
Actions.sh(command.join(" "))
elsif !params[:select_for_current_build_only]
command << "install"
command << "'#{version}'"
command << "--update" if params[:update_list]
command << "--select"
Actions.sh(command.join(" "))
end

command = []
command << binary
command << "installed"
rogerluan marked this conversation as resolved.
Show resolved Hide resolved
command << "'#{version}'"
# Prints something like /Applications/Xcode-14.app
xcode_path = Actions.sh(command.join(" ")).strip
xcode_developer_path = File.join(xcode_path, "/Contents/Developer")

UI.message("Setting Xcode version '#{version}' at '#{xcode_path}' for all build steps")
ENV["DEVELOPER_DIR"] = xcode_developer_path
Actions.lane_context[SharedValues::XCODES_XCODE_PATH] = xcode_developer_path
return xcode_path
end

#####################################################
# @!group Documentation
#####################################################

def self.description
"Make sure a certain version of Xcode is installed, installing it only if needed"
end

def self.details
[
"Makes sure a specific version of Xcode is installed. If that's not the case, it will automatically be downloaded by [xcodes](https://github.com/RobotsAndPencils/xcodes).",
"This will make sure to use the correct Xcode version for later actions.",
"Note that this action depends on [xcodes](https://github.com/RobotsAndPencils/xcodes) CLI, so make sure you have it installed in your environment. For the installation guide, see: https://github.com/RobotsAndPencils/xcodes#installation"
].join("\n")
end

def self.available_options
[
FastlaneCore::ConfigItem.new(key: :version,
env_name: "FL_XCODE_VERSION",
description: "The version number of the version of Xcode to install. Defaults to the value specified in the .xcode-version file",
default_value: Helper::XcodesHelper.read_xcode_version_file,
default_value_dynamic: true,
verify_block: Helper::XcodesHelper::Verify.method(:requirement)),
FastlaneCore::ConfigItem.new(key: :update_list,
env_name: "FL_XCODES_UPDATE_LIST",
description: "Whether the list of available Xcode versions should be updated before running the install command",
type: Boolean,
default_value: true),
FastlaneCore::ConfigItem.new(key: :select_for_current_build_only,
env_name: "FL_XCODES_SELECT_FOR_CURRENT_BUILD_ONLY",
description: [
"When true, it won't attempt to install an Xcode version, just find the installed Xcode version that best matches the passed version argument, and select it for the current build steps.",
"It doesn't change the global Xcode version (e.g. via 'xcrun xcode-select'), which would require sudo permissions — when this option is true, this action doesn't require sudo permissions"
].join(" "),
type: Boolean,
default_value: false),
FastlaneCore::ConfigItem.new(key: :binary_path,
env_name: "FL_XCODES_BINARY_PATH",
description: "Where the xcodes binary lives on your system (full path)",
default_value: Helper::XcodesHelper.find_xcodes_binary_path,
default_value_dynamic: true,
verify_block: proc do |value|
UI.user_error!("'xcodes' doesn't seem to be installed. Please follow the installation guide at https://github.com/RobotsAndPencils/xcodes#installation before proceeding") if value.empty?
UI.user_error!("Couldn't find xcodes binary at path '#{value}'") unless File.exist?(value)
end),
FastlaneCore::ConfigItem.new(key: :xcodes_args,
env_name: "FL_XCODES_ARGS",
description: "Pass in xcodes command line arguments directly. When present, other parameters are ignored and only this parameter is used to build the command to be executed",
type: :shell_string,
optional: true)
]
end

def self.output
[
['XCODES_XCODE_PATH', 'The path to the newly installed Xcode version']
]
end

def self.return_value
"The path to the newly installed Xcode version"
end

def self.return_type
:string
end

def self.authors
["rogerluan"]
end

def self.is_supported?(platform)
[:ios, :mac].include?(platform)
end

def self.example_code
[
'xcodes(version: "14.1")',
'xcodes # When missing, the version value defaults to the value specified in the .xcode-version file'
]
end

def self.category
:building
end
end
end
end
25 changes: 10 additions & 15 deletions fastlane/lib/fastlane/actions/xcversion.rb
Expand Up @@ -15,16 +15,6 @@ def self.run(params)
ENV["DEVELOPER_DIR"] = File.join(xcode.path, "/Contents/Developer")
end

def self.read_xcode_version_file
xcode_version_paths = Dir.glob(".xcode-version")

if xcode_version_paths.first
return File.read(xcode_version_paths.first).strip
end

return nil
end

def self.description
"Select an Xcode to use by version specifier"
end
Expand All @@ -44,10 +34,10 @@ def self.available_options
[
FastlaneCore::ConfigItem.new(key: :version,
env_name: "FL_XCODE_VERSION",
description: "The version of Xcode to select specified as a Gem::Version requirement string (e.g. '~> 7.1.0')",
default_value: self.read_xcode_version_file,
description: "The version of Xcode to select specified as a Gem::Version requirement string (e.g. '~> 7.1.0'). Defaults to the value specified in the .xcode-version file ",
default_value: Helper::XcodesHelper.read_xcode_version_file,
default_value_dynamic: true,
verify_block: Helper::XcversionHelper::Verify.method(:requirement))
verify_block: Helper::XcodesHelper::Verify.method(:requirement))
]
end

Expand All @@ -58,12 +48,17 @@ def self.is_supported?(platform)
def self.example_code
[
'xcversion(version: "8.1") # Selects Xcode 8.1.0',
'xcversion(version: "~> 8.1.0") # Selects the latest installed version from the 8.1.x set'
'xcversion(version: "~> 8.1.0") # Selects the latest installed version from the 8.1.x set',
'xcversion # When missing, the version value defaults to the value specified in the .xcode-version file'
]
end

def self.category
:building
:deprecated
end

def self.deprecated_notes
"The xcode-install gem, which this action depends on, has been sunset. Please migrate to [xcodes](https://docs.fastlane.tools/actions/xcodes). You can find a migration guide here: [xcpretty/xcode-install/MIGRATION.md](https://github.com/xcpretty/xcode-install/blob/master/MIGRATION.md)"
end
end
end
Expand Down
28 changes: 28 additions & 0 deletions fastlane/lib/fastlane/helper/xcodes_helper.rb
@@ -0,0 +1,28 @@
module Fastlane
module Helper
class XcodesHelper
def self.read_xcode_version_file
xcode_version_paths = Dir.glob(".xcode-version")

if xcode_version_paths.first
return File.read(xcode_version_paths.first).strip
end

return nil
end

def self.find_xcodes_binary_path
`which xcodes`.strip
end

module Verify
def self.requirement(req)
UI.user_error!("Version must be specified") if req.nil? || req.to_s.strip.size == 0
Gem::Requirement.new(req.to_s)
rescue Gem::Requirement::BadRequirementError
UI.user_error!("The requirement '#{req}' is not a valid RubyGems style requirement")
end
end
end
end
end
9 changes: 0 additions & 9 deletions fastlane/lib/fastlane/helper/xcversion_helper.rb
Expand Up @@ -11,15 +11,6 @@ def self.find_xcode(req)
req.satisfied_by?(Gem::Version.new(xcode.version))
end
end

module Verify
def self.requirement(req)
UI.user_error!("Version must be specified") if req.nil? || req.to_s.strip.size == 0
Gem::Requirement.new(req.to_s)
rescue Gem::Requirement::BadRequirementError
UI.user_error!("The requirement '#{req}' is not a valid RubyGems style requirement")
end
end
end
end
end