Skip to content

Commit

Permalink
Merge branch 'release/5.221.0'
Browse files Browse the repository at this point in the history
  • Loading branch information
github-actions[bot] committed Dec 2, 2024
2 parents 214808a + 6ae9727 commit 6551330
Show file tree
Hide file tree
Showing 406 changed files with 20,026 additions and 1,806 deletions.
3 changes: 2 additions & 1 deletion .github/actions/assign-release-task/github_asana_mapping.yml
Original file line number Diff line number Diff line change
Expand Up @@ -10,4 +10,5 @@ lmac012: "1205617573940213"
nalcalag: "1201807753392396"
CrisBarreiro: "1204920898013507"
0nko: "1207418217763343"
mikescamell: "1207908161520961"
mikescamell: "1207908161520961"
LukasPaczos: "1208671518759204"
28 changes: 28 additions & 0 deletions .github/actions/check-for-changes-since-tag/action.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
name: 'Check for code changes after a specific tag'
description: 'Checks if there are any new commits to the develop branch since the specified tag'

inputs:
tag:
description: 'Tag to check'
required: true

outputs:
has_changes:
description: Whether there are new commits since the last tag
value: ${{ steps.check_for_changes.outputs.has_changes }}

runs:
using: 'composite'
steps:
- id: check_for_changes
shell: bash
run: |
# Check if there are any new commits since the tag
new_commits=$(git rev-list ${{ inputs.tag }}..develop --count)
echo "$new_commits commits since ${{ inputs.tag }} tag"
if [ $new_commits -gt 0 ]; then
echo "has_changes=true" >> $GITHUB_OUTPUT
else
echo "has_changes=false" >> $GITHUB_OUTPUT
fi
32 changes: 31 additions & 1 deletion .github/workflows/release_nightly.yml
Original file line number Diff line number Diff line change
Expand Up @@ -48,71 +48,101 @@ jobs:
echo "Latest tag: $output"
echo "latest_tag=$output" >> $GITHUB_OUTPUT
- name: Check for changes
id: check_for_changes
uses: ./.github/actions/check-for-changes-since-tag
with:
github_token: ${{ secrets.GT_DAXMOBILE }}
tag: ${{ steps.get_latest_tag.outputs.latest_tag }}

- name: Notify if no changes
if: steps.check_for_changes.outputs.has_changes == 'false'
run: |
echo "No new commits since the last tag. Skipping nightly release."
echo "No new commits since the last tag. Skipping nightly release." >> $GITHUB_STEP_SUMMARY
exit 0
- name: Decode upload keys
if: steps.check_for_changes.outputs.has_changes == 'true'
uses: davidSchuppa/base64Secret-toFile-action@199e78f212c854d2284fada7f3cd3aba3e37d208
with:
secret: ${{ secrets.UPLOAD_RELEASE_PROPERTIES }}
fileName: ddg_android_build_upload.properties
destination-path: $HOME/jenkins_static/com.duckduckgo.mobile.android/

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

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

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

- name: Clean project
if: steps.check_for_changes.outputs.has_changes == 'true'
run: |
gradle clean
- name: Assemble the bundle
run: gradle bundleInternalRelease -PversionNameSuffix=-nightly -PuseUploadSigning -PlatestTag=${{ steps.get_latest_tag.outputs.latest_tag }}
if: steps.check_for_changes.outputs.has_changes == 'true'
run: gradle bundleInternalRelease -PversionNameSuffix=-nightly -PuseUploadSigning -PlatestTag=${{ steps.get_latest_tag.outputs.latest_tag }} -Pbuild-date-time

- name: Generate nightly version name
if: steps.check_for_changes.outputs.has_changes == 'true'
id: generate_version_name
run: |
output=$(gradle getBuildVersionName -PversionNameSuffix=-nightly -PlatestTag=${{ steps.get_latest_tag.outputs.latest_tag }} --quiet | tail -n 1)
echo "version=$output" >> $GITHUB_OUTPUT
- name: Capture App Bundle Path
if: steps.check_for_changes.outputs.has_changes == 'true'
id: capture_output
run: |
output=$(find app/build/outputs/bundle/internalRelease -name "*.aab")
echo "bundle_path=$output" >> $GITHUB_OUTPUT
- name: Upload bundle to Play Store Internal track
if: steps.check_for_changes.outputs.has_changes == 'true'
id: create_app_bundle
run: |
bundle exec fastlane deploy_dogfood aab_path:${{ steps.capture_output.outputs.bundle_path }}
- name: Tag Nightly release
if: steps.check_for_changes.outputs.has_changes == 'true'
id: tag_nightly_release
run: |
git checkout develop
git tag -a ${{ steps.generate_version_name.outputs.version }} -m "Create tag ${{ steps.generate_version_name.outputs.version }} for nightly release."
git push origin ${{ steps.generate_version_name.outputs.version }}
- name: Upload APK as artifact
if: steps.check_for_changes.outputs.has_changes == 'true'
uses: actions/upload-artifact@v4
with:
name: duckduckgo-${{ steps.generate_version_name.outputs.version }}.apk
path: duckduckgo.apk

