From 0fd512d66fb600fdb72c9e30d032e314c1f48f3b Mon Sep 17 00:00:00 2001 From: Brian Hall Date: Tue, 14 Jan 2025 14:04:33 +0100 Subject: [PATCH 01/12] Convert Verecor child sites to be parent sites (#3678) Task/Issue URL: https://app.asana.com/0/608920331025329/1209014062691302/f Tech Design URL: CC: **Description**: **Optional E2E tests**: - [x] Run PIR E2E tests Check this to run the Personal Information Removal end to end tests. If updating CCF, or any PIR related code, tick this. **Steps to test this PR**: 1. **Definition of Done**: * [ ] Does this PR satisfy our [Definition of Done](https://app.asana.com/0/1202500774821704/1207634633537039/f)? --- ###### Internal references: [Pull Request Review Checklist](https://app.asana.com/0/1202500774821704/1203764234894239/f) [Software Engineering Expectations](https://app.asana.com/0/59792373528535/199064865822552) [Technical Design Template](https://app.asana.com/0/59792373528535/184709971311943) [Pull Request Documentation](https://app.asana.com/0/1202500774821704/1204012835277482/f) --- .../Resources/JSON/backgroundcheck.run.json | 69 +++++++++++++++- .../Resources/JSON/clubset.com.json | 79 ++++++++++++++++++- .../Resources/JSON/councilon.com.json | 79 ++++++++++++++++++- .../Resources/JSON/curadvisor.com.json | 79 ++++++++++++++++++- .../Resources/JSON/kwold.com.json | 79 ++++++++++++++++++- .../Resources/JSON/newenglandfacts.com.json | 69 +++++++++++++++- .../JSON/people-background-check.com.json | 69 +++++++++++++++- .../Resources/JSON/vericora.com.json | 79 ++++++++++++++++++- .../Resources/JSON/veriforia.com.json | 79 ++++++++++++++++++- .../Resources/JSON/virtory.com.json | 79 ++++++++++++++++++- .../Resources/JSON/wellnut.com.json | 79 ++++++++++++++++++- 11 files changed, 795 insertions(+), 44 deletions(-) diff --git a/LocalPackages/DataBrokerProtection/Sources/DataBrokerProtection/Resources/JSON/backgroundcheck.run.json b/LocalPackages/DataBrokerProtection/Sources/DataBrokerProtection/Resources/JSON/backgroundcheck.run.json index d8ba2b8237..973b139e4c 100644 --- a/LocalPackages/DataBrokerProtection/Sources/DataBrokerProtection/Resources/JSON/backgroundcheck.run.json +++ b/LocalPackages/DataBrokerProtection/Sources/DataBrokerProtection/Resources/JSON/backgroundcheck.run.json @@ -1,8 +1,7 @@ { "name": "backgroundcheck.run", "url": "backgroundcheck.run", - "version": "0.4.0", - "parent": "verecor.com", + "version": "0.5.0", "addedDatetime": 1677736800000, "optOutUrl": "https://backgroundcheck.run/ng/control/privacy", "steps": [ @@ -51,8 +50,70 @@ }, { "stepType": "optOut", - "optOutType": "parentSiteOptOut", - "actions": [] + "optOutType": "formOptOut", + "actions": [ + { + "actionType": "navigate", + "url": "https://backgroundcheck.run/ng/control/privacy", + "id": "fa29793c-3f85-4f01-a5fe-4ffcc26c197c" + }, + { + "actionType": "fillForm", + "selector": ".ahm", + "elements": [ + { + "type": "fullName", + "selector": "#name" + }, + { + "type": "email", + "selector": "#email" + }, + { + "type": "profileUrl", + "selector": "#url" + } + ], + "id": "71be571c-ce0c-43cb-afad-ae6547d44726" + }, + { + "actionType": "click", + "elements": [ + { + "type": "button", + "selector": ".//button[@type='submit']" + } + ], + "id": "e8794659-162d-4de7-9845-bbd140c54a00" + }, + { + "actionType": "expectation", + "expectations": [ + { + "type": "text", + "selector": "body", + "expect": "Your removal request has been received" + } + ], + "id": "6ab596e2-3642-4dba-97f0-1270d8feefd1" + }, + { + "actionType": "emailConfirmation", + "pollingTime": 30, + "id": "9431f4e4-140a-4ade-8e74-3b7917b6ab2b" + }, + { + "actionType": "expectation", + "expectations": [ + { + "type": "text", + "selector": "body", + "expect": "Your information control request has been confirmed." + } + ], + "id": "92e1c4ff-4466-42e7-b2dd-70a319af48da" + } + ] } ], "schedulingConfig": { diff --git a/LocalPackages/DataBrokerProtection/Sources/DataBrokerProtection/Resources/JSON/clubset.com.json b/LocalPackages/DataBrokerProtection/Sources/DataBrokerProtection/Resources/JSON/clubset.com.json index 3561e4963f..03f73fa09c 100644 --- a/LocalPackages/DataBrokerProtection/Sources/DataBrokerProtection/Resources/JSON/clubset.com.json +++ b/LocalPackages/DataBrokerProtection/Sources/DataBrokerProtection/Resources/JSON/clubset.com.json @@ -1,8 +1,7 @@ { "name": "Clubset", "url": "clubset.com", - "version": "0.4.0", - "parent": "verecor.com", + "version": "0.5.0", "addedDatetime": 1702965600000, "optOutUrl": "https://clubset.com/private/control/privacy", "steps": [ @@ -63,8 +62,80 @@ }, { "stepType": "optOut", - "optOutType": "parentSiteOptOut", - "actions": [] + "optOutType": "formOptOut", + "actions": [ + { + "actionType": "navigate", + "url": "https://clubset.com/private/control/privacy", + "id": "87fb7e0b-87ea-413d-847a-e88b3d023776" + }, + { + "actionType": "fillForm", + "selector": ".ahm", + "elements": [ + { + "type": "fullName", + "selector": "#user_name" + }, + { + "type": "email", + "selector": "#user_email" + }, + { + "type": "profileUrl", + "selector": "#url" + } + ], + "id": "48c3acd8-61fc-4680-9811-77dc5ba9c9a6" + }, + { + "actionType": "getCaptchaInfo", + "selector": ".g-recaptcha", + "id": "47d8cf16-354f-4359-ac37-05c617d5f03e" + }, + { + "actionType": "solveCaptcha", + "selector": ".g-recaptcha", + "id": "eb5e43df-d4dd-45e8-8192-bfcb3e814ed5" + }, + { + "actionType": "click", + "elements": [ + { + "type": "button", + "selector": ".//button[@type='submit']" + } + ], + "id": "2521002e-f825-4a93-aa6e-966f499096d1" + }, + { + "actionType": "expectation", + "expectations": [ + { + "type": "text", + "selector": "body", + "expect": "Your removal request has been received" + } + ], + "id": "f72634ca-60c3-450f-9656-52d924d8361f" + }, + { + "actionType": "emailConfirmation", + "pollingTime": 30, + "id": "075640a6-f010-4135-9b46-25655e5eadd1" + }, + { + "actionType": "expectation", + "expectations": [ + { + "type": "text", + "selector": "body", + "expect": "Your information control request has been confirmed." + } + ], + "id": "96a083a1-f84b-42df-89bd-b5d0601468b2" + } + ] } ], "schedulingConfig": { diff --git a/LocalPackages/DataBrokerProtection/Sources/DataBrokerProtection/Resources/JSON/councilon.com.json b/LocalPackages/DataBrokerProtection/Sources/DataBrokerProtection/Resources/JSON/councilon.com.json index f15cee8c2e..e5eb48aae1 100644 --- a/LocalPackages/DataBrokerProtection/Sources/DataBrokerProtection/Resources/JSON/councilon.com.json +++ b/LocalPackages/DataBrokerProtection/Sources/DataBrokerProtection/Resources/JSON/councilon.com.json @@ -1,8 +1,7 @@ { "name": "Councilon", "url": "councilon.com", - "version": "0.4.0", - "parent": "verecor.com", + "version": "0.5.0", "addedDatetime": 1702965600000, "optOutUrl": "https://councilon.com/ex/control/privacy", "steps": [ @@ -63,8 +62,80 @@ }, { "stepType": "optOut", - "optOutType": "parentSiteOptOut", - "actions": [] + "optOutType": "formOptOut", + "actions": [ + { + "actionType": "navigate", + "url": "https://councilon.com/ex/control/privacy", + "id": "9f4ef020-811e-4d02-8622-ebe7a714a0d0" + }, + { + "actionType": "fillForm", + "selector": ".ahm", + "elements": [ + { + "type": "fullName", + "selector": "#user_name" + }, + { + "type": "email", + "selector": "#user_email" + }, + { + "type": "profileUrl", + "selector": "#url" + } + ], + "id": "8e7adf0a-58fb-4e57-b3b3-79cd99eeb395" + }, + { + "actionType": "getCaptchaInfo", + "selector": ".g-recaptcha", + "id": "c80c3e5c-fa66-45c8-816b-bb320a247777" + }, + { + "actionType": "solveCaptcha", + "selector": ".g-recaptcha", + "id": "30cfa92e-627c-4b00-9fd1-032952338468" + }, + { + "actionType": "click", + "elements": [ + { + "type": "button", + "selector": ".//button[@type='submit']" + } + ], + "id": "1d3fe64a-d23d-448c-bf34-aeccf32beb87" + }, + { + "actionType": "expectation", + "expectations": [ + { + "type": "text", + "selector": "body", + "expect": "Your removal request has been received" + } + ], + "id": "e6840eae-b334-431d-bbb8-94189e09023d" + }, + { + "actionType": "emailConfirmation", + "pollingTime": 30, + "id": "8983034c-211a-4d98-8f31-bdf28a4e5011" + }, + { + "actionType": "expectation", + "expectations": [ + { + "type": "text", + "selector": "body", + "expect": "Your information control request has been confirmed." + } + ], + "id": "ffb143e1-a408-456b-9e27-d5b199cd0b52" + } + ] } ], "schedulingConfig": { diff --git a/LocalPackages/DataBrokerProtection/Sources/DataBrokerProtection/Resources/JSON/curadvisor.com.json b/LocalPackages/DataBrokerProtection/Sources/DataBrokerProtection/Resources/JSON/curadvisor.com.json index f415eab9f9..8176c3940e 100644 --- a/LocalPackages/DataBrokerProtection/Sources/DataBrokerProtection/Resources/JSON/curadvisor.com.json +++ b/LocalPackages/DataBrokerProtection/Sources/DataBrokerProtection/Resources/JSON/curadvisor.com.json @@ -1,8 +1,7 @@ { "name": "CurAdvisor", "url": "curadvisor.com", - "version": "0.4.0", - "parent": "verecor.com", + "version": "0.5.0", "addedDatetime": 1703052000000, "optOutUrl": "https://curadvisor.com/nada/control/privacy", "steps": [ @@ -63,8 +62,80 @@ }, { "stepType": "optOut", - "optOutType": "parentSiteOptOut", - "actions": [] + "optOutType": "formOptOut", + "actions": [ + { + "actionType": "navigate", + "url": "https://curadvisor.com/nada/control/privacy", + "id": "0a0fd3f4-4505-4ebc-bbbe-819b86ac18a7" + }, + { + "actionType": "fillForm", + "selector": ".ahm", + "elements": [ + { + "type": "fullName", + "selector": "#user_name" + }, + { + "type": "email", + "selector": "#user_email" + }, + { + "type": "profileUrl", + "selector": "#url" + } + ], + "id": "0cb160f0-3475-4476-a87f-2a084bcbd4d8" + }, + { + "actionType": "getCaptchaInfo", + "selector": ".g-recaptcha", + "id": "5ebf6fc6-a3ee-41f2-875f-82e9d11d24e9" + }, + { + "actionType": "solveCaptcha", + "selector": ".g-recaptcha", + "id": "22ec8469-c3f8-41e5-8537-6406e817da06" + }, + { + "actionType": "click", + "elements": [ + { + "type": "button", + "selector": ".//button[@type='submit']" + } + ], + "id": "d02dd323-1508-4be7-b2d2-72f4bd67fc95" + }, + { + "actionType": "expectation", + "expectations": [ + { + "type": "text", + "selector": "body", + "expect": "Your removal request has been received" + } + ], + "id": "be51eb91-bba3-4f2d-8e33-d973372e281d" + }, + { + "actionType": "emailConfirmation", + "pollingTime": 30, + "id": "e417378b-bb62-4d63-ad8b-f2e1c3b30e1a" + }, + { + "actionType": "expectation", + "expectations": [ + { + "type": "text", + "selector": "body", + "expect": "Your information control request has been confirmed." + } + ], + "id": "e47c20c6-c45f-4d75-b514-06ffa97e35d5" + } + ] } ], "schedulingConfig": { diff --git a/LocalPackages/DataBrokerProtection/Sources/DataBrokerProtection/Resources/JSON/kwold.com.json b/LocalPackages/DataBrokerProtection/Sources/DataBrokerProtection/Resources/JSON/kwold.com.json index cbe6abc734..4372ba6bb6 100644 --- a/LocalPackages/DataBrokerProtection/Sources/DataBrokerProtection/Resources/JSON/kwold.com.json +++ b/LocalPackages/DataBrokerProtection/Sources/DataBrokerProtection/Resources/JSON/kwold.com.json @@ -1,8 +1,7 @@ { "name": "Kwold", "url": "kwold.com", - "version": "0.4.0", - "parent": "verecor.com", + "version": "0.5.0", "addedDatetime": 1702965600000, "optOutUrl": "https://kwold.com/ns/control/privacy", "steps": [ @@ -63,8 +62,80 @@ }, { "stepType": "optOut", - "optOutType": "parentSiteOptOut", - "actions": [] + "optOutType": "formOptOut", + "actions": [ + { + "actionType": "navigate", + "url": "https://kwold.com/ns/control/privacy", + "id": "037f7920-b9e7-4214-a937-171ec641d641" + }, + { + "actionType": "fillForm", + "selector": ".ahm", + "elements": [ + { + "type": "fullName", + "selector": "#user_name" + }, + { + "type": "email", + "selector": "#user_email" + }, + { + "type": "profileUrl", + "selector": "#url" + } + ], + "id": "5b9de12f-a52e-4bd0-b6ac-6884377d309b" + }, + { + "actionType": "getCaptchaInfo", + "selector": ".g-recaptcha", + "id": "48e5e7a8-af33-4629-a849-2cf926a518a3" + }, + { + "actionType": "solveCaptcha", + "selector": ".g-recaptcha", + "id": "bc2d26dc-3eef-478a-a04b-5671a1dbdf8b" + }, + { + "actionType": "click", + "elements": [ + { + "type": "button", + "selector": ".//button[@type='submit']" + } + ], + "id": "7f2a685e-ddad-4c5a-8e80-a6d3a690851f" + }, + { + "actionType": "expectation", + "expectations": [ + { + "type": "text", + "selector": "body", + "expect": "Your removal request has been received" + } + ], + "id": "3a8a6e9d-c9a0-4e59-a8a4-fe4a05f3ce68" + }, + { + "actionType": "emailConfirmation", + "pollingTime": 30, + "id": "93ccf84a-a5ce-4dcf-8a78-143610723488" + }, + { + "actionType": "expectation", + "expectations": [ + { + "type": "text", + "selector": "body", + "expect": "Your information control request has been confirmed." + } + ], + "id": "fcddc35b-6298-4f2b-a04c-08a2d6f7ceaa" + } + ] } ], "schedulingConfig": { diff --git a/LocalPackages/DataBrokerProtection/Sources/DataBrokerProtection/Resources/JSON/newenglandfacts.com.json b/LocalPackages/DataBrokerProtection/Sources/DataBrokerProtection/Resources/JSON/newenglandfacts.com.json index 9be7b4f7d9..ce93b0c82f 100644 --- a/LocalPackages/DataBrokerProtection/Sources/DataBrokerProtection/Resources/JSON/newenglandfacts.com.json +++ b/LocalPackages/DataBrokerProtection/Sources/DataBrokerProtection/Resources/JSON/newenglandfacts.com.json @@ -1,8 +1,7 @@ { "name": "New England Facts", "url": "newenglandfacts.com", - "version": "0.3.0", - "parent": "verecor.com", + "version": "0.4.0", "addedDatetime": 1703052000000, "optOutUrl": "https://newenglandfacts.com/ng/control/privacy", "steps": [ @@ -61,8 +60,70 @@ }, { "stepType": "optOut", - "optOutType": "parentSiteOptOut", - "actions": [] + "optOutType": "formOptOut", + "actions": [ + { + "actionType": "navigate", + "url": "https://newenglandfacts.com/ng/control/privacy", + "id": "08332622-1749-4bdc-97d0-2366fef87522" + }, + { + "actionType": "fillForm", + "selector": ".ahm", + "elements": [ + { + "type": "fullName", + "selector": "#name" + }, + { + "type": "email", + "selector": "#email" + }, + { + "type": "profileUrl", + "selector": "#url" + } + ], + "id": "e3fdaaf0-70a5-4b7b-afa8-18306276f13a" + }, + { + "actionType": "click", + "elements": [ + { + "type": "button", + "selector": ".//button[@type='submit']" + } + ], + "id": "05bcd52d-21c7-4c00-bb18-b1de4b6803aa" + }, + { + "actionType": "expectation", + "expectations": [ + { + "type": "text", + "selector": "body", + "expect": "Your removal request has been received" + } + ], + "id": "37511ba6-e622-4614-8657-d4523f650a18" + }, + { + "actionType": "emailConfirmation", + "pollingTime": 30, + "id": "80f13572-98f8-4aeb-a77c-25dcc863681a" + }, + { + "actionType": "expectation", + "expectations": [ + { + "type": "text", + "selector": "body", + "expect": "Your information control request has been confirmed." + } + ], + "id": "fd232579-b39e-40c8-ab33-596b7e01bf33" + } + ] } ], "schedulingConfig": { diff --git a/LocalPackages/DataBrokerProtection/Sources/DataBrokerProtection/Resources/JSON/people-background-check.com.json b/LocalPackages/DataBrokerProtection/Sources/DataBrokerProtection/Resources/JSON/people-background-check.com.json index cad2226e09..ba41e564c6 100644 --- a/LocalPackages/DataBrokerProtection/Sources/DataBrokerProtection/Resources/JSON/people-background-check.com.json +++ b/LocalPackages/DataBrokerProtection/Sources/DataBrokerProtection/Resources/JSON/people-background-check.com.json @@ -1,8 +1,7 @@ { "name": "People Background Check", "url": "people-background-check.com", - "version": "0.5.0", - "parent": "verecor.com", + "version": "0.6.0", "addedDatetime": 1702965600000, "optOutUrl": "https://people-background-check.com/ng/control/privacy", "steps": [ @@ -51,8 +50,70 @@ }, { "stepType": "optOut", - "optOutType": "parentSiteOptOut", - "actions": [] + "optOutType": "formOptOut", + "actions": [ + { + "actionType": "navigate", + "url": "https://people-background-check.com/ng/control/privacy", + "id": "bc160586-6a98-4eac-9fbf-fa7d24ef8bd7" + }, + { + "actionType": "fillForm", + "selector": ".ahm", + "elements": [ + { + "type": "fullName", + "selector": "#name" + }, + { + "type": "email", + "selector": "#email" + }, + { + "type": "profileUrl", + "selector": "#url" + } + ], + "id": "02e4ce59-a0e1-42cb-9adc-d07e4f28a7ff" + }, + { + "actionType": "click", + "elements": [ + { + "type": "button", + "selector": ".//button[@type='submit']" + } + ], + "id": "3ab8814b-39c1-4d3b-ab1d-5cbc69e43919" + }, + { + "actionType": "expectation", + "expectations": [ + { + "type": "text", + "selector": "body", + "expect": "Your removal request has been received" + } + ], + "id": "b3260029-4cec-43cf-9da2-dc15467e7264" + }, + { + "actionType": "emailConfirmation", + "pollingTime": 30, + "id": "c1b7e968-a183-4d91-88da-b8c70313e9b9" + }, + { + "actionType": "expectation", + "expectations": [ + { + "type": "text", + "selector": "body", + "expect": "Your information control request has been confirmed." + } + ], + "id": "14e8f388-a24f-4ce8-a3d5-e3e6eda1e8ef" + } + ] } ], "schedulingConfig": { diff --git a/LocalPackages/DataBrokerProtection/Sources/DataBrokerProtection/Resources/JSON/vericora.com.json b/LocalPackages/DataBrokerProtection/Sources/DataBrokerProtection/Resources/JSON/vericora.com.json index 110c78ffbb..76a017a3b1 100644 --- a/LocalPackages/DataBrokerProtection/Sources/DataBrokerProtection/Resources/JSON/vericora.com.json +++ b/LocalPackages/DataBrokerProtection/Sources/DataBrokerProtection/Resources/JSON/vericora.com.json @@ -1,8 +1,7 @@ { "name": "Vericora", "url": "vericora.com", - "version": "0.4.0", - "parent": "verecor.com", + "version": "0.5.0", "addedDatetime": 1677736800000, "optOutUrl": "https://vericora.com/ng/control/privacy", "steps": [ @@ -60,8 +59,80 @@ }, { "stepType": "optOut", - "optOutType": "parentSiteOptOut", - "actions": [] + "optOutType": "formOptOut", + "actions": [ + { + "actionType": "navigate", + "url": "https://vericora.com/ng/control/privacy", + "id": "db351d7c-3ca0-4af4-9aed-b2f8fba15622" + }, + { + "actionType": "fillForm", + "selector": ".ahm", + "elements": [ + { + "type": "fullName", + "selector": "#user_name" + }, + { + "type": "email", + "selector": "#user_email" + }, + { + "type": "profileUrl", + "selector": "#url" + } + ], + "id": "c26a1a7c-46c5-4a10-a9d3-ff0660e15e32" + }, + { + "actionType": "getCaptchaInfo", + "selector": ".g-recaptcha", + "id": "09599d30-8953-477a-bb70-8042baa20cb5" + }, + { + "actionType": "solveCaptcha", + "selector": ".g-recaptcha", + "id": "a2af0d54-7170-4181-908b-669bf4dfbcea" + }, + { + "actionType": "click", + "elements": [ + { + "type": "button", + "selector": ".//button[@type='submit']" + } + ], + "id": "caf8c297-2e02-4d0b-a9ef-fb9fdb39315d" + }, + { + "actionType": "expectation", + "expectations": [ + { + "type": "text", + "selector": "body", + "expect": "Your removal request has been received" + } + ], + "id": "b22b9195-acae-4c23-aeaf-a45e39b7a776" + }, + { + "actionType": "emailConfirmation", + "pollingTime": 30, + "id": "e8a95e02-89a0-4c6b-980d-36db2780b54b" + }, + { + "actionType": "expectation", + "expectations": [ + { + "type": "text", + "selector": "body", + "expect": "Your information control request has been confirmed." + } + ], + "id": "9adf03c9-444f-450d-992f-adbbdf80a211" + } + ] } ], "schedulingConfig": { diff --git a/LocalPackages/DataBrokerProtection/Sources/DataBrokerProtection/Resources/JSON/veriforia.com.json b/LocalPackages/DataBrokerProtection/Sources/DataBrokerProtection/Resources/JSON/veriforia.com.json index 96a6e53137..2dd08c02e8 100644 --- a/LocalPackages/DataBrokerProtection/Sources/DataBrokerProtection/Resources/JSON/veriforia.com.json +++ b/LocalPackages/DataBrokerProtection/Sources/DataBrokerProtection/Resources/JSON/veriforia.com.json @@ -1,8 +1,7 @@ { "name": "Veriforia", "url": "veriforia.com", - "version": "0.4.0", - "parent": "verecor.com", + "version": "0.5.0", "addedDatetime": 1677736800000, "optOutUrl": "https://veriforia.com/ng/control/privacy", "steps": [ @@ -60,8 +59,80 @@ }, { "stepType": "optOut", - "optOutType": "parentSiteOptOut", - "actions": [] + "optOutType": "formOptOut", + "actions": [ + { + "actionType": "navigate", + "url": "https://veriforia.com/ng/control/privacy", + "id": "943c387c-9cb2-42d6-afd5-a48cf4c2cf3d" + }, + { + "actionType": "fillForm", + "selector": ".ahm", + "elements": [ + { + "type": "fullName", + "selector": "#user_name" + }, + { + "type": "email", + "selector": "#user_email" + }, + { + "type": "profileUrl", + "selector": "#url" + } + ], + "id": "cf78bb16-b608-4a50-975b-844dad3db1db" + }, + { + "actionType": "getCaptchaInfo", + "selector": ".g-recaptcha", + "id": "4c0b8064-1e2b-4598-92a9-e832e73726db" + }, + { + "actionType": "solveCaptcha", + "selector": ".g-recaptcha", + "id": "c53bc12e-0cf6-4628-b99f-3219cb0f0c1a" + }, + { + "actionType": "click", + "elements": [ + { + "type": "button", + "selector": ".//button[@type='submit']" + } + ], + "id": "0aaae970-81d9-4d63-86d0-da4d0a3f5cf4" + }, + { + "actionType": "expectation", + "expectations": [ + { + "type": "text", + "selector": "body", + "expect": "Your removal request has been received" + } + ], + "id": "9b6fad42-babc-4777-92af-d415ea9aef5b" + }, + { + "actionType": "emailConfirmation", + "pollingTime": 30, + "id": "d0d5f4d0-7183-40f5-b476-4315c751bcc5" + }, + { + "actionType": "expectation", + "expectations": [ + { + "type": "text", + "selector": "body", + "expect": "Your information control request has been confirmed." + } + ], + "id": "434d001d-f6cb-4df9-acf3-e62dc821a25a" + } + ] } ], "schedulingConfig": { diff --git a/LocalPackages/DataBrokerProtection/Sources/DataBrokerProtection/Resources/JSON/virtory.com.json b/LocalPackages/DataBrokerProtection/Sources/DataBrokerProtection/Resources/JSON/virtory.com.json index 02dda9a3df..adc8d3a901 100644 --- a/LocalPackages/DataBrokerProtection/Sources/DataBrokerProtection/Resources/JSON/virtory.com.json +++ b/LocalPackages/DataBrokerProtection/Sources/DataBrokerProtection/Resources/JSON/virtory.com.json @@ -1,8 +1,7 @@ { "name": "Virtory", "url": "virtory.com", - "version": "0.4.0", - "parent": "verecor.com", + "version": "0.5.0", "addedDatetime": 1703052000000, "optOutUrl": "https://virtory.com/prvt/control/privacy", "steps": [ @@ -63,8 +62,80 @@ }, { "stepType": "optOut", - "optOutType": "parentSiteOptOut", - "actions": [] + "optOutType": "formOptOut", + "actions": [ + { + "actionType": "navigate", + "url": "https://virtory.com/prvt/control/privacy", + "id": "ef272fd4-f284-47ca-aa0c-b4589a85bd81" + }, + { + "actionType": "fillForm", + "selector": ".ahm", + "elements": [ + { + "type": "fullName", + "selector": "#user_name" + }, + { + "type": "email", + "selector": "#user_email" + }, + { + "type": "profileUrl", + "selector": "#url" + } + ], + "id": "3eb2431f-0c00-440c-8a80-b6d95e0b5ee0" + }, + { + "actionType": "getCaptchaInfo", + "selector": ".g-recaptcha", + "id": "2a7550ed-6b80-4d32-adc1-20c96107afcb" + }, + { + "actionType": "solveCaptcha", + "selector": ".g-recaptcha", + "id": "d7c8d9eb-7239-42d1-9323-566ef1cf4665" + }, + { + "actionType": "click", + "elements": [ + { + "type": "button", + "selector": ".//button[@type='submit']" + } + ], + "id": "d4072304-d8c9-47ac-8c47-591a417c15b3" + }, + { + "actionType": "expectation", + "expectations": [ + { + "type": "text", + "selector": "body", + "expect": "Your removal request has been received" + } + ], + "id": "c17b21dd-25cf-43ad-9836-01de7f2138cd" + }, + { + "actionType": "emailConfirmation", + "pollingTime": 30, + "id": "a3ea0213-bd64-4221-add5-58b517f78223" + }, + { + "actionType": "expectation", + "expectations": [ + { + "type": "text", + "selector": "body", + "expect": "Your information control request has been confirmed." + } + ], + "id": "d4d7d0c6-3bba-470a-9fe7-6a154aa07751" + } + ] } ], "schedulingConfig": { diff --git a/LocalPackages/DataBrokerProtection/Sources/DataBrokerProtection/Resources/JSON/wellnut.com.json b/LocalPackages/DataBrokerProtection/Sources/DataBrokerProtection/Resources/JSON/wellnut.com.json index 5bcf4aa418..2c6e15a62c 100644 --- a/LocalPackages/DataBrokerProtection/Sources/DataBrokerProtection/Resources/JSON/wellnut.com.json +++ b/LocalPackages/DataBrokerProtection/Sources/DataBrokerProtection/Resources/JSON/wellnut.com.json @@ -1,8 +1,7 @@ { "name": "Wellnut", "url": "wellnut.com", - "version": "0.4.0", - "parent": "verecor.com", + "version": "0.5.0", "addedDatetime": 1703052000000, "optOutUrl": "https://wellnut.com/noi/control/privacy", "steps": [ @@ -63,8 +62,80 @@ }, { "stepType": "optOut", - "optOutType": "parentSiteOptOut", - "actions": [] + "optOutType": "formOptOut", + "actions": [ + { + "actionType": "navigate", + "url": "https://wellnut.com/noi/control/privacy", + "id": "af96e7b3-fc16-4eed-9307-32da204941a1" + }, + { + "actionType": "fillForm", + "selector": ".ahm", + "elements": [ + { + "type": "fullName", + "selector": "#user_name" + }, + { + "type": "email", + "selector": "#user_email" + }, + { + "type": "profileUrl", + "selector": "#url" + } + ], + "id": "ce8f2fbd-04f7-48fd-8d67-2cf083b48df3" + }, + { + "actionType": "getCaptchaInfo", + "selector": ".g-recaptcha", + "id": "7b01c715-eb45-4b8c-94f0-cb5280a4f1d8" + }, + { + "actionType": "solveCaptcha", + "selector": ".g-recaptcha", + "id": "d3a79100-785b-4cf8-8bbe-5df701851925" + }, + { + "actionType": "click", + "elements": [ + { + "type": "button", + "selector": ".//button[@type='submit']" + } + ], + "id": "d6b36f44-291b-4951-8444-ea4a08a3c1fc" + }, + { + "actionType": "expectation", + "expectations": [ + { + "type": "text", + "selector": "body", + "expect": "Your removal request has been received" + } + ], + "id": "a3a7cf9b-4653-4aac-9004-c2f738121ed7" + }, + { + "actionType": "emailConfirmation", + "pollingTime": 30, + "id": "cbafc394-018e-47ff-b95e-fbc521508e3f" + }, + { + "actionType": "expectation", + "expectations": [ + { + "type": "text", + "selector": "body", + "expect": "Your information control request has been confirmed." + } + ], + "id": "918f6692-c5c4-4072-95c8-795296e1a956" + } + ] } ], "schedulingConfig": { From 3cedd4664f9e89546bb605df562e4061f4a84657 Mon Sep 17 00:00:00 2001 From: Brian Hall Date: Tue, 14 Jan 2025 14:43:01 +0100 Subject: [PATCH 02/12] Add support for conditional clicking (#3623) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Task/Issue URL: https://app.asana.com/0/1199230911884351/1208647902506360/f Tech Design URL: CC: **Description**: Adds support for conditional clicking of elements by adding “choices” and “default” keys to the click action. **Optional E2E tests**: - [x] Run PIR E2E tests Check this to run the Personal Information Removal end to end tests. If updating CCF, or any PIR related code, tick this. **Steps to test this PR**: The easiest way to test whether the decoding is working is to setup one of the test files from the C-S-S integration tests as a fake broker: 1. Download [this file](https://github.com/duckduckgo/content-scope-scripts/blob/main/injected/integration-test/test-pages/broker-protection/pages/expectation-actions.html) on your local machine. Open it to copy the file path, should start with `file://` 2. Download [this JSON](https://gist.github.com/brianhall/969d81b04b8d4fff4e21c9c6b48164b9) and update the url to the file path you copied in 1. 3. Save the JSON file in the macos-browser repo under `LocalPackages/DataBrokerProtection/Sources/DataBrokerProtection/Resources/JSON` 4. Build the browser (no need for any special dependencies, just build `main`), then open the debug version of PIR: Debug Menu -> Personal Information Removal -> Run Personal Information Removal in Debug Mode. 5. In Birth Year enter `1965`, then select **Test Broker** in the list of brokers and click the Run button. 6. After about 30 seconds, right click the webview and Inspect Element, then click the console tab and type `window.location.href` and hit enter. You should see a url that ends with `#1`, which means that the user was older than 45. 7. Do steps 5-6 again, but for birth year enter `1990`, when you do `window.location.href` you should get a url that ends with `#2` instead, indicating that the user is < 45. 8. Edit the mybrokertest.com.json file, copy/paste the contents of [this gist](https://gist.github.com/brianhall/ebac912c56c5e904ec86c05e3fa3ab30) in and save. This just sets the default case at the bottom to `null`. _Now re-build the browser to load the updated JSON._ 9. Run steps 5-7 again, this time `window.location.href` should return a url with `#1` for step 5, and a url with no `#` at the end for step 7, meaning that nothing was clicked and no error was triggered. 10. Edit the mybrokertest.com.json file again and remove line 45 (and the comma above on line 44) and then rebuild the browser to update the JSON. Finally steps 5-7 again - step 5 should return no errors (and have a `#1` hash at the end of the url), and step 7 should not return an error, but also not have any hash (e.g. `#1`) at the end of the url. **Definition of Done**: * [ ] Does this PR satisfy our [Definition of Done](https://app.asana.com/0/1202500774821704/1207634633537039/f)? — ###### Internal references: [Pull Request Review Checklist](https://app.asana.com/0/1202500774821704/1203764234894239/f) [Software Engineering Expectations](https://app.asana.com/0/59792373528535/199064865822552) [Technical Design Template](https://app.asana.com/0/59792373528535/184709971311943) [Pull Request Documentation](https://app.asana.com/0/1202500774821704/1204012835277482/f) --- .../Model/Actions/Click.swift | 66 ++++++++++++++++++- .../DataBrokerOperationActionTests.swift | 2 +- 2 files changed, 66 insertions(+), 2 deletions(-) diff --git a/LocalPackages/DataBrokerProtection/Sources/DataBrokerProtection/Model/Actions/Click.swift b/LocalPackages/DataBrokerProtection/Sources/DataBrokerProtection/Model/Actions/Click.swift index a75fe0113f..e237d32bfb 100644 --- a/LocalPackages/DataBrokerProtection/Sources/DataBrokerProtection/Model/Actions/Click.swift +++ b/LocalPackages/DataBrokerProtection/Sources/DataBrokerProtection/Model/Actions/Click.swift @@ -18,9 +18,73 @@ import Foundation +struct Condition: Codable, Sendable { + let left: String + let operation: String + let right: String +} + +struct Choice: Codable, Sendable { + let condition: Condition + let elements: [PageElement] +} + struct ClickAction: Action { let id: String let actionType: ActionType - let elements: [PageElement] + let elements: [PageElement]? let dataSource: DataSource? + let choices: [Choice]? + let `default`: Default? + + let hasDefault: Bool + + struct Default: Codable { + let elements: [PageElement]? + } + + init(id: String, actionType: ActionType, elements: [PageElement]? = nil, dataSource: DataSource? = nil, choices: [Choice]? = nil, `default`: Default? = nil, hasDefault: Bool = false) { + self.id = id + self.actionType = actionType + self.elements = elements + self.dataSource = dataSource + self.choices = choices + self.default = `default` + self.hasDefault = `default` != nil + } + + init(from decoder: any Decoder) throws { + let container = try decoder.container(keyedBy: CodingKeys.self) + self.id = try container.decode(String.self, forKey: .id) + self.actionType = try container.decode(ActionType.self, forKey: .actionType) + self.elements = try container.decodeIfPresent([PageElement].self, forKey: .elements) + self.dataSource = try container.decodeIfPresent(DataSource.self, forKey: .dataSource) + self.choices = try container.decodeIfPresent([Choice].self, forKey: .choices) + self.default = try container.decodeIfPresent(Default.self, forKey: .default) + self.hasDefault = container.contains(.default) + } + + enum CodingKeys: String, CodingKey { + case id + case actionType + case elements + case dataSource + case choices + case `default` + } + + func encode(to encoder: any Encoder) throws { + var container = encoder.container(keyedBy: CodingKeys.self) + try container.encode(self.id, forKey: .id) + try container.encode(self.actionType, forKey: .actionType) + try container.encodeIfPresent(self.elements, forKey: .elements) + try container.encodeIfPresent(self.dataSource, forKey: .dataSource) + try container.encodeIfPresent(self.choices, forKey: .choices) + + if self.hasDefault { + try container.encode(self.default, forKey: .default) + } else { + try container.encodeNil(forKey: .default) + } + } } diff --git a/LocalPackages/DataBrokerProtection/Tests/DataBrokerProtectionTests/DataBrokerOperationActionTests.swift b/LocalPackages/DataBrokerProtection/Tests/DataBrokerProtectionTests/DataBrokerOperationActionTests.swift index cc14f56b56..e5c816432c 100644 --- a/LocalPackages/DataBrokerProtection/Tests/DataBrokerProtectionTests/DataBrokerOperationActionTests.swift +++ b/LocalPackages/DataBrokerProtection/Tests/DataBrokerProtectionTests/DataBrokerOperationActionTests.swift @@ -394,7 +394,7 @@ final class DataBrokerOperationActionTests: XCTestCase { func testWhenClickActionRuns_thenStageIsSetToSubmit() async { let mockStageCalculator = MockStageDurationCalculator() - let clickAction = ClickAction(id: "1", actionType: .click, elements: [PageElement](), dataSource: nil) + let clickAction = ClickAction(id: "1", actionType: .click, elements: [PageElement](), dataSource: nil, choices: nil, default: nil, hasDefault: false) let sut = OptOutJob( privacyConfig: PrivacyConfigurationManagingMock(), prefs: ContentScopeProperties.mock, From 283861994c628a030acb567b79b97ca0cf2cc592 Mon Sep 17 00:00:00 2001 From: Daniel Bernal Date: Wed, 15 Jan 2025 14:41:39 +0100 Subject: [PATCH 03/12] Fix Duckplayer handler URL (#3730) Task/Issue URL: https://app.asana.com/0/1204099484721401/1209111326156032/f Tech Design URL: CC: Description: Fixes issue causing DuckPlayer to render the same (incorrect) video ###### Internal references: [Pull Request Review Checklist](https://app.asana.com/0/1202500774821704/1203764234894239/f) [Software Engineering Expectations](https://app.asana.com/0/59792373528535/199064865822552) [Technical Design Template](https://app.asana.com/0/59792373528535/184709971311943) [Pull Request Documentation](https://app.asana.com/0/1202500774821704/1204012835277482/f) --- DuckDuckGo/Tab/Navigation/DuckURLSchemeHandler.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/DuckDuckGo/Tab/Navigation/DuckURLSchemeHandler.swift b/DuckDuckGo/Tab/Navigation/DuckURLSchemeHandler.swift index bd3a2962dc..3ddbb252a4 100644 --- a/DuckDuckGo/Tab/Navigation/DuckURLSchemeHandler.swift +++ b/DuckDuckGo/Tab/Navigation/DuckURLSchemeHandler.swift @@ -53,7 +53,7 @@ final class DuckURLSchemeHandler: NSObject, WKURLSchemeHandler { case .onboarding, .releaseNotes: handleSpecialPages(urlSchemeTask: urlSchemeTask) case .duckPlayer: - handleDuckPlayer(requestURL: requestURL, urlSchemeTask: urlSchemeTask, webView: webView) + handleDuckPlayer(requestURL: webViewURL, urlSchemeTask: urlSchemeTask, webView: webView) case .error: handleErrorPage(urlSchemeTask: urlSchemeTask) case .newTab where isNTPSpecialPageSupported && featureFlagger.isFeatureOn(.htmlNewTabPage): From 7fb3c163ea0afcb7860feed0dc2878b865cf418c Mon Sep 17 00:00:00 2001 From: Sabrina Tardio <44158575+SabrinaTardio@users.noreply.github.com> Date: Wed, 15 Jan 2025 15:24:40 +0100 Subject: [PATCH 04/12] re-enabled new onboarding for old macOS versions (#3735) Task/Issue URL: https://app.asana.com/0/0/1209153206410271/f **Description**: Re-enable new onboarding on old mac-OS version after fix is available on C-S-S --- DuckDuckGo/Tab/Model/Tab.swift | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/DuckDuckGo/Tab/Model/Tab.swift b/DuckDuckGo/Tab/Model/Tab.swift index 8266a42ae9..b3344ceefb 100644 --- a/DuckDuckGo/Tab/Model/Tab.swift +++ b/DuckDuckGo/Tab/Model/Tab.swift @@ -795,11 +795,7 @@ protocol NewWindowPolicyDecisionMaker { return } #endif - if #available(macOS 13, *) { - setContent(PixelExperiment.cohort == .newOnboarding ? .onboarding : .onboardingDeprecated) - } else { - setContent(.onboardingDeprecated) - } + setContent(PixelExperiment.cohort == .newOnboarding ? .onboarding : .onboardingDeprecated) } @MainActor(unsafe) From ca9cfb30fe77b903783178c77a7864f71cd2f85b Mon Sep 17 00:00:00 2001 From: Diego Rey Mendez Date: Wed, 15 Jan 2025 17:54:07 +0100 Subject: [PATCH 05/12] Add VPN App Exclusions remote feature-flag (#3734) Task/Issue URL: https://app.asana.com/0/1203108348835387/1209150117333883/f iOS PR: https://github.com/duckduckgo/iOS/pull/3808 BSK PR: https://github.com/duckduckgo/BrowserServicesKit/pull/1164 ## Description Adds the VPN App Exclusions remote feature-flag with support for overriding locally. --- DuckDuckGo.xcodeproj/project.pbxproj | 2 +- .../xcshareddata/swiftpm/Package.resolved | 4 ++-- LocalPackages/DataBrokerProtection/Package.swift | 2 +- LocalPackages/FeatureFlags/Package.swift | 2 +- .../FeatureFlags/Sources/FeatureFlags/FeatureFlag.swift | 7 +++++++ LocalPackages/NetworkProtectionMac/Package.swift | 2 +- LocalPackages/NewTabPage/Package.swift | 2 +- LocalPackages/SubscriptionUI/Package.swift | 2 +- LocalPackages/WebKitExtensions/Package.swift | 2 +- 9 files changed, 16 insertions(+), 9 deletions(-) diff --git a/DuckDuckGo.xcodeproj/project.pbxproj b/DuckDuckGo.xcodeproj/project.pbxproj index 3f11e2a26a..ea44e6de8b 100644 --- a/DuckDuckGo.xcodeproj/project.pbxproj +++ b/DuckDuckGo.xcodeproj/project.pbxproj @@ -15366,7 +15366,7 @@ repositoryURL = "https://github.com/duckduckgo/BrowserServicesKit"; requirement = { kind = exactVersion; - version = 224.6.1; + version = 224.6.2; }; }; 9FF521422BAA8FF300B9819B /* XCRemoteSwiftPackageReference "lottie-spm" */ = { diff --git a/DuckDuckGo.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved b/DuckDuckGo.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved index 6858bc2967..86f13ce5b9 100644 --- a/DuckDuckGo.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved +++ b/DuckDuckGo.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved @@ -32,8 +32,8 @@ "kind" : "remoteSourceControl", "location" : "https://github.com/duckduckgo/BrowserServicesKit", "state" : { - "revision" : "58efae813cae03d71af87aab863af5c25a3a8a6e", - "version" : "224.6.1" + "revision" : "a2a5a32d111aadac6316db4cc629e5dd635939ba", + "version" : "224.6.2" } }, { diff --git a/LocalPackages/DataBrokerProtection/Package.swift b/LocalPackages/DataBrokerProtection/Package.swift index ae79ec3dc2..7618d47027 100644 --- a/LocalPackages/DataBrokerProtection/Package.swift +++ b/LocalPackages/DataBrokerProtection/Package.swift @@ -29,7 +29,7 @@ let package = Package( targets: ["DataBrokerProtection"]) ], dependencies: [ - .package(url: "https://github.com/duckduckgo/BrowserServicesKit", exact: "224.6.1"), + .package(url: "https://github.com/duckduckgo/BrowserServicesKit", exact: "224.6.2"), .package(path: "../SwiftUIExtensions"), .package(path: "../AppKitExtensions"), .package(path: "../XPCHelper"), diff --git a/LocalPackages/FeatureFlags/Package.swift b/LocalPackages/FeatureFlags/Package.swift index 420330703d..1e06afc0e5 100644 --- a/LocalPackages/FeatureFlags/Package.swift +++ b/LocalPackages/FeatureFlags/Package.swift @@ -32,7 +32,7 @@ let package = Package( targets: ["FeatureFlags"]), ], dependencies: [ - .package(url: "https://github.com/duckduckgo/BrowserServicesKit", exact: "224.6.1"), + .package(url: "https://github.com/duckduckgo/BrowserServicesKit", exact: "224.6.2"), ], targets: [ // Targets are the basic building blocks of a package, defining a module or a test suite. diff --git a/LocalPackages/FeatureFlags/Sources/FeatureFlags/FeatureFlag.swift b/LocalPackages/FeatureFlags/Sources/FeatureFlags/FeatureFlag.swift index ca29d420f8..d2e954453b 100644 --- a/LocalPackages/FeatureFlags/Sources/FeatureFlags/FeatureFlag.swift +++ b/LocalPackages/FeatureFlags/Sources/FeatureFlags/FeatureFlag.swift @@ -38,6 +38,9 @@ public enum FeatureFlag: String, CaseIterable { case credentialsImportPromotionForExistingUsers + /// https://app.asana.com/0/0/1209150117333883/f + case networkProtectionAppExclusions + /// https://app.asana.com/0/72649045549333/1208231259093710/f case networkProtectionUserTips @@ -59,6 +62,8 @@ extension FeatureFlag: FeatureFlagDescribing { return true case .autofillPartialFormSaves: return true + case .networkProtectionAppExclusions: + return true case .debugMenu, .sslCertificatesBypass, .appendAtbToSerpQueries, @@ -90,6 +95,8 @@ extension FeatureFlag: FeatureFlagDescribing { return .remoteReleasable(.feature(.contextualOnboarding)) case .credentialsImportPromotionForExistingUsers: return .remoteReleasable(.subfeature(AutofillSubfeature.credentialsImportPromotionForExistingUsers)) + case .networkProtectionAppExclusions: + return .remoteDevelopment(.subfeature(NetworkProtectionSubfeature.appExclusions)) case .networkProtectionUserTips: return .remoteDevelopment(.subfeature(NetworkProtectionSubfeature.userTips)) case .networkProtectionEnforceRoutes: diff --git a/LocalPackages/NetworkProtectionMac/Package.swift b/LocalPackages/NetworkProtectionMac/Package.swift index 1f9bf7fdb6..5953abda77 100644 --- a/LocalPackages/NetworkProtectionMac/Package.swift +++ b/LocalPackages/NetworkProtectionMac/Package.swift @@ -33,7 +33,7 @@ let package = Package( .library(name: "VPNAppLauncher", targets: ["VPNAppLauncher"]), ], dependencies: [ - .package(url: "https://github.com/duckduckgo/BrowserServicesKit", exact: "224.6.1"), + .package(url: "https://github.com/duckduckgo/BrowserServicesKit", exact: "224.6.2"), .package(url: "https://github.com/airbnb/lottie-spm", exact: "4.4.3"), .package(path: "../AppLauncher"), .package(path: "../UDSHelper"), diff --git a/LocalPackages/NewTabPage/Package.swift b/LocalPackages/NewTabPage/Package.swift index 9e09166b8a..381d475142 100644 --- a/LocalPackages/NewTabPage/Package.swift +++ b/LocalPackages/NewTabPage/Package.swift @@ -32,7 +32,7 @@ let package = Package( targets: ["NewTabPage"]), ], dependencies: [ - .package(url: "https://github.com/duckduckgo/BrowserServicesKit", exact: "224.6.1"), + .package(url: "https://github.com/duckduckgo/BrowserServicesKit", exact: "224.6.2"), .package(path: "../WebKitExtensions"), .package(path: "../Utilities"), ], diff --git a/LocalPackages/SubscriptionUI/Package.swift b/LocalPackages/SubscriptionUI/Package.swift index 1962ca4f7c..05175bd8c4 100644 --- a/LocalPackages/SubscriptionUI/Package.swift +++ b/LocalPackages/SubscriptionUI/Package.swift @@ -13,7 +13,7 @@ let package = Package( targets: ["SubscriptionUI"]), ], dependencies: [ - .package(url: "https://github.com/duckduckgo/BrowserServicesKit", exact: "224.6.1"), + .package(url: "https://github.com/duckduckgo/BrowserServicesKit", exact: "224.6.2"), .package(path: "../SwiftUIExtensions"), .package(path: "../FeatureFlags") ], diff --git a/LocalPackages/WebKitExtensions/Package.swift b/LocalPackages/WebKitExtensions/Package.swift index bb45452c2f..23a4472f32 100644 --- a/LocalPackages/WebKitExtensions/Package.swift +++ b/LocalPackages/WebKitExtensions/Package.swift @@ -32,7 +32,7 @@ let package = Package( ), ], dependencies: [ - .package(url: "https://github.com/duckduckgo/BrowserServicesKit", exact: "224.6.1"), + .package(url: "https://github.com/duckduckgo/BrowserServicesKit", exact: "224.6.2"), .package(path: "../AppKitExtensions") ], targets: [ From 6ee747e25236196a25ba85a238c8939c685b73cc Mon Sep 17 00:00:00 2001 From: Anh Do <18567+quanganhdo@users.noreply.github.com> Date: Thu, 16 Jan 2025 09:42:58 +0800 Subject: [PATCH 06/12] Handle child to parent broker migration (#3596) --- .../Model/DataBroker.swift | 7 + .../Operations/DataBrokerOperation.swift | 49 ++++++- ...taBrokerProfileQueryOperationManager.swift | 4 +- .../OperationPreferredDateCalculator.swift | 8 +- .../DataBrokerProtectionStatsPixels.swift | 4 + .../DataBrokerProtection/UI/UIMapper.swift | 5 +- .../DataBrokerOperationTests.swift | 99 ++++++++++++++ ...kerProfileQueryOperationManagerTests.swift | 35 ++--- .../MapperToUITests.swift | 10 +- .../DataBrokerProtectionTests/Mocks.swift | 7 + ...perationPreferredDateCalculatorTests.swift | 128 +++++++++++++----- 11 files changed, 285 insertions(+), 71 deletions(-) create mode 100644 LocalPackages/DataBrokerProtection/Tests/DataBrokerProtectionTests/DataBrokerOperationTests.swift diff --git a/LocalPackages/DataBrokerProtection/Sources/DataBrokerProtection/Model/DataBroker.swift b/LocalPackages/DataBrokerProtection/Sources/DataBrokerProtection/Model/DataBroker.swift index 4d87ae1416..97bdfe5283 100644 --- a/LocalPackages/DataBrokerProtection/Sources/DataBrokerProtection/Model/DataBroker.swift +++ b/LocalPackages/DataBrokerProtection/Sources/DataBrokerProtection/Model/DataBroker.swift @@ -25,6 +25,13 @@ struct DataBrokerScheduleConfig: Codable { let confirmOptOutScan: Int let maintenanceScan: Int let maxAttempts: Int + + // Used when scheduling the subsequent opt-out attempt following a successful opt-out request submission + // This value should be less than `confirmOptOutScan` to ensure the next attempt occurs before + // the confirmation scan. + var hoursUntilNextOptOutAttempt: Int { + maintenanceScan + } } extension Int { diff --git a/LocalPackages/DataBrokerProtection/Sources/DataBrokerProtection/Operations/DataBrokerOperation.swift b/LocalPackages/DataBrokerProtection/Sources/DataBrokerProtection/Operations/DataBrokerOperation.swift index b7f3e6fe7f..7ee7a87300 100644 --- a/LocalPackages/DataBrokerProtection/Sources/DataBrokerProtection/Operations/DataBrokerOperation.swift +++ b/LocalPackages/DataBrokerProtection/Sources/DataBrokerProtection/Operations/DataBrokerOperation.swift @@ -115,7 +115,7 @@ class DataBrokerOperation: Operation, @unchecked Sendable { } } - private func filterAndSortOperationsData(brokerProfileQueriesData: [BrokerProfileQueryData], operationType: OperationType, priorityDate: Date?) -> [BrokerJobData] { + static func filterAndSortOperationsData(brokerProfileQueriesData: [BrokerProfileQueryData], operationType: OperationType, priorityDate: Date?) -> [BrokerJobData] { let operationsData: [BrokerJobData] switch operationType { @@ -131,8 +131,8 @@ class DataBrokerOperation: Operation, @unchecked Sendable { if let priorityDate = priorityDate { filteredAndSortedOperationsData = operationsData - .filter { $0.preferredRunDate != nil && $0.preferredRunDate! <= priorityDate } - .sorted { $0.preferredRunDate! < $1.preferredRunDate! } + .eligibleForRun(byDate: priorityDate) + .sortedByPreferredRunDate() } else { filteredAndSortedOperationsData = operationsData } @@ -152,9 +152,9 @@ class DataBrokerOperation: Operation, @unchecked Sendable { let brokerProfileQueriesData = allBrokerProfileQueryData.filter { $0.dataBroker.id == dataBrokerID } - let filteredAndSortedOperationsData = filterAndSortOperationsData(brokerProfileQueriesData: brokerProfileQueriesData, - operationType: operationType, - priorityDate: priorityDate) + let filteredAndSortedOperationsData = Self.filterAndSortOperationsData(brokerProfileQueriesData: brokerProfileQueriesData, + operationType: operationType, + priorityDate: priorityDate) Logger.dataBrokerProtection.log("filteredAndSortedOperationsData count: \(filteredAndSortedOperationsData.count, privacy: .public) for brokerID \(self.dataBrokerID, privacy: .public)") @@ -215,3 +215,40 @@ class DataBrokerOperation: Operation, @unchecked Sendable { } } // swiftlint:enable explicit_non_final_class + +extension Array where Element == BrokerJobData { + /// Filters jobs based on their preferred run date: + /// - Opt-out jobs with no preferred run date are included. + /// - Jobs with a preferred run date on or before the priority date are included. + /// + /// Note: Opt-out jobs without a preferred run date may be: + /// 1. From child brokers (will be skipped during runOptOutOperation). + /// 2. From former child brokers now acting as parent brokers (will be processed if extractedProfile hasn't been removed). + func eligibleForRun(byDate priorityDate: Date) -> [BrokerJobData] { + filter { jobData in + guard let preferredRunDate = jobData.preferredRunDate else { + return jobData is OptOutJobData + } + + return preferredRunDate <= priorityDate + } + } + + /// Sorts BrokerJobData array based on their preferred run dates. + /// - Jobs with non-nil preferred run dates are sorted in ascending order (earliest date first). + /// - Opt-out jobs with nil preferred run dates come last, maintaining their original relative order. + func sortedByPreferredRunDate() -> [BrokerJobData] { + sorted { lhs, rhs in + switch (lhs.preferredRunDate, rhs.preferredRunDate) { + case (nil, nil): + return false + case (_, nil): + return true + case (nil, _): + return false + case (let lhsRunDate?, let rhsRunDate?): + return lhsRunDate < rhsRunDate + } + } + } +} diff --git a/LocalPackages/DataBrokerProtection/Sources/DataBrokerProtection/Operations/DataBrokerProfileQueryOperationManager.swift b/LocalPackages/DataBrokerProtection/Sources/DataBrokerProtection/Operations/DataBrokerProfileQueryOperationManager.swift index f8d0161d74..d0bcf65a78 100644 --- a/LocalPackages/DataBrokerProtection/Sources/DataBrokerProtection/Operations/DataBrokerProfileQueryOperationManager.swift +++ b/LocalPackages/DataBrokerProtection/Sources/DataBrokerProtection/Operations/DataBrokerProfileQueryOperationManager.swift @@ -291,11 +291,11 @@ struct DataBrokerProfileQueryOperationManager: OperationsManager { } guard extractedProfile.removedDate == nil else { - Logger.dataBrokerProtection.log("Profile already extracted, skipping...") + Logger.dataBrokerProtection.log("Profile already removed, skipping...") return } - guard let optOutStep = brokerProfileQueryData.dataBroker.optOutStep(), optOutStep.optOutType != .parentSiteOptOut else { + guard !brokerProfileQueryData.dataBroker.performsOptOutWithinParent() else { Logger.dataBrokerProtection.log("Broker opts out in parent, skipping...") return } diff --git a/LocalPackages/DataBrokerProtection/Sources/DataBrokerProtection/Operations/OperationPreferredDateCalculator.swift b/LocalPackages/DataBrokerProtection/Sources/DataBrokerProtection/Operations/OperationPreferredDateCalculator.swift index dae2ad1b09..ec8c83b3fb 100644 --- a/LocalPackages/DataBrokerProtection/Sources/DataBrokerProtection/Operations/OperationPreferredDateCalculator.swift +++ b/LocalPackages/DataBrokerProtection/Sources/DataBrokerProtection/Operations/OperationPreferredDateCalculator.swift @@ -81,8 +81,14 @@ struct OperationPreferredDateCalculator { return date.now.addingTimeInterval(calculateNextRunDateOnError(schedulingConfig: schedulingConfig, historyEvents: historyEvents)) case .optOutStarted, .scanStarted, .noMatchFound: return currentPreferredRunDate - case .optOutConfirmed, .optOutRequested: + case .optOutConfirmed: return nil + case .optOutRequested: + // Previously, opt-out jobs with `nil` preferredRunDate were never executed, + // but we need this following the child-to-parent-broker transition + // to prevent repeated scheduling of those former child broker opt-out jobs. + // https://app.asana.com/0/0/1208832818650310/f + return date.now.addingTimeInterval(schedulingConfig.hoursUntilNextOptOutAttempt.hoursToSeconds) } } diff --git a/LocalPackages/DataBrokerProtection/Sources/DataBrokerProtection/Pixels/DataBrokerProtectionStatsPixels.swift b/LocalPackages/DataBrokerProtection/Sources/DataBrokerProtection/Pixels/DataBrokerProtectionStatsPixels.swift index 7534b98ee9..22798d7eb3 100644 --- a/LocalPackages/DataBrokerProtection/Sources/DataBrokerProtection/Pixels/DataBrokerProtectionStatsPixels.swift +++ b/LocalPackages/DataBrokerProtection/Sources/DataBrokerProtection/Pixels/DataBrokerProtectionStatsPixels.swift @@ -172,6 +172,10 @@ extension Date { static func nowMinus(hours: Int) -> Date { Calendar.current.date(byAdding: .hour, value: -hours, to: Date()) ?? Date() } + + static func nowPlus(hours: Int) -> Date { + nowMinus(hours: -hours) + } } final class DataBrokerProtectionStatsPixels: StatsPixels { diff --git a/LocalPackages/DataBrokerProtection/Sources/DataBrokerProtection/UI/UIMapper.swift b/LocalPackages/DataBrokerProtection/Sources/DataBrokerProtection/UI/UIMapper.swift index c144931dab..fc1fe9d46b 100644 --- a/LocalPackages/DataBrokerProtection/Sources/DataBrokerProtection/UI/UIMapper.swift +++ b/LocalPackages/DataBrokerProtection/Sources/DataBrokerProtection/UI/UIMapper.swift @@ -40,7 +40,7 @@ struct MapperToUI { brokerQueryGroup.scannedBrokers } - let scanProgress = DBPUIScanProgress(currentScans: partiallyScannedBrokers.currentScans, + let scanProgress = DBPUIScanProgress(currentScans: partiallyScannedBrokers.completeBrokerScansCount, totalScans: totalScans, scannedBrokers: partiallyScannedBrokers) @@ -452,8 +452,7 @@ fileprivate extension Array where Element == BrokerProfileQueryData { } extension Array where Element == DBPUIScanProgress.ScannedBroker { - /// Number of completed broker scans - var currentScans: Int { + var completeBrokerScansCount: Int { reduce(0) { accumulator, scannedBrokers in scannedBrokers.status == .completed ? accumulator + 1 : accumulator } diff --git a/LocalPackages/DataBrokerProtection/Tests/DataBrokerProtectionTests/DataBrokerOperationTests.swift b/LocalPackages/DataBrokerProtection/Tests/DataBrokerProtectionTests/DataBrokerOperationTests.swift new file mode 100644 index 0000000000..ad5a8aedb1 --- /dev/null +++ b/LocalPackages/DataBrokerProtection/Tests/DataBrokerProtectionTests/DataBrokerOperationTests.swift @@ -0,0 +1,99 @@ +// +// DataBrokerOperationTests.swift +// +// Copyright © 2024 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. +// + +@testable import DataBrokerProtection +import XCTest + +final class DataBrokerOperationTests: XCTestCase { + lazy var mockOptOutQueryData: [BrokerProfileQueryData] = { + let brokerId: Int64 = 1 + + let mockNilPreferredRunDateQueryData = Array(1...10).map { + BrokerProfileQueryData.mock(preferredRunDate: nil, optOutJobData: [BrokerProfileQueryData.createOptOutJobData(extractedProfileId: Int64($0), brokerId: brokerId, profileQueryId: Int64($0), preferredRunDate: nil)]) + } + let mockPastQueryData = Array(1...10).map { + BrokerProfileQueryData.mock(preferredRunDate: .nowMinus(hours: $0), optOutJobData: [BrokerProfileQueryData.createOptOutJobData(extractedProfileId: Int64($0), brokerId: brokerId, profileQueryId: Int64($0), preferredRunDate: .nowMinus(hours: $0))]) + } + let mockFutureQueryData = Array(1...10).map { + BrokerProfileQueryData.mock(preferredRunDate: .nowPlus(hours: $0), optOutJobData: [BrokerProfileQueryData.createOptOutJobData(extractedProfileId: Int64($0), brokerId: brokerId, profileQueryId: Int64($0), preferredRunDate: .nowPlus(hours: $0))]) + } + + return mockNilPreferredRunDateQueryData + mockPastQueryData + mockFutureQueryData + }() + + lazy var mockScanQueryData: [BrokerProfileQueryData] = { + let mockNilPreferredRunDateQueryData = Array(1...10).map { _ in + BrokerProfileQueryData.mock(preferredRunDate: nil) + } + let mockPastQueryData = Array(1...10).map { + BrokerProfileQueryData.mock(preferredRunDate: .nowMinus(hours: $0)) + } + let mockFutureQueryData = Array(1...10).map { + BrokerProfileQueryData.mock(preferredRunDate: .nowPlus(hours: $0)) + } + + return mockNilPreferredRunDateQueryData + mockPastQueryData + mockFutureQueryData + }() + + func testWhenFilteringOptOutOperationData_thenAllButFuturePreferredRunDateIsReturned() { + let operationData1 = MockDataBrokerOperation.filterAndSortOperationsData(brokerProfileQueriesData: mockOptOutQueryData, operationType: .optOut, priorityDate: nil) + let operationData2 = MockDataBrokerOperation.filterAndSortOperationsData(brokerProfileQueriesData: mockOptOutQueryData, operationType: .optOut, priorityDate: .now) + let operationData3 = MockDataBrokerOperation.filterAndSortOperationsData(brokerProfileQueriesData: mockOptOutQueryData, operationType: .optOut, priorityDate: .distantPast) + let operationData4 = MockDataBrokerOperation.filterAndSortOperationsData(brokerProfileQueriesData: mockOptOutQueryData, operationType: .optOut, priorityDate: .distantFuture) + + XCTAssertEqual(operationData1.count, 30) // all jobs + XCTAssertEqual(operationData2.count, 20) // nil preferred run date + past jobs + XCTAssertEqual(operationData3.count, 10) // nil preferred run date jobs + XCTAssertEqual(operationData4.count, 30) // all jobs + } + + func testWhenFilteringScanOperationData_thenPreferredRunDatePriorToPriorityDateIsReturned() { + let operationData1 = MockDataBrokerOperation.filterAndSortOperationsData(brokerProfileQueriesData: mockScanQueryData, operationType: .scheduledScan, priorityDate: nil) + let operationData2 = MockDataBrokerOperation.filterAndSortOperationsData(brokerProfileQueriesData: mockScanQueryData, operationType: .manualScan, priorityDate: .now) + let operationData3 = MockDataBrokerOperation.filterAndSortOperationsData(brokerProfileQueriesData: mockScanQueryData, operationType: .scheduledScan, priorityDate: .distantPast) + let operationData4 = MockDataBrokerOperation.filterAndSortOperationsData(brokerProfileQueriesData: mockScanQueryData, operationType: .manualScan, priorityDate: .distantFuture) + + XCTAssertEqual(operationData1.count, 30) // all jobs + XCTAssertEqual(operationData2.count, 10) // past jobs + XCTAssertEqual(operationData3.count, 0) // no jobs + XCTAssertEqual(operationData4.count, 20) // past + future jobs + } + + func testFilteringAllOperationData() { + let operationData1 = MockDataBrokerOperation.filterAndSortOperationsData(brokerProfileQueriesData: mockOptOutQueryData, operationType: .all, priorityDate: nil) + let operationData2 = MockDataBrokerOperation.filterAndSortOperationsData(brokerProfileQueriesData: mockOptOutQueryData, operationType: .all, priorityDate: .now) + let operationData3 = MockDataBrokerOperation.filterAndSortOperationsData(brokerProfileQueriesData: mockOptOutQueryData, operationType: .all, priorityDate: .distantPast) + let operationData4 = MockDataBrokerOperation.filterAndSortOperationsData(brokerProfileQueriesData: mockOptOutQueryData, operationType: .all, priorityDate: .distantFuture) + + XCTAssertEqual(operationData1.filter { $0 is ScanJobData }.count, 30) // all jobs + XCTAssertEqual(operationData1.filter { $0 is OptOutJobData }.count, 30) // all jobs + XCTAssertEqual(operationData1.count, 30+30) + + XCTAssertEqual(operationData2.filter { $0 is ScanJobData }.count, 10) // past jobs + XCTAssertEqual(operationData2.filter { $0 is OptOutJobData }.count, 20) // nil preferred run date + past jobs + XCTAssertEqual(operationData2.count, 10+20) + + XCTAssertEqual(operationData3.filter { $0 is ScanJobData }.count, 0) // no jobs + XCTAssertEqual(operationData3.filter { $0 is OptOutJobData }.count, 10) // nil preferred run date jobs + XCTAssertEqual(operationData3.count, 0+10) + + XCTAssertEqual(operationData4.filter { $0 is ScanJobData }.count, 20) // past + future jobs + XCTAssertEqual(operationData4.filter { $0 is OptOutJobData }.count, 30) // all jobs + XCTAssertEqual(operationData4.count, 20+30) + } +} diff --git a/LocalPackages/DataBrokerProtection/Tests/DataBrokerProtectionTests/DataBrokerProfileQueryOperationManagerTests.swift b/LocalPackages/DataBrokerProtection/Tests/DataBrokerProtectionTests/DataBrokerProfileQueryOperationManagerTests.swift index 5e772ac0ee..ca3760e701 100644 --- a/LocalPackages/DataBrokerProtection/Tests/DataBrokerProtectionTests/DataBrokerProfileQueryOperationManagerTests.swift +++ b/LocalPackages/DataBrokerProtection/Tests/DataBrokerProtectionTests/DataBrokerProfileQueryOperationManagerTests.swift @@ -369,24 +369,17 @@ final class DataBrokerProfileQueryOperationManagerTests: XCTestCase { } } - func testWhenRemovedProfileIsFound_thenOptOutConfirmedIsAddedRemoveDateIsUpdatedAndPreferredRunDateIsSetToNil() async { + func testWhenRemovedProfileIsFound_thenOptOutConfirmedIsAddedRemoveDateIsUpdated() async { do { - let extractedProfileId: Int64 = 1 - let brokerId: Int64 = 1 - let profileQueryId: Int64 = 1 - let mockHistoryEvent = HistoryEvent(extractedProfileId: extractedProfileId, brokerId: brokerId, profileQueryId: profileQueryId, type: .optOutRequested) - let mockBrokerProfileQuery = BrokerProfileQueryData( - dataBroker: .mock, - profileQuery: .mock, - scanJobData: .mock, - optOutJobData: [.mock(with: .mockWithoutRemovedDate, preferredRunDate: Date(), historyEvents: [mockHistoryEvent])] - ) - mockWebOperationRunner.scanResults = [.mockWithoutId] - mockDatabase.brokerProfileQueryDataToReturn = [mockBrokerProfileQuery] _ = try await sut.runScanOperation( on: mockWebOperationRunner, - brokerProfileQueryData: mockBrokerProfileQuery, + brokerProfileQueryData: .init( + dataBroker: .mock, + profileQuery: .mock, + scanJobData: .mock, + optOutJobData: [OptOutJobData.mock(with: .mockWithoutRemovedDate)] + ), database: mockDatabase, notificationCenter: .default, pixelHandler: MockDataBrokerProtectionPixelsHandler(), @@ -396,8 +389,6 @@ final class DataBrokerProfileQueryOperationManagerTests: XCTestCase { XCTAssertTrue(mockDatabase.optOutEvents.contains(where: { $0.type == .optOutConfirmed })) XCTAssertTrue(mockDatabase.wasUpdateRemoveDateCalled) XCTAssertNotNil(mockDatabase.extractedProfileRemovedDate) - XCTAssertTrue(mockDatabase.wasUpdatedPreferredRunDateForOptOutCalled) - XCTAssertNil(mockDatabase.lastPreferredRunDateOnOptOut) } catch { XCTFail("Should not throw") } @@ -841,7 +832,7 @@ final class DataBrokerProfileQueryOperationManagerTests: XCTestCase { XCTAssertTrue(areDatesEqualIgnoringSeconds(date1: mockDatabase.lastPreferredRunDateOnScan, date2: Date().addingTimeInterval(schedulingConfig.confirmOptOutScan.hoursToSeconds))) } - func testWhenUpdatingDatesAndLastEventIsOptOutRequested_thenWeSetOptOutPreferredRunDateToNil() throws { + func testWhenUpdatingDatesAndLastEventIsOptOutRequested_thenWeSetOptOutPreferredRunDateToOptOutReattempt() throws { let brokerId: Int64 = 1 let profileQueryId: Int64 = 1 let extractedProfileId: Int64 = 1 @@ -851,7 +842,7 @@ final class DataBrokerProfileQueryOperationManagerTests: XCTestCase { try sut.updateOperationDataDates(origin: .scan, brokerId: brokerId, profileQueryId: profileQueryId, extractedProfileId: extractedProfileId, schedulingConfig: schedulingConfig, database: mockDatabase) XCTAssertTrue(mockDatabase.wasUpdatedPreferredRunDateForScanCalled) - XCTAssertNil(mockDatabase.lastPreferredRunDateOnOptOut) + XCTAssertTrue(areDatesEqualIgnoringSeconds(date1: mockDatabase.lastPreferredRunDateOnOptOut, date2: Date().addingTimeInterval(schedulingConfig.hoursUntilNextOptOutAttempt.hoursToSeconds))) } func testWhenUpdatingDatesAndLastEventIsMatchesFound_thenWeSetScanPreferredDateToMaintanence() throws { @@ -918,7 +909,9 @@ final class DataBrokerProfileQueryOperationManagerTests: XCTestCase { // If the date is not going to be set, we don't call the database function XCTAssertFalse(mockDatabase.wasUpdatedPreferredRunDateForScanCalled) - XCTAssertFalse(mockDatabase.wasUpdatedPreferredRunDateForOptOutCalled) + + XCTAssertTrue(mockDatabase.wasUpdatedPreferredRunDateForOptOutCalled) + XCTAssertTrue(areDatesEqualIgnoringSeconds(date1: mockDatabase.lastPreferredRunDateOnOptOut, date2: Date().addingTimeInterval(config.hoursUntilNextOptOutAttempt.hoursToSeconds))) } func testUpdatingScanDateFromScan_thenScanDoesNotRespectMostRecentDate() throws { @@ -942,8 +935,10 @@ final class DataBrokerProfileQueryOperationManagerTests: XCTestCase { try sut.updateOperationDataDates(origin: .scan, brokerId: brokerId, profileQueryId: profileQueryId, extractedProfileId: extractedProfileId, schedulingConfig: config, database: mockDatabase) XCTAssertTrue(mockDatabase.wasUpdatedPreferredRunDateForScanCalled) - XCTAssertFalse(mockDatabase.wasUpdatedPreferredRunDateForOptOutCalled) XCTAssertTrue(areDatesEqualIgnoringSeconds(date1: mockDatabase.lastPreferredRunDateOnScan, date2: expectedPreferredRunDate), "\(String(describing: mockDatabase.lastPreferredRunDateOnScan)) is not equal to \(expectedPreferredRunDate)") + + XCTAssertTrue(mockDatabase.wasUpdatedPreferredRunDateForOptOutCalled) + XCTAssertTrue(areDatesEqualIgnoringSeconds(date1: mockDatabase.lastPreferredRunDateOnOptOut, date2: Date().addingTimeInterval(config.hoursUntilNextOptOutAttempt.hoursToSeconds))) } } diff --git a/LocalPackages/DataBrokerProtection/Tests/DataBrokerProtectionTests/MapperToUITests.swift b/LocalPackages/DataBrokerProtection/Tests/DataBrokerProtectionTests/MapperToUITests.swift index da95b47da0..eb86e913b5 100644 --- a/LocalPackages/DataBrokerProtection/Tests/DataBrokerProtectionTests/MapperToUITests.swift +++ b/LocalPackages/DataBrokerProtection/Tests/DataBrokerProtectionTests/MapperToUITests.swift @@ -59,7 +59,7 @@ final class MapperToUITests: XCTestCase { let result = sut.initialScanState(brokerProfileQueryData) XCTAssertEqual(result.scanProgress.currentScans, brokerProfileQueryData.legacyCurrentScans) - XCTAssertEqual(result.scanProgress.currentScans, expected.currentScans) + XCTAssertEqual(result.scanProgress.currentScans, expected.completeBrokerScansCount) XCTAssertEqual(result.scanProgress.scannedBrokers.count, expected.count) XCTAssertEqual(result.scanProgress.scannedBrokers.first!.name, expected.first!.name) XCTAssertTrue(result.resultsFound.isEmpty) @@ -79,7 +79,7 @@ final class MapperToUITests: XCTestCase { let result = sut.initialScanState(brokerProfileQueryData) XCTAssertEqual(result.scanProgress.currentScans, brokerProfileQueryData.legacyCurrentScans) - XCTAssertEqual(result.scanProgress.currentScans, expected.currentScans) + XCTAssertEqual(result.scanProgress.currentScans, expected.completeBrokerScansCount) XCTAssertEqual(result.scanProgress.scannedBrokers.count, expected.count) XCTAssertEqual(result.scanProgress.scannedBrokers.first!.name, expected.first!.name) XCTAssertTrue(result.resultsFound.isEmpty) @@ -121,7 +121,7 @@ final class MapperToUITests: XCTestCase { XCTAssertEqual(result.scanProgress.totalScans, result.scanProgress.currentScans) XCTAssertEqual(result.scanProgress.currentScans, brokerProfileQueryData.legacyCurrentScans) - XCTAssertEqual(result.scanProgress.currentScans, expected.currentScans) + XCTAssertEqual(result.scanProgress.currentScans, expected.completeBrokerScansCount) XCTAssertEqual(result.scanProgress.scannedBrokers.count, expected.count) XCTAssertEqual(result.scanProgress.scannedBrokers.map{ $0.name }.sorted(), expected.map(\.name)) } @@ -143,7 +143,7 @@ final class MapperToUITests: XCTestCase { XCTAssertEqual(result.scanProgress.totalScans, 2) XCTAssertEqual(result.scanProgress.currentScans, brokerProfileQueryData.legacyCurrentScans) - XCTAssertEqual(result.scanProgress.currentScans, expected.currentScans) + XCTAssertEqual(result.scanProgress.currentScans, expected.completeBrokerScansCount) XCTAssertEqual(result.scanProgress.scannedBrokers.count, expected.count) XCTAssertEqual(result.scanProgress.scannedBrokers.map{ $0.name }.sorted(), expected.map(\.name)) XCTAssertEqual(result.resultsFound.count, 1) @@ -167,7 +167,7 @@ final class MapperToUITests: XCTestCase { XCTAssertEqual(result.scanProgress.totalScans, 2) XCTAssertEqual(result.scanProgress.currentScans, brokerProfileQueryData.legacyCurrentScans) - XCTAssertEqual(result.scanProgress.currentScans, expected.currentScans) + XCTAssertEqual(result.scanProgress.currentScans, expected.completeBrokerScansCount) XCTAssertEqual(result.scanProgress.scannedBrokers.count, expected.count) XCTAssertEqual(result.scanProgress.scannedBrokers.map{ $0.name }.sorted(), expected.map(\.name)) XCTAssertEqual(result.resultsFound.count, 1) diff --git a/LocalPackages/DataBrokerProtection/Tests/DataBrokerProtectionTests/Mocks.swift b/LocalPackages/DataBrokerProtection/Tests/DataBrokerProtectionTests/Mocks.swift index 40d6db23b0..a1ee759fac 100644 --- a/LocalPackages/DataBrokerProtection/Tests/DataBrokerProtectionTests/Mocks.swift +++ b/LocalPackages/DataBrokerProtection/Tests/DataBrokerProtectionTests/Mocks.swift @@ -117,6 +117,13 @@ extension BrokerProfileQueryData { return [broker1Data, broker2Data, broker3Data] } + static func createOptOutJobData(extractedProfileId: Int64, brokerId: Int64, profileQueryId: Int64, preferredRunDate: Date?) -> OptOutJobData { + + let extractedProfile = ExtractedProfile(id: extractedProfileId) + + return OptOutJobData(brokerId: brokerId, profileQueryId: profileQueryId, createdDate: .now, preferredRunDate: preferredRunDate, historyEvents: [], attemptCount: 0, extractedProfile: extractedProfile) + } + static func createOptOutJobData(extractedProfileId: Int64, brokerId: Int64, profileQueryId: Int64, startEventHoursAgo: Int, requestEventHoursAgo: Int, jobCreatedHoursAgo: Int) -> OptOutJobData { let extractedProfile = ExtractedProfile(id: extractedProfileId) diff --git a/LocalPackages/DataBrokerProtection/Tests/DataBrokerProtectionTests/OperationPreferredDateCalculatorTests.swift b/LocalPackages/DataBrokerProtection/Tests/DataBrokerProtectionTests/OperationPreferredDateCalculatorTests.swift index 555c19a9e7..40c691b25f 100644 --- a/LocalPackages/DataBrokerProtection/Tests/DataBrokerProtectionTests/OperationPreferredDateCalculatorTests.swift +++ b/LocalPackages/DataBrokerProtection/Tests/DataBrokerProtectionTests/OperationPreferredDateCalculatorTests.swift @@ -24,8 +24,8 @@ final class OperationPreferredDateCalculatorTests: XCTestCase { private let schedulingConfig = DataBrokerScheduleConfig( retryError: 48, - confirmOptOutScan: 2000, - maintenanceScan: 3000, + confirmOptOutScan: 72, + maintenanceScan: 120, maxAttempts: 3 ) @@ -498,9 +498,7 @@ final class OperationPreferredDateCalculatorTests: XCTestCase { XCTAssertTrue(areDatesEqualIgnoringSeconds(date1: expectedOptOutDate, date2: actualOptOutDate)) } - func testOptOutConfirmedWithCurrentPreferredDate_thenOptOutIsNil() throws { - let expectedOptOutDate: Date? = nil - + func testOptOutConfirmedWithCurrentPreferredDate_thenOptOutIsNotScheduled() throws { let historyEvents = [ HistoryEvent(extractedProfileId: 1, brokerId: 1, @@ -515,12 +513,10 @@ final class OperationPreferredDateCalculatorTests: XCTestCase { schedulingConfig: schedulingConfig, attemptCount: 0) - XCTAssertTrue(areDatesEqualIgnoringSeconds(date1: expectedOptOutDate, date2: actualOptOutDate)) + XCTAssertNil(actualOptOutDate) } - func testOptOutConfirmedWithoutCurrentPreferredDate_thenOptOutIsNil() throws { - let expectedOptOutDate: Date? = nil - + func testOptOutConfirmedWithoutCurrentPreferredDate_thenOptOutIsNotScheduled() throws { let historyEvents = [ HistoryEvent(extractedProfileId: 1, brokerId: 1, @@ -529,17 +525,17 @@ final class OperationPreferredDateCalculatorTests: XCTestCase { let calculator = OperationPreferredDateCalculator() - let actualOptOutDate = try calculator.dateForOptOutOperation(currentPreferredRunDate: nil, + let actualOptOutDate = try calculator.dateForOptOutOperation(currentPreferredRunDate: Date(), historyEvents: historyEvents, extractedProfileID: nil, schedulingConfig: schedulingConfig, attemptCount: 0) - XCTAssertTrue(areDatesEqualIgnoringSeconds(date1: expectedOptOutDate, date2: actualOptOutDate)) + XCTAssertNil(actualOptOutDate) } - func testOptOutRequestedWithCurrentPreferredDate_thenOptOutIsNil() throws { - let expectedOptOutDate: Date? = nil + func testOptOutRequestedWithCurrentPreferredDate_thenOptOutIsNotScheduled() throws { + let expectedOptOutDate = MockDate().now.addingTimeInterval(schedulingConfig.hoursUntilNextOptOutAttempt.hoursToSeconds) let historyEvents = [ HistoryEvent(extractedProfileId: 1, @@ -553,13 +549,14 @@ final class OperationPreferredDateCalculatorTests: XCTestCase { historyEvents: historyEvents, extractedProfileID: nil, schedulingConfig: schedulingConfig, - attemptCount: 0) + attemptCount: 0, + date: MockDate()) - XCTAssertTrue(areDatesEqualIgnoringSeconds(date1: expectedOptOutDate, date2: actualOptOutDate)) + XCTAssertTrue(areDatesEqualIgnoringSeconds(date1: actualOptOutDate, date2: expectedOptOutDate)) } - func testOptOutRequestedWithoutCurrentPreferredDate_thenOptOutIsNil() throws { - let expectedOptOutDate: Date? = nil + func testOptOutRequestedWithoutCurrentPreferredDate_thenOptOutIsNotScheduled() throws { + let expectedOptOutDate = MockDate().now.addingTimeInterval(schedulingConfig.hoursUntilNextOptOutAttempt.hoursToSeconds) let historyEvents = [ HistoryEvent(extractedProfileId: 1, @@ -573,9 +570,10 @@ final class OperationPreferredDateCalculatorTests: XCTestCase { historyEvents: historyEvents, extractedProfileID: nil, schedulingConfig: schedulingConfig, - attemptCount: 0) + attemptCount: 0, + date: MockDate()) - XCTAssertTrue(areDatesEqualIgnoringSeconds(date1: expectedOptOutDate, date2: actualOptOutDate)) + XCTAssertTrue(areDatesEqualIgnoringSeconds(date1: actualOptOutDate, date2: expectedOptOutDate)) } func testScanStarted_thenOptOutDoesNotChange() throws { @@ -610,10 +608,10 @@ final class OperationPreferredDateCalculatorTests: XCTestCase { let calculator = OperationPreferredDateCalculator() let actualOptOutDate = try calculator.dateForOptOutOperation(currentPreferredRunDate: nil, - historyEvents: historyEvents, - extractedProfileID: nil, - schedulingConfig: schedulingConfig, - attemptCount: 0) + historyEvents: historyEvents, + extractedProfileID: nil, + schedulingConfig: schedulingConfig, + attemptCount: 0) XCTAssertTrue(areDatesEqualIgnoringSeconds(date1: expectedOptOutDate, date2: actualOptOutDate)) } @@ -758,6 +756,69 @@ final class OperationPreferredDateCalculatorTests: XCTestCase { } } + func testChildBrokerTurnsParentBroker_whenFirstOptOutSucceeds_thenOptOutDateIsNotScheduled() throws { + let expectedOptOutDate = MockDate().now.addingTimeInterval(schedulingConfig.hoursUntilNextOptOutAttempt.hoursToSeconds) + + let historyEvents = [ + HistoryEvent(extractedProfileId: 1, + brokerId: 1, + profileQueryId: 1, + type: .optOutRequested), + ] + let calculator = OperationPreferredDateCalculator() + let actualOptOutDate = try calculator.dateForOptOutOperation(currentPreferredRunDate: nil, + historyEvents: historyEvents, + extractedProfileID: 1, + schedulingConfig: schedulingConfig, + attemptCount: 1, + date: MockDate()) + + XCTAssertTrue(areDatesEqualIgnoringSeconds(date1: actualOptOutDate, date2: expectedOptOutDate)) + } + + func testChildBrokerTurnsParentBroker_whenFirstOptOutFails_thenOptOutIsScheduled() throws { + let expectedOptOutDate = Calendar.current.date(byAdding: .hour, value: 2, to: Date())! + + let historyEvents = [ + HistoryEvent(extractedProfileId: 1, + brokerId: 1, + profileQueryId: 1, + type: .error(error: .malformedURL)), + ] + let calculator = OperationPreferredDateCalculator() + let actualOptOutDate = try calculator.dateForOptOutOperation(currentPreferredRunDate: nil, + historyEvents: historyEvents, + extractedProfileID: 1, + schedulingConfig: schedulingConfig, + attemptCount: 1) + + XCTAssertTrue(areDatesEqualIgnoringSeconds(date1: expectedOptOutDate, date2: actualOptOutDate)) + } + + func testRequestedOptOut_whenProfileReappears_thenOptOutIsScheduled() throws { + let expectedOptOutDate = Date() + + let historyEvents = [ + HistoryEvent(extractedProfileId: 1, + brokerId: 1, + profileQueryId: 1, + type: .optOutRequested, + date: .nowMinus(hours: 24*10)), + HistoryEvent(extractedProfileId: 1, + brokerId: 1, + profileQueryId: 1, + type: .reAppearence), + ] + let calculator = OperationPreferredDateCalculator() + let actualOptOutDate = try calculator.dateForOptOutOperation(currentPreferredRunDate: .distantFuture, + historyEvents: historyEvents, + extractedProfileID: 1, + schedulingConfig: schedulingConfig, + attemptCount: 1) + + XCTAssertTrue(areDatesEqualIgnoringSeconds(date1: expectedOptOutDate, date2: actualOptOutDate)) + } + func testOptOutStartedWithRecentDate_thenOptOutDateDoesNotChange() throws { let expectedOptOutDate = Date() @@ -779,8 +840,6 @@ final class OperationPreferredDateCalculatorTests: XCTestCase { } func testOptOutConfirmedWithRecentDate_thenOptOutDateDoesNotChange() throws { - let expectedOptOutDate: Date? = nil - let historyEvents = [ HistoryEvent(extractedProfileId: 1, brokerId: 1, @@ -790,16 +849,16 @@ final class OperationPreferredDateCalculatorTests: XCTestCase { let calculator = OperationPreferredDateCalculator() let actualOptOutDate = try calculator.dateForOptOutOperation(currentPreferredRunDate: nil, - historyEvents: historyEvents, - extractedProfileID: nil, - schedulingConfig: schedulingConfig, - attemptCount: 0) + historyEvents: historyEvents, + extractedProfileID: nil, + schedulingConfig: schedulingConfig, + attemptCount: 0) - XCTAssertTrue(areDatesEqualIgnoringSeconds(date1: expectedOptOutDate, date2: actualOptOutDate)) + XCTAssertNil(actualOptOutDate) } - func testOptOutRequestedWithRecentDate_thenOptOutDateDoesNotChange() throws { - let expectedOptOutDate: Date? = nil + func testOptOutRequestedWithRecentDate_thenOutOutIsNotScheduled() throws { + let expectedOptOutDate = MockDate().now.addingTimeInterval(schedulingConfig.hoursUntilNextOptOutAttempt.hoursToSeconds) let historyEvents = [ HistoryEvent(extractedProfileId: 1, @@ -813,9 +872,10 @@ final class OperationPreferredDateCalculatorTests: XCTestCase { historyEvents: historyEvents, extractedProfileID: nil, schedulingConfig: schedulingConfig, - attemptCount: 0) + attemptCount: 0, + date: MockDate()) - XCTAssertTrue(areDatesEqualIgnoringSeconds(date1: expectedOptOutDate, date2: actualOptOutDate)) + XCTAssertTrue(areDatesEqualIgnoringSeconds(date1: actualOptOutDate, date2: expectedOptOutDate)) } func testScanStartedWithRecentDate_thenOptOutDateDoesNotChange() throws { From 7ac867d8e4dd8d0d3467fbf0d905c5e28b58538e Mon Sep 17 00:00:00 2001 From: Anka Date: Thu, 16 Jan 2025 05:18:05 +0000 Subject: [PATCH 07/12] Bump version to 1.122.0 (342) --- Configuration/BuildNumber.xcconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Configuration/BuildNumber.xcconfig b/Configuration/BuildNumber.xcconfig index 69a58722c1..56a27d3518 100644 --- a/Configuration/BuildNumber.xcconfig +++ b/Configuration/BuildNumber.xcconfig @@ -1 +1 @@ -CURRENT_PROJECT_VERSION = 341 +CURRENT_PROJECT_VERSION = 342 From b47c5a2d586cf2933cc301d0f6e2c846d15c3572 Mon Sep 17 00:00:00 2001 From: Alexey Martemyanov Date: Thu, 16 Jan 2025 12:49:54 +0600 Subject: [PATCH 08/12] fix circular reference in AddressBarModel (#3733) Task/Issue URL: https://app.asana.com/0/1201048563534612/1209158272007943/f --- DuckDuckGo/HomePage/Model/HomePageAddressBarModel.swift | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/DuckDuckGo/HomePage/Model/HomePageAddressBarModel.swift b/DuckDuckGo/HomePage/Model/HomePageAddressBarModel.swift index 9d5f2ed60d..550990296d 100644 --- a/DuckDuckGo/HomePage/Model/HomePageAddressBarModel.swift +++ b/DuckDuckGo/HomePage/Model/HomePageAddressBarModel.swift @@ -105,7 +105,7 @@ extension HomePage.Models { } } - let tabCollectionViewModel: TabCollectionViewModel + private weak var tabCollectionViewModel: TabCollectionViewModel? private var isExperimentActive: Bool = false { didSet { @@ -140,9 +140,7 @@ extension HomePage.Models { let storyboard = NSStoryboard(name: "NavigationBar", bundle: .main) let viewController: AddressBarViewController = storyboard .instantiateController(identifier: "AddressBarViewController") { [weak self] coder in - guard let self else { - return nil - } + guard let self, let tabCollectionViewModel else { return nil } return AddressBarViewController( coder: coder, tabCollectionViewModel: tabCollectionViewModel, @@ -170,7 +168,7 @@ extension HomePage.Models { } private func subscribeToCustomBackground(_ viewController: AddressBarViewController) { - guard !tabCollectionViewModel.isBurner else { + guard let tabCollectionViewModel, !tabCollectionViewModel.isBurner else { return } From 8178b69b661e8f735749603283c79a44c6bfff5a Mon Sep 17 00:00:00 2001 From: Pete Smith <5278441+aataraxiaa@users.noreply.github.com> Date: Thu, 16 Jan 2025 14:37:48 +0000 Subject: [PATCH 09/12] BSK Bump - Defaults internal Privacy Pro links to /subscriptions (#3741) Task/Issue URL: https://app.asana.com/0/72649045549333/1209009315184468/f **Description**: Previously, default Privacy Pro links were sent to `/subscriptions/welcome`, and the frontend redirected to `/subscriptions`. --- DuckDuckGo.xcodeproj/project.pbxproj | 2 +- .../project.xcworkspace/xcshareddata/swiftpm/Package.resolved | 4 ++-- LocalPackages/DataBrokerProtection/Package.swift | 2 +- LocalPackages/FeatureFlags/Package.swift | 2 +- LocalPackages/NetworkProtectionMac/Package.swift | 2 +- LocalPackages/NewTabPage/Package.swift | 2 +- LocalPackages/SubscriptionUI/Package.swift | 2 +- LocalPackages/WebKitExtensions/Package.swift | 2 +- 8 files changed, 9 insertions(+), 9 deletions(-) diff --git a/DuckDuckGo.xcodeproj/project.pbxproj b/DuckDuckGo.xcodeproj/project.pbxproj index ea44e6de8b..5e107a76ba 100644 --- a/DuckDuckGo.xcodeproj/project.pbxproj +++ b/DuckDuckGo.xcodeproj/project.pbxproj @@ -15366,7 +15366,7 @@ repositoryURL = "https://github.com/duckduckgo/BrowserServicesKit"; requirement = { kind = exactVersion; - version = 224.6.2; + version = 224.7.1; }; }; 9FF521422BAA8FF300B9819B /* XCRemoteSwiftPackageReference "lottie-spm" */ = { diff --git a/DuckDuckGo.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved b/DuckDuckGo.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved index 86f13ce5b9..6bd4e7c6a0 100644 --- a/DuckDuckGo.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved +++ b/DuckDuckGo.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved @@ -32,8 +32,8 @@ "kind" : "remoteSourceControl", "location" : "https://github.com/duckduckgo/BrowserServicesKit", "state" : { - "revision" : "a2a5a32d111aadac6316db4cc629e5dd635939ba", - "version" : "224.6.2" + "revision" : "5acb297db5c0edabe13c79efa33b1d0e545d6bff", + "version" : "224.7.1" } }, { diff --git a/LocalPackages/DataBrokerProtection/Package.swift b/LocalPackages/DataBrokerProtection/Package.swift index 7618d47027..232ca49829 100644 --- a/LocalPackages/DataBrokerProtection/Package.swift +++ b/LocalPackages/DataBrokerProtection/Package.swift @@ -29,7 +29,7 @@ let package = Package( targets: ["DataBrokerProtection"]) ], dependencies: [ - .package(url: "https://github.com/duckduckgo/BrowserServicesKit", exact: "224.6.2"), + .package(url: "https://github.com/duckduckgo/BrowserServicesKit", exact: "224.7.1"), .package(path: "../SwiftUIExtensions"), .package(path: "../AppKitExtensions"), .package(path: "../XPCHelper"), diff --git a/LocalPackages/FeatureFlags/Package.swift b/LocalPackages/FeatureFlags/Package.swift index 1e06afc0e5..ee50b226de 100644 --- a/LocalPackages/FeatureFlags/Package.swift +++ b/LocalPackages/FeatureFlags/Package.swift @@ -32,7 +32,7 @@ let package = Package( targets: ["FeatureFlags"]), ], dependencies: [ - .package(url: "https://github.com/duckduckgo/BrowserServicesKit", exact: "224.6.2"), + .package(url: "https://github.com/duckduckgo/BrowserServicesKit", exact: "224.7.1"), ], targets: [ // Targets are the basic building blocks of a package, defining a module or a test suite. diff --git a/LocalPackages/NetworkProtectionMac/Package.swift b/LocalPackages/NetworkProtectionMac/Package.swift index 5953abda77..f786888b71 100644 --- a/LocalPackages/NetworkProtectionMac/Package.swift +++ b/LocalPackages/NetworkProtectionMac/Package.swift @@ -33,7 +33,7 @@ let package = Package( .library(name: "VPNAppLauncher", targets: ["VPNAppLauncher"]), ], dependencies: [ - .package(url: "https://github.com/duckduckgo/BrowserServicesKit", exact: "224.6.2"), + .package(url: "https://github.com/duckduckgo/BrowserServicesKit", exact: "224.7.1"), .package(url: "https://github.com/airbnb/lottie-spm", exact: "4.4.3"), .package(path: "../AppLauncher"), .package(path: "../UDSHelper"), diff --git a/LocalPackages/NewTabPage/Package.swift b/LocalPackages/NewTabPage/Package.swift index 381d475142..9914544166 100644 --- a/LocalPackages/NewTabPage/Package.swift +++ b/LocalPackages/NewTabPage/Package.swift @@ -32,7 +32,7 @@ let package = Package( targets: ["NewTabPage"]), ], dependencies: [ - .package(url: "https://github.com/duckduckgo/BrowserServicesKit", exact: "224.6.2"), + .package(url: "https://github.com/duckduckgo/BrowserServicesKit", exact: "224.7.1"), .package(path: "../WebKitExtensions"), .package(path: "../Utilities"), ], diff --git a/LocalPackages/SubscriptionUI/Package.swift b/LocalPackages/SubscriptionUI/Package.swift index 05175bd8c4..04e5282fbf 100644 --- a/LocalPackages/SubscriptionUI/Package.swift +++ b/LocalPackages/SubscriptionUI/Package.swift @@ -13,7 +13,7 @@ let package = Package( targets: ["SubscriptionUI"]), ], dependencies: [ - .package(url: "https://github.com/duckduckgo/BrowserServicesKit", exact: "224.6.2"), + .package(url: "https://github.com/duckduckgo/BrowserServicesKit", exact: "224.7.1"), .package(path: "../SwiftUIExtensions"), .package(path: "../FeatureFlags") ], diff --git a/LocalPackages/WebKitExtensions/Package.swift b/LocalPackages/WebKitExtensions/Package.swift index 23a4472f32..f2a1e545f5 100644 --- a/LocalPackages/WebKitExtensions/Package.swift +++ b/LocalPackages/WebKitExtensions/Package.swift @@ -32,7 +32,7 @@ let package = Package( ), ], dependencies: [ - .package(url: "https://github.com/duckduckgo/BrowserServicesKit", exact: "224.6.2"), + .package(url: "https://github.com/duckduckgo/BrowserServicesKit", exact: "224.7.1"), .package(path: "../AppKitExtensions") ], targets: [ From 0905fdb0c182a58224f692d5ac8a20f9a6055239 Mon Sep 17 00:00:00 2001 From: Sam Symons Date: Thu, 16 Jan 2025 16:49:52 -0800 Subject: [PATCH 10/12] [Release PR] Update GitHub Actions workflow naming (#3732) Task/Issue URL: https://app.asana.com/0/1199230911884351/1209141686015373/f Tech Design URL: CC: Description: This PR renames workflow files and names to include the macOS platform string. This is to differentiate them from iOS workflows once we move to a monorepo. --- ..._appstore.yml => macos_build_appstore.yml} | 6 +++--- ...ase.yml => macos_build_hotfix_release.yml} | 8 ++++---- ...otarized.yml => macos_build_notarized.yml} | 8 ++++---- ...se.yml => macos_bump_internal_release.yml} | 10 +++++----- ...{code_freeze.yml => macos_code_freeze.yml} | 8 ++++---- ...e_variant.yml => macos_create_variant.yml} | 6 +++--- ...variants.yml => macos_create_variants.yml} | 18 ++++++++--------- .../{danger.yml => macos_danger.yml} | 4 ++-- .../{hotfix.yml => macos_hotfix.yml} | 2 +- ...sts.yml => macos_pir_end_to_end_tests.yml} | 12 +++++------ .github/workflows/{pr.yml => macos_pr.yml} | 8 ++++---- ...{pr_task_url.yml => macos_pr_task_url.yml} | 4 ++-- ...eport.yml => macos_private_api_report.yml} | 2 +- ...light.yml => macos_promote_testflight.yml} | 5 ++--- ...ease.yml => macos_publish_dmg_release.yml} | 20 +++++++++---------- .../{release.yml => macos_release.yml} | 12 +++++------ .../{stale_pr.yml => macos_stale_pr.yml} | 2 +- ...d_to_end.yml => macos_sync_end_to_end.yml} | 6 +++--- ...ml => macos_sync_end_to_end_legacy_os.yml} | 20 +++++++++---------- ...{tag_release.yml => macos_tag_release.yml} | 2 +- .../{ui_tests.yml => macos_ui_tests.yml} | 10 +++++----- ... macos_update_phishing_detection_data.yml} | 2 +- 22 files changed, 87 insertions(+), 88 deletions(-) rename .github/workflows/{build_appstore.yml => macos_build_appstore.yml} (97%) rename .github/workflows/{build_hotfix_release.yml => macos_build_hotfix_release.yml} (95%) rename .github/workflows/{build_notarized.yml => macos_build_notarized.yml} (99%) rename .github/workflows/{bump_internal_release.yml => macos_bump_internal_release.yml} (96%) rename .github/workflows/{code_freeze.yml => macos_code_freeze.yml} (96%) rename .github/workflows/{create_variant.yml => macos_create_variant.yml} (99%) rename .github/workflows/{create_variants.yml => macos_create_variants.yml} (96%) rename .github/workflows/{danger.yml => macos_danger.yml} (93%) rename .github/workflows/{hotfix.yml => macos_hotfix.yml} (98%) rename .github/workflows/{pir_end_to_end_tests.yml => macos_pir_end_to_end_tests.yml} (98%) rename .github/workflows/{pr.yml => macos_pr.yml} (99%) rename .github/workflows/{pr_task_url.yml => macos_pr_task_url.yml} (99%) rename .github/workflows/{private_api_report.yml => macos_private_api_report.yml} (96%) rename .github/workflows/{promote_testflight.yml => macos_promote_testflight.yml} (94%) rename .github/workflows/{publish_dmg_release.yml => macos_publish_dmg_release.yml} (98%) rename .github/workflows/{release.yml => macos_release.yml} (94%) rename .github/workflows/{stale_pr.yml => macos_stale_pr.yml} (93%) rename .github/workflows/{sync_end_to_end.yml => macos_sync_end_to_end.yml} (98%) rename .github/workflows/{sync_end_to_end_legacy_os.yml => macos_sync_end_to_end_legacy_os.yml} (95%) rename .github/workflows/{tag_release.yml => macos_tag_release.yml} (99%) rename .github/workflows/{ui_tests.yml => macos_ui_tests.yml} (98%) rename .github/workflows/{update_phishing_detection_data.yml => macos_update_phishing_detection_data.yml} (96%) diff --git a/.github/workflows/build_appstore.yml b/.github/workflows/macos_build_appstore.yml similarity index 97% rename from .github/workflows/build_appstore.yml rename to .github/workflows/macos_build_appstore.yml index 6931896c98..50e20041b7 100644 --- a/.github/workflows/build_appstore.yml +++ b/.github/workflows/macos_build_appstore.yml @@ -1,6 +1,6 @@ -name: Make App Store Connect Release +name: macOS - Make App Store Connect Release -on: +on: workflow_dispatch: inputs: destination: @@ -140,7 +140,7 @@ jobs: AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }} AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }} AWS_DEFAULT_REGION: ${{ vars.AWS_DEFAULT_REGION }} - DSYM_S3_PATH: s3://${{ vars.DSYM_BUCKET_NAME }}/${{ vars.DSYM_BUCKET_PREFIX }}/DuckDuckGo-AppStore-${{ env.app-version }}-dSYM.zip + DSYM_S3_PATH: s3://${{ vars.DSYM_BUCKET_NAME }}/${{ vars.MACOS_DSYM_BUCKET_PREFIX }}/DuckDuckGo-AppStore-${{ env.app-version }}-dSYM.zip run: | echo "dsym-s3-path=${DSYM_S3_PATH}" >> $GITHUB_OUTPUT aws s3 cp ${{ env.dsym-path }} ${{ env.DSYM_S3_PATH }} diff --git a/.github/workflows/build_hotfix_release.yml b/.github/workflows/macos_build_hotfix_release.yml similarity index 95% rename from .github/workflows/build_hotfix_release.yml rename to .github/workflows/macos_build_hotfix_release.yml index 473fe43c2a..d200115a39 100644 --- a/.github/workflows/build_hotfix_release.yml +++ b/.github/workflows/macos_build_hotfix_release.yml @@ -1,4 +1,4 @@ -name: Build Hotfix Release +name: macOS - Build Hotfix Release on: workflow_dispatch: @@ -39,7 +39,7 @@ jobs: name: Run Tests needs: assert_release_branch - uses: ./.github/workflows/pr.yml + uses: ./.github/workflows/macos_pr.yml secrets: APPLE_API_KEY_BASE64: ${{ secrets.APPLE_API_KEY_BASE64 }} APPLE_API_KEY_ID: ${{ secrets.APPLE_API_KEY_ID }} @@ -91,7 +91,7 @@ jobs: prepare_release: name: Prepare Release needs: run_tests - uses: ./.github/workflows/release.yml + uses: ./.github/workflows/macos_release.yml with: asana-task-url: ${{ github.event.inputs.asana-task-url }} destination: appstore @@ -112,7 +112,7 @@ jobs: tag_and_merge: name: Tag and Merge Branch needs: [ prepare_release, update_asana ] - uses: ./.github/workflows/tag_release.yml + uses: ./.github/workflows/macos_tag_release.yml with: asana-task-url: ${{ github.event.inputs.asana-task-url }} branch: ${{ github.ref_name }} diff --git a/.github/workflows/build_notarized.yml b/.github/workflows/macos_build_notarized.yml similarity index 99% rename from .github/workflows/build_notarized.yml rename to .github/workflows/macos_build_notarized.yml index 127f139e3c..3a2f328801 100644 --- a/.github/workflows/build_notarized.yml +++ b/.github/workflows/macos_build_notarized.yml @@ -1,6 +1,6 @@ -name: Make Notarized DMG Release +name: macOS - Make Notarized DMG Release -on: +on: workflow_dispatch: inputs: release-type: @@ -181,7 +181,7 @@ jobs: AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }} AWS_DEFAULT_REGION: ${{ vars.AWS_DEFAULT_REGION }} DSYM_BUCKET_NAME: ${{ vars.DSYM_BUCKET_NAME }} - DSYM_BUCKET_PREFIX: ${{ vars.DSYM_BUCKET_PREFIX }} + DSYM_BUCKET_PREFIX: ${{ vars.MACOS_DSYM_BUCKET_PREFIX }} DSYM_NAME: ${{ steps.set-outputs.outputs.dsym-name }} DSYM_LOCAL_PATH: "${{ github.workspace }}/release/${{ steps.set-outputs.outputs.dsym-name }}" run: | @@ -383,7 +383,7 @@ jobs: Gemfile Gemfile.lock fastlane - + - name: Set up fastlane run: bundle install diff --git a/.github/workflows/bump_internal_release.yml b/.github/workflows/macos_bump_internal_release.yml similarity index 96% rename from .github/workflows/bump_internal_release.yml rename to .github/workflows/macos_bump_internal_release.yml index d9482b5be9..bd6e14d025 100644 --- a/.github/workflows/bump_internal_release.yml +++ b/.github/workflows/macos_bump_internal_release.yml @@ -1,4 +1,4 @@ -name: Bump Internal Release +name: macOS - Bump Internal Release on: schedule: @@ -72,7 +72,7 @@ jobs: needs: validate_input_conditions if: needs.validate_input_conditions.outputs.skip-release != 'true' - uses: ./.github/workflows/pr.yml + uses: ./.github/workflows/macos_pr.yml with: branch: ${{ needs.validate_input_conditions.outputs.release-branch }} secrets: @@ -124,7 +124,7 @@ jobs: prepare_release: name: Prepare Release needs: [ validate_input_conditions, increment_build_number ] - uses: ./.github/workflows/release.yml + uses: ./.github/workflows/macos_release.yml with: asana-task-url: ${{ needs.validate_input_conditions.outputs.asana-task-url }} branch: ${{ needs.validate_input_conditions.outputs.release-branch }} @@ -146,7 +146,7 @@ jobs: tag_and_merge: name: Tag and Merge Branch needs: [ validate_input_conditions, prepare_release ] - uses: ./.github/workflows/tag_release.yml + uses: ./.github/workflows/macos_tag_release.yml with: asana-task-url: ${{ needs.validate_input_conditions.outputs.asana-task-url }} branch: ${{ needs.validate_input_conditions.outputs.release-branch }} @@ -160,7 +160,7 @@ jobs: publish_release: name: Publish DMG Release needs: [ validate_input_conditions, tag_and_merge ] - uses: ./.github/workflows/publish_dmg_release.yml + uses: ./.github/workflows/macos_publish_dmg_release.yml with: asana-task-url: ${{ needs.validate_input_conditions.outputs.asana-task-url }} branch: ${{ needs.validate_input_conditions.outputs.release-branch }} diff --git a/.github/workflows/code_freeze.yml b/.github/workflows/macos_code_freeze.yml similarity index 96% rename from .github/workflows/code_freeze.yml rename to .github/workflows/macos_code_freeze.yml index 767dc80a67..d4f3142ef1 100644 --- a/.github/workflows/code_freeze.yml +++ b/.github/workflows/macos_code_freeze.yml @@ -1,4 +1,4 @@ -name: Code Freeze +name: macOS - Code Freeze on: workflow_dispatch: @@ -56,7 +56,7 @@ jobs: name: Run Tests needs: create_release_branch - uses: ./.github/workflows/pr.yml + uses: ./.github/workflows/macos_pr.yml with: branch: ${{ needs.create_release_branch.outputs.release_branch_name }} secrets: @@ -99,7 +99,7 @@ jobs: prepare_release: name: Prepare Release needs: [ create_release_branch, increment_build_number ] - uses: ./.github/workflows/release.yml + uses: ./.github/workflows/macos_release.yml with: asana-task-url: ${{ needs.create_release_branch.outputs.asana_task_url }} branch: ${{ needs.create_release_branch.outputs.release_branch_name }} @@ -120,7 +120,7 @@ jobs: tag_and_merge: name: Tag and Merge Branch needs: [ create_release_branch, prepare_release ] - uses: ./.github/workflows/tag_release.yml + uses: ./.github/workflows/macos_tag_release.yml with: asana-task-url: ${{ needs.create_release_branch.outputs.asana_task_url }} base-branch: ${{ github.ref_name }} diff --git a/.github/workflows/create_variant.yml b/.github/workflows/macos_create_variant.yml similarity index 99% rename from .github/workflows/create_variant.yml rename to .github/workflows/macos_create_variant.yml index 88ea096685..7c29e630fc 100644 --- a/.github/workflows/create_variant.yml +++ b/.github/workflows/macos_create_variant.yml @@ -1,4 +1,4 @@ -name: Create DMG Variant +name: macOS - Create DMG Variant on: workflow_dispatch: @@ -40,7 +40,7 @@ on: jobs: create-dmg-variant: - + name: Create DMG Variant env: @@ -69,7 +69,7 @@ jobs: - name: Set up fastlane run: bundle install - + - name: Sync code signing assets env: APPLE_API_KEY_BASE64: ${{ secrets.APPLE_API_KEY_BASE64 }} diff --git a/.github/workflows/create_variants.yml b/.github/workflows/macos_create_variants.yml similarity index 96% rename from .github/workflows/create_variants.yml rename to .github/workflows/macos_create_variants.yml index 0c801b4a5d..818c12dbcb 100644 --- a/.github/workflows/create_variants.yml +++ b/.github/workflows/macos_create_variants.yml @@ -1,4 +1,4 @@ -name: Create DMG Variants +name: macOS - Create DMG Variants on: workflow_dispatch: @@ -42,7 +42,7 @@ jobs: steps: - name: Check out repository uses: actions/checkout@v4 - + - name: Fetch Build Variants id: get-build-variants uses: ./.github/actions/asana-get-build-variants-list @@ -50,7 +50,7 @@ jobs: access-token: ${{ secrets.ASANA_ACCESS_TOKEN }} atb-asana-task-id: ${{ vars.DMG_VARIANTS_LIST_TASK_ID }} origin-asana-section-id: ${{ vars.DMG_VARIANTS_ORIGIN_SECTION_ID }} - + download-dmg-and-upload-artifact: name: Download Release App and upload artifact @@ -78,7 +78,7 @@ jobs: strategy: fail-fast: false matrix: ${{ fromJSON(needs.set-up-variants.outputs.build-variants-1) }} - uses: ./.github/workflows/create_variant.yml + uses: ./.github/workflows/macos_create_variant.yml with: atb-variant: ${{ matrix.variant }} origin-variant: ${{ matrix.origin }} @@ -99,7 +99,7 @@ jobs: strategy: fail-fast: false matrix: ${{ fromJSON(needs.set-up-variants.outputs.build-variants-2) }} - uses: ./.github/workflows/create_variant.yml + uses: ./.github/workflows/macos_create_variant.yml with: atb-variant: ${{ matrix.variant }} origin-variant: ${{ matrix.origin }} @@ -111,17 +111,17 @@ jobs: AWS_SECRET_ACCESS_KEY_RELEASE_S3: ${{ secrets.AWS_SECRET_ACCESS_KEY_RELEASE_S3 }} MATCH_PASSWORD: ${{ secrets.MATCH_PASSWORD }} SSH_PRIVATE_KEY_FASTLANE_MATCH: ${{ secrets.SSH_PRIVATE_KEY_FASTLANE_MATCH }} - + mattermost: - + name: Send Mattermost message needs: [create-variants-1, create-variants-2] runs-on: macos-15 - + env: success: ${{ needs.create-variants-1.result == 'success' && needs.create-variants-2.result == 'success' }} failure: ${{ needs.create-variants-1.result == 'failure' || needs.create-variants-2.result == 'failure' }} - + steps: - name: Check out the code if: ${{ env.success || env.failure }} # Don't execute when cancelled diff --git a/.github/workflows/danger.yml b/.github/workflows/macos_danger.yml similarity index 93% rename from .github/workflows/danger.yml rename to .github/workflows/macos_danger.yml index 3e27085c64..53a9302609 100644 --- a/.github/workflows/danger.yml +++ b/.github/workflows/macos_danger.yml @@ -1,5 +1,5 @@ -name: Danger JS -on: +name: macOS - Danger JS +on: pull_request: types: [labeled, unlabeled, opened, reopened, edited, synchronize] diff --git a/.github/workflows/hotfix.yml b/.github/workflows/macos_hotfix.yml similarity index 98% rename from .github/workflows/hotfix.yml rename to .github/workflows/macos_hotfix.yml index 147fb67619..9d4e2c7f45 100644 --- a/.github/workflows/hotfix.yml +++ b/.github/workflows/macos_hotfix.yml @@ -1,4 +1,4 @@ -name: Set Up Hotfix Release Branch +name: macOS - Set Up Hotfix Release Branch on: workflow_dispatch: diff --git a/.github/workflows/pir_end_to_end_tests.yml b/.github/workflows/macos_pir_end_to_end_tests.yml similarity index 98% rename from .github/workflows/pir_end_to_end_tests.yml rename to .github/workflows/macos_pir_end_to_end_tests.yml index 55afc4e252..5870e17d83 100644 --- a/.github/workflows/pir_end_to_end_tests.yml +++ b/.github/workflows/macos_pir_end_to_end_tests.yml @@ -1,11 +1,11 @@ -name: PIR E2E Tests +name: macOS - PIR E2E Tests on: workflow_dispatch: schedule: - cron: '0 3 * * 1-5' # 3AM UTC offsetted to legacy to avoid action-junit-report@v4 bug pull_request: - + jobs: pir-e2e-tests: name: PIR e2e tests @@ -48,11 +48,11 @@ jobs: - name: Start PIR Fake Broker run: | - cd pir-fake-broker + cd pir-fake-broker cd scripts ./install-prerequisites.sh ./setup-ci.sh - cd .. + cd .. pnpm start:all & - name: Check out the code @@ -65,7 +65,7 @@ jobs: run: | cd main bundle install - + - name: Sync code signing assets env: APPLE_API_KEY_BASE64: ${{ secrets.APPLE_API_KEY_BASE64 }} @@ -130,7 +130,7 @@ jobs: - name: Publish tests report uses: mikepenz/action-junit-report@v4 - if: always() + if: always() with: check_name: "Test Report ${{ matrix.runner }}" report_paths: pir-e2e-tests.xml diff --git a/.github/workflows/pr.yml b/.github/workflows/macos_pr.yml similarity index 99% rename from .github/workflows/pr.yml rename to .github/workflows/macos_pr.yml index 363a206b91..cd5ec04405 100644 --- a/.github/workflows/pr.yml +++ b/.github/workflows/macos_pr.yml @@ -1,6 +1,6 @@ -name: PR Checks +name: macOS - PR Checks -on: +on: push: branches: [ main, "release/**" ] pull_request: @@ -156,7 +156,7 @@ jobs: MATCH_PASSWORD: ${{ secrets.MATCH_PASSWORD }} SSH_PRIVATE_KEY_FASTLANE_MATCH: ${{ secrets.SSH_PRIVATE_KEY_FASTLANE_MATCH }} run: bundle exec fastlane sync_signing_ci - + - name: Set cache key hash run: | has_only_tags=$(jq '[ .pins[].state | has("version") ] | all' DuckDuckGo.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved) @@ -305,7 +305,7 @@ jobs: name: Private API Report needs: tests if: ${{ success() || needs.tests.outputs.private-api-check-report }} - uses: ./.github/workflows/private_api_report.yml + uses: ./.github/workflows/macos_private_api_report.yml with: report: ${{ needs.tests.outputs.private-api-check-report }} diff --git a/.github/workflows/pr_task_url.yml b/.github/workflows/macos_pr_task_url.yml similarity index 99% rename from .github/workflows/pr_task_url.yml rename to .github/workflows/macos_pr_task_url.yml index c1dcdbb7a2..256b524232 100644 --- a/.github/workflows/pr_task_url.yml +++ b/.github/workflows/macos_pr_task_url.yml @@ -1,6 +1,6 @@ -name: Asana PR Task URL +name: macOS - Asana PR Task URL -on: +on: pull_request: types: [opened, edited, closed, synchronize, review_requested, ready_for_review] diff --git a/.github/workflows/private_api_report.yml b/.github/workflows/macos_private_api_report.yml similarity index 96% rename from .github/workflows/private_api_report.yml rename to .github/workflows/macos_private_api_report.yml index a1159d4b07..d0a4f0c44b 100644 --- a/.github/workflows/private_api_report.yml +++ b/.github/workflows/macos_private_api_report.yml @@ -1,4 +1,4 @@ -name: Private API Usage Report +name: macOS - Private API Usage Report on: workflow_call: diff --git a/.github/workflows/promote_testflight.yml b/.github/workflows/macos_promote_testflight.yml similarity index 94% rename from .github/workflows/promote_testflight.yml rename to .github/workflows/macos_promote_testflight.yml index 5c971349ea..6e7cb23ee8 100644 --- a/.github/workflows/promote_testflight.yml +++ b/.github/workflows/macos_promote_testflight.yml @@ -1,6 +1,6 @@ -name: Promote TestFlight to App Store +name: macOS - Promote TestFlight to App Store -on: +on: workflow_dispatch: {} jobs: @@ -31,4 +31,3 @@ jobs: git config --global user.name "Dax the Duck" git config --global user.email "dax@duckduckgo.com" bundle exec fastlane promote_latest_testflight_to_appstore - diff --git a/.github/workflows/publish_dmg_release.yml b/.github/workflows/macos_publish_dmg_release.yml similarity index 98% rename from .github/workflows/publish_dmg_release.yml rename to .github/workflows/macos_publish_dmg_release.yml index dcd7a4cf61..d47cb054c4 100644 --- a/.github/workflows/publish_dmg_release.yml +++ b/.github/workflows/macos_publish_dmg_release.yml @@ -1,4 +1,4 @@ -name: Publish DMG Release +name: macOS - Publish DMG Release on: workflow_dispatch: @@ -52,7 +52,7 @@ jobs: # Run if release-type is provided (not empty) and is not internal if: github.event.inputs.release-type != null && github.event.inputs.release-type != 'internal' - uses: ./.github/workflows/tag_release.yml + uses: ./.github/workflows/macos_tag_release.yml with: asana-task-url: ${{ inputs.asana-task-url || github.event.inputs.asana-task-url }} branch: ${{ github.ref_name }} @@ -214,7 +214,7 @@ jobs: appcast_patch_name="appcast2-${VERSION}.patch" mv -f ${{ env.SPARKLE_DIR }}/appcast_diff.txt ${{ env.SPARKLE_DIR }}/${appcast_patch_name} echo "appcast-patch-name=${appcast_patch_name}" >> $GITHUB_OUTPUT - + - name: Upload appcast diff artifact uses: actions/upload-artifact@v4 with: @@ -294,7 +294,7 @@ jobs: if: always() id: asana-templates run: | - if [[ ${{ steps.upload.outcome }} == "success" ]]; then + if [[ ${{ steps.upload.outcome }} == "success" ]]; then if [[ "${RELEASE_TYPE}" == "internal" ]]; then echo "task-template=validate-check-for-updates-internal" >> $GITHUB_OUTPUT echo "comment-template=validate-check-for-updates-internal" >> $GITHUB_OUTPUT @@ -346,7 +346,7 @@ jobs: run: | bundle exec fastlane run asana_upload \ file_name:"${{ env.SPARKLE_DIR }}/${{ steps.appcast.outputs.appcast-patch-name }}" \ - task_id:"${{ steps.create-task.outputs.asana_new_task_id }}" + task_id:"${{ steps.create-task.outputs.asana_new_task_id }}" - name: Upload old appcast file to the Asana task id: upload-old-appcast @@ -356,8 +356,8 @@ jobs: run: | bundle exec fastlane run asana_upload \ file_name:"${{ env.OLD_APPCAST_NAME }}" \ - task_id:"${{ steps.create-task.outputs.asana_new_task_id }}" - + task_id:"${{ steps.create-task.outputs.asana_new_task_id }}" + - name: Upload release notes to the Asana task id: upload-release-notes if: success() @@ -366,8 +366,8 @@ jobs: run: | bundle exec fastlane run asana_upload \ file_name:"${{ env.RELEASE_NOTES_FILE }}" \ - task_id:"${{ steps.create-task.outputs.asana_new_task_id }}" - + task_id:"${{ steps.create-task.outputs.asana_new_task_id }}" + - name: Report status if: always() env: @@ -402,7 +402,7 @@ jobs: # Run if release-type is provided (not empty) an is not internal if: github.event.inputs.release-type != null && github.event.inputs.release-type != 'internal' - uses: duckduckgo/macos-browser/.github/workflows/create_variants.yml@main + uses: duckduckgo/macos-browser/.github/workflows/macos_create_variants.yml@main secrets: APPLE_API_KEY_BASE64: ${{ secrets.APPLE_API_KEY_BASE64 }} APPLE_API_KEY_ID: ${{ secrets.APPLE_API_KEY_ID }} diff --git a/.github/workflows/release.yml b/.github/workflows/macos_release.yml similarity index 94% rename from .github/workflows/release.yml rename to .github/workflows/macos_release.yml index b3dad26b56..b69832f7d2 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/macos_release.yml @@ -1,6 +1,6 @@ -name: Prepare Release +name: macOS - Prepare Release -on: +on: workflow_dispatch: inputs: asana-task-url: @@ -11,7 +11,7 @@ on: description: "Skip App Store release and only make a DMG build" default: false type: boolean - destination: + destination: description: "Upload destination (TestFlight or App Store)" required: false default: testflight @@ -30,7 +30,7 @@ on: description: "Skip App Store release and only make a DMG build" default: false type: boolean - destination: + destination: description: "Upload destination (TestFlight or App Store)" required: false default: testflight @@ -65,7 +65,7 @@ jobs: dmg-release: name: Prepare DMG Release - uses: ./.github/workflows/build_notarized.yml + uses: ./.github/workflows/macos_build_notarized.yml with: release-type: release create-dmg: true @@ -90,7 +90,7 @@ jobs: if: inputs.skip-appstore != 'true' - uses: ./.github/workflows/build_appstore.yml + uses: ./.github/workflows/macos_build_appstore.yml with: destination: ${{ inputs.destination }} asana-task-url: ${{ inputs.asana-task-url }} diff --git a/.github/workflows/stale_pr.yml b/.github/workflows/macos_stale_pr.yml similarity index 93% rename from .github/workflows/stale_pr.yml rename to .github/workflows/macos_stale_pr.yml index a4a6e92c29..4e65adef76 100644 --- a/.github/workflows/stale_pr.yml +++ b/.github/workflows/macos_stale_pr.yml @@ -1,4 +1,4 @@ -name: Close Stale Pull Requests +name: macOS - Close Stale Pull Requests on: schedule: diff --git a/.github/workflows/sync_end_to_end.yml b/.github/workflows/macos_sync_end_to_end.yml similarity index 98% rename from .github/workflows/sync_end_to_end.yml rename to .github/workflows/macos_sync_end_to_end.yml index 193310e200..3285b029e4 100644 --- a/.github/workflows/sync_end_to_end.yml +++ b/.github/workflows/macos_sync_end_to_end.yml @@ -1,4 +1,4 @@ -name: Sync End-to-End tests +name: macOS - Sync End-to-End tests on: workflow_dispatch: @@ -8,7 +8,7 @@ on: jobs: create-notarized-app: name: Build Notarized Review app - uses: ./.github/workflows/build_notarized.yml + uses: ./.github/workflows/macos_build_notarized.yml with: release-type: review create-dmg: false @@ -77,7 +77,7 @@ jobs: SSH_PRIVATE_KEY_FASTLANE_MATCH: ${{ secrets.SSH_PRIVATE_KEY_FASTLANE_MATCH }} run: | bundle exec fastlane sync_signing_ci - + - name: Download and unzip artifact uses: actions/download-artifact@v4 diff --git a/.github/workflows/sync_end_to_end_legacy_os.yml b/.github/workflows/macos_sync_end_to_end_legacy_os.yml similarity index 95% rename from .github/workflows/sync_end_to_end_legacy_os.yml rename to .github/workflows/macos_sync_end_to_end_legacy_os.yml index 72c4172c5f..4572a908b6 100644 --- a/.github/workflows/sync_end_to_end_legacy_os.yml +++ b/.github/workflows/macos_sync_end_to_end_legacy_os.yml @@ -1,4 +1,4 @@ -name: Sync-End-to-End tests MacOS11/12 +name: macOS - Sync-End-to-End tests MacOS11/12 on: workflow_dispatch: @@ -8,7 +8,7 @@ on: jobs: create-notarized-app: name: Prepare DMG Release - uses: ./.github/workflows/build_notarized.yml + uses: ./.github/workflows/macos_build_notarized.yml with: release-type: review create-dmg: false @@ -64,7 +64,7 @@ jobs: run: | bundle exec fastlane sync_signing_dmg_review bundle exec fastlane sync_signing_ci - + - name: Download and unzip artifact uses: actions/download-artifact@v4 @@ -101,18 +101,18 @@ jobs: debug: true # This first bit is a hack to stop the app building package dependencies that isn't needed by the test runner - - name: Build test runner + - name: Build test runner run: | rm -rf LocalPackages - rm -rf /Users/runner/work/macos-browser/macos-browser/DuckDuckGo.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved + rm -rf /Users/runner/work/macos-browser/macos-browser/DuckDuckGo.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved sed -i '' '/\/\* Begin XCSwiftPackageProductDependency section \*\//,/\/\* End XCSwiftPackageProductDependency section \*\//d' DuckDuckGo.xcodeproj/project.pbxproj sed -i '' '/\/\* Begin XCRemoteSwiftPackageReference section \*\//,/\/\* End XCRemoteSwiftPackageReference section \*\//d' DuckDuckGo.xcodeproj/project.pbxproj set -o pipefail && xcodebuild build-for-testing \ -scheme "SyncE2EUITestsOldVersions" \ -derivedDataPath DerivedData \ - -configuration Review - - - name: Unzip and Copy app to /DerivedData + -configuration Review + + - name: Unzip and Copy app to /DerivedData run: | cd DuckDuckGo-review-*.app && unzip DuckDuckGo-*.zip cp -R "DuckDuckGo Review.app" "../DerivedData/Build/Products/Review/DuckDuckGo Review.app" @@ -148,14 +148,14 @@ jobs: - name: Publish tests report uses: mikepenz/action-junit-report@v4 - if: always() + if: always() with: check_name: "Test Report ${{ matrix.runner }}" report_paths: ui-tests.xml - name: Upload logs when workflow failed uses: actions/upload-artifact@v4 - if: always() + if: always() with: name: "BuildLogs ${{ matrix.runner }}" path: | diff --git a/.github/workflows/tag_release.yml b/.github/workflows/macos_tag_release.yml similarity index 99% rename from .github/workflows/tag_release.yml rename to .github/workflows/macos_tag_release.yml index d526a30f73..c1327d6efa 100644 --- a/.github/workflows/tag_release.yml +++ b/.github/workflows/macos_tag_release.yml @@ -1,4 +1,4 @@ -name: Tag Release +name: macOS - Tag Release on: workflow_dispatch: diff --git a/.github/workflows/ui_tests.yml b/.github/workflows/macos_ui_tests.yml similarity index 98% rename from .github/workflows/ui_tests.yml rename to .github/workflows/macos_ui_tests.yml index c624ae2f37..7db3821acf 100644 --- a/.github/workflows/ui_tests.yml +++ b/.github/workflows/macos_ui_tests.yml @@ -1,4 +1,4 @@ -name: UI Tests +name: macOS - UI Tests on: workflow_dispatch: @@ -8,11 +8,11 @@ on: branches: - hotfix/* - release/* - + jobs: create-notarized-app: name: Build Notarized Review app - uses: ./.github/workflows/build_notarized.yml + uses: ./.github/workflows/macos_build_notarized.yml with: release-type: review create-dmg: false @@ -78,7 +78,7 @@ jobs: - name: Create Default Keychain run: bundle exec fastlane create_keychain_ui_tests - + - name: Sync code signing assets env: APPLE_API_KEY_BASE64: ${{ secrets.APPLE_API_KEY_BASE64 }} @@ -151,7 +151,7 @@ jobs: - name: Publish tests report uses: mikepenz/action-junit-report@v4 - if: always() + if: always() with: check_name: "Test Report ${{ matrix.runner }}" report_paths: ui-tests.xml diff --git a/.github/workflows/update_phishing_detection_data.yml b/.github/workflows/macos_update_phishing_detection_data.yml similarity index 96% rename from .github/workflows/update_phishing_detection_data.yml rename to .github/workflows/macos_update_phishing_detection_data.yml index 0b722dc0ec..52771b268e 100644 --- a/.github/workflows/update_phishing_detection_data.yml +++ b/.github/workflows/macos_update_phishing_detection_data.yml @@ -1,4 +1,4 @@ -name: Update Phishing Detection Datasets +name: macOS - Update Phishing Detection Datasets on: schedule: - cron: '0 0 * * 0' # Midnight UTC every Sunday From be426a6a1a0fc425968dfcd29a7bf8891fb8c37f Mon Sep 17 00:00:00 2001 From: Anka Date: Fri, 17 Jan 2025 01:03:47 +0000 Subject: [PATCH 11/12] Bump version to 1.122.0 (343) --- Configuration/BuildNumber.xcconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Configuration/BuildNumber.xcconfig b/Configuration/BuildNumber.xcconfig index 56a27d3518..a587ad2f48 100644 --- a/Configuration/BuildNumber.xcconfig +++ b/Configuration/BuildNumber.xcconfig @@ -1 +1 @@ -CURRENT_PROJECT_VERSION = 342 +CURRENT_PROJECT_VERSION = 343 From f9c494ce60de3a10c6090bbc51b77cb9e7772c07 Mon Sep 17 00:00:00 2001 From: Anka Date: Fri, 17 Jan 2025 01:58:59 +0000 Subject: [PATCH 12/12] Bump version to 1.122.0 (344) --- Configuration/BuildNumber.xcconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Configuration/BuildNumber.xcconfig b/Configuration/BuildNumber.xcconfig index a587ad2f48..cfe922e0f9 100644 --- a/Configuration/BuildNumber.xcconfig +++ b/Configuration/BuildNumber.xcconfig @@ -1 +1 @@ -CURRENT_PROJECT_VERSION = 343 +CURRENT_PROJECT_VERSION = 344