Skip to content

Commit 6551330

Browse files
Merge branch 'release/5.221.0'
2 parents 214808a + 6ae9727 commit 6551330

File tree

406 files changed

+20026
-1806
lines changed

Some content is hidden

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

406 files changed

+20026
-1806
lines changed

.github/actions/assign-release-task/github_asana_mapping.yml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,4 +10,5 @@ lmac012: "1205617573940213"
1010
nalcalag: "1201807753392396"
1111
CrisBarreiro: "1204920898013507"
1212
0nko: "1207418217763343"
13-
mikescamell: "1207908161520961"
13+
mikescamell: "1207908161520961"
14+
LukasPaczos: "1208671518759204"
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
name: 'Check for code changes after a specific tag'
2+
description: 'Checks if there are any new commits to the develop branch since the specified tag'
3+
4+
inputs:
5+
tag:
6+
description: 'Tag to check'
7+
required: true
8+
9+
outputs:
10+
has_changes:
11+
description: Whether there are new commits since the last tag
12+
value: ${{ steps.check_for_changes.outputs.has_changes }}
13+
14+
runs:
15+
using: 'composite'
16+
steps:
17+
- id: check_for_changes
18+
shell: bash
19+
run: |
20+
# Check if there are any new commits since the tag
21+
new_commits=$(git rev-list ${{ inputs.tag }}..develop --count)
22+
echo "$new_commits commits since ${{ inputs.tag }} tag"
23+
24+
if [ $new_commits -gt 0 ]; then
25+
echo "has_changes=true" >> $GITHUB_OUTPUT
26+
else
27+
echo "has_changes=false" >> $GITHUB_OUTPUT
28+
fi

.github/workflows/release_nightly.yml

Lines changed: 31 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,71 +48,101 @@ jobs:
4848
echo "Latest tag: $output"
4949
echo "latest_tag=$output" >> $GITHUB_OUTPUT
5050
51+
- name: Check for changes
52+
id: check_for_changes
53+
uses: ./.github/actions/check-for-changes-since-tag
54+
with:
55+
github_token: ${{ secrets.GT_DAXMOBILE }}
56+
tag: ${{ steps.get_latest_tag.outputs.latest_tag }}
57+
58+
- name: Notify if no changes
59+
if: steps.check_for_changes.outputs.has_changes == 'false'
60+
run: |
61+
echo "No new commits since the last tag. Skipping nightly release."
62+
echo "No new commits since the last tag. Skipping nightly release." >> $GITHUB_STEP_SUMMARY
63+
exit 0
64+
5165
- name: Decode upload keys
66+
if: steps.check_for_changes.outputs.has_changes == 'true'
5267
uses: davidSchuppa/base64Secret-toFile-action@199e78f212c854d2284fada7f3cd3aba3e37d208
5368
with:
5469
secret: ${{ secrets.UPLOAD_RELEASE_PROPERTIES }}
5570
fileName: ddg_android_build_upload.properties
5671
destination-path: $HOME/jenkins_static/com.duckduckgo.mobile.android/
5772

5873
- name: Decode key file
74+
if: steps.check_for_changes.outputs.has_changes == 'true'
5975
uses: davidSchuppa/base64Secret-toFile-action@199e78f212c854d2284fada7f3cd3aba3e37d208
6076
with:
6177
secret: ${{ secrets.UPLOAD_RELEASE_KEY }}
6278
fileName: ddg-upload-keystore.jks
6379
destination-path: $HOME/jenkins_static/com.duckduckgo.mobile.android/
6480

6581
- name: Decode Play Store credentials file
82+
if: steps.check_for_changes.outputs.has_changes == 'true'
6683
uses: davidSchuppa/base64Secret-toFile-action@199e78f212c854d2284fada7f3cd3aba3e37d208
6784
with:
6885
secret: ${{ secrets.UPLOAD_PLAY_CREDENTIALS }}
6986
fileName: api.json
7087
destination-path: $HOME/jenkins_static/com.duckduckgo.mobile.android/
7188

7289
- name: Decode Firebase credentials file
90+
if: steps.check_for_changes.outputs.has_changes == 'true'
7391
uses: davidSchuppa/base64Secret-toFile-action@199e78f212c854d2284fada7f3cd3aba3e37d208
7492
with:
7593
secret: ${{ secrets.UPLOAD_FIREBASE_CREDENTIALS }}
7694
fileName: ddg-upload-firebase.json
7795
destination-path: $HOME/jenkins_static/com.duckduckgo.mobile.android/
7896