- name: Set successful summary
if: steps.check_for_changes.outputs.has_changes == 'true'
run: |
echo "### Nightly release completed! :rocket:" >> $GITHUB_STEP_SUMMARY
- name: Create Asana task when workflow failed
if: ${{ failure() }}
uses: duckduckgo/[email protected]
Expand Down
12 changes: 3 additions & 9 deletions .github/workflows/release_upload_play_store.yml
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ jobs:
destination-path: $HOME/jenkins_static/com.duckduckgo.mobile.android/

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

- name: Capture App Bundle Path
id: capture_output
Expand All @@ -72,21 +72,15 @@ jobs:
echo "bundle_path=$output" >> $GITHUB_OUTPUT
- name: Upload bundle to Play Store
id: create_app_bundle
id: upload_bundle_play
run: |
bundle exec fastlane deploy_playstore
- name: Upload Universal APK to Github
id: create_app_bundle
id: upload_bundle_github
run: |
bundle exec fastlane deploy_github
- name: Upload APK as artifact
uses: actions/upload-artifact@v4
with:
name: duckduckgo-${{ steps.generate_version_name.outputs.version }}.apk
path: duckduckgo.apk

- name: Create Asana task when workflow failed
if: ${{ failure() }}
uses: duckduckgo/[email protected]
Expand Down
3 changes: 2 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -99,4 +99,5 @@ report
!/node_modules/@duckduckgo/content-scope-scripts/build/android/pages/
/node_modules/@duckduckgo/content-scope-scripts/build/android/pages/*
!/node_modules/@duckduckgo/content-scope-scripts/build/android/pages/duckplayer/
!/node_modules/@duckduckgo/content-scope-scripts/build/android/contentScope.js
!/node_modules/@duckduckgo/content-scope-scripts/build/android/contentScope.js
!/node_modules/@duckduckgo/content-scope-scripts/build/android/autofillPasswordImport.js
Original file line number Diff line number Diff line change
Expand Up @@ -118,7 +118,6 @@ class ContributesRemoteFeatureCodeGenerator : CodeGenerator {
.flavorNameProvider({ appBuildConfig.flavor.name })
.featureName(%S)
.appVariantProvider({ appBuildConfig.variantName })
.localeProvider({ appBuildConfig.deviceLocale })
.callback(callback)
// save empty variants will force the default variant to be set
.forceDefaultVariantProvider({ variantManager.updateVariants(emptyList()) })
Expand Down Expand Up @@ -521,6 +520,8 @@ class ContributesRemoteFeatureCodeGenerator : CodeGenerator {
variantKey = target.variantKey,
localeCountry = target.localeCountry,
localeLanguage = target.localeLanguage,
isReturningUser = target.isReturningUser,
isPrivacyProEligible = target.isPrivacyProEligible,
)
} ?: emptyList()
val cohorts = jsonToggle?.cohorts?.map { cohort ->
Expand Down Expand Up @@ -727,11 +728,22 @@ class ContributesRemoteFeatureCodeGenerator : CodeGenerator {
.addParameter("variantKey", String::class.asClassName())
.addParameter("localeCountry", String::class.asClassName())
.addParameter("localeLanguage", String::class.asClassName())
.addParameter("isReturningUser", Boolean::class.asClassName().copy(nullable = true))
.addParameter("isPrivacyProEligible", Boolean::class.asClassName().copy(nullable = true))
.build(),
)
.addProperty(PropertySpec.builder("variantKey", String::class.asClassName()).initializer("variantKey").build())
.addProperty(PropertySpec.builder("localeCountry", String::class.asClassName()).initializer("localeCountry").build())
.addProperty(PropertySpec.builder("localeLanguage", String::class.asClassName()).initializer("localeLanguage").build())
.addProperty(
PropertySpec.builder("isReturningUser", Boolean::class.asClassName().copy(nullable = true)).initializer("isReturningUser").build(),
)
.addProperty(
PropertySpec
.builder("isPrivacyProEligible", Boolean::class.asClassName().copy(nullable = true))
.initializer("isPrivacyProEligible")
.build(),
)
.build()
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ interface AppBuildConfig {
val model: String
val deviceLocale: Locale
val isDefaultVariantForced: Boolean
val buildDateTimeMillis: Long

/**
* You should call [variantName] in a background thread
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ enum class DeviceShieldPixelNames(override val pixelName: String, val enqueue: B
ATP_DISABLE_DAILY("m_atp_ev_disabled_d"),

ATP_ENABLE_UNIQUE("m_atp_ev_enabled_u"),
ATP_ENABLE_MONTHLY("m_atp_ev_enabled_monthly"),
ATP_ENABLE_FROM_REMINDER_NOTIFICATION_UNIQUE("m_atp_ev_enabled_reminder_notification_u"),
ATP_ENABLE_FROM_REMINDER_NOTIFICATION_DAILY("m_atp_ev_enabled_reminder_notification_d"),
ATP_ENABLE_FROM_REMINDER_NOTIFICATION("m_atp_ev_enabled_reminder_notification_c"),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,10 +24,13 @@ import com.duckduckgo.di.scopes.AppScope
import com.squareup.anvil.annotations.ContributesBinding
import dagger.SingleInstanceIn
import java.time.Instant
import java.time.LocalDate
import java.time.ZoneOffset
import java.time.format.DateTimeFormatter
import java.time.temporal.ChronoUnit
import java.util.*
import javax.inject.Inject
import kotlin.math.absoluteValue

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

override fun reportDisabled() {
Expand Down Expand Up @@ -934,6 +938,45 @@ class RealDeviceShieldPixels @Inject constructor(
}
}

private fun tryToFireMonthlyPixel(
pixel: DeviceShieldPixelNames,
payload: Map<String, String> = emptyMap(),
) {
tryToFireMonthlyPixel(pixel.pixelName, payload, pixel.enqueue)
}

private fun tryToFireMonthlyPixel(
pixelName: String,
payload: Map<String, String> = emptyMap(),
enqueue: Boolean = false,
) {
fun isMoreThan28DaysApart(date1: String, date2: String): Boolean {
// Parse the strings into LocalDate objects
val firstDate = LocalDate.parse(date1)
val secondDate = LocalDate.parse(date2)

// Calculate the difference in days
val daysBetween = ChronoUnit.DAYS.between(firstDate, secondDate).absoluteValue

// Check if the difference is more than 28 days
return daysBetween > 28
}

val now = getUtcIsoLocalDate()
val timestamp = preferences.getString(pixelName.appendTimestampSuffix(), null)

// check if pixel was already sent in the current day
if (timestamp == null || isMoreThan28DaysApart(now, timestamp)) {
if (enqueue) {
this.pixel.enqueueFire(pixelName, payload)
.also { preferences.edit { putString(pixelName.appendTimestampSuffix(), now) } }
} else {
this.pixel.fire(pixelName, payload)
.also { preferences.edit { putString(pixelName.appendTimestampSuffix(), now) } }
}
}
}

private fun tryToFireUniquePixel(
pixel: DeviceShieldPixelNames,
tag: String? = null,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -89,10 +89,6 @@ class PProUpsellBannerPlugin @Inject constructor(
startActivity(browserNav.openInNewTab(this, PPRO_UPSELL_URL))
}

private suspend fun Subscriptions.isUpsellEligible(): Boolean {
return getAccessToken() == null && isEligible()
}

companion object {
internal const val PRIORITY_PPRO_UPSELL_BANNER = PRIORITY_ACTION_REQUIRED - 1
private const val PPRO_UPSELL_URL = "https://duckduckgo.com/pro?origin=funnel_pro_android_apptp_banner"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -72,10 +72,6 @@ class PproUpsellDisabledMessagePlugin @Inject constructor(
startActivity(browserNav.openInNewTab(this, PPRO_UPSELL_URL))
}

private suspend fun Subscriptions.isUpsellEligible(): Boolean {
return getAccessToken() == null && isEligible()
}

companion object {
internal const val PRIORITY_PPRO_DISABLED = PRIORITY_DISABLED - 1
private const val PPRO_UPSELL_ANNOTATION = "ppro_upsell_link"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -70,10 +70,6 @@ class PproUpsellRevokedMessagePlugin @Inject constructor(
startActivity(browserNav.openInNewTab(this, PPRO_UPSELL_URL))
}

private suspend fun Subscriptions.isUpsellEligible(): Boolean {
return getAccessToken() == null && isEligible()
}

companion object {
internal const val PRIORITY_PPRO_REVOKED = PRIORITY_REVOKED - 1
private const val PPRO_UPSELL_ANNOTATION = "ppro_upsell_link"
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
/*
* Copyright (c) 2024 DuckDuckGo
*
* 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.
*/

package com.duckduckgo.mobile.android.vpn.ui.tracker_activity.view.message

import com.duckduckgo.subscriptions.api.Subscriptions

suspend fun Subscriptions.isUpsellEligible(): Boolean {
return !isSignedIn() && isEligible()
}
Loading

0 comments on commit 6551330

Please sign in to comment.