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

Add automation and configuration for Prototype Builds #1769

Merged
merged 23 commits into from
Jun 4, 2024
Merged
Show file tree
Hide file tree
Changes from 14 commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
73dbaed
Rename unused (?) Staging build configuration to Prototype
mokagio May 17, 2024
ad872c3
Move bundle id definition to `xcconfig`
mokagio May 17, 2024
33c5d8d
Parameterize and differentiate bundle ids between AS and Prototype
mokagio May 17, 2024
f166314
Add scheme and lane for Enterprise/Prototype Build
mokagio May 17, 2024
90f853d
Push code sign identity definitions at project level (DRY)
mokagio May 17, 2024
da34412
Push development team definition to `base.xcconfig` (DRY)
mokagio May 17, 2024
2cc0ef5
Use Enterprise dev team for Prototype build configuration
mokagio May 17, 2024
fc4235c
Order extensions alphabetically like Developer Portal does
mokagio May 17, 2024
b86f6a2
Remove legacy Today Extension scheme
mokagio May 17, 2024
f257d72
Remove dead references to Today Extension target
mokagio May 17, 2024
65d64d6
Add entitlements files for Prototype bulid
mokagio May 17, 2024
76774f7
Add prototype entitlements for PodcastsIntents, Share, and Widget ext.
mokagio May 17, 2024
2aa1986
DRY provisioning profile definition and remove cruft
mokagio May 17, 2024
c34b76a
DRY and update provisioning profiles for Prototype Build
mokagio May 17, 2024
379f558
Remove `-D STAGING` flag from Prototype build configuration
mokagio May 21, 2024
ce45265
Remove `-D DEBUG` from Prototype build configuration
mokagio May 21, 2024
96dd4c9
Move `OTHER_SWIFT_FLAGS = -D DEBUG` to the `xcconfig` level
mokagio May 21, 2024
2068f14
Reintroduce Staging build configuration
mokagio May 21, 2024
d7df0e7
Add dedicated scheme to run Staging app
mokagio May 21, 2024
049f84a
Make prototype build run with `-D DEBUG`
mokagio May 29, 2024
151204b
Compute `WKCompanionAppBundleIdentifier` for watch app from `xcconfig`
mokagio May 29, 2024
d3b6d7a
Add bundle identifier to dev menu for reference
mokagio May 29, 2024
2b02c50
Extract lane to build for ASC without uploading
mokagio Jun 4, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions PodcastsIntents/PodcastsIntents.prototype.entitlements
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>com.apple.security.application-groups</key>
<array>
<string>group.au.com.shiftyjelly.pocketcasts.prototype</string>
</array>
</dict>
</plist>
10 changes: 10 additions & 0 deletions Share Extension/Share Extension.prototype.entitlements
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>com.apple.security.application-groups</key>
<array>
<string>group.au.com.shiftyjelly.pocketcasts.prototype</string>
</array>
</dict>
</plist>
10 changes: 10 additions & 0 deletions WidgetExtension/WidgetExtension.prototype.entitlements
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>com.apple.security.application-groups</key>
<array>
<string>group.au.com.shiftyjelly.pocketcasts.prototype</string>
</array>
</dict>
</plist>
9 changes: 7 additions & 2 deletions config/PocketCasts.base.xcconfig
Original file line number Diff line number Diff line change
Expand Up @@ -4,5 +4,10 @@ SWIFT_VERSION = 5.0

// Map our custom version values (used by the automation tooling) to the values
// Xcode uses
MARKETING_VERSION=$(VERSION_SHORT)
CURRENT_PROJECT_VERSION=$(VERSION_LONG)
MARKETING_VERSION = $(VERSION_SHORT)
CURRENT_PROJECT_VERSION = $(VERSION_LONG)

// Define a root bundle identifier so that extensions can append to it
PRODUCT_BUNDLE_IDENTIFIER_ROOT = au.com.shiftyjelly.podcasts

DEVELOPMENT_TEAM = PZYM8XX95Q // Automattic, Inc. (Company)
2 changes: 2 additions & 0 deletions config/PocketCasts.debug.xcconfig
Original file line number Diff line number Diff line change
@@ -1 +1,3 @@
#include "PocketCasts.base.xcconfig"

