Skip to content

Commit

Permalink
Merge branch 'release/1.85.0' into dominik/test-base-branch
Browse files Browse the repository at this point in the history
  • Loading branch information
ayoy committed Apr 26, 2024
2 parents d81f607 + e9577f6 commit 98bdfb5
Show file tree
Hide file tree
Showing 564 changed files with 29,481 additions and 11,026 deletions.
36 changes: 36 additions & 0 deletions .github/actions/asana-get-build-variants-list/action.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
name: Get The List of Build Variants From Asana
description: |
Fetch the lists of build variants to measure retention (ATB) and attribution (Origin) from different Asana projects and combine them in a list.
inputs:
access-token:
description: "Asana access token"
required: true
type: string
github-token:
description: "GitHub Token"
required: false
type: string
atb-asana-task-id:
description: "Asana Task id for the ATB list."
required: true
type: string
origin-asana-section-id:
description: "Asana Section id for the Origins list"
required: true
type: string
outputs:
build-variants:
description: "The list of build variants to create"
value: ${{ steps.get-build-variants-task.outputs.build-variants }}
runs:
using: "composite"
steps:
- id: get-build-variants-task
shell: bash
env:
ASANA_ACCESS_TOKEN: ${{ inputs.access-token }}
GITHUB_TOKEN: ${{ inputs.github-token || github.token }}
ORIGIN_ASANA_SECTION_ID: ${{ inputs.origin-asana-section-id }}
ATB_ASANA_TASK_ID: ${{ inputs.atb-asana-task-id }}
run: |
${{ github.action_path }}/get_build_variants_list.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@
#!/bin/bash
#
# This scripts fetches Asana tasks from the Origins section defined in the Asana project https://app.asana.com/0/1206716555947156/1206716715679835.
#

set -e -o pipefail

asana_api_url="https://app.asana.com/api/1.0"

# Create a JSON string with the `origin-variant` pairs from the list of .
_create_origins_and_variants() {
local response="$1"
local origin_field="Origin"
local atb_field="ATB"

# for each element in the data array.
# filter out element with null `origin`.
# select `origin` and `variant` from the custom_fields response and make a key:value pair structure like {origin: <origin_value>, variant: <variant_value>}.
# if variant is not null we need to create two entries. One only with `origin` and one with `origin` and `variant`
# replace the new line with a comma
# remove the trailing comma at the end of the line.
jq -c '.data[]
| select(.custom_fields[] | select(.name == "'"${origin_field}"'").text_value != null)
| {origin: (.custom_fields[] | select(.name == "'"${origin_field}"'") | .text_value), variant: (.custom_fields[] | select(.name == "'"${atb_field}"'") | .text_value)}
| if .variant != null then {origin}, {origin, variant} else {origin} end' <<< "$response" \
| tr '\n' ',' \
| sed 's/,$//'
}

# Fetch all the Asana tasks in the section specified by ORIGIN_ASANA_SECTION_ID for a project.
# This function fetches only uncompleted tasks.
# If there are more than 100 items the function takes care of pagination.
# Returns a JSON string consisting of a list of `origin-variant` pairs concatenated by a comma. Eg. `{"origin":"app","variant":"ab"},{"origin":"app.search","variant":null}`.
_fetch_origin_tasks() {
# Fetches only tasks that have not been completed yet, includes in the response section name, name of the task and its custom fields.
local query="completed_since=now&opt_fields=name,custom_fields.id_prefix,custom_fields.name,custom_fields.text_value&opt_expand=custom_fields&opt_fields=memberships.section.name&limit=100"

local url="${asana_api_url}/sections/${ORIGIN_ASANA_SECTION_ID}/tasks?${query}"
local response
local origin_variants=()

# go through all tasks in the section (there may be multiple requests in case there are more than 100 tasks in the section)
# repeat until no more pages (next_page.uri is null)
while true; do
response="$(curl -fLSs "$url" -H "Authorization: Bearer ${ASANA_ACCESS_TOKEN}")"

# extract the object in the data array and append to result
origin_variants+=("$(_create_origins_and_variants "$response")")

# set new URL to next page URL
url="$(jq -r .next_page.uri <<< "$response")"

# break on last page
if [[ "$url" == "null" ]]; then
break
fi
done

echo "${origin_variants}"
}

