Skip to content

Commit

Permalink
Merge remote-tracking branch 'origin/develop' into graeme/ios-nightly…
Browse files Browse the repository at this point in the history
…-builds
  • Loading branch information
graeme committed Sep 8, 2023
2 parents fb98f6a + f115b40 commit 8aa0e6a
Show file tree
Hide file tree
Showing 52 changed files with 2,654 additions and 1,198 deletions.
50 changes: 50 additions & 0 deletions .github/workflows/codeql.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
# For most projects, this workflow file will not need changing; you simply need
# to commit it to your repository.
#
# You may wish to alter this file to override the set of languages analyzed,
# or to provide custom queries or build logic.
#
# ******** NOTE ********
# We have attempted to detect the languages in your repository. Please check
# the `language` matrix defined below to confirm you have the correct set of
# supported CodeQL languages.
#
name: "CodeQL"

on:
schedule:
- cron: '0 2 * * *' # Run at 2 AM UTC

jobs:
analyze:
name: Analyze
runs-on: macos-13
timeout-minutes: 60
permissions:
actions: read
contents: read
security-events: write

steps:
- name: Checkout repository
uses: actions/checkout@v3

- name: Initialize CodeQL
uses: github/codeql-action/init@v2
with:
languages: 'swift'

- name: Select Xcode
run: sudo xcode-select -s /Applications/Xcode_$(<.xcode-version).app/Contents/Developer

- name: Build
run: |
xcodebuild clean build \
-target "DuckDuckGo" \
-scheme "DuckDuckGo" \
-destination "platform=iOS Simulator,name=iPhone 14,OS=16.4"
- name: Perform CodeQL Analysis
uses: github/codeql-action/analyze@v2
with:
category: "/language:swift"
15 changes: 14 additions & 1 deletion .github/workflows/pr.yml
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,19 @@ jobs:
with:
report_paths: unittests.xml

- name: Update Asana with failed unit tests
if: always() # always run even if the previous step fails
env:
ASANA_ACCESS_TOKEN: ${{ secrets.ASANA_ACCESS_TOKEN }}
WORKFLOW_URL: https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }}
run: |
# Extract failed tests from the junit report
# Only keep failures unique by classname and name (column 1 and 2 of the yq output)
yq < unittests.xml -p xml -o json -r \
$'[.testsuites.testsuite[].testcase] | flatten | map(select(.failure) | .+@classname + " " + .+@name + " \'" + .failure.+@message + "\' ${{ env.WORKFLOW_URL }}") | .[]' \
| sort -u -k 1,2 \
| xargs -L 1 ./scripts/report-failed-unit-test.sh -s ${{ vars.APPLE_CI_FAILING_TESTS_FAILED_TESTS_SECTION_ID }}
release-build:

name: Make Release Build
Expand Down Expand Up @@ -181,4 +194,4 @@ jobs:
asana-section: ${{ vars.APPLE_CI_FAILING_TESTS_IOS_POST_MERGE_SECTION_ID }}
asana-task-name: 'PR Check is failing on develop'
action: create-asana-task
asana-task-description: PR Checks conducted after merging have failed. See ${{ env.WORKFLOW_URL }}
asana-task-description: PR Checks conducted after merging have failed. See ${{ env.WORKFLOW_URL }}. Follow the steps on https://app.asana.com/0/1202500774821704/1205317064731691 to resolve this issue.
28 changes: 28 additions & 0 deletions Configuration/Configuration-Alpha.xcconfig
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
//
// Configuration-Alpha.xcconfig
// DuckDuckGo
//
// Copyright © 2023 DuckDuckGo. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//

#include "DuckDuckGoDeveloper.xcconfig"
#include? "ExternalDeveloper.xcconfig"
#include? "Version.xcconfig"

// The app bundle identifier
APP_ID = com.duckduckgo.mobile.ios.alpha