7997
- name: Clean project
98+
if: steps.check_for_changes.outputs.has_changes == 'true'
8099
run: |
81100
gradle clean
82101
83102
- name: Assemble the bundle
84-
run: gradle bundleInternalRelease -PversionNameSuffix=-nightly -PuseUploadSigning -PlatestTag=${{ steps.get_latest_tag.outputs.latest_tag }}
103+
if: steps.check_for_changes.outputs.has_changes == 'true'
104+
run: gradle bundleInternalRelease -PversionNameSuffix=-nightly -PuseUploadSigning -PlatestTag=${{ steps.get_latest_tag.outputs.latest_tag }} -Pbuild-date-time
85105

86106
- name: Generate nightly version name
107+
if: steps.check_for_changes.outputs.has_changes == 'true'
87108
id: generate_version_name
88109
run: |
89110
output=$(gradle getBuildVersionName -PversionNameSuffix=-nightly -PlatestTag=${{ steps.get_latest_tag.outputs.latest_tag }} --quiet | tail -n 1)
90111
echo "version=$output" >> $GITHUB_OUTPUT
91112
92113
- name: Capture App Bundle Path
114+
if: steps.check_for_changes.outputs.has_changes == 'true'
93115
id: capture_output
94116
run: |
95117
output=$(find app/build/outputs/bundle/internalRelease -name "*.aab")
96118
echo "bundle_path=$output" >> $GITHUB_OUTPUT
97119
98120
- name: Upload bundle to Play Store Internal track
121+
if: steps.check_for_changes.outputs.has_changes == 'true'
99122
id: create_app_bundle
100123
run: |
101124
bundle exec fastlane deploy_dogfood aab_path:${{ steps.capture_output.outputs.bundle_path }}
102125
103126
- name: Tag Nightly release
127+
if: steps.check_for_changes.outputs.has_changes == 'true'
104128
id: tag_nightly_release
105129
run: |
106130
git checkout develop
107131
git tag -a ${{ steps.generate_version_name.outputs.version }} -m "Create tag ${{ steps.generate_version_name.outputs.version }} for nightly release."
108132
git push origin ${{ steps.generate_version_name.outputs.version }}
109133
110134
- name: Upload APK as artifact
135+
if: steps.check_for_changes.outputs.has_changes == 'true'
111136
uses: actions/upload-artifact@v4
112137
with:
113138
name: duckduckgo-${{ steps.generate_version_name.outputs.version }}.apk
114139
path: duckduckgo.apk
115140

141+
- name: Set successful summary
142+
if: steps.check_for_changes.outputs.has_changes == 'true'
143+
run: |
144+
echo "### Nightly release completed! :rocket:" >> $GITHUB_STEP_SUMMARY
145+
116146
- name: Create Asana task when workflow failed
117147
if: ${{ failure() }}
118148
uses: duckduckgo/[email protected]

.github/workflows/release_upload_play_store.yml

Lines changed: 3 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,7 @@ jobs:
6363
destination-path: $HOME/jenkins_static/com.duckduckgo.mobile.android/
6464

6565
- name: Assemble the bundle
66-
run: ./gradleW bundleRelease -PuseUploadSigning
66+
run: ./gradlew bundleRelease -PuseUploadSigning -Pbuild-date-time
6767

6868
- name: Capture App Bundle Path
6969
id: capture_output
@@ -72,21 +72,15 @@ jobs:
7272
echo "bundle_path=$output" >> $GITHUB_OUTPUT
7373
7474
- name: Upload bundle to Play Store
75-
id: create_app_bundle
75+
id: upload_bundle_play
7676
run: |
7777
bundle exec fastlane deploy_playstore
7878
7979
- name: Upload Universal APK to Github
80-
id: create_app_bundle
80+
id: upload_bundle_github
8181
run: |
8282
bundle exec fastlane deploy_github
8383
84-
- name: Upload APK as artifact
85-
uses: actions/upload-artifact@v4
86-
with:
87-
name: duckduckgo-${{ steps.generate_version_name.outputs.version }}.apk
88-
path: duckduckgo.apk
89-
9084
- name: Create Asana task when workflow failed
9185
if: ${{ failure() }}
9286
uses: duckduckgo/[email protected]

