Skip to content

Commit 013d873

Browse files
authored
Override API connection via step inputs (#303)
* Override API connection via step inputs * Refactor * Fix method name * Unset test app commit env var * Remove commit ref from test * Update go-xcode * Clear Bitrise API envs for testing * yamllint fix * Fix script * Update readme with connection override inputs * Don't try connection if API env vars are not defined * Add debug log statements * Debug * Debug * Fix nil pointer dereference * Remove debug logs
1 parent 7073b5f commit 013d873

File tree

99 files changed

+6948
-2526
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

99 files changed

+6948
-2526
lines changed

README.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,8 @@ Under **Automatic code signing**:
4242
3. **The minimum days the Provisioning Profile should be valid**: If this input is set to >0, the managed Provisioning Profile will be renewed if it expires within the configured number of days. Otherwise the Step renews the managed Provisioning Profile if it is expired.
4343
4. The **Code signing certificate URL**, the **Code signing certificate passphrase**, the **Keychain path**, and the **Keychain password** inputs are automatically populated if certificates are uploaded to Bitrise's **Code Signing** tab. If you store your files in a private repo, you can manually edit these fields.
4444

45+
If you want to set the Apple service connection credentials on the step-level (instead of using the one configured in the App Settings), use the Step inputs in the **App Store Connect connection override** category. Note that this only works if **Automatic code signing method** is set to `api-key`.
46+
4547
Under **IPA export configuration**:
4648
1. **Developer Portal team**: Add the Developer Portal team's name to use for this export. This input defaults to the team used to build the archive.
4749
2. **Rebuild from bitcode**: For non-App Store exports, should Xcode re-compile the app from bitcode?
@@ -131,6 +133,9 @@ Build a development IPA with custom xcconfig file path:
131133
| `export_all_dsyms` | Export additional dSYM files besides the app dSYM file for Frameworks. | required | `yes` |
132134
| `artifact_name` | This name will be used as basename for the generated Xcode Archive, App, IPA and dSYM files. If not specified, the Product Name (`PRODUCT_NAME`) Build settings value will be used. If Product Name is not specified, the Scheme will be used. | | |
133135
| `cache_level` | Defines what cache content should be automatically collected. Available options: - `none`: Disable collecting cache content - `swift_packages`: Collect Swift PM packages added to the Xcode project | required | `swift_packages` |
136+
| `api_key_path` | Local path or remote URL to the private key (p8 file) for App Store Connect API. This overrides the Bitrise-managed API connection, only set this input if you want to control the API connection on a step-level. Most of the time it's easier to set up the connection on the App Settings page on Bitrise. The input value can be a file path (eg. `$TMPDIR/private_key.p8`) or an HTTPS URL. This input only takes effect if the other two connection override inputs are set too (`api_key_id`, `api_key_issuer_id`). | | |
137+
| `api_key_id` | Private key ID used for App Store Connect authentication. This overrides the Bitrise-managed API connection, only set this input if you want to control the API connection on a step-level. Most of the time it's easier to set up the connection on the App Settings page on Bitrise. This input only takes effect if the other two connection override inputs are set too (`api_key_path`, `api_key_issuer_id`). | | |
138+
| `api_key_issuer_id` | Private key issuer ID used for App Store Connect authentication. This overrides the Bitrise-managed API connection, only set this input if you want to control the API connection on a step-level. Most of the time it's easier to set up the connection on the App Settings page on Bitrise. This input only takes effect if the other two connection override inputs are set too (`api_key_path`, `api_key_id`). | | |
134139
| `verbose_log` | If this input is set, the Step will print additional logs for debugging. | required | `no` |
135140
</details>
136141

e2e/bitrise.yml

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,9 +14,44 @@ app:
1414
- BITFALL_APPLE_PROVISIONING_PROFILE_URL_LIST: $BITFALL_APPLE_PROVISIONING_PROFILE_URL_LIST
1515

1616
- BITFALL_APPSTORECONNECT_API_KEY_URL: $BITFALL_APPSTORECONNECT_API_KEY_URL
17+
- BITFALL_APPSTORECONNECT_API_KEY_ID: $BITFALL_APPSTORECONNECT_API_KEY_ID
1718
- BITFALL_APPSTORECONNECT_API_KEY_ISSUER_ID: $BITFALL_APPSTORECONNECT_API_KEY_ISSUER_ID
1819

1920
workflows:
21+
22+
test_override_api_key_signing:
23+
description: Test API key based signing on a project where code signing is not managed automatically, by step inputs
24+
envs:
25+
- TEST_APP_URL: https://github.com/bitrise-io/Fruta
26+
- TEST_APP_BRANCH: manual-signing
27+
- TEST_APP_COMMIT: ""
28+
- BITRISE_PROJECT_PATH: Fruta.xcodeproj
29+
- BITRISE_SCHEME: Fruta iOS
30+
- CODE_SIGNING_METHOD: api-key
31+
- API_KEY_PATH: $BITFALL_APPSTORECONNECT_API_KEY_URL
32+
- API_KEY_ID: $BITFALL_APPSTORECONNECT_API_KEY_ID
33+
- API_KEY_ISSUER_ID: $BITFALL_APPSTORECONNECT_API_KEY_ISSUER_ID
34+
- MIN_DAYS_PROFILE_VALID: 0
35+
- IPA_EXPORT_METHOD: development
36+
- LOG_FORMATTER: xcodebuild
37+
steps:
38+
- script:
39+
title: Unset Bitrise API connection env vars
40+
inputs:
41+
- content: |-
42+
#!/usr/bin/env bash
43+
set -ex
44+
envman add --key BITRISE_BUILD_URL_BACKUP --value $BITRISE_BUILD_URL
45+
envman add --key BITRISE_BUILD_API_TOKEN_BACKUP --value $BITRISE_BUILD_API_TOKEN
46+
envman unset --key BITRISE_BUILD_URL
47+
envman unset --key BITRISE_BUILD_API_TOKEN
48+
49+
after_run:
50+
- _run
51+
- _check_outputs
52+
- _check_exported_artifacts
53+
- _restore_api_envs
54+
2055
test_single_certificate_no_passphrase:
2156
steps:
2257
- script:
@@ -412,6 +447,9 @@ workflows:
412447
- keychain_path: $BITRISE_KEYCHAIN_PATH
413448
- keychain_password: $BITRISE_KEYCHAIN_PASSWORD
414449
- fallback_provisioning_profile_url_list: $FALLBACK_PROFILES
450+
- api_key_path: $API_KEY_PATH
451+
- api_key_id: $API_KEY_ID
452+
- api_key_issuer_id: $API_KEY_ISSUER_ID
415453

416454
_check_outputs:
417455
steps:
@@ -540,3 +578,13 @@ workflows:
540578
xcode_major_version=${BASH_REMATCH[1]}
541579
echo "Xcode major version: $xcode_major_version"
542580
envman add --key XCODE_MAJOR_VERSION --value $xcode_major_version
581+
582+
_restore_api_envs:
583+
steps:
584+
- script:
585+
title: Restore Bitrise API connection env vars
586+
inputs:
587+
- content: |-
588+
set -ex
589+
envman add --key BITRISE_BUILD_URL --value $BITRISE_BUILD_URL_BACKUP
590+
envman add --key BITRISE_BUILD_API_TOKEN --value $BITRISE_BUILD_API_TOKEN_BACKUP

go.mod

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,13 +5,12 @@ go 1.16
55
require (
66
github.com/bitrise-io/go-steputils/v2 v2.0.0-alpha.2
77
github.com/bitrise-io/go-utils v1.0.2
8-
github.com/bitrise-io/go-utils/v2 v2.0.0-alpha.7
9-
github.com/bitrise-io/go-xcode v1.0.8
10-
github.com/bitrise-io/go-xcode/v2 v2.0.0-alpha.17
8+
github.com/bitrise-io/go-utils/v2 v2.0.0-alpha.11
9+
github.com/bitrise-io/go-xcode v1.0.9
10+
github.com/bitrise-io/go-xcode/v2 v2.0.0-alpha.20
1111
github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51
1212
github.com/stretchr/testify v1.7.1
1313
golang.org/x/crypto v0.0.0-20220525230936-793ad666bf5e // indirect
14-
golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a // indirect
1514
golang.org/x/term v0.0.0-20220526004731-065cf7ba2467 // indirect
1615
gopkg.in/yaml.v3 v3.0.1
1716
howett.net/plist v1.0.0

go.sum

Lines changed: 8 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -9,13 +9,12 @@ github.com/bitrise-io/go-utils v1.0.1/go.mod h1:ZY1DI+fEpZuFpO9szgDeICM4QbqoWVt0
99
github.com/bitrise-io/go-utils v1.0.2 h1:w4Mz2IvrgDzrFJECuHdvsK1LHO30cdtuy9bBa7Lw2c0=
1010
github.com/bitrise-io/go-utils v1.0.2/go.mod h1:ZY1DI+fEpZuFpO9szgDeICM4QbqoWVt0RSY3tRI1heY=
1111
github.com/bitrise-io/go-utils/v2 v2.0.0-alpha.1/go.mod h1:sy+Ir1X8P3tAAx/qU/r+hqDjHDcrMjIzDEvId1wqNc4=
12-
github.com/bitrise-io/go-utils/v2 v2.0.0-alpha.7 h1:d0XDESvQwOO+V9afZrI8QGR7bJGDkmE4Q9ezIBB4TLw=
13-
github.com/bitrise-io/go-utils/v2 v2.0.0-alpha.7/go.mod h1:6i0Gt0JRIbXpsrFDJT1YWghFfdN8qF26/fnpc/6d/88=
14-
github.com/bitrise-io/go-xcode v1.0.6/go.mod h1:Y0Wu2dXm0MilJ/4D3+gPHaNMlUcP+1DjIPoLPykq7wY=
15-
github.com/bitrise-io/go-xcode v1.0.8 h1:fNB5TmbfsqWRh5ibtKdFdxPEua8gaNBmDt1rPM/GDuo=
16-
github.com/bitrise-io/go-xcode v1.0.8/go.mod h1:Y0Wu2dXm0MilJ/4D3+gPHaNMlUcP+1DjIPoLPykq7wY=
17-
github.com/bitrise-io/go-xcode/v2 v2.0.0-alpha.17 h1:aLlblow6vgnFKBRJRPz03O/M6x6LYY57wDkRCh66XL0=
18-
github.com/bitrise-io/go-xcode/v2 v2.0.0-alpha.17/go.mod h1:oYILBt4j8jn69avylknuqsUO/BSiRx9i+JaxcNOtWMA=
12+
github.com/bitrise-io/go-utils/v2 v2.0.0-alpha.11 h1:IacLMHL7hhgVcqtx15Bysq738P8FRCp6ckGk1NvioWo=
13+
github.com/bitrise-io/go-utils/v2 v2.0.0-alpha.11/go.mod h1:SJqGxzwjIAx2LVQxNGS4taN7X//eDPJLrFxJ1MpOuyA=
14+
github.com/bitrise-io/go-xcode v1.0.9 h1:+sbqOYidQ+aiFfCTDpf2LdGSQEM5RfbtDsiG27zJG+s=
15+
github.com/bitrise-io/go-xcode v1.0.9/go.mod h1:Y0Wu2dXm0MilJ/4D3+gPHaNMlUcP+1DjIPoLPykq7wY=
16+
github.com/bitrise-io/go-xcode/v2 v2.0.0-alpha.20 h1:MIH3eGNcAsc5VBACiU+EFcmUfqCyT6/fMSi2UjYR9+s=
17+
github.com/bitrise-io/go-xcode/v2 v2.0.0-alpha.20/go.mod h1:8WBcRgrVXY8tzR7NcjE4fw6WguOIfB3YcC7ZTcQYUEY=
1918
github.com/bitrise-io/pkcs12 v0.0.0-20211108084543-e52728e011c8 h1:kmvU8AxrNTxXsVPKepBHD8W+eCVmeaKyTkRuUJB2K38=
2019
github.com/bitrise-io/pkcs12 v0.0.0-20211108084543-e52728e011c8/go.mod h1:UiXKNs0essbC14a2TvGlnUKo9isP9m4guPrp8KJHJpU=
2120
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
@@ -74,8 +73,8 @@ golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7w
7473
golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
7574
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
7675
golang.org/x/sys v0.0.0-20211205182925-97ca703d548d/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
77-
golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a h1:dGzPydgVsqGcTRVwiLJ1jVbufYwmzD3LfVPLKsKg+0k=
78-
golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
76+
golang.org/x/sys v0.0.0-20220712014510-0a85c31ab51e h1:NHvCuwuS43lGnYhten69ZWqi2QOj/CiDNcKbVqwVoew=
77+
golang.org/x/sys v0.0.0-20220712014510-0a85c31ab51e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
7978
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
8079
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
8180
golang.org/x/term v0.0.0-20220526004731-065cf7ba2467 h1:CBpWXWQpIRjzmkkA+M7q9Fqnwd2mZr3AFqexg8YTfoM=

main.go

Lines changed: 23 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -106,6 +106,9 @@ type Inputs struct {
106106
RegisterTestDevices bool `env:"register_test_devices,opt[yes,no]"`
107107
MinDaysProfileValid int `env:"min_profile_validity,required"`
108108
FallbackProvisioningProfileURLs string `env:"fallback_provisioning_profile_url_list"`
109+
APIKeyPath stepconf.Secret `env:"api_key_path"`
110+
APIKeyID string `env:"api_key_id"`
111+
APIKeyIssuerID string `env:"api_key_issuer_id"`
109112
BuildURL string `env:"BITRISE_BUILD_URL"`
110113
BuildAPIToken stepconf.Secret `env:"BITRISE_BUILD_API_TOKEN"`
111114
}
@@ -355,15 +358,22 @@ func (s XcodeArchiveStep) createCodesignManager(config Config) (codesign.Manager
355358
return codesign.Manager{}, fmt.Errorf("issue with input: %s", err)
356359
}
357360

358-
var serviceConnection *devportalservice.AppleDeveloperConnection = nil
359361
devPortalClientFactory := devportalclient.NewFactory(logger)
360-
if authType == codesign.APIKeyAuth || authType == codesign.AppleIDAuth {
362+
363+
var serviceConnection *devportalservice.AppleDeveloperConnection = nil
364+
if config.BuildURL != "" && config.BuildAPIToken != "" {
361365
if serviceConnection, err = devPortalClientFactory.CreateBitriseConnection(config.BuildURL, string(config.BuildAPIToken)); err != nil {
362366
return codesign.Manager{}, err
363367
}
364368
}
365369

366-
appleAuthCredentials, err := codesign.SelectConnectionCredentials(authType, serviceConnection, logger)
370+
connectionInputs := codesign.ConnectionOverrideInputs{
371+
APIKeyPath: config.Inputs.APIKeyPath,
372+
APIKeyID: config.Inputs.APIKeyID,
373+
APIKeyIssuerID: config.Inputs.APIKeyIssuerID,
374+
}
375+
376+
appleAuthCredentials, err := codesign.SelectConnectionCredentials(authType, serviceConnection, connectionInputs, logger)
367377
if err != nil {
368378
return codesign.Manager{}, err
369379
}
@@ -390,10 +400,14 @@ func (s XcodeArchiveStep) createCodesignManager(config Config) (codesign.Manager
390400
}
391401

392402
client := retry.NewHTTPClient().StandardClient()
403+
var testDevices []devportalservice.TestDevice
404+
if serviceConnection != nil {
405+
testDevices = serviceConnection.TestDevices
406+
}
393407
return codesign.NewManagerWithProject(
394408
opts,
395409
appleAuthCredentials,
396-
serviceConnection,
410+
testDevices,
397411
devPortalClientFactory,
398412
certdownloader.NewDownloader(codesignConfig.CertificatesAndPassphrases, client),
399413
profiledownloader.New(codesignConfig.FallbackProvisioningProfiles, client),
@@ -509,24 +523,17 @@ func (s XcodeArchiveStep) xcodeArchive(opts xcodeArchiveOpts) (xcodeArchiveOutpu
509523
logger.Println()
510524
logger.TInfof("Creating the Archive ...")
511525

512-
isWorkspace := false
513-
ext := filepath.Ext(opts.ProjectPath)
514-
if ext == ".xcodeproj" {
515-
isWorkspace = false
516-
} else if ext == ".xcworkspace" {
517-
isWorkspace = true
526+
var actions []string
527+
if opts.PerformCleanAction {
528+
actions = []string{"clean", "archive"}
518529
} else {
519-
return out, fmt.Errorf("project file extension should be .xcodeproj or .xcworkspace, but got: %s", ext)
530+
actions = []string{"archive"}
520531
}
521532

522-
archiveCmd := xcodebuild.NewCommandBuilder(opts.ProjectPath, isWorkspace, xcodebuild.ArchiveAction)
533+
archiveCmd := xcodebuild.NewCommandBuilder(opts.ProjectPath, actions...)
523534
archiveCmd.SetScheme(opts.Scheme)
524535
archiveCmd.SetConfiguration(opts.Configuration)
525536

526-
if opts.PerformCleanAction {
527-
archiveCmd.SetCustomBuildAction("clean")
528-
}
529-
530537
if opts.XcconfigContent != "" {
531538
xcconfigWriter := xcconfig.NewWriter(s.pathProvider, s.fileManager, s.pathChecker, s.pathModifier)
532539
xcconfigPath, err := xcconfigWriter.Write(opts.XcconfigContent)

step.yml

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,8 @@ description: |-
3636
3. **The minimum days the Provisioning Profile should be valid**: If this input is set to >0, the managed Provisioning Profile will be renewed if it expires within the configured number of days. Otherwise the Step renews the managed Provisioning Profile if it is expired.
3737
4. The **Code signing certificate URL**, the **Code signing certificate passphrase**, the **Keychain path**, and the **Keychain password** inputs are automatically populated if certificates are uploaded to Bitrise's **Code Signing** tab. If you store your files in a private repo, you can manually edit these fields.
3838
39+
If you want to set the Apple service connection credentials on the step-level (instead of using the one configured in the App Settings), use the Step inputs in the **App Store Connect connection override** category. Note that this only works if **Automatic code signing method** is set to `api-key`.
40+
3941
Under **IPA export configuration**:
4042
1. **Developer Portal team**: Add the Developer Portal team's name to use for this export. This input defaults to the team used to build the archive.
4143
2. **Rebuild from bitcode**: For non-App Store exports, should Xcode re-compile the app from bitcode?
@@ -392,6 +394,45 @@ inputs:
392394
- swift_packages
393395
is_required: true
394396

397+
# App Store Connect connection override
398+
399+
- api_key_path:
400+
opts:
401+
category: App Store Connect connection override
402+
title: App Store Connect API private key
403+
summary: Local path or remote URL to the private key (p8 file). This overrides the Bitrise-managed API connection.
404+
description: |-
405+
Local path or remote URL to the private key (p8 file) for App Store Connect API.
406+
This overrides the Bitrise-managed API connection, only set this input if you want to control the API connection
407+
on a step-level. Most of the time it's easier to set up the connection on the App Settings page on Bitrise.
408+
The input value can be a file path (eg. `$TMPDIR/private_key.p8`) or an HTTPS URL.
409+
This input only takes effect if the other two connection override inputs are set too (`api_key_id`, `api_key_issuer_id`).
410+
is_required: false
411+
412+
- api_key_id:
413+
opts:
414+
category: App Store Connect connection override
415+
title: App Store Connect API key ID
416+
summary: Private key ID used for App Store Connect authentication. This overrides the Bitrise-managed API connection.
417+
description: |-
418+
Private key ID used for App Store Connect authentication.
419+
This overrides the Bitrise-managed API connection, only set this input if you want to control the API connection
420+
on a step-level. Most of the time it's easier to set up the connection on the App Settings page on Bitrise.
421+
This input only takes effect if the other two connection override inputs are set too (`api_key_path`, `api_key_issuer_id`).
422+
is_required: false
423+
424+
- api_key_issuer_id:
425+
opts:
426+
category: App Store Connect connection override
427+
title: App Store Connect API issuer ID
428+
summary: Private key issuer ID used for App Store Connect authentication. This overrides the Bitrise-managed API connection.
429+
description: |-
430+
Private key issuer ID used for App Store Connect authentication.
431+
This overrides the Bitrise-managed API connection, only set this input if you want to control the API connection
432+
on a step-level. Most of the time it's easier to set up the connection on the App Settings page on Bitrise.
433+
This input only takes effect if the other two connection override inputs are set too (`api_key_path`, `api_key_id`).
434+
is_required: false
435+
395436
# Debugging
396437

397438
- verbose_log: "no"

vendor/github.com/bitrise-io/go-utils/v2/retryhttp/retryhttp.go

Lines changed: 25 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)