PRODUCT_BUNDLE_IDENTIFIER = $PRODUCT_BUNDLE_IDENTIFIER_ROOT
12 changes: 12 additions & 0 deletions config/PocketCasts.prototype.xcconfig
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
#include "PocketCasts.base.xcconfig"

// Redefining doesn't seem to work, Xcode resolves it as ".prototype" only
//PRODUCT_BUNDLE_IDENTIFIER_ROOT = $(PRODUCT_BUNDLE_IDENTIFIER_ROOT).prototype
PRODUCT_BUNDLE_IDENTIFIER_ROOT = au.com.shiftyjelly.podcasts.prototype
PRODUCT_BUNDLE_IDENTIFIER = $(PRODUCT_BUNDLE_IDENTIFIER_ROOT)

DEVELOPMENT_TEAM = 99KV9Z6BKV // Automattic, Inc. (Enterprise)

// Notice that because currently all extensions use this xcconfig for the Prototype bulid configuration,
// this line is enough to set the Provisioning Profiles for all.
PROVISIONING_PROFILE_SPECIFIER = match InHouse $(PRODUCT_BUNDLE_IDENTIFIER)
mokagio marked this conversation as resolved.
Show resolved Hide resolved
5 changes: 5 additions & 0 deletions config/PocketCasts.release.xcconfig
Original file line number Diff line number Diff line change
@@ -1 +1,6 @@
#include "PocketCasts.base.xcconfig"

PRODUCT_BUNDLE_IDENTIFIER = $PRODUCT_BUNDLE_IDENTIFIER_ROOT
// Notice that because currently all extensions use this xcconfig for the Release bulid configuration,
// this line is enough to set the Provisioning Profiles for all.
PROVISIONING_PROFILE_SPECIFIER = match AppStore $(PRODUCT_BUNDLE_IDENTIFIER)
1 change: 0 additions & 1 deletion config/PocketCasts.staging.xcconfig

This file was deleted.

76 changes: 68 additions & 8 deletions fastlane/Fastfile
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ ENV_FILE_NAME = 'pocket-casts-ios.env'
USER_ENV_FILE_PATH = File.join(Dir.home, '.a8c-apps', ENV_FILE_NAME)

TEAM_ID_APP_STORE = 'PZYM8XX95Q'
TEAM_ID_ENTERPRISE = '99KV9Z6BKV'