.gitignore

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -99,4 +99,5 @@ report
9999
!/node_modules/@duckduckgo/content-scope-scripts/build/android/pages/
100100
/node_modules/@duckduckgo/content-scope-scripts/build/android/pages/*
101101
!/node_modules/@duckduckgo/content-scope-scripts/build/android/pages/duckplayer/
102-
!/node_modules/@duckduckgo/content-scope-scripts/build/android/contentScope.js
102+
!/node_modules/@duckduckgo/content-scope-scripts/build/android/contentScope.js
103+
!/node_modules/@duckduckgo/content-scope-scripts/build/android/autofillPasswordImport.js

anvil/anvil-compiler/src/main/java/com/duckduckgo/anvil/compiler/ContributesRemoteFeatureCodeGenerator.kt

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -118,7 +118,6 @@ class ContributesRemoteFeatureCodeGenerator : CodeGenerator {
118118
.flavorNameProvider({ appBuildConfig.flavor.name })
119119
.featureName(%S)
120120
.appVariantProvider({ appBuildConfig.variantName })
121-
.localeProvider({ appBuildConfig.deviceLocale })
122121
.callback(callback)
123122
// save empty variants will force the default variant to be set
124123
.forceDefaultVariantProvider({ variantManager.updateVariants(emptyList()) })
@@ -521,6 +520,8 @@ class ContributesRemoteFeatureCodeGenerator : CodeGenerator {
521520
variantKey = target.variantKey,
522521
localeCountry = target.localeCountry,
523522
localeLanguage = target.localeLanguage,
523+
isReturningUser = target.isReturningUser,
524+
isPrivacyProEligible = target.isPrivacyProEligible,
524525
)
525526
} ?: emptyList()
526527
val cohorts = jsonToggle?.cohorts?.map { cohort ->
@@ -727,11 +728,22 @@ class ContributesRemoteFeatureCodeGenerator : CodeGenerator {
727728
.addParameter("variantKey", String::class.asClassName())
728729
.addParameter("localeCountry", String::class.asClassName())
729730
.addParameter("localeLanguage", String::class.asClassName())
731+
.addParameter("isReturningUser", Boolean::class.asClassName().copy(nullable = true))
732+
.addParameter("isPrivacyProEligible", Boolean::class.asClassName().copy(nullable = true))
730733
.build(),
731734
)
732735
.addProperty(PropertySpec.builder("variantKey", String::class.asClassName()).initializer("variantKey").build())
733736
.addProperty(PropertySpec.builder("localeCountry", String::class.asClassName()).initializer("localeCountry").build())
734737
.addProperty(PropertySpec.builder("localeLanguage", String::class.asClassName()).initializer("localeLanguage").build())
738+
.addProperty(
739+
PropertySpec.builder("isReturningUser", Boolean::class.asClassName().copy(nullable = true)).initializer("isReturningUser").build(),
740+
)
741+
.addProperty(
742+
PropertySpec
743+
.builder("isPrivacyProEligible", Boolean::class.asClassName().copy(nullable = true))
744+
.initializer("isPrivacyProEligible")
745+
.build(),
746+
)
735747
.build()
736748
}
737749

app-build-config/app-build-config-api/src/main/java/com/duckduckgo/appbuildconfig/api/AppBuildConfig.kt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ interface AppBuildConfig {
3232
val model: String
3333
val deviceLocale: Locale
3434
val isDefaultVariantForced: Boolean
35+
val buildDateTimeMillis: Long
3536

3637
/**
3738
* You should call [variantName] in a background thread

app-tracking-protection/vpn-impl/src/main/java/com/duckduckgo/mobile/android/vpn/pixels/DeviceShieldPixelNames.kt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@ enum class DeviceShieldPixelNames(override val pixelName: String, val enqueue: B
3939
ATP_DISABLE_DAILY("m_atp_ev_disabled_d"),
4040

4141
ATP_ENABLE_UNIQUE("m_atp_ev_enabled_u"),
42+
ATP_ENABLE_MONTHLY("m_atp_ev_enabled_monthly"),
4243
ATP_ENABLE_FROM_REMINDER_NOTIFICATION_UNIQUE("m_atp_ev_enabled_reminder_notification_u"),
4344
ATP_ENABLE_FROM_REMINDER_NOTIFICATION_DAILY("m_atp_ev_enabled_reminder_notification_d"),
4445
ATP_ENABLE_FROM_REMINDER_NOTIFICATION("m_atp_ev_enabled_reminder_notification_c"),

app-tracking-protection/vpn-impl/src/main/java/com/duckduckgo/mobile/android/vpn/pixels/DeviceShieldPixels.kt

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,10 +24,13 @@ import com.duckduckgo.di.scopes.AppScope
2424
import com.squareup.anvil.annotations.ContributesBinding
2525
import dagger.SingleInstanceIn
2626
import java.time.Instant
27+
import java.time.LocalDate
2728
import java.time.ZoneOffset
2829
import java.time.format.DateTimeFormatter
30+
import java.time.temporal.ChronoUnit
2931
import java.util.*
3032
import javax.inject.Inject
33+
import kotlin.math.absoluteValue
3134

3235
interface DeviceShieldPixels {
3336
/** This pixel will be unique on a given day, no matter how many times we call this fun */
@@ -414,6 +417,7 @@ class RealDeviceShieldPixels @Inject constructor(
414417
override fun reportEnabled() {
415418
tryToFireUniquePixel(DeviceShieldPixelNames.ATP_ENABLE_UNIQUE)
416419
tryToFireDailyPixel(DeviceShieldPixelNames.ATP_ENABLE_DAILY)
420+
tryToFireMonthlyPixel(DeviceShieldPixelNames.ATP_ENABLE_MONTHLY)
417421
}
418422

419423
override fun reportDisabled() {
@@ -934,6 +938,45 @@ class RealDeviceShieldPixels @Inject constructor(
934938
}
935939
}
936940

941+
private fun tryToFireMonthlyPixel(
942+
pixel: DeviceShieldPixelNames,
943+
payload: Map<String, String> = emptyMap(),
944+
) {
945+
tryToFireMonthlyPixel(pixel.pixelName, payload, pixel.enqueue)
946+
}
947+
948+
private fun tryToFireMonthlyPixel(
949+
pixelName: String,
950+
payload: Map<String, String> = emptyMap(),
951+
enqueue: Boolean = false,
952+
) {
953+
fun isMoreThan28DaysApart(date1: String, date2: String): Boolean {
954+
// Parse the strings into LocalDate objects
955+
val firstDate = LocalDate.parse(date1)
956+
val secondDate = LocalDate.parse(date2)
957+
958+
// Calculate the difference in days
959+
val daysBetween = ChronoUnit.DAYS.between(firstDate, secondDate).absoluteValue
960+
961+
// Check if the difference is more than 28 days
962+
return daysBetween > 28
963+
}
964+
965+
val now = getUtcIsoLocalDate()
966+
val timestamp = preferences.getString(pixelName.appendTimestampSuffix(), null)
967+
968+
// check if pixel was already sent in the current day
969+
if (timestamp == null || isMoreThan28DaysApart(now, timestamp)) {
970+
if (enqueue) {
971+
this.pixel.enqueueFire(pixelName, payload)
972+
.also { preferences.edit { putString(pixelName.appendTimestampSuffix(), now) } }
973+
} else {
974+
this.pixel.fire(pixelName, payload)
975+
.also { preferences.edit { putString(pixelName.appendTimestampSuffix(), now) } }
976+
}
977+
}
978+
}
979+
937980
private fun tryToFireUniquePixel(
938981
pixel: DeviceShieldPixelNames,
939982
tag: String? = null,

app-tracking-protection/vpn-impl/src/main/java/com/duckduckgo/mobile/android/vpn/ui/tracker_activity/view/message/PProUpsellBannerPlugin.kt

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -89,10 +89,6 @@ class PProUpsellBannerPlugin @Inject constructor(
8989
startActivity(browserNav.openInNewTab(this, PPRO_UPSELL_URL))
9090
}
9191

92-
private suspend fun Subscriptions.isUpsellEligible(): Boolean {
93-
return getAccessToken() == null && isEligible()
94-
}
95-
9692
companion object {
9793
internal const val PRIORITY_PPRO_UPSELL_BANNER = PRIORITY_ACTION_REQUIRED - 1
9894
private const val PPRO_UPSELL_URL = "https://duckduckgo.com/pro?origin=funnel_pro_android_apptp_banner"

0 commit comments

Comments
 (0)