# Create a JSON string from the list of ATB items passed.
_create_atb_variant_pairs() {
local response="$1"

# read the response raw and format in a compact JSON mode
# map each element to the structure {variant:<element>}
# remove the array
# replace the new line with a comma
# remove the trailing comma at the end of the line.
jq -R -c 'split(",")
| map({variant: .})
| .[]' <<< "$response" \
| tr '\n' ',' \
| sed 's/,$//'
}

# Fetches all the ATB variants defined in the ATB_ASANA_TASK_ID at the Variants list (comma separated) section.
_fetch_atb_variants() {
local url="${asana_api_url}/tasks/${ATB_ASANA_TASK_ID}?opt_fields=notes"
local atb_variants

# fetches the items
# read the response raw
# select only Variants list section
# output last line of the input to get all the list of variants.
atb_variants="$(curl -fSsL ${url} \
-H "Authorization: Bearer ${ASANA_ACCESS_TOKEN}" \
| jq -r .data.notes \
| grep -A1 '^Variants list' \
| tail -1)"

variants_list=("$(_create_atb_variant_pairs "$atb_variants")")

echo "${variants_list}"
}

main() {
# fetch ATB variants
local atb_variants=$(_fetch_atb_variants)
# fetch Origin variants
local origin_variants=$(_fetch_origin_tasks)
# merges the two list together. Use `include` keyword for later usage in matrix.
# for more info see https://docs.github.com/en/actions/using-jobs/using-a-matrix-for-your-jobs#example-adding-configurations.
local merged_variants="{\"include\": [${atb_variants},${origin_variants}]}"
# write in GitHub output
echo "build-variants=${merged_variants}" >> "$GITHUB_OUTPUT"
}

main
215 changes: 215 additions & 0 deletions .github/workflows/create_variant.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,215 @@
on:
workflow_dispatch:
inputs:
atb-variant:
description: "ATB variant. Used for measuring attribution and retention."
required: false
type: string
origin-variant:
description: "Origin variant. Used for measuring attribution only."
required: false
type: string
workflow_call:
inputs:
atb-variant:
description: "ATB variant. Used for measuring attribution and retention. Passed by the caller workflow."
required: false
type: string
origin-variant:
description: "Origin variant. Used for measuring attribution only. Passed by the caller workflow."
required: false
type: string
secrets:
BUILD_CERTIFICATE_BASE64:
required: true
P12_PASSWORD:
required: true
KEYCHAIN_PASSWORD:
required: true
REVIEW_PROVISION_PROFILE_BASE64:
required: true
RELEASE_PROVISION_PROFILE_BASE64:
required: true
DBP_AGENT_RELEASE_PROVISION_PROFILE_BASE64:
required: true
DBP_AGENT_REVIEW_PROVISION_PROFILE_BASE64:
required: true
NETP_SYSEX_RELEASE_PROVISION_PROFILE_BASE64_V2:
required: true
NETP_SYSEX_REVIEW_PROVISION_PROFILE_BASE64_V2:
required: true
NETP_AGENT_RELEASE_PROVISION_PROFILE_BASE64_V2:
required: true
NETP_AGENT_REVIEW_PROVISION_PROFILE_BASE64_V2:
required: true
NETP_NOTIFICATIONS_RELEASE_PROVISION_PROFILE_BASE64:
required: true
NETP_NOTIFICATIONS_REVIEW_PROVISION_PROFILE_BASE64:
required: true
APPLE_API_KEY_BASE64:
required: true
APPLE_API_KEY_ID:
required: true
APPLE_API_KEY_ISSUER:
required: true
ASANA_ACCESS_TOKEN:
required: true
MM_HANDLES_BASE64:
required: true
MM_WEBHOOK_URL:
required: true
AWS_ACCESS_KEY_ID_RELEASE_S3:
required: true
AWS_SECRET_ACCESS_KEY_RELEASE_S3:
required: true

