Skip to content

Commit

Permalink
[fastlane] Delete IDFA declarations for Apple App Store submission
Browse files Browse the repository at this point in the history
  • Loading branch information
fr0l committed May 9, 2024
1 parent e8fe2a9 commit f8653e1
Show file tree
Hide file tree
Showing 18 changed files with 10 additions and 445 deletions.
2 changes: 1 addition & 1 deletion deliver/lib/deliver/options.rb
Original file line number Diff line number Diff line change
Expand Up @@ -249,7 +249,7 @@ def self.available_options
end),
FastlaneCore::ConfigItem.new(key: :submission_information,
short_option: "-b",
description: "Extra information for the submission (e.g. compliance specifications, IDFA settings)",
description: "Extra information for the submission (e.g. compliance specifications)",
type: Hash,
optional: true),

Expand Down
77 changes: 0 additions & 77 deletions deliver/lib/deliver/submit_for_review.rb
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,6 @@ def submit!(options)
build = select_build(options, app, version, platform)

update_export_compliance(options, app, build)
update_idfa(options, app, version)
update_submission_information(options, app)

create_review_submission(options, app, version, platform)
Expand Down Expand Up @@ -120,82 +119,6 @@ def update_export_compliance(options, app, build)
end
end

def update_idfa(options, app, version)
submission_information = options[:submission_information] || {}
submission_information = submission_information.transform_keys(&:to_sym)

uses_idfa = submission_information[:add_id_info_uses_idfa]

idfa_declaration = begin
version.fetch_idfa_declaration
rescue
nil
end

updated_idfa = false

# Set IDFA on version
unless uses_idfa.nil?
UI.verbose("Updating app store version for IDFA status of '#{uses_idfa}'")
version = version.update(attributes: {
usesIdfa: uses_idfa
})
UI.verbose("Updated app store version for IDFA status of '#{version.uses_idfa}'")
updated_idfa = true
end

# Error if uses_idfa not set
if version.uses_idfa.nil?
message = [
"Use of Advertising Identifier (IDFA) is required to submit",
"Add information to the :submission_information option...",
" Docs: http://docs.fastlane.tools/actions/deliver/#compliance-and-idfa-settings",
" Example: submission_information: { add_id_info_uses_idfa: false }",
" Example: submission_information: {",
" add_id_info_uses_idfa: true,",
" add_id_info_serves_ads: false,",
" add_id_info_tracks_install: true,",
" add_id_info_tracks_action: true,",
" add_id_info_limits_tracking: true",
" }",
" Example CLI:",
" --submission_information \"{\\\"add_id_info_uses_idfa\\\": false}\""
].join("\n")
UI.user_error!(message)
end

# Create, update, or delete IDFA declaration
if uses_idfa == false
if idfa_declaration
UI.verbose("Deleting IDFA declaration")
idfa_declaration.delete!
updated_idfa = true
UI.verbose("Deleted IDFA declaration")
end
elsif uses_idfa == true
attributes = {
honorsLimitedAdTracking: !!submission_information[:add_id_info_limits_tracking],
servesAds: !!submission_information[:add_id_info_serves_ads],
attributesAppInstallationToPreviousAd: !!submission_information[:add_id_info_tracks_install],
attributesActionWithPreviousAd: !!submission_information[:add_id_info_tracks_action]
}

if idfa_declaration
UI.verbose("Updating IDFA declaration")
idfa_declaration.update(attributes: attributes)
UI.verbose("Updated IDFA declaration")
else
UI.verbose("Creating IDFA declaration")
version.create_idfa_declaration(attributes: attributes)
UI.verbose("Created IDFA declaration")
end

updated_idfa = true
end

UI.success("Successfully updated IDFA declarations on App Store Connect") if updated_idfa
end

def update_submission_information(options, app)
submission_information = options[:submission_information] || {}
submission_information = submission_information.transform_keys(&:to_sym)
Expand Down
178 changes: 0 additions & 178 deletions deliver/spec/submit_for_review_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,6 @@
version_string: "1.0.0")
end
let(:selected_build) { double('selected_build') }
let(:idfa_declaration) { double('idfa_declaration') }