// A prefix for group ids. Must start with "group.".
GROUP_ID_PREFIX = group.com.duckduckgo.alpha
2 changes: 1 addition & 1 deletion Configuration/Version.xcconfig
Original file line number Diff line number Diff line change
@@ -1 +1 @@
MARKETING_VERSION = 7.86.0
MARKETING_VERSION = 7.88.0
4 changes: 2 additions & 2 deletions Core/AppPrivacyConfigurationDataProvider.swift
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,8 @@ import BrowserServicesKit
final public class AppPrivacyConfigurationDataProvider: EmbeddedDataProvider {

public struct Constants {
public static let embeddedDataETag = "\"2308844373650298899d98be1f5e6766\""
public static let embeddedDataSHA = "160ffa9156640742a4be26a644354940ad0f3ea42e98e3cbfbe26e8d7a5c653a"
public static let embeddedDataETag = "\"b3acf772994c82ed870835c27a94de36\""
public static let embeddedDataSHA = "955ebdcac92bf5589e34e174e9cb8bcbe5170c9bbb5f6d0b4fa32290368a22b2"
}

public var embeddedDataEtag: String {
Expand Down
4 changes: 2 additions & 2 deletions Core/AppTrackerDataSetProvider.swift
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,8 @@ import BrowserServicesKit
final public class AppTrackerDataSetProvider: EmbeddedDataProvider {

public struct Constants {
public static let embeddedDataETag = "\"fe1c5d43a3f99c0733a19d87415953fc\""
public static let embeddedDataSHA = "edc1c2496d5010ba7916bd5773fdb8ca5f06faaba4454494e97954427cc04bb4"
public static let embeddedDataETag = "\"c9a18e593a4f5f8d32a18db294497226\""
public static let embeddedDataSHA = "6264eb92240fee69aeebb14aa333bdc8d76b2818fb7f44f0acb1fb0373d50af4"
}

public var embeddedDataEtag: String {
Expand Down
2 changes: 2 additions & 0 deletions Core/Pixel.swift
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,8 @@ public struct PixelParameters {
// Remote messaging
public static let message = "message"
public static let sheetResult = "success"

public static let defaultBrowser = "default_browser"
}

public struct PixelValues {
Expand Down
29 changes: 16 additions & 13 deletions Core/PixelEvent.swift
Original file line number Diff line number Diff line change
Expand Up @@ -302,12 +302,9 @@ extension Pixel {
case remoteMessageSecondaryActionClicked
case remoteMessageSheet

// MARK: Lock Screen widgets
case lockScreenWidgetNewSearch
case lockScreenWidgetFavorites
case lockScreenWidgetFireButton
case lockScreenWidgetVoiceSearch
case lockScreenWidgetNewEmail
// MARK: Set as Default
case onboardingSetDefaultOpened
case onboardingSetDefaultSkipped

// MARK: debug pixels
case dbCrashDetected
Expand Down Expand Up @@ -427,6 +424,8 @@ extension Pixel {
case syncBookmarksFailed
case syncCredentialsProviderInitializationFailed
case syncCredentialsFailed
case syncSettingsFailed
case syncSettingsMetadataUpdateFailed

case bookmarksCleanupFailed
case bookmarksCleanupAttemptedWhileSyncWasEnabled
Expand All @@ -436,6 +435,8 @@ extension Pixel {

case invalidPayload(Configuration)

case dailyActiveUser

case emailIncontextPromptDisplayed
case emailIncontextPromptConfirmed
case emailIncontextPromptDismissed
Expand Down Expand Up @@ -686,7 +687,7 @@ extension Pixel.Event {
case .secureVaultInitFailedError: return "m_secure-vault_error_init-failed"
case .secureVaultFailedToOpenDatabaseError: return "m_secure-vault_error_failed-to-open-database"

case .secureVaultIsEnabledCheckedWhenEnabledAndBackgrounded: return "m_secure-vault_is-enabled-checked_when-enabled-and-backgrounded"
case .secureVaultIsEnabledCheckedWhenEnabledAndBackgrounded: return "m_secure-vault_is-enabled-checked_when-enabled-and-backgrounded_2"

// MARK: Ad Click Attribution pixels

Expand Down Expand Up @@ -733,12 +734,9 @@ extension Pixel.Event {
case .remoteMessageSecondaryActionClicked: return "m_remote_message_secondary_action_clicked"
case .remoteMessageSheet: return "m_remote_message_sheet"

// Lock Screen Widgets
case .lockScreenWidgetNewSearch: return "m_lockscreen_newsearch"
case .lockScreenWidgetFavorites: return "m_lockscreen_favorites"
case .lockScreenWidgetFireButton: return "m_lockscreen_fire"
case .lockScreenWidgetVoiceSearch: return "m_lockscreen_voicesearch"
case .lockScreenWidgetNewEmail: return "m_lockscreen_newemail"
// MARK: Set as default measuring
case .onboardingSetDefaultOpened: return "m_onboarding_set-default-opened"
case .onboardingSetDefaultSkipped: return "m_onboarding_set-default-skipped"

// MARK: debug pixels

Expand Down Expand Up @@ -860,6 +858,9 @@ extension Pixel.Event {
case .syncBookmarksFailed: return "m_d_sync_bookmarks_failed"
case .syncCredentialsProviderInitializationFailed: return "m_d_sync_credentials_provider_initialization_failed"
case .syncCredentialsFailed: return "m_d_sync_credentials_failed"
case .syncSettingsFailed: return "m_d_sync_settings_failed"
case .syncSettingsMetadataUpdateFailed: return "m_d_sync_settings_metadata_update_failed"


case .bookmarksCleanupFailed: return "m_d_bookmarks_cleanup_failed"
case .bookmarksCleanupAttemptedWhileSyncWasEnabled: return "m_d_bookmarks_cleanup_attempted_while_sync_was_enabled"
Expand All @@ -869,6 +870,8 @@ extension Pixel.Event {

case .invalidPayload(let configuration): return "m_d_\(configuration.rawValue)_invalid_payload".lowercased()

case .dailyActiveUser: return "m_daily_active_user"

// MARK: - InContext Email Protection
case .emailIncontextPromptDisplayed: return "m_email_incontext_prompt_displayed"
case .emailIncontextPromptConfirmed: return "m_email_incontext_prompt_confirmed"
Expand Down
55 changes: 55 additions & 0 deletions Core/SetAsDefaultStatistics.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
//
// SetAsDefaultStatistics.swift
// DuckDuckGo
//
// Copyright © 2023 DuckDuckGo. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//

import Foundation

/// Measuring set as default usage. To be removed mid-end October.
public class SetAsDefaultStatistics {

@UserDefaultsWrapper(key: .defaultBrowserUsageLastSeen, defaultValue: nil)
var defaultBrowserUsageLastSeen: Date?

/// We assume we're default if we the app was launched with a URL in the last 7 days
public var isDefault: Bool {
guard let lastSeen = defaultBrowserUsageLastSeen,
let days = Calendar.current.numberOfDaysBetween(lastSeen, and: Date()) else { return false }
return (0...7).contains(days)
}

public init() { }

public func openedAsDefault() {
defaultBrowserUsageLastSeen = Date()
}

public func setAsDefaultOpened() {
Pixel.fire(pixel: .onboardingSetDefaultOpened)
}

public func setAsDefaultSkipped() {
Pixel.fire(pixel: .onboardingSetDefaultSkipped)
}

public func fireDailyActiveUser() {
DailyPixel.fire(pixel: .dailyActiveUser, withAdditionalParameters: [
PixelParameters.defaultBrowser: "\(isDefault)"
])
}

}
8 changes: 6 additions & 2 deletions Core/StatisticsLoader.swift
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,9 @@ public class StatisticsLoader {
requestInstallStatistics(completion: completion)
return
}


SetAsDefaultStatistics().fireDailyActiveUser()

let configuration = APIRequest.Configuration(url: url)
let request = APIRequest(configuration: configuration, urlSession: .session())

Expand All @@ -109,7 +111,9 @@ public class StatisticsLoader {
requestInstallStatistics(completion: completion)
return
}


SetAsDefaultStatistics().fireDailyActiveUser()

let configuration = APIRequest.Configuration(url: url)
let request = APIRequest(configuration: configuration, urlSession: .session())

Expand Down
50 changes: 23 additions & 27 deletions Core/SyncBookmarksAdapter.swift
Original file line number Diff line number Diff line change
Expand Up @@ -58,36 +58,32 @@ public final class SyncBookmarksAdapter {
guard provider == nil else {
return
}
do {
let provider = try BookmarksProvider(
database: database,
metadataStore: metadataStore,
syncDidUpdateData: { [syncDidCompleteSubject] in
syncDidCompleteSubject.send()
}
)

syncErrorCancellable = provider.syncErrorPublisher
.sink { error in
switch error {
case let syncError as SyncError:
Pixel.fire(pixel: .syncBookmarksFailed, error: syncError)
default:
let nsError = error as NSError
if nsError.domain != NSURLErrorDomain {
let processedErrors = CoreDataErrorsParser.parse(error: error as NSError)
let params = processedErrors.errorPixelParameters
Pixel.fire(pixel: .syncBookmarksFailed, error: error, withAdditionalParameters: params)
}
let provider = BookmarksProvider(
database: database,
metadataStore: metadataStore,
syncDidUpdateData: { [syncDidCompleteSubject] in
syncDidCompleteSubject.send()
}
)

syncErrorCancellable = provider.syncErrorPublisher
.sink { error in
switch error {
case let syncError as SyncError:
Pixel.fire(pixel: .syncBookmarksFailed, error: syncError)
default:
let nsError = error as NSError
if nsError.domain != NSURLErrorDomain {
let processedErrors = CoreDataErrorsParser.parse(error: error as NSError)
let params = processedErrors.errorPixelParameters
Pixel.fire(pixel: .syncBookmarksFailed, error: error, withAdditionalParameters: params)
}
os_log(.error, log: OSLog.syncLog, "Bookmarks Sync error: %{public}s", String(reflecting: error))
}
self.provider = provider
} catch let error as NSError {
let processedErrors = CoreDataErrorsParser.parse(error: error)
let params = processedErrors.errorPixelParameters
Pixel.fire(pixel: .syncBookmarksProviderInitializationFailed, error: error, withAdditionalParameters: params)
}
os_log(.error, log: OSLog.syncLog, "Bookmarks Sync error: %{public}s", String(reflecting: error))
}

self.provider = provider
}

private var syncDidCompleteSubject = PassthroughSubject<Void, Never>()
Expand Down
6 changes: 5 additions & 1 deletion Core/SyncDataProviders.swift
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ import SyncDataProviders
public class SyncDataProviders: DataProvidersSource {
public let bookmarksAdapter: SyncBookmarksAdapter
public let credentialsAdapter: SyncCredentialsAdapter
public let settingsAdapter: SyncSettingsAdapter

public func makeDataProviders() -> [DataProviding] {
initializeMetadataDatabaseIfNeeded()
Expand All @@ -38,10 +39,12 @@ public class SyncDataProviders: DataProvidersSource {

bookmarksAdapter.setUpProviderIfNeeded(database: bookmarksDatabase, metadataStore: syncMetadata)
credentialsAdapter.setUpProviderIfNeeded(secureVaultFactory: secureVaultFactory, metadataStore: syncMetadata)
settingsAdapter.setUpProviderIfNeeded(metadataDatabase: syncMetadataDatabase, metadataStore: syncMetadata)

let providers: [Any] = [
bookmarksAdapter.provider as Any,
credentialsAdapter.provider as Any
credentialsAdapter.provider as Any,
settingsAdapter.provider as Any
]

return providers.compactMap { $0 as? DataProviding }
Expand Down Expand Up @@ -88,6 +91,7 @@ public class SyncDataProviders: DataProvidersSource {
self.secureVaultErrorReporter = secureVaultErrorReporter
bookmarksAdapter = SyncBookmarksAdapter(database: bookmarksDatabase)
credentialsAdapter = SyncCredentialsAdapter(secureVaultFactory: secureVaultFactory, secureVaultErrorReporter: secureVaultErrorReporter)
settingsAdapter = SyncSettingsAdapter()
}

private func initializeMetadataDatabaseIfNeeded() {
Expand Down
Loading

0 comments on commit 8aa0e6a

Please sign in to comment.