CODE_SIGNING_STORAGE_OPTIONS = {
storage_mode: 's3',
Expand All @@ -36,6 +37,7 @@ GHHELPER_REPO = 'Automattic/pocket-casts-ios'
DEFAULT_BRANCH = 'trunk'

SCHEME = 'pocketcasts'
SCHEME_ENTERPRISE = 'Pocket Casts Prototype Build'

# Instanstiate versioning classes
VERSION_CALCULATOR = Fastlane::Wpmreleasetoolkit::Versioning::SemanticVersionCalculator.new
Expand All @@ -44,22 +46,35 @@ BUILD_CODE_FORMATTER = Fastlane::Wpmreleasetoolkit::Versioning::FourPartBuildCod
VERSION_FILE = Fastlane::Wpmreleasetoolkit::Versioning::IOSVersionFile.new(xcconfig_path: VERSION_XCCONFIG_PATH)

APP_BUNDLE_IDENTIFIER_APP_STORE = 'au.com.shiftyjelly.podcasts'
APP_BUNDLE_IDENTIFIER_ENTERPRISE = "#{APP_BUNDLE_IDENTIFIER_APP_STORE}.prototype".freeze

# Keep this in alphabetical case-insensitive order so it's easier to visually compare with the list on the Developers Portal.
EXTENSIONS = %w[
NotificationExtension
NotificationContent
watchkitapp
NotificationExtension
PodcastsIntents
PodcastsIntentsUI
WidgetExtension
Share-Extension
watchkitapp
WidgetExtension
].freeze

BUNDLE_IDENTIFIERS_APP_STORE = [
APP_BUNDLE_IDENTIFIER_APP_STORE,
*EXTENSIONS.map { |suffix| "#{APP_BUNDLE_IDENTIFIER_APP_STORE}.#{suffix}" }
].freeze

BUNDLE_IDENTIFIERS_ENTERPRISE = [
APP_BUNDLE_IDENTIFIER_ENTERPRISE,
*EXTENSIONS.map { |suffix| "#{APP_BUNDLE_IDENTIFIER_ENTERPRISE}.#{suffix}" }
].freeze

ASC_API_KEY_ENV_VARS = %w[
APP_STORE_CONNECT_API_KEY_KEY_ID
APP_STORE_CONNECT_API_KEY_ISSUER_ID
APP_STORE_CONNECT_API_KEY_KEY
].freeze

FROZEN_STRINGS_PATH = File.join(FASTLANE_FOLDER, 'Frozen.strings')

EN_LPROJ_FOLDER = File.join(PROJECT_ROOT_FOLDER, 'podcasts', 'en.lproj')
Expand Down Expand Up @@ -156,11 +171,7 @@ platform :ios do

desc 'Download and configure code signing certificates and provisioning profiles for the App Store build.'
lane :configure_code_signing_app_store do |options|
require_env_vars!(
'APP_STORE_CONNECT_API_KEY_KEY_ID',
'APP_STORE_CONNECT_API_KEY_ISSUER_ID',
'APP_STORE_CONNECT_API_KEY_KEY'
)
require_env_vars!(*ASC_API_KEY_ENV_VARS)

sync_code_signing(
type: 'appstore',
Expand All @@ -174,6 +185,39 @@ platform :ios do
)
end

desc 'Download and configure code signing certificates and provisioning profiles for the Enterprise build, i.e. Prototype Builds.'
lane :configure_code_signing_enterprise do |options|
require_env_vars!(*ASC_API_KEY_ENV_VARS)

readonly = options.fetch(:readonly, true)

if readonly
# In readonly mode, we can use the API key.
#
# Notice the `in_house: true` parameter.
# Unfortunately, even using it, the API does not allow modifying certs or profiles via API key.
# It's here for reference and future-proofing.
api_key = app_store_connect_api_key(in_house: true)
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I discovered the in_house parameter in the docs while working on something else. I had my hopes up it would have spared us the trouble of authenticating locally when running for Enterprise in readonly: false but it didn't work...

else
# The Enterprise account APIs do not support authentication via API key.
# If we want to modify data (readonly = false) we need to authenticate manually.
prompt_user_for_app_store_connect_credentials
# We also need to pass no API key, otherwise Fastlane will give precedence to that authentication mode.
api_key = nil
end

sync_code_signing(
type: 'enterprise',
team_id: TEAM_ID_ENTERPRISE,
api_key: api_key,
app_identifier: BUNDLE_IDENTIFIERS_ENTERPRISE,
# This might turn out to be useful in the future
# template_name: 'CarPlay audio app (CarPlay + Media Player frameworks)iOS (Dist)'
readonly: options.fetch(:readonly, true),
**CODE_SIGNING_STORAGE_OPTIONS
)
end

#####################################################################################
# Release Lanes
#####################################################################################
Expand Down Expand Up @@ -550,6 +594,22 @@ platform :ios do
trigger_beta_build(branch_to_build: release_branch_name)
end

desc 'Builds for Enterprise distribution (Prototype Build)'
lane :build_enterprise do
configure_code_signing_enterprise

build_app(
scheme: SCHEME_ENTERPRISE,
include_bitcode: false,
include_symbols: true,
clean: true,
export_options: {
method: 'enterprise',
manageAppVersionAndBuildNumber: false
}
)
end

# Sets the stage to start working on a hotfix
#
# - Cuts a new `release/x.y.z` branch from the tag from the latest (`x.y`) version
Expand Down
9 changes: 9 additions & 0 deletions fastlane/lib/helpers.rb
Original file line number Diff line number Diff line change
Expand Up @@ -33,3 +33,12 @@ def get_required_env!(key, env_file_path: USER_ENV_FILE_PATH)

ENV.fetch(key)
end

def prompt_user_for_app_store_connect_credentials
require 'credentials_manager'

# If Fastlane cannot instantiate a user, it will ask the caller for the email.
# Once we have it, we can set it as `FASTLANE_USER` in the environment (which has lifecycle limited to this call) so that the next commands will already have access to it.
# Note: if the user is already available to `AccountManager`, setting it in the env is redundant, but Fastlane doesn't provide a way to check it so we have to do it anyway.
ENV['FASTLANE_USER'] = CredentialsManager::AccountManager.new.user
end
Loading