let(:submission) do
double('submission',
Expand Down Expand Up @@ -66,26 +65,6 @@
review_submitter.submit!(options)
end.to raise_error("boom")
end

it 'needs to set export_compliance_uses_encryption' do
options = {
platform: Spaceship::ConnectAPI::Platform::IOS
}

expect(app).to receive(:get_edit_app_store_version).and_return(edit_version)
expect(review_submitter).to receive(:select_build).and_return(selected_build)

expect(selected_build).to receive(:uses_non_exempt_encryption).and_return(false)

expect(edit_version).to receive(:fetch_idfa_declaration).and_return(nil)
expect(edit_version).to receive(:uses_idfa).and_return(nil)

expect(UI).to receive(:user_error!).with(/Use of Advertising Identifier \(IDFA\) is required to submit/).and_raise("boom")

expect do
review_submitter.submit!(options)
end.to raise_error("boom")
end
end

context 'submits successfully' do
Expand All @@ -101,9 +80,6 @@

expect(selected_build).to receive(:uses_non_exempt_encryption).and_return(false)

expect(edit_version).to receive(:fetch_idfa_declaration).and_return(nil)
expect(edit_version).to receive(:uses_idfa).and_return(false)

expect(app).to receive(:get_in_progress_review_submission).and_return(submission)

expect do
Expand All @@ -121,9 +97,6 @@

expect(selected_build).to receive(:uses_non_exempt_encryption).and_return(false)

expect(edit_version).to receive(:fetch_idfa_declaration).and_return(nil)
expect(edit_version).to receive(:uses_idfa).and_return(false)

expect(app).to receive(:get_in_progress_review_submission).and_return(nil)
expect(app).to receive(:get_ready_review_submission).and_return(submission)
expect(submission).to receive(:items).and_return([])
Expand All @@ -146,9 +119,6 @@

expect(selected_build).to receive(:uses_non_exempt_encryption).and_return(false)

expect(edit_version).to receive(:fetch_idfa_declaration).and_return(nil)
expect(edit_version).to receive(:uses_idfa).and_return(false)

expect(app).to receive(:get_in_progress_review_submission).and_return(nil)
expect(app).to receive(:get_ready_review_submission).and_return(submission)
expect(submission).to receive(:items).and_return([double('some item')])
Expand All @@ -170,9 +140,6 @@

expect(selected_build).to receive(:uses_non_exempt_encryption).and_return(false)

expect(edit_version).to receive(:fetch_idfa_declaration).and_return(nil)
expect(edit_version).to receive(:uses_idfa).and_return(false)

expect(app).to receive(:get_in_progress_review_submission).and_return(nil)
expect(app).to receive(:get_ready_review_submission).and_return(submission)
expect(submission).to receive(:items).and_return([])
Expand Down Expand Up @@ -203,9 +170,6 @@
expect(selected_build).to receive(:update).with(attributes: { usesNonExemptEncryption: false }).and_return(selected_build)
expect(selected_build).to receive(:uses_non_exempt_encryption).and_return(false)

expect(edit_version).to receive(:fetch_idfa_declaration).and_return(nil)
expect(edit_version).to receive(:uses_idfa).and_return(false)

expect(app).to receive(:get_in_progress_review_submission).and_return(nil)
expect(app).to receive(:get_ready_review_submission).and_return(nil)
expect(app).to receive(:create_review_submission).and_return(submission)
Expand All @@ -232,9 +196,6 @@

expect(selected_build).to receive(:uses_non_exempt_encryption).and_return(false)

expect(edit_version).to receive(:fetch_idfa_declaration).and_return(nil)
expect(edit_version).to receive(:uses_idfa).and_return(false)

expect(app).to receive(:update).with(attributes: {
contentRightsDeclaration: "USES_THIRD_PARTY_CONTENT"
})
Expand All @@ -250,145 +211,6 @@
review_submitter.submit!(options)
end
end

context 'IDFA' do
it 'submission information with idfa false with no idfa' do
options = {
platform: Spaceship::ConnectAPI::Platform::IOS,
submission_information: {
add_id_info_uses_idfa: false
}
}

expect(app).to receive(:get_edit_app_store_version).and_return(edit_version)
expect(review_submitter).to receive(:select_build).and_return(selected_build)

expect(selected_build).to receive(:uses_non_exempt_encryption).and_return(false)

expect(edit_version).to receive(:fetch_idfa_declaration).and_return(nil)
expect(edit_version).to receive(:update).with(attributes: { usesIdfa: false }).and_return(edit_version)
expect(edit_version).to receive(:uses_idfa).and_return(false).exactly(2).times

expect(app).to receive(:get_in_progress_review_submission).and_return(nil)
expect(app).to receive(:get_ready_review_submission).and_return(nil)
expect(app).to receive(:create_review_submission).and_return(submission)

expect(submission).to receive(:add_app_store_version_to_review_items).with(app_store_version_id: edit_version.id)
expect(Spaceship::ConnectAPI::AppStoreVersion).to receive(:get).and_return(ready_for_review_version)
expect(submission).to receive(:submit_for_review)

review_submitter.submit!(options)
end

it 'submission information with idfa false with existing idfa' do
options = {
platform: Spaceship::ConnectAPI::Platform::IOS,
submission_information: {
add_id_info_uses_idfa: false
}
}

expect(app).to receive(:get_edit_app_store_version).and_return(edit_version)
expect(review_submitter).to receive(:select_build).and_return(selected_build)

expect(selected_build).to receive(:uses_non_exempt_encryption).and_return(false)

expect(edit_version).to receive(:fetch_idfa_declaration).and_return(idfa_declaration)
expect(edit_version).to receive(:update).with(attributes: { usesIdfa: false }).and_return(edit_version)
expect(edit_version).to receive(:uses_idfa).and_return(false).exactly(2).times
expect(idfa_declaration).to receive(:delete!)

expect(app).to receive(:get_in_progress_review_submission).and_return(nil)
expect(app).to receive(:get_ready_review_submission).and_return(nil)
expect(app).to receive(:create_review_submission).and_return(submission)

expect(submission).to receive(:add_app_store_version_to_review_items).with(app_store_version_id: edit_version.id)
expect(Spaceship::ConnectAPI::AppStoreVersion).to receive(:get).and_return(ready_for_review_version)
expect(submission).to receive(:submit_for_review)

review_submitter.submit!(options)
end

it 'submission information with idfa true with no idfa' do
options = {
platform: Spaceship::ConnectAPI::Platform::IOS,
submission_information: {
add_id_info_uses_idfa: true,

add_id_info_limits_tracking: true,
add_id_info_serves_ads: true,
add_id_info_tracks_install: true,
add_id_info_tracks_action: true
}
}

expect(app).to receive(:get_edit_app_store_version).and_return(edit_version)
expect(review_submitter).to receive(:select_build).and_return(selected_build)

expect(selected_build).to receive(:uses_non_exempt_encryption).and_return(false)

expect(edit_version).to receive(:fetch_idfa_declaration).and_return(nil)
expect(edit_version).to receive(:update).with(attributes: { usesIdfa: true }).and_return(edit_version)
expect(edit_version).to receive(:uses_idfa).and_return(true).exactly(2).times

expect(edit_version).to receive(:create_idfa_declaration).with(attributes: {
honorsLimitedAdTracking: true,
servesAds: true,
attributesAppInstallationToPreviousAd: true,
attributesActionWithPreviousAd: true
})

expect(app).to receive(:get_in_progress_review_submission).and_return(nil)
expect(app).to receive(:get_ready_review_submission).and_return(nil)
expect(app).to receive(:create_review_submission).and_return(submission)

expect(submission).to receive(:add_app_store_version_to_review_items).with(app_store_version_id: edit_version.id)
expect(Spaceship::ConnectAPI::AppStoreVersion).to receive(:get).and_return(ready_for_review_version)
expect(submission).to receive(:submit_for_review)

review_submitter.submit!(options)
end

it 'submission information with idfa true with existing idfa' do
options = {
platform: Spaceship::ConnectAPI::Platform::IOS,
submission_information: {
add_id_info_uses_idfa: true,

add_id_info_limits_tracking: true,
add_id_info_serves_ads: true,
add_id_info_tracks_install: true,
add_id_info_tracks_action: true
}
}

expect(app).to receive(:get_edit_app_store_version).and_return(edit_version)
expect(review_submitter).to receive(:select_build).and_return(selected_build)

expect(selected_build).to receive(:uses_non_exempt_encryption).and_return(false)

expect(edit_version).to receive(:fetch_idfa_declaration).and_return(idfa_declaration)
expect(edit_version).to receive(:update).with(attributes: { usesIdfa: true }).and_return(edit_version)
expect(edit_version).to receive(:uses_idfa).and_return(true).exactly(2).times

expect(idfa_declaration).to receive(:update).with(attributes: {
honorsLimitedAdTracking: true,
servesAds: true,
attributesAppInstallationToPreviousAd: true,
attributesActionWithPreviousAd: true
})

expect(app).to receive(:get_in_progress_review_submission).and_return(nil)
expect(app).to receive(:get_ready_review_submission).and_return(nil)
expect(app).to receive(:create_review_submission).and_return(submission)

expect(submission).to receive(:add_app_store_version_to_review_items).with(app_store_version_id: edit_version.id)
expect(Spaceship::ConnectAPI::AppStoreVersion).to receive(:get).and_return(ready_for_review_version)
expect(submission).to receive(:submit_for_review)

review_submitter.submit!(options)
end
end
end
end
end
6 changes: 3 additions & 3 deletions fastlane/lib/fastlane/actions/docs/upload_to_app_store.md.erb
Original file line number Diff line number Diff line change
Expand Up @@ -431,12 +431,12 @@ end

Omit `build_number` to let _fastlane_ automatically select the latest build number for the current version being edited for release from App Store Connect.

### Compliance and IDFA settings
### Compliance settings

Use the `submission_information` parameter for additional submission specifiers, including compliance and IDFA settings. Look at the Spaceship's [`app_submission.rb`](https://github.com/fastlane/fastlane/blob/master/spaceship/lib/spaceship/tunes/app_submission.rb) file for options. See [this example](https://github.com/artsy/eigen/blob/faa02e2746194d8d7c11899474de9c517435eca4/fastlane/Fastfile#L131-L149).
Use the `submission_information` parameter for additional submission specifiers, including compliance settings. Look at the Spaceship's [`app_submission.rb`](https://github.com/fastlane/fastlane/blob/master/spaceship/lib/spaceship/tunes/app_submission.rb) file for options. See [this example](https://github.com/artsy/eigen/blob/faa02e2746194d8d7c11899474de9c517435eca4/fastlane/Fastfile#L131-L149).

```no-highlight
fastlane deliver submit_build --build_number 830 --submission_information "{\"export_compliance_uses_encryption\": false, \"add_id_info_uses_idfa\": false }"
fastlane deliver submit_build --build_number 830 --submission_information "{\"export_compliance_uses_encryption\": false }"
```

### App Privacy Details
Expand Down
2 changes: 1 addition & 1 deletion fastlane/swift/DeliverfileProtocol.swift
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,7 @@ public protocol DeliverfileProtocol: AnyObject {
/// Path to the app rating's config
var appRatingConfigPath: String? { get }

/// Extra information for the submission (e.g. compliance specifications, IDFA settings)
/// Extra information for the submission (e.g. compliance specifications)
var submissionInformation: [String: Any]? { get }

/// The ID of your App Store Connect team if you're in multiple teams
Expand Down
6 changes: 3 additions & 3 deletions fastlane/swift/Fastlane.swift
Original file line number Diff line number Diff line change
Expand Up @@ -674,7 +674,7 @@ public func appledoc(input: [String],
- resetRatings: Reset the summary rating when you release a new version of the application
- priceTier: The price tier of this application
- appRatingConfigPath: Path to the app rating's config
- submissionInformation: Extra information for the submission (e.g. compliance specifications, IDFA settings)
- submissionInformation: Extra information for the submission (e.g. compliance specifications)
- teamId: The ID of your App Store Connect team if you're in multiple teams
- teamName: The name of your App Store Connect team if you're in multiple teams
- devPortalTeamId: The short ID of your Developer Portal team, if you're in multiple teams. Different from your iTC team ID!
Expand Down Expand Up @@ -3714,7 +3714,7 @@ public func deleteKeychain(name: OptionalConfigValue<String?> = .fastlaneDefault
- resetRatings: Reset the summary rating when you release a new version of the application
- priceTier: The price tier of this application
- appRatingConfigPath: Path to the app rating's config
- submissionInformation: Extra information for the submission (e.g. compliance specifications, IDFA settings)
- submissionInformation: Extra information for the submission (e.g. compliance specifications)
- teamId: The ID of your App Store Connect team if you're in multiple teams
- teamName: The name of your App Store Connect team if you're in multiple teams
- devPortalTeamId: The short ID of your Developer Portal team, if you're in multiple teams. Different from your iTC team ID!
Expand Down Expand Up @@ -12536,7 +12536,7 @@ public func uploadSymbolsToSentry(apiHost: String = "https://app.getsentry.com/a
- resetRatings: Reset the summary rating when you release a new version of the application
- priceTier: The price tier of this application
- appRatingConfigPath: Path to the app rating's config
- submissionInformation: Extra information for the submission (e.g. compliance specifications, IDFA settings)
- submissionInformation: Extra information for the submission (e.g. compliance specifications)
- teamId: The ID of your App Store Connect team if you're in multiple teams
- teamName: The name of your App Store Connect team if you're in multiple teams
- devPortalTeamId: The short ID of your Developer Portal team, if you're in multiple teams. Different from your iTC team ID!
Expand Down
Loading

0 comments on commit f8653e1

Please sign in to comment.