jobs:

create-dmg-variant:

name: Create DMG Variant

env:
ATB_VARIANT_NAME: ${{ inputs.atb-variant || github.event.inputs.atb-variant }}
ORIGIN_VARIANT_NAME: ${{ inputs.origin-variant || github.event.inputs.origin-variant }}

runs-on: macos-12
timeout-minutes: 15

steps:

- name: Check out the code
uses: actions/checkout@v4
with:
ref: main
sparse-checkout: |
.github
scripts
- name: Download DMG artifact
id: download-dmg-artifact
continue-on-error: true
uses: actions/download-artifact@v4
with:
name: duckduckgo-dmg
path: ${{ github.workspace }}

- name: Download release app
# Download the release app only if download-dmg-artifact fails
if: ${{ steps.download-dmg-artifact.outcome == 'failure' }}
run: |
curl -fLSs "${{ vars.RELEASE_DMG_URL }}" --output duckduckgo.dmg
- name: Extract App from DMG
id: extract-app-from-dmg
run: |
hdiutil attach duckduckgo.dmg -mountpoint vanilla
mkdir -p dmg
cp -R vanilla/DuckDuckGo.app dmg/DuckDuckGo.app
hdiutil detach vanilla
rm -f duckduckgo.dmg
- name: Install create-dmg
run: brew install create-dmg

- name: Install Apple Developer ID Application certificate
uses: ./.github/actions/install-certs-and-profiles
with:
BUILD_CERTIFICATE_BASE64: ${{ secrets.BUILD_CERTIFICATE_BASE64 }}
P12_PASSWORD: ${{ secrets.P12_PASSWORD }}
KEYCHAIN_PASSWORD: ${{ secrets.KEYCHAIN_PASSWORD }}
REVIEW_PROVISION_PROFILE_BASE64: ${{ secrets.REVIEW_PROVISION_PROFILE_BASE64 }}
RELEASE_PROVISION_PROFILE_BASE64: ${{ secrets.RELEASE_PROVISION_PROFILE_BASE64 }}
DBP_AGENT_RELEASE_PROVISION_PROFILE_BASE64: ${{ secrets.DBP_AGENT_RELEASE_PROVISION_PROFILE_BASE64 }}
DBP_AGENT_REVIEW_PROVISION_PROFILE_BASE64: ${{ secrets.DBP_AGENT_REVIEW_PROVISION_PROFILE_BASE64 }}
NETP_SYSEX_RELEASE_PROVISION_PROFILE_BASE64: ${{ secrets.NETP_SYSEX_RELEASE_PROVISION_PROFILE_BASE64_V2 }}
NETP_SYSEX_REVIEW_PROVISION_PROFILE_BASE64: ${{ secrets.NETP_SYSEX_REVIEW_PROVISION_PROFILE_BASE64_V2 }}
NETP_AGENT_RELEASE_PROVISION_PROFILE_BASE64: ${{ secrets.NETP_AGENT_RELEASE_PROVISION_PROFILE_BASE64_V2 }}
NETP_AGENT_REVIEW_PROVISION_PROFILE_BASE64: ${{ secrets.NETP_AGENT_REVIEW_PROVISION_PROFILE_BASE64_V2 }}
NETP_NOTIFICATIONS_RELEASE_PROVISION_PROFILE_BASE64: ${{ secrets.NETP_NOTIFICATIONS_RELEASE_PROVISION_PROFILE_BASE64 }}
NETP_NOTIFICATIONS_REVIEW_PROVISION_PROFILE_BASE64: ${{ secrets.NETP_NOTIFICATIONS_REVIEW_PROVISION_PROFILE_BASE64 }}

- name: Set up variant
working-directory: ${{ github.workspace }}/dmg
run: |
codesign -d --entitlements :- DuckDuckGo.app > entitlements.plist
echo "${{ env.ATB_VARIANT_NAME }}" > "DuckDuckGo.app/Contents/Resources/variant.txt"
echo "${{ env.ORIGIN_VARIANT_NAME }}" > "DuckDuckGo.app/Contents/Resources/Origin.txt"
sign_identity="$(security find-certificate -a -c "Developer ID Application" -Z | grep ^SHA-1 | cut -d " " -f3 | uniq)"
/usr/bin/codesign \
--force \
--sign ${sign_identity} \
--options runtime \
--entitlements entitlements.plist \
--generate-entitlement-der "DuckDuckGo.app"
rm -f entitlements.plist
- name: Notarize the app
env:
APPLE_API_KEY_BASE64: ${{ secrets.APPLE_API_KEY_BASE64 }}
APPLE_API_KEY_ID: ${{ secrets.APPLE_API_KEY_ID }}
APPLE_API_KEY_ISSUER: ${{ secrets.APPLE_API_KEY_ISSUER }}
working-directory: ${{ github.workspace }}/dmg
run: |
# import API Key from secrets
export APPLE_API_KEY_PATH="$RUNNER_TEMP/apple_api_key.pem"
echo -n "$APPLE_API_KEY_BASE64" | base64 --decode -o $APPLE_API_KEY_PATH
notarization_zip_path="DuckDuckGo-for-notarization.zip"
ditto -c -k --keepParent "DuckDuckGo.app" "${notarization_zip_path}"
xcrun notarytool submit \
--key "${APPLE_API_KEY_PATH}" \
--key-id "${{ env.APPLE_API_KEY_ID }}" \
--issuer "${{ env.APPLE_API_KEY_ISSUER }}" \
--wait \
"${notarization_zip_path}"
xcrun stapler staple "DuckDuckGo.app"
rm -rf "${notarization_zip_path}"
- name: Create variant DMG
env:
GH_TOKEN: ${{ github.token }}
run: |
retries=3
while [[ $retries -gt 0 ]]; do
if create-dmg --volname "DuckDuckGo" \
--icon "DuckDuckGo.app" 140 160 \
--background "scripts/assets/dmg-background.png" \
--window-size 600 400 \
--icon-size 120 \
--app-drop-link 430 160 "duckduckgo.dmg" \
"dmg"
then
break
fi
retries=$((retries-1))
done
- name: Set variant name
id: set-variant-name
run: |
if [ -z "$ORIGIN_VARIANT_NAME" ] && [ -n "$ATB_VARIANT_NAME" ]; then
name=$ATB_VARIANT_NAME
elif [ -n "$ORIGIN_VARIANT_NAME" ] && [ -z "$ATB_VARIANT_NAME" ]; then
name=$ORIGIN_VARIANT_NAME
elif [ -n "$ORIGIN_VARIANT_NAME" ] && [ -n "$ATB_VARIANT_NAME" ]; then
name="${ORIGIN_VARIANT_NAME}-${ATB_VARIANT_NAME}"
else
echo "Neither ATB_VARIANT_NAME nor ORIGIN_VARIANT_NAME is set"
exit 1
fi
echo "variant-name=${name}" >> "$GITHUB_OUTPUT"
- name: Upload variant DMG
env:
AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID_RELEASE_S3 }}
AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY_RELEASE_S3 }}
AWS_DEFAULT_REGION: ${{ vars.AWS_DEFAULT_REGION }}
run: |
aws s3 cp duckduckgo.dmg \
s3://${{ vars.RELEASE_BUCKET_NAME }}/${{ vars.RELEASE_BUCKET_PREFIX }}/${{ steps.set-variant-name.outputs.variant-name }}/duckduckgo.dmg \
--acl public-read
Loading

0 comments on commit 98bdfb5

Please sign in to comment.