diff --git a/README.md b/README.md index 40d2219a..f479e870 100644 --- a/README.md +++ b/README.md @@ -123,8 +123,9 @@ Build a development IPA with custom xcconfig file path: | --- | --- | --- | --- | | `project_path` | Xcode Project (`.xcodeproj`) or Workspace (`.xcworkspace`) path. The input value sets xcodebuild's `-project` or `-workspace` option. | required | `$BITRISE_PROJECT_PATH` | | `scheme` | Xcode Scheme name. The input value sets xcodebuild's `-scheme` option. | required | `$BITRISE_SCHEME` | -| `distribution_method` | Describes how Xcode should export the archive. | required | `development` | +| `distribution_method` | Describes how Xcode should export the archive. The input value sets the method in the export options plist content. From Xcode 15.3 onwards, updated methods are used: - `debugging`, when `development` is selected - `app-store-connect`, when `app-store` is selected - `release-testing`, when `ad-hoc` is selected - `enterprise` is unchanged | required | `development` | | `configuration` | Xcode Build Configuration. If not specified, the default Build Configuration will be used. The input value sets xcodebuild's `-configuration` option. | | | +| `lock_swift_packages` | If this input is set, the Step will disable Swift Package Manager automatic resolution. When enabled, runs the following: ``` defaults write com.apple.dt.Xcode IDEPackageOnlyUseVersionsFromResolvedFile -bool YES defaults write com.apple.dt.Xcode IDEDisableAutomaticPackageResolution -bool YES ``` | required | `no` | | `xcconfig_content` | Build settings to override the project's build settings, using xcodebuild's `-xcconfig` option. You can't define `-xcconfig` option in `Additional options for the xcodebuild command` if this input is set. If empty, no setting is changed. When set it can be either: 1. Existing `.xcconfig` file path. Example: `./ios-sample/ios-sample/Configurations/Dev.xcconfig` 2. The contents of a newly created temporary `.xcconfig` file. (This is the default.) Build settings must be separated by newline character (`\n`). Example: ``` COMPILER_INDEX_STORE_ENABLE = NO ONLY_ACTIVE_ARCH[config=Debug][sdk=*][arch=*] = YES ``` | | `COMPILER_INDEX_STORE_ENABLE = NO` | | `perform_clean_action` | If this input is set, `clean` xcodebuild action will be performed besides the `archive` action. | required | `no` | | `xcodebuild_options` | Additional options to be added to the executed xcodebuild command. Prefer using `Build settings (xcconfig)` input for specifying `-xcconfig` option. You can't use both. `-destination` is set automatically, unless specified explicitely. | | | diff --git a/e2e/bitrise.yml b/e2e/bitrise.yml index 7b71743b..b0a8c9e0 100644 --- a/e2e/bitrise.yml +++ b/e2e/bitrise.yml @@ -39,7 +39,7 @@ workflows: # - BITRISE_SCHEME: World # - CODE_SIGNING_METHOD: api-key # - MIN_DAYS_PROFILE_VALID: 0 - # - FORCE_CODE_SIGN_IDENTITY: "iPhone Developer: Tooling Bot Bitrise" + # - FORCE_CODE_SIGN_IDENTITY: "Apple Development: Tooling Bot Bitrise" # - TEAM_ID: 72SA8V3WYL # - FORCE_PROV_PROFILE_SPECIFIER: "" # - IPA_EXPORT_METHOD: development @@ -102,6 +102,7 @@ workflows: inputs: - project_path: ./_tmp/ios-simple-objc/ios-simple-objc.xcodeproj - scheme: ios-simple-objc + - lock_swift_packages: "yes" - automatic_code_signing: api-key - certificate_url_list: $BITFALL_APPLE_IOS_CERTIFICATE_NOPASSPHRASE_URL - passphrase_list: "" @@ -161,9 +162,10 @@ workflows: - project_path: ./_tmp/$BITRISE_PROJECT_PATH - scheme: $BITRISE_SCHEME - automatic_code_signing: $CODE_SIGNING_METHOD + - lock_swift_packages: "yes" - xcconfig_content: | COMPILER_INDEX_STORE_ENABLE = NO - CODE_SIGN_IDENTITY = iPhone Developer: Tooling Bot Bitrise + CODE_SIGN_IDENTITY = Apple Development: Tooling Bot Bitrise - distribution_method: $IPA_EXPORT_METHOD - icloud_container_environment: $IPA_EXPORT_ICLOUD_CONTAINER_ENVIRONMENT - export_development_team: $TEAM_ID @@ -191,7 +193,7 @@ workflows: - CODE_SIGNING_METHOD: api-key - XCCONFIG_CONTENT: | COMPILER_INDEX_STORE_ENABLE = NO - CODE_SIGN_IDENTITY = iPhone Developer: Tooling Bot Bitrise + CODE_SIGN_IDENTITY = Apple Development: Tooling Bot Bitrise - MIN_DAYS_PROFILE_VALID: 0 - IPA_EXPORT_METHOD: development - LOG_FORMATTER: xcodebuild @@ -444,7 +446,7 @@ workflows: - BITRISE_SCHEME: Catalyst Sample - CODE_SIGNING_METHOD: api-key - MIN_DAYS_PROFILE_VALID: 0 - - FORCE_CODE_SIGN_IDENTITY: "iPhone Developer: Tooling Bot Bitrise" + - FORCE_CODE_SIGN_IDENTITY: "Apple Development: Tooling Bot Bitrise" - TEAM_ID: 72SA8V3WYL - FORCE_PROV_PROFILE_SPECIFIER: "" - IPA_EXPORT_METHOD: development @@ -484,6 +486,7 @@ workflows: inputs: - project_path: ./_tmp/$BITRISE_PROJECT_PATH - scheme: $BITRISE_SCHEME + - lock_swift_packages: "yes" - automatic_code_signing: $CODE_SIGNING_METHOD - min_profile_validity: $MIN_DAYS_PROFILE_VALID - certificate_url_list: $BITFALL_APPLE_APPLE_CERTIFICATE_URL_LIST|$BITFALL_APPLE_IOS_CERTIFICATE_URL_LIST diff --git a/go.mod b/go.mod index 89b51bdb..dd98cb2a 100644 --- a/go.mod +++ b/go.mod @@ -1,6 +1,6 @@ module github.com/bitrise-steplib/steps-xcode-archive -go 1.22 +go 1.23.0 toolchain go1.23.5 @@ -9,7 +9,7 @@ require ( github.com/bitrise-io/go-utils v1.0.14 github.com/bitrise-io/go-utils/v2 v2.0.0-alpha.23 github.com/bitrise-io/go-xcode v1.3.0 - github.com/bitrise-io/go-xcode/v2 v2.0.0-alpha.55 + github.com/bitrise-io/go-xcode/v2 v2.0.0-alpha.56 github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51 github.com/stretchr/testify v1.10.0 gopkg.in/yaml.v3 v3.0.1 diff --git a/go.sum b/go.sum index 4a65b910..c62ceafb 100644 --- a/go.sum +++ b/go.sum @@ -13,8 +13,8 @@ github.com/bitrise-io/go-utils/v2 v2.0.0-alpha.23 h1:Dfh4nyZPuEtilBisidejqxBrkx9 github.com/bitrise-io/go-utils/v2 v2.0.0-alpha.23/go.mod h1:3XUplo0dOWc3DqT2XA2SeHToDSg7+j1y1HTHibT2H68= github.com/bitrise-io/go-xcode v1.3.0 h1:QB8Vyr2oZQro/ocs9DJai80rlYL1hU1kwjHqdGslFLo= github.com/bitrise-io/go-xcode v1.3.0/go.mod h1:9OwsvrhZ4A2JxHVoEY7CPcABAKA+OE7FQqFfBfvbFuY= -github.com/bitrise-io/go-xcode/v2 v2.0.0-alpha.55 h1:hLLVWstKv0KZZexCWE9so1mDB4MnDZK2TrX5jz2AYpI= -github.com/bitrise-io/go-xcode/v2 v2.0.0-alpha.55/go.mod h1:T4rhWQljdgH5As4Dq/RQWuazdScY0YB7uZAMuBUnxeY= +github.com/bitrise-io/go-xcode/v2 v2.0.0-alpha.56 h1:JSwOStu6HCkT6b7icTQ3x/0OBNPQ8mD7Q6vQt2hG7fg= +github.com/bitrise-io/go-xcode/v2 v2.0.0-alpha.56/go.mod h1:zoLzT5fJE8V2SeYq0D0Z+ZN2FAzERjV3uiqDg5H8Bug= github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= diff --git a/main.go b/main.go index 20e794e1..91c66950 100644 --- a/main.go +++ b/main.go @@ -13,6 +13,7 @@ import ( "github.com/bitrise-io/go-utils/v2/log" "github.com/bitrise-io/go-utils/v2/pathutil" "github.com/bitrise-io/go-xcode/v2/xcodecommand" + "github.com/bitrise-io/go-xcode/v2/xcodeversion" "github.com/bitrise-steplib/steps-xcode-archive/step" ) @@ -58,11 +59,11 @@ func run() int { func createConfigParser(logger log.Logger) step.XcodebuildArchiveConfigParser { envRepository := env.NewRepository() inputParser := stepconf.NewInputParser(envRepository) - xcodeVersionProvider := step.NewXcodebuildXcodeVersionProvider() fileManager := fileutil.NewFileManager() cmdFactory := command.NewFactory(envRepository) + xcodeVersionReader := xcodeversion.NewXcodeVersionProvider(cmdFactory) - return step.NewXcodeArchiveConfigParser(inputParser, xcodeVersionProvider, fileManager, cmdFactory, logger) + return step.NewXcodeArchiveConfigParser(inputParser, xcodeVersionReader, fileManager, cmdFactory, logger) } func createXcodebuildArchiver(logger log.Logger, logFormatter string) (step.XcodebuildArchiver, error) { @@ -72,6 +73,7 @@ func createXcodebuildArchiver(logger log.Logger, logFormatter string) (step.Xcod pathModifier := pathutil.NewPathModifier() fileManager := fileutil.NewFileManager() cmdFactory := command.NewFactory(envRepository) + xcodeVersionReader := xcodeversion.NewXcodeVersionProvider(cmdFactory) xcodeCommandRunner := xcodecommand.Runner(nil) switch logFormatter { @@ -92,7 +94,7 @@ func createXcodebuildArchiver(logger log.Logger, logFormatter string) (step.Xcod panic(fmt.Sprintf("Unknown log formatter: %s", logFormatter)) } - return step.NewXcodebuildArchiver(xcodeCommandRunner, logFormatter, pathProvider, pathChecker, pathModifier, fileManager, cmdFactory, logger), nil + return step.NewXcodebuildArchiver(xcodeCommandRunner, logFormatter, xcodeVersionReader, pathProvider, pathChecker, pathModifier, fileManager, cmdFactory, logger), nil } func createRunOptions(config step.Config) step.RunOpts { @@ -103,6 +105,8 @@ func createRunOptions(config step.Config) step.RunOpts { XcodeMajorVersion: config.XcodeMajorVersion, ArtifactName: config.ArtifactName, + ShouldLockSwiftPackages: config.ShouldLockSwiftPackages, + CodesignManager: config.CodesignManager, PerformCleanAction: config.PerformCleanAction, diff --git a/mocks/XcodeVersionReader.go b/mocks/XcodeVersionReader.go new file mode 100644 index 00000000..156c0970 --- /dev/null +++ b/mocks/XcodeVersionReader.go @@ -0,0 +1,55 @@ +// Code generated by mockery v2.53.3. DO NOT EDIT. + +package mocks + +import ( + xcodeversion "github.com/bitrise-io/go-xcode/v2/xcodeversion" + mock "github.com/stretchr/testify/mock" +) + +// Reader is an autogenerated mock type for the Reader type +type Reader struct { + mock.Mock +} + +// GetVersion provides a mock function with no fields +func (_m *Reader) GetVersion() (xcodeversion.Version, error) { + ret := _m.Called() + + if len(ret) == 0 { + panic("no return value specified for GetVersion") + } + + var r0 xcodeversion.Version + var r1 error + if rf, ok := ret.Get(0).(func() (xcodeversion.Version, error)); ok { + return rf() + } + if rf, ok := ret.Get(0).(func() xcodeversion.Version); ok { + r0 = rf() + } else { + r0 = ret.Get(0).(xcodeversion.Version) + } + + if rf, ok := ret.Get(1).(func() error); ok { + r1 = rf() + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// NewXcodeVersionReader creates a new instance of Reader. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations. +// The first argument is typically a *testing.T value. +func NewXcodeVersionReader(t interface { + mock.TestingT + Cleanup(func()) +}) *Reader { + mock := &Reader{} + mock.Mock.Test(t) + + t.Cleanup(func() { mock.AssertExpectations(t) }) + + return mock +} diff --git a/step.yml b/step.yml index d909f397..acc41cc5 100644 --- a/step.yml +++ b/step.yml @@ -94,6 +94,16 @@ inputs: opts: title: Distribution method summary: Describes how Xcode should export the archive. + description: |- + Describes how Xcode should export the archive. + + The input value sets the method in the export options plist content. + + From Xcode 15.3 onwards, updated methods are used: + - `debugging`, when `development` is selected + - `app-store-connect`, when `app-store` is selected + - `release-testing`, when `ad-hoc` is selected + - `enterprise` is unchanged value_options: - development - app-store @@ -115,6 +125,24 @@ inputs: The input value sets xcodebuild's `-configuration` option. +- lock_swift_packages: "no" + opts: + category: xcodebuild configuration + title: Disable Swift Package Manager automatic resolution + summary: If this input is set, the Step will disable Swift Package Manager automatic resolution. + description: |- + If this input is set, the Step will disable Swift Package Manager automatic resolution. + + When enabled, runs the following: + ``` + defaults write com.apple.dt.Xcode IDEPackageOnlyUseVersionsFromResolvedFile -bool YES + defaults write com.apple.dt.Xcode IDEDisableAutomaticPackageResolution -bool YES + ``` + value_options: + - "yes" + - "no" + is_required: true + - xcconfig_content: COMPILER_INDEX_STORE_ENABLE = NO opts: category: xcodebuild configuration diff --git a/step/step.go b/step/step.go index a6783c93..1e3cffda 100644 --- a/step/step.go +++ b/step/step.go @@ -32,6 +32,7 @@ import ( "github.com/bitrise-io/go-xcode/v2/xcconfig" cache "github.com/bitrise-io/go-xcode/v2/xcodecache" "github.com/bitrise-io/go-xcode/v2/xcodecommand" + "github.com/bitrise-io/go-xcode/v2/xcodeversion" "github.com/bitrise-io/go-xcode/xcarchive" "github.com/bitrise-io/go-xcode/xcodebuild" "github.com/kballard/go-shellquote" @@ -76,10 +77,11 @@ type Inputs struct { ExportMethod string `env:"distribution_method,opt[app-store,ad-hoc,enterprise,development]"` // xcodebuild configuration - Configuration string `env:"configuration"` - XcconfigContent string `env:"xcconfig_content"` - PerformCleanAction bool `env:"perform_clean_action,opt[yes,no]"` - XcodebuildOptions string `env:"xcodebuild_options"` + Configuration string `env:"configuration"` + ShouldLockSwiftPackages bool `env:"lock_swift_packages,opt[yes,no]"` + XcconfigContent string `env:"xcconfig_content"` + PerformCleanAction bool `env:"perform_clean_action,opt[yes,no]"` + XcodebuildOptions string `env:"xcodebuild_options"` // xcodebuild log formatting LogFormatter string `env:"log_formatter,opt[xcbeautify,xcodebuild,xcpretty]"` @@ -134,17 +136,18 @@ type Config struct { } type XcodebuildArchiveConfigParser struct { - stepInputParser stepconf.InputParser - xcodeVersionProvider XcodeVersionProvider - fileManager fileutil.FileManager - cmdFactory command.Factory - logger log.Logger + stepInputParser stepconf.InputParser + xcodeVersionReader xcodeversion.Reader + fileManager fileutil.FileManager + cmdFactory command.Factory + logger log.Logger } // XcodebuildArchiver ... type XcodebuildArchiver struct { xcodeCommandRunner xcodecommand.Runner logFormatter string + xcodeVersionReader xcodeversion.Reader pathProvider pathutil.PathProvider pathChecker pathutil.PathChecker pathModifier pathutil.PathModifier @@ -153,21 +156,22 @@ type XcodebuildArchiver struct { cmdFactory command.Factory } -func NewXcodeArchiveConfigParser(stepInputParser stepconf.InputParser, xcodeVersionProvider XcodeVersionProvider, fileManager fileutil.FileManager, cmdFactory command.Factory, logger log.Logger) XcodebuildArchiveConfigParser { +func NewXcodeArchiveConfigParser(stepInputParser stepconf.InputParser, xcodeVersionReader xcodeversion.Reader, fileManager fileutil.FileManager, cmdFactory command.Factory, logger log.Logger) XcodebuildArchiveConfigParser { return XcodebuildArchiveConfigParser{ - stepInputParser: stepInputParser, - xcodeVersionProvider: xcodeVersionProvider, - fileManager: fileManager, - cmdFactory: cmdFactory, - logger: logger, + stepInputParser: stepInputParser, + xcodeVersionReader: xcodeVersionReader, + fileManager: fileManager, + cmdFactory: cmdFactory, + logger: logger, } } // NewXcodebuildArchiver ... -func NewXcodebuildArchiver(xcodecommandRunner xcodecommand.Runner, logFormatter string, pathProvider pathutil.PathProvider, pathChecker pathutil.PathChecker, pathModifier pathutil.PathModifier, fileManager fileutil.FileManager, cmdFactory command.Factory, logger log.Logger) XcodebuildArchiver { +func NewXcodebuildArchiver(xcodecommandRunner xcodecommand.Runner, logFormatter string, xcodeVersionReader xcodeversion.Reader, pathProvider pathutil.PathProvider, pathChecker pathutil.PathChecker, pathModifier pathutil.PathModifier, fileManager fileutil.FileManager, cmdFactory command.Factory, logger log.Logger) XcodebuildArchiver { return XcodebuildArchiver{ xcodeCommandRunner: xcodecommandRunner, logFormatter: logFormatter, + xcodeVersionReader: xcodeVersionReader, pathProvider: pathProvider, pathChecker: pathChecker, pathModifier: pathModifier, @@ -222,17 +226,16 @@ func (s XcodebuildArchiveConfigParser) ProcessInputs() (Config, error) { s.logger.Infof("Xcode version:") // Detect Xcode major version - xcodebuildVersion, err := s.xcodeVersionProvider.GetXcodeVersion() + xcodebuildVersion, err := s.xcodeVersionReader.GetVersion() if err != nil { return Config{}, fmt.Errorf("failed to determine xcode version, error: %s", err) } s.logger.Printf("%s (%s)", xcodebuildVersion.Version, xcodebuildVersion.BuildVersion) - xcodeMajorVersion := xcodebuildVersion.MajorVersion - if xcodeMajorVersion < minSupportedXcodeMajorVersion { - return Config{}, fmt.Errorf("invalid xcode major version (%d), should not be less then min supported: %d", xcodeMajorVersion, minSupportedXcodeMajorVersion) + if xcodebuildVersion.Major < minSupportedXcodeMajorVersion { + return Config{}, fmt.Errorf("invalid xcode major version (%d), should not be less then min supported: %d", xcodebuildVersion.Major, minSupportedXcodeMajorVersion) } - config.XcodeMajorVersion = int(xcodeMajorVersion) + config.XcodeMajorVersion = int(xcodebuildVersion.Major) // Validation ExportOptionsPlistContent exportOptionsPlistContent := strings.TrimSpace(config.ExportOptionsPlistContent) @@ -319,6 +322,8 @@ type RunOpts struct { XcodeMajorVersion int ArtifactName string + ShouldLockSwiftPackages bool + // Code signing, nil if automatic code signing is "off" CodesignManager *codesign.Manager @@ -361,6 +366,13 @@ func (s XcodebuildArchiver) Run(opts RunOpts) (RunResult, error) { s.logger.Println() if opts.XcodeMajorVersion >= 11 { + if opts.ShouldLockSwiftPackages { + s.logger.Infof("Swift package dependencies are locked, disabling automatic updates") + if err := lockSwiftPackages(s.logger, s.cmdFactory); err != nil { + return out, fmt.Errorf("failed to lock swift packages: %w", err) + } + } + s.logger.Infof("Running resolve Swift package dependencies") // Resolve Swift package dependencies, so running -showBuildSettings later is faster later // Specifying a scheme is required for workspaces @@ -1003,9 +1015,9 @@ func (s XcodebuildArchiver) xcodeIPAExport(opts xcodeIPAExportOpts) (xcodeIPAExp signingStyle = exportoptions.SigningStyleAutomatic } - generator := exportoptionsgenerator.New(xcodeProj, scheme, configuration, s.logger) + generator := exportoptionsgenerator.New(xcodeProj, scheme, configuration, s.xcodeVersionReader, s.logger) exportOptions, err := generator.GenerateApplicationExportOptions(exportMethod, opts.ICloudContainerEnvironment, opts.ExportDevelopmentTeam, - opts.UploadBitcode, opts.CompileBitcode, archiveCodeSignIsXcodeManaged, signingStyle, int64(opts.XcodeMajorVersion), opts.TestFlightInternalTestingOnly) + opts.UploadBitcode, opts.CompileBitcode, archiveCodeSignIsXcodeManaged, signingStyle, opts.TestFlightInternalTestingOnly) if err != nil { return out, err } diff --git a/step/step_test.go b/step/step_test.go index dae0b7d0..1659f1ac 100644 --- a/step/step_test.go +++ b/step/step_test.go @@ -36,9 +36,8 @@ func TestXcodeArchiveStep_ProcessInputs(t *testing.T) { t.Run(tt.name, func(t *testing.T) { envRepository := MockEnvRepository{envs: tt.envs} s := XcodebuildArchiveConfigParser{ - xcodeVersionProvider: NewMockXcodeVersionProvider(models.XcodebuildVersionModel{MajorVersion: 11}), - stepInputParser: stepconf.NewInputParser(envRepository), - logger: log.NewLogger(), + stepInputParser: stepconf.NewInputParser(envRepository), + logger: log.NewLogger(), } config, err := s.ProcessInputs() diff --git a/step/utils.go b/step/utils.go index 1cce2a76..719e3ef8 100644 --- a/step/utils.go +++ b/step/utils.go @@ -3,12 +3,14 @@ package step import ( "bufio" "fmt" + "os" "regexp" "strings" "github.com/bitrise-io/go-utils/colorstring" "github.com/bitrise-io/go-utils/sliceutil" "github.com/bitrise-io/go-utils/stringutil" + "github.com/bitrise-io/go-utils/v2/command" "github.com/bitrise-io/go-utils/v2/log" "github.com/bitrise-io/go-xcode/exportoptions" ) @@ -91,3 +93,23 @@ func findIDEDistrubutionLogsPath(output string, logger log.Logger) (string, erro return "", nil } + +func lockSwiftPackages(logger log.Logger, cmdFactory command.Factory) error { + cmdOpts := &command.Opts{ + Stdout: os.Stdout, + Stderr: os.Stderr, + } + deafultsCommands := []command.Command{ + cmdFactory.Create("defaults", []string{"write", "com.apple.dt.Xcode", "IDEPackageOnlyUseVersionsFromResolvedFile", "-bool", "YES"}, cmdOpts), + cmdFactory.Create("defaults", []string{"write", "com.apple.dt.Xcode", "IDEDisableAutomaticPackageResolution", "-bool", "YES"}, cmdOpts), + } + + for _, cmd := range deafultsCommands { + logger.TPrintf("$ %s", cmd.PrintableCommandArgs()) + if err := cmd.Run(); err != nil { + return fmt.Errorf("Locking Swift pacakges failed: %w", err) + } + } + + return nil +} diff --git a/step/xcode_version_provider.go b/step/xcode_version_provider.go deleted file mode 100644 index dd0c65dd..00000000 --- a/step/xcode_version_provider.go +++ /dev/null @@ -1,22 +0,0 @@ -package step - -import ( - "github.com/bitrise-io/go-xcode/models" - "github.com/bitrise-io/go-xcode/utility" -) - -type XcodeVersionProvider interface { - GetXcodeVersion() (models.XcodebuildVersionModel, error) -} - -type xcodebuildXcodeVersionProvider struct { -} - -func NewXcodebuildXcodeVersionProvider() XcodeVersionProvider { - return xcodebuildXcodeVersionProvider{} -} - -// GetXcodeVersion ... -func (p xcodebuildXcodeVersionProvider) GetXcodeVersion() (models.XcodebuildVersionModel, error) { - return utility.GetXcodeVersion() -} diff --git a/vendor/github.com/bitrise-io/go-xcode/v2/exportoptionsgenerator/exportoptionsgenerator.go b/vendor/github.com/bitrise-io/go-xcode/v2/exportoptionsgenerator/exportoptionsgenerator.go index 32ff1828..6eff3b9c 100644 --- a/vendor/github.com/bitrise-io/go-xcode/v2/exportoptionsgenerator/exportoptionsgenerator.go +++ b/vendor/github.com/bitrise-io/go-xcode/v2/exportoptionsgenerator/exportoptionsgenerator.go @@ -10,6 +10,7 @@ import ( "github.com/bitrise-io/go-xcode/exportoptions" "github.com/bitrise-io/go-xcode/plistutil" "github.com/bitrise-io/go-xcode/profileutil" + "github.com/bitrise-io/go-xcode/v2/xcodeversion" "github.com/bitrise-io/go-xcode/xcodeproject/serialized" "github.com/bitrise-io/go-xcode/xcodeproject/xcodeproj" "github.com/bitrise-io/go-xcode/xcodeproject/xcscheme" @@ -26,6 +27,7 @@ type ExportOptionsGenerator struct { scheme *xcscheme.Scheme configuration string + xcodeVersionReader xcodeversion.Reader certificateProvider CodesignIdentityProvider profileProvider ProvisioningProfileProvider targetInfoProvider TargetInfoProvider @@ -33,11 +35,12 @@ type ExportOptionsGenerator struct { } // New constructs a new ExportOptionsGenerator. -func New(xcodeProj *xcodeproj.XcodeProj, scheme *xcscheme.Scheme, configuration string, logger log.Logger) ExportOptionsGenerator { +func New(xcodeProj *xcodeproj.XcodeProj, scheme *xcscheme.Scheme, configuration string, xcodeVersionReader xcodeversion.Reader, logger log.Logger) ExportOptionsGenerator { g := ExportOptionsGenerator{ - xcodeProj: xcodeProj, - scheme: scheme, - configuration: configuration, + xcodeProj: xcodeProj, + scheme: scheme, + configuration: configuration, + xcodeVersionReader: xcodeVersionReader, } g.certificateProvider = LocalCodesignIdentityProvider{} g.profileProvider = LocalProvisioningProfileProvider{} @@ -55,26 +58,30 @@ func (g ExportOptionsGenerator) GenerateApplicationExportOptions( compileBitcode bool, archivedWithXcodeManagedProfiles bool, codeSigningStyle exportoptions.SigningStyle, - xcodeMajorVersion int64, testFlightInternalTestingOnly bool, ) (exportoptions.ExportOptions, error) { + xcodeVersion, err := g.xcodeVersionReader.GetVersion() + if err != nil { + return nil, fmt.Errorf("failed to get Xcode version: %w", err) + } + mainTargetBundleID, entitlementsByBundleID, err := g.applicationTargetsAndEntitlements(exportMethod) if err != nil { return nil, err } - iCloudContainerEnvironment, err := determineIcloudContainerEnvironment(containerEnvironment, entitlementsByBundleID, exportMethod, xcodeMajorVersion) + iCloudContainerEnvironment, err := determineIcloudContainerEnvironment(containerEnvironment, entitlementsByBundleID, exportMethod, xcodeVersion.Major) if err != nil { return nil, err } - exportOpts := generateBaseExportOptions(exportMethod, uploadBitcode, compileBitcode, iCloudContainerEnvironment) + exportOpts := generateBaseExportOptions(exportMethod, xcodeVersion, uploadBitcode, compileBitcode, iCloudContainerEnvironment) - if xcodeMajorVersion >= 12 { + if xcodeVersion.Major >= 12 { exportOpts = addDistributionBundleIdentifierFromXcode12(exportOpts, mainTargetBundleID) } - if xcodeMajorVersion >= 13 { + if xcodeVersion.Major >= 13 { exportOpts = disableManagedBuildNumberFromXcode13(exportOpts) } @@ -92,7 +99,7 @@ func (g ExportOptionsGenerator) GenerateApplicationExportOptions( exportOpts = addManualSigningFields(exportOpts, codeSignGroup, archivedWithXcodeManagedProfiles, g.logger) } - if xcodeMajorVersion >= 15 { + if xcodeVersion.Major >= 15 { if testFlightInternalTestingOnly { exportOpts = addTestFlightInternalTestingOnly(exportOpts, testFlightInternalTestingOnly) } @@ -292,11 +299,11 @@ func determineIcloudContainerEnvironment(desiredIcloudContainerEnvironment strin } // From Xcode 9 iCloudContainerEnvironment is required for every export method, before that version only for non app-store exports. - if xcodeMajorVersion < 9 && exportMethod == exportoptions.MethodAppStore { + if xcodeMajorVersion < 9 && exportMethod.IsAppStore() { return "", nil } - if exportMethod == exportoptions.MethodAppStore { + if exportMethod.IsAppStore() { return "Production", nil } @@ -332,9 +339,13 @@ func projectUsesCloudKit(bundleIDEntitlementsMap map[string]plistutil.PlistData) } // generateBaseExportOptions creates a default exportOptions introduced in Xcode 7. -func generateBaseExportOptions(exportMethod exportoptions.Method, cfgUploadBitcode, cfgCompileBitcode bool, iCloudContainerEnvironment string) exportoptions.ExportOptions { - if exportMethod == exportoptions.MethodAppStore { - appStoreOptions := exportoptions.NewAppStoreOptions() +func generateBaseExportOptions(exportMethod exportoptions.Method, xcodeVersion xcodeversion.Version, cfgUploadBitcode, cfgCompileBitcode bool, iCloudContainerEnvironment string) exportoptions.ExportOptions { + if xcodeVersion.IsGreaterThanOrEqualTo(15, 3) { + exportMethod = exportoptions.UpgradeToXcode15_3MethodName(exportMethod) + } + + if exportMethod.IsAppStore() { + appStoreOptions := exportoptions.NewAppStoreConnectOptions(exportMethod) appStoreOptions.UploadBitcode = cfgUploadBitcode if iCloudContainerEnvironment != "" { appStoreOptions.ICloudContainerEnvironment = exportoptions.ICloudContainerEnvironment(iCloudContainerEnvironment) diff --git a/vendor/github.com/bitrise-io/go-xcode/v2/exportoptionsgenerator/targets.go b/vendor/github.com/bitrise-io/go-xcode/v2/exportoptionsgenerator/targets.go index fa2d9042..b503f9a5 100644 --- a/vendor/github.com/bitrise-io/go-xcode/v2/exportoptionsgenerator/targets.go +++ b/vendor/github.com/bitrise-io/go-xcode/v2/exportoptionsgenerator/targets.go @@ -2,6 +2,7 @@ package exportoptionsgenerator import ( "fmt" + "github.com/bitrise-io/go-xcode/exportoptions" "github.com/bitrise-io/go-xcode/xcodeproject/serialized" "github.com/bitrise-io/go-xcode/xcodeproject/xcodeproj" @@ -62,7 +63,7 @@ func filterApplicationBundleTargets(targets []xcodeproj.Target, exportMethod exp // Development App Clip Profile // // .., - if exportMethod != exportoptions.MethodAppStore && target.IsAppClipProduct() { + if !exportMethod.IsAppStore() && target.IsAppClipProduct() { continue } diff --git a/vendor/github.com/bitrise-io/go-xcode/v2/xcodeversion/utility.go b/vendor/github.com/bitrise-io/go-xcode/v2/xcodeversion/utility.go new file mode 100644 index 00000000..ca542714 --- /dev/null +++ b/vendor/github.com/bitrise-io/go-xcode/v2/xcodeversion/utility.go @@ -0,0 +1,45 @@ +package xcodeversion + +import ( + "fmt" + "regexp" + "strconv" +) + +func getXcodeVersionFromXcodebuildOutput(outStr string) (Version, error) { + versionRegexp := regexp.MustCompile(`(?m)^Xcode +(\d+)(\.(\d+))?.*$`) + buildVersionRegexp := regexp.MustCompile(`(?m)^Build version +(\w.*)$`) + + xcodeVersionMatch := versionRegexp.FindStringSubmatch(outStr) + if len(xcodeVersionMatch) < 4 { + return Version{}, fmt.Errorf("couldn't find Xcode version in output: (%s)", outStr) + } + + xcodebuildVersion := xcodeVersionMatch[0] + majorVersionStr := xcodeVersionMatch[1] + majorVersion, err := strconv.Atoi(majorVersionStr) + if err != nil { + return Version{}, fmt.Errorf("failed to parse xcodebuild major version (output %s): %w", outStr, err) + } + + minorVersion := int(0) + minorVersionStr := xcodeVersionMatch[3] + if minorVersionStr != "" { + if minorVersion, err = strconv.Atoi(minorVersionStr); err != nil { + return Version{}, fmt.Errorf("failed to parse xcodebuild minor version (output %s): %w", outStr, err) + } + } + + buildVersionMatch := buildVersionRegexp.FindStringSubmatch(outStr) + buildVersion := "unknown" + if len(buildVersionMatch) >= 2 { + buildVersion = buildVersionMatch[1] + } + + return Version{ + Version: xcodebuildVersion, + BuildVersion: buildVersion, + Major: int64(majorVersion), + Minor: int64(minorVersion), + }, nil +} diff --git a/vendor/github.com/bitrise-io/go-xcode/v2/xcodeversion/xcodeversion.go b/vendor/github.com/bitrise-io/go-xcode/v2/xcodeversion/xcodeversion.go new file mode 100644 index 00000000..a28c3652 --- /dev/null +++ b/vendor/github.com/bitrise-io/go-xcode/v2/xcodeversion/xcodeversion.go @@ -0,0 +1,54 @@ +package xcodeversion + +import ( + "fmt" + + "github.com/bitrise-io/go-utils/v2/command" +) + +// Version ... +type Version struct { + Version string + BuildVersion string + Major int64 + Minor int64 +} + +// Reader ... +type Reader interface { + GetVersion() (Version, error) +} + +type reader struct { + commandFactory command.Factory +} + +// NewXcodeVersionProvider ... +func NewXcodeVersionProvider(commandFactory command.Factory) Reader { + return &reader{ + commandFactory: commandFactory, + } +} + +// GetVersion ... +func (b *reader) GetVersion() (Version, error) { + cmd := b.commandFactory.Create("xcodebuild", []string{"-version"}, &command.Opts{}) + + outStr, err := cmd.RunAndReturnTrimmedCombinedOutput() + if err != nil { + return Version{}, fmt.Errorf("xcodebuild -version failed: %s, output: %s", err, outStr) + } + + return getXcodeVersionFromXcodebuildOutput(outStr) +} + +// IsGreaterThanOrEqualTo checks if the Xcode version is greater than or equal to the given major and minor version. +func (v Version) IsGreaterThanOrEqualTo(major, minor int64) bool { + if v.Major > major { + return true + } + if v.Major == major && v.Minor >= minor { + return true + } + return false +} diff --git a/vendor/modules.txt b/vendor/modules.txt index e2dca666..88b08d6c 100644 --- a/vendor/modules.txt +++ b/vendor/modules.txt @@ -57,7 +57,7 @@ github.com/bitrise-io/go-xcode/xcodeproject/serialized github.com/bitrise-io/go-xcode/xcodeproject/xcodeproj github.com/bitrise-io/go-xcode/xcodeproject/xcscheme github.com/bitrise-io/go-xcode/xcodeproject/xcworkspace -# github.com/bitrise-io/go-xcode/v2 v2.0.0-alpha.55 +# github.com/bitrise-io/go-xcode/v2 v2.0.0-alpha.56 ## explicit; go 1.22 github.com/bitrise-io/go-xcode/v2/autocodesign github.com/bitrise-io/go-xcode/v2/autocodesign/certdownloader @@ -79,6 +79,7 @@ github.com/bitrise-io/go-xcode/v2/xcarchive github.com/bitrise-io/go-xcode/v2/xcconfig github.com/bitrise-io/go-xcode/v2/xcodecache github.com/bitrise-io/go-xcode/v2/xcodecommand +github.com/bitrise-io/go-xcode/v2/xcodeversion # github.com/davecgh/go-spew v1.1.1 ## explicit github.com/davecgh/go-spew/spew