diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index a133fe94f..92cec8527 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -9,474 +9,23 @@ on: paths-ignore: - ".github/workflows/**" workflow_dispatch: + inputs: {} jobs: - cloc: - name: CLOC - runs-on: ubuntu-22.04 - steps: - - name: Checkout repo - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 - - - name: Set up CLOC - run: | - sudo apt-get update - sudo apt-get -y install cloc - - - name: Print lines of code - run: cloc --vcs git --exclude-dir Resources,store,test,Properties --include-lang C#,XAML - - - setup: - name: Setup - runs-on: ubuntu-22.04 - outputs: - rc_branch_exists: ${{ steps.branch-check.outputs.rc_branch_exists }} - hotfix_branch_exists: ${{ steps.branch-check.outputs.hotfix_branch_exists }} - steps: - - name: Checkout repo - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 - with: - submodules: 'true' - - - name: Check if special branches exist - id: branch-check - run: | - if [[ $(git ls-remote --heads origin rc) ]]; then - echo "rc_branch_exists=1" >> $GITHUB_OUTPUT - else - echo "rc_branch_exists=0" >> $GITHUB_OUTPUT - fi - - if [[ $(git ls-remote --heads origin hotfix-rc) ]]; then - echo "hotfix_branch_exists=1" >> $GITHUB_OUTPUT - else - echo "hotfix_branch_exists=0" >> $GITHUB_OUTPUT - fi - - - android: - name: Android - runs-on: windows-2022 - needs: setup - strategy: - fail-fast: false - matrix: - variant: ["prod", "qa"] - steps: - - name: Setup NuGet - uses: nuget/setup-nuget@296fd3ccf8528660c91106efefe2364482f86d6f # v1.2.0 - with: - nuget-version: 5.9.0 - - - name: Set up .NET - uses: actions/setup-dotnet@4d6c8fcf3c8f7a60068d26b594648e99df24cee3 # v4.0.0 - with: - dotnet-version: '3.1.x' - - - name: Set up MSBuild - uses: microsoft/setup-msbuild@031090342aeefe171e49f3820f3b52110c66e402 # v1.3.2 - - - name: Setup Windows builder - run: choco install checksum --no-progress - - - name: Install Microsoft OpenJDK 11 - run: | - choco install microsoft-openjdk11 --no-progress - Write-Output "JAVA_HOME=$(Get-ChildItem -Path 'C:\Program Files\Microsoft\jdk*' | Select -First 1 -ExpandProperty FullName)" | Out-File -FilePath $env:GITHUB_ENV -Encoding utf8 -Append - Write-Output "Java Home: $env:JAVA_HOME" - - - name: Print environment - run: | - nuget help | grep Version - msbuild -version - dotnet --info - echo "GitHub ref: $GITHUB_REF" - echo "GitHub event: $GITHUB_EVENT" - - - name: Checkout repo - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 - with: - fetch-depth: 0 - - - name: Decrypt secrets - env: - DECRYPT_FILE_PASSWORD: ${{ secrets.DECRYPT_FILE_PASSWORD }} - run: | - mkdir -p ~/secrets - - gpg --quiet --batch --yes --decrypt --passphrase="$DECRYPT_FILE_PASSWORD" \ - --output ./src/Android/app_play-keystore.jks ./.github/secrets/app_play-keystore.jks.gpg - gpg --quiet --batch --yes --decrypt --passphrase="$DECRYPT_FILE_PASSWORD" \ - --output ./src/Android/app_upload-keystore.jks ./.github/secrets/app_upload-keystore.jks.gpg - gpg --quiet --batch --yes --decrypt --passphrase="$DECRYPT_FILE_PASSWORD" \ - --output $HOME/secrets/play_creds.json ./.github/secrets/play_creds.json.gpg - shell: bash - - - name: Decrypt secrets - Google Services - if: ${{ matrix.variant == 'prod' }} - env: - DECRYPT_FILE_PASSWORD: ${{ secrets.DECRYPT_FILE_PASSWORD }} - run: | - gpg --quiet --batch --yes --decrypt --passphrase="$DECRYPT_FILE_PASSWORD" \ - --output ./src/Android/google-services.json ./.github/secrets/google-services.json.gpg - shell: bash - - - name: Increment version - run: | - BUILD_NUMBER=$((3000 + $GITHUB_RUN_NUMBER)) - - echo "########################################" - echo "##### Setting Version Code $BUILD_NUMBER" - echo "########################################" - - sed -i "s/android:versionCode=\"1\"/android:versionCode=\"$BUILD_NUMBER\"/" \ - ./src/Android/Properties/AndroidManifest.xml - shell: bash - - - name: Restore packages - run: nuget restore - - - name: Restore tools - run: dotnet tool restore - - - name: Verify Format - run: dotnet tool run dotnet-format --check - - - name: Run Core tests - run: dotnet test test/Core.Test/Core.Test.csproj --logger "trx;LogFileName=test-results.trx" - - - name: Report test results - uses: dorny/test-reporter@eaa763f6ffc21c7a37837f56cd5f9737f27fc6c8 # v1.8.0 - if: always() - with: - name: Test Results - path: "**/test-results.trx" - reporter: dotnet-trx - fail-on-error: true - - - name: Build Play Store publisher - if: ${{ matrix.variant == 'prod' }} - run: dotnet build ./store/google/Publisher/Publisher.csproj -p:Configuration=Release - - - name: Setup Android build (${{ matrix.variant }}) - run: dotnet cake build.cake --target Android --variant ${{ matrix.variant }} - - - name: Build Android - run: | - $configuration = "Release"; - - Write-Output "########################################" - Write-Output "##### Build $configuration Configuration" - Write-Output "########################################" - msbuild "$($env:GITHUB_WORKSPACE + "/src/Android/Android.csproj")" "/p:Configuration=$configuration" - - - name: Sign Android Build - env: - PLAY_KEYSTORE_PASSWORD: ${{ secrets.PLAY_KEYSTORE_PASSWORD }} - UPLOAD_KEYSTORE_PASSWORD: ${{ secrets.UPLOAD_KEYSTORE_PASSWORD }} - run: | - $androidPath = $($env:GITHUB_WORKSPACE + "/src/Android/Android.csproj"); - $packageName = "com.x8bit.bitwarden"; - - if ("${{ matrix.variant }}" -ne "prod") - { - $packageName = "com.x8bit.bitwarden.${{ matrix.variant }}"; - } - Write-Output "########################################" - Write-Output "##### Sign Google Play Bundle Release Configuration" - Write-Output "########################################" - - msbuild "$($androidPath)" "/t:SignAndroidPackage" "/p:Configuration=Release" "/p:AndroidKeyStore=true" ` - "/p:AndroidSigningKeyAlias=upload" "/p:AndroidSigningKeyPass=$($env:UPLOAD_KEYSTORE_PASSWORD)" ` - "/p:AndroidSigningKeyStore=$("app_upload-keystore.jks")" ` - "/p:AndroidSigningStorePass=$($env:UPLOAD_KEYSTORE_PASSWORD)" "/p:AndroidPackageFormat=aab" "/v:quiet" - - Write-Output "########################################" - Write-Output "##### Copy Google Play Bundle to project root" - Write-Output "########################################" - - $signedAabPath = $($env:GITHUB_WORKSPACE + "/src/Android/bin/Release/$($packageName)-Signed.aab"); - $signedAabDestPath = $($env:GITHUB_WORKSPACE + "/$($packageName).aab"); - Copy-Item $signedAabPath $signedAabDestPath - - Write-Output "########################################" - Write-Output "##### Sign APK Release Configuration" - Write-Output "########################################" - - msbuild "$($androidPath)" "/t:SignAndroidPackage" "/p:Configuration=Release" "/p:AndroidKeyStore=true" ` - "/p:AndroidSigningKeyAlias=bitwarden" "/p:AndroidSigningKeyPass=$($env:PLAY_KEYSTORE_PASSWORD)" ` - "/p:AndroidSigningKeyStore=$("app_play-keystore.jks")" ` - "/p:AndroidSigningStorePass=$($env:PLAY_KEYSTORE_PASSWORD)" "/v:quiet" - - Write-Output "########################################" - Write-Output "##### Copy Release APK to project root" - Write-Output "########################################" - - $signedApkPath = $($env:GITHUB_WORKSPACE + "/src/Android/bin/Release/$($packageName)-Signed.apk"); - $signedApkDestPath = $($env:GITHUB_WORKSPACE + "/$($packageName).apk"); - - Copy-Item $signedApkPath $signedApkDestPath - - - name: Upload Prod .aab artifact - if: ${{ matrix.variant == 'prod' }} - uses: actions/upload-artifact@26f96dfa697d77e81fd5907df203aa23a56210a8 # v4.3.0 - with: - name: com.x8bit.bitwarden.aab - path: ./com.x8bit.bitwarden.aab - if-no-files-found: error - - - name: Upload Prod .apk artifact - if: ${{ matrix.variant == 'prod' }} - uses: actions/upload-artifact@26f96dfa697d77e81fd5907df203aa23a56210a8 # v4.3.0 - with: - name: com.x8bit.bitwarden.apk - path: ./com.x8bit.bitwarden.apk - if-no-files-found: error - - - name: Upload Other .apk artifact - if: ${{ matrix.variant != 'prod' }} - uses: actions/upload-artifact@26f96dfa697d77e81fd5907df203aa23a56210a8 # v4.3.0 - with: - name: com.x8bit.bitwarden.${{ matrix.variant }}.apk - path: ./com.x8bit.bitwarden.${{ matrix.variant }}.apk - if-no-files-found: error - - - name: Create checksum for Prod .apk artifact - if: ${{ matrix.variant == 'prod' }} - run: | - checksum -f="./com.x8bit.bitwarden.apk" ` - -t sha256 | Out-File -Encoding ASCII ./bw-android-apk-sha256.txt - - - name: Create checksum for Other .apk artifact - if: ${{ matrix.variant != 'prod' }} - run: | - checksum -f="./com.x8bit.bitwarden.${{ matrix.variant }}.apk" ` - -t sha256 | Out-File -Encoding ASCII ./bw-android-${{ matrix.variant }}-apk-sha256.txt - - - name: Upload .apk sha file for prod - if: ${{ matrix.variant == 'prod' }} - uses: actions/upload-artifact@26f96dfa697d77e81fd5907df203aa23a56210a8 # v4.3.0 - with: - name: bw-android-apk-sha256.txt - path: ./bw-android-apk-sha256.txt - if-no-files-found: error - - - name: Upload .apk sha file for other - if: ${{ matrix.variant != 'prod' }} - uses: actions/upload-artifact@26f96dfa697d77e81fd5907df203aa23a56210a8 # v4.3.0 - with: - name: bw-android-${{ matrix.variant }}-apk-sha256.txt - path: ./bw-android-${{ matrix.variant }}-apk-sha256.txt - if-no-files-found: error - - - name: Deploy to Play Store - if: ${{ matrix.variant == 'prod' && (( github.ref == 'refs/heads/main' - && needs.setup.outputs.rc_branch_exists == 0 - && needs.setup.outputs.hotfix_branch_exists == 0) - || (github.ref == 'refs/heads/rc' && needs.setup.outputs.hotfix_branch_exists == 0) - || github.ref == 'refs/heads/hotfix-rc' ) }} - run: | - PUBLISHER_PATH="$GITHUB_WORKSPACE/store/google/Publisher/bin/Release/netcoreapp3.1/Publisher.dll" - CREDS_PATH="$HOME/secrets/play_creds.json" - AAB_PATH="$GITHUB_WORKSPACE/com.x8bit.bitwarden.aab" - TRACK="internal" - - dotnet $PUBLISHER_PATH $CREDS_PATH $AAB_PATH $TRACK - shell: bash - - - f-droid: - name: F-Droid Build - runs-on: windows-2022 - steps: - - name: Setup NuGet - uses: nuget/setup-nuget@296fd3ccf8528660c91106efefe2364482f86d6f # v1.2.0 - with: - nuget-version: 5.9.0 - - - name: Set up MSBuild - uses: microsoft/setup-msbuild@031090342aeefe171e49f3820f3b52110c66e402 # v1.3.2 - - - name: Setup Windows builder - run: choco install checksum --no-progress - - - name: Install Microsoft OpenJDK 11 - run: | - choco install microsoft-openjdk11 --no-progress - Write-Output "JAVA_HOME=$(Get-ChildItem -Path 'C:\Program Files\Microsoft\jdk*' | Select -First 1 -ExpandProperty FullName)" | Out-File -FilePath $env:GITHUB_ENV -Encoding utf8 -Append - Write-Output "Java Home: $env:JAVA_HOME" - - - name: Print environment - run: | - nuget help | grep Version - msbuild -version - dotnet --info - echo "GitHub ref: $GITHUB_REF" - echo "GitHub event: $GITHUB_EVENT" - - - name: Checkout repo - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 - - - name: Decrypt secrets - env: - DECRYPT_FILE_PASSWORD: ${{ secrets.DECRYPT_FILE_PASSWORD }} - run: | - mkdir -p ~/secrets - - gpg --quiet --batch --yes --decrypt --passphrase="$DECRYPT_FILE_PASSWORD" \ - --output ./src/Android/app_fdroid-keystore.jks ./.github/secrets/app_fdroid-keystore.jks.gpg - shell: bash - - - name: Increment version - run: | - BUILD_NUMBER=$((3000 + $GITHUB_RUN_NUMBER)) - - echo "########################################" - echo "##### Setting Version Code $BUILD_NUMBER" - echo "########################################" - - sed -i "s/android:versionCode=\"1\"/android:versionCode=\"$BUILD_NUMBER\"/" \ - ./src/Android/Properties/AndroidManifest.xml - shell: bash - - - name: Clean for F-Droid - run: | - $androidPath = $($env:GITHUB_WORKSPACE + "/src/Android/Android.csproj"); - $appPath = $($env:GITHUB_WORKSPACE + "/src/App/App.csproj"); - $corePath = $($env:GITHUB_WORKSPACE + "/src/Core/Core.csproj"); - - $androidManifest = $($env:GITHUB_WORKSPACE + "/src/Android/Properties/AndroidManifest.xml"); - - Write-Output "########################################" - Write-Output "##### Clean Android and App" - Write-Output "########################################" - - msbuild "$($androidPath)" "/t:Clean" "/p:Configuration=FDroid" - msbuild "$($appPath)" "/t:Clean" "/p:Configuration=FDroid" - - Write-Output "########################################" - Write-Output "##### Backup project files" - Write-Output "########################################" - - Copy-Item $androidManifest $($androidManifest + ".original"); - Copy-Item $androidPath $($androidPath + ".original"); - Copy-Item $appPath $($appPath + ".original"); - - Write-Output "########################################" - Write-Output "##### Cleanup Android Manifest" - Write-Output "########################################" - - $xml=New-Object XML; - $xml.Load($androidManifest); - - $nsAndroid=New-Object System.Xml.XmlNamespaceManager($xml.NameTable); - $nsAndroid.AddNamespace("android", "http://schemas.android.com/apk/res/android"); - - $xml.Save($androidManifest); - - Write-Output "########################################" - Write-Output "##### Uninstall from Android.csproj" - Write-Output "########################################" - - $xml=New-Object XML; - $xml.Load($androidPath); - - $ns=New-Object System.Xml.XmlNamespaceManager($xml.NameTable); - $ns.AddNamespace("ns", $xml.DocumentElement.NamespaceURI); - - $firebaseNode=$xml.SelectSingleNode(` - "/ns:Project/ns:ItemGroup/ns:PackageReference[@Include='Xamarin.Firebase.Messaging']", $ns); - $firebaseNode.ParentNode.RemoveChild($firebaseNode); - - $daggerNode=$xml.SelectSingleNode(` - "/ns:Project/ns:ItemGroup/ns:PackageReference[@Include='Xamarin.Google.Dagger']", $ns); - $daggerNode.ParentNode.RemoveChild($daggerNode); - - $safetyNetNode=$xml.SelectSingleNode(` - "/ns:Project/ns:ItemGroup/ns:PackageReference[@Include='Xamarin.GooglePlayServices.SafetyNet']", $ns); - $safetyNetNode.ParentNode.RemoveChild($safetyNetNode); - - $xml.Save($androidPath); - - Write-Output "########################################" - Write-Output "##### Uninstall from Core.csproj" - Write-Output "########################################" - - $xml=New-Object XML; - $xml.Load($corePath); - - $appCenterNode=$xml.SelectSingleNode("/Project/ItemGroup/PackageReference[@Include='Microsoft.AppCenter.Crashes']"); - $appCenterNode.ParentNode.RemoveChild($appCenterNode); - - $xml.Save($corePath); - - - name: Restore packages - run: nuget restore - - - name: Build for F-Droid - run: | - $configuration = "FDroid"; - - Write-Output "########################################" - Write-Output "##### Build $configuration Configuration" - Write-Output "########################################" - - msbuild "$($env:GITHUB_WORKSPACE + "/src/Android/Android.csproj")" "/p:Configuration=$configuration" - - - name: Sign for F-Droid - env: - FDROID_KEYSTORE_PASSWORD: ${{ secrets.FDROID_KEYSTORE_PASSWORD }} - run: | - Write-Output "########################################" - Write-Output "##### Sign FDroid Configuration" - Write-Output "########################################" - - msbuild "$($env:GITHUB_WORKSPACE + "/src/Android/Android.csproj")" ` - "/t:SignAndroidPackage" "/p:Configuration=FDroid" "/p:AndroidKeyStore=true" ` - "/p:AndroidSigningKeyAlias=bitwarden" "/p:AndroidSigningKeyPass=$($env:FDROID_KEYSTORE_PASSWORD)" ` - "/p:AndroidSigningKeyStore=$("app_fdroid-keystore.jks")" ` - "/p:AndroidSigningStorePass=$($env:FDROID_KEYSTORE_PASSWORD)" "/v:quiet" - - Write-Output "########################################" - Write-Output "##### Copy FDroid apk to project root" - Write-Output "########################################" - - $signedApkPath = $($env:GITHUB_WORKSPACE + "/src/Android/bin/FDroid/com.x8bit.bitwarden-Signed.apk"); - $signedApkDestPath = $($env:GITHUB_WORKSPACE + "/com.x8bit.bitwarden-fdroid.apk"); - - Copy-Item $signedApkPath $signedApkDestPath - - - name: Upload F-Droid .apk artifact - uses: actions/upload-artifact@26f96dfa697d77e81fd5907df203aa23a56210a8 # v4.3.0 - with: - name: com.x8bit.bitwarden-fdroid.apk - path: ./com.x8bit.bitwarden-fdroid.apk - if-no-files-found: error - - - name: Create checksum for F-Droid artifact - run: | - checksum -f="./com.x8bit.bitwarden-fdroid.apk" ` - -t sha256 | Out-File -Encoding ASCII ./bw-fdroid-apk-sha256.txt - - - name: Upload F-Droid sha file - uses: actions/upload-artifact@26f96dfa697d77e81fd5907df203aa23a56210a8 # v4.3.0 - with: - name: bw-fdroid-apk-sha256.txt - path: ./bw-fdroid-apk-sha256.txt - if-no-files-found: error - - ios: name: Apple iOS - runs-on: macos-12 - needs: setup + runs-on: macos-13 steps: - name: Setup NuGet uses: nuget/setup-nuget@296fd3ccf8528660c91106efefe2364482f86d6f # v1.2.0 with: nuget-version: 5.9.0 + - name: Install Xamarin + run: | + brew install --cask xamarin-ios + brew install --cask xamarin-android + - name: Print environment run: | nuget help | grep Version @@ -486,12 +35,12 @@ jobs: echo "GitHub event: $GITHUB_EVENT" - name: Checkout repo - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 + uses: actions/checkout@ac593985615ec2ede58e132d2e21d2b1cbd6127c # v3.3.0 with: submodules: 'true' - name: Login to Azure - CI Subscription - uses: Azure/login@e15b166166a8746d1a47596803bd8c1b595455cf # v1.6.0 + uses: Azure/login@92a5484dfaf04ca78a94597f4f19fea633851fa2 # v1.4.6 with: creds: ${{ secrets.AZURE_KV_CI_SERVICE_PRINCIPAL }} @@ -502,33 +51,40 @@ jobs: keyvault: "bitwarden-ci" secrets: "appcenter-ios-token" - - name: Decrypt secrets + - name: Download Provisioning Profiles secrets env: - DECRYPT_FILE_PASSWORD: ${{ secrets.DECRYPT_FILE_PASSWORD }} + ACCOUNT_NAME: bitwardenci + CONTAINER_NAME: profiles run: | - mkdir -p ~/secrets + mkdir -p $HOME/secrets + profiles=( + "dist_autofill.mobileprovision" + "dist_bitwarden.mobileprovision" + "dist_extension.mobileprovision" + "dist_share_extension.mobileprovision" + "dist_bitwarden_watch_app.mobileprovision" + "dist_bitwarden_watch_app_extension.mobileprovision" + ) - gpg --quiet --batch --yes --decrypt --passphrase="$DECRYPT_FILE_PASSWORD" \ - --output $HOME/secrets/bitwarden-mobile-key.p12 ./.github/secrets/bitwarden-mobile-key.p12.gpg - gpg --quiet --batch --yes --decrypt --passphrase="$DECRYPT_FILE_PASSWORD" \ - --output $HOME/secrets/iphone-distribution-cert.p12 ./.github/secrets/iphone-distribution-cert.p12.gpg - gpg --quiet --batch --yes --decrypt --passphrase="$DECRYPT_FILE_PASSWORD" \ - --output $HOME/secrets/dist_autofill.mobileprovision ./.github/secrets/dist_autofill.mobileprovision.gpg - gpg --quiet --batch --yes --decrypt --passphrase="$DECRYPT_FILE_PASSWORD" \ - --output $HOME/secrets/dist_bitwarden.mobileprovision ./.github/secrets/dist_bitwarden.mobileprovision.gpg - gpg --quiet --batch --yes --decrypt --passphrase="$DECRYPT_FILE_PASSWORD" \ - --output $HOME/secrets/dist_extension.mobileprovision ./.github/secrets/dist_extension.mobileprovision.gpg - gpg --quiet --batch --yes --decrypt --passphrase="$DECRYPT_FILE_PASSWORD" \ - --output $HOME/secrets/dist_share_extension.mobileprovision \ - ./.github/secrets/dist_share_extension.mobileprovision.gpg - gpg --quiet --batch --yes --decrypt --passphrase="$DECRYPT_FILE_PASSWORD" \ - --output $HOME/secrets/dist_watch_app.mobileprovision \ - ./.github/secrets/dist_watch_app.mobileprovision.gpg - gpg --quiet --batch --yes --decrypt --passphrase="$DECRYPT_FILE_PASSWORD" \ - --output $HOME/secrets/dist_watch_app_extension.mobileprovision \ - ./.github/secrets/dist_watch_app_extension.mobileprovision.gpg - gpg --quiet --batch --yes --decrypt --passphrase="$DECRYPT_FILE_PASSWORD" \ - --output ./src/watchOS/bitwarden/GoogleService-Info.plist ./.github/secrets/GoogleService-Info.plist.gpg + for FILE in "${profiles[@]}" + do + az storage blob download --account-name $ACCOUNT_NAME --container-name $CONTAINER_NAME --name $FILE \ + --file $HOME/secrets/$FILE --output none + done + + cd $HOME/secrets + mv dist_bitwarden_watch_app.mobileprovision dist_watch_app.mobileprovision + mv dist_bitwarden_watch_app_extension.mobileprovision dist_watch_app_extension.mobileprovision + + - name: Download Google Services secret + env: + ACCOUNT_NAME: bitwardenci + CONTAINER_NAME: mobile + FILE: GoogleService-Info.plist + run: | + mkdir -p $HOME/secrets + az storage blob download --account-name $ACCOUNT_NAME --container-name $CONTAINER_NAME --name $FILE \ + --file src/watchOS/bitwarden/$FILE --output none - name: Increment version run: | @@ -544,6 +100,8 @@ jobs: perl -0777 -pi.bak -e 's/CFBundleVersion<\/key>\s*1<\/string>/CFBundleVersion<\/key>\n\t'"$BUILD_NUMBER"'<\/string>/' ./src/iOS.ShareExtension/Info.plist cd src/watchOS/bitwarden agvtool new-version -all $BUILD_NUMBER + cd ../../.. + shell: bash - name: Update Entitlements run: | @@ -552,22 +110,29 @@ jobs: echo "########################################" perl -0777 -pi.bak -e 's/aps-environment<\/key>\s*development<\/string>/aps-environment<\/key>\n\tproduction<\/string>/' ./src/iOS/Entitlements.plist + shell: bash + + - name: Get certificates + run: | + mkdir -p $HOME/certificates + az keyvault secret show --id https://bitwarden-ci.vault.azure.net/certificates/ios-distribution | + jq -r .value | base64 -d > $HOME/certificates/ios-distribution.p12 + + cd $HOME/certificates + mv ios-distribution.p12 $HOME/secrets/iphone-distribution-cert.p12 - name: Set up Keychain env: KEYCHAIN_PASSWORD: ${{ secrets.IOS_KEYCHAIN_PASSWORD }} - MOBILE_KEY_PASSWORD: ${{ secrets.IOS_KEY_PASSWORD }} - DIST_CERT_PASSWORD: ${{ secrets.IOS_DIST_CERT_PASSWORD }} run: | security create-keychain -p $KEYCHAIN_PASSWORD build.keychain security default-keychain -s build.keychain security unlock-keychain -p $KEYCHAIN_PASSWORD build.keychain security set-keychain-settings -lut 1200 build.keychain - security import ~/secrets/bitwarden-mobile-key.p12 -k build.keychain -P $MOBILE_KEY_PASSWORD \ - -T /usr/bin/codesign -T /usr/bin/security - security import ~/secrets/iphone-distribution-cert.p12 -k build.keychain -P $DIST_CERT_PASSWORD \ + security import ~/secrets/iphone-distribution-cert.p12 -k build.keychain -P "" \ -T /usr/bin/codesign -T /usr/bin/security security set-key-partition-list -S apple-tool:,apple:,codesign: -s -k $KEYCHAIN_PASSWORD build.keychain + shell: bash - name: Set up provisioning profiles run: | @@ -598,6 +163,7 @@ jobs: WATCH_APP_EXTENSION_UUID=$(grep UUID -A1 -a $WATCH_APP_EXTENSION_PROFILE_PATH | grep -io "[-A-F0-9]\{36\}") cp $WATCH_APP_EXTENSION_PROFILE_PATH "$PROFILES_DIR_PATH/$WATCH_APP_EXTENSION_UUID.mobileprovision" + shell: bash - name: Bulid WatchApp run: | @@ -610,6 +176,7 @@ jobs: echo "########################################" echo "##### Done" echo "########################################" + shell: bash - name: Restore packages run: nuget restore @@ -655,6 +222,7 @@ jobs: xcodebuild -exportArchive -archivePath $ARCHIVE_PATH -exportPath $EXPORT_PATH \ -exportOptionsPlist $EXPORT_OPTIONS_PATH + shell: bash - name: Export .app for Automation CI run: | @@ -663,6 +231,7 @@ jobs: zip -r -q BitwardeniOS.app.zip $ARCHIVE_PATH mv BitwardeniOS.app.zip $EXPORT_PATH + shell: bash - name: Copy all dSYMs files to upload run: | @@ -675,9 +244,10 @@ jobs: cp -r -v $ARCHIVE_DSYMS_PATH $EXPORT_PATH mkdir $WATCH_DSYMS_EXPORT_PATH cp -r -v $WATCH_ARCHIVE_DSYMS_PATH $WATCH_DSYMS_EXPORT_PATH + shell: bash - name: Upload App Store .ipa & dSYMs artifacts - uses: actions/upload-artifact@26f96dfa697d77e81fd5907df203aa23a56210a8 # v4.3.0 + uses: actions/upload-artifact@65462800fd760344b1a7b4382951275a0abb4808 # v4.3.3 with: name: Bitwarden iOS path: | @@ -686,152 +256,36 @@ jobs: if-no-files-found: error - name: Upload .app file for Automation CI - uses: actions/upload-artifact@26f96dfa697d77e81fd5907df203aa23a56210a8 # v4.3.0 + uses: actions/upload-artifact@6673cd052c4cd6fcf4b4e6e60ea986c889389535 # v3.0.0 with: name: BitwardeniOS.app.zip path: ./bitwarden-export/BitwardeniOS.app.zip if-no-files-found: error - name: Install AppCenter CLI - if: | - (github.ref == 'refs/heads/main' - && needs.setup.outputs.rc_branch_exists == 0 - && needs.setup.outputs.hotfix_branch_exists == 0) - || (github.ref == 'refs/heads/rc' && needs.setup.outputs.hotfix_branch_exists == 0) - || github.ref == 'refs/heads/hotfix-rc' run: npm install -g appcenter-cli - name: Upload dSYMs to App Center - if: | - (github.ref == 'refs/heads/main' - && needs.setup.outputs.rc_branch_exists == 0 - && needs.setup.outputs.hotfix_branch_exists == 0) - || (github.ref == 'refs/heads/rc' && needs.setup.outputs.hotfix_branch_exists == 0) - || github.ref == 'refs/heads/hotfix-rc' env: APPCENTER_IOS_TOKEN: ${{ steps.retrieve-secrets.outputs.appcenter-ios-token }} run: appcenter crashes upload-symbols -a bitwarden/bitwarden -s "./bitwarden-export/dSYMs" --token $APPCENTER_IOS_TOKEN + shell: bash - name: Upload Watch dSYMs to Firebase Crashlytics - if: | - (github.ref == 'refs/heads/main' - && needs.setup.outputs.rc_branch_exists == 0 - && needs.setup.outputs.hotfix_branch_exists == 0) - || (github.ref == 'refs/heads/rc' && needs.setup.outputs.hotfix_branch_exists == 0) - || github.ref == 'refs/heads/hotfix-rc' run: | + echo "########################################" echo "##### Uploading Watch dSYMs to Firebase" echo "########################################" find "$HOME/Library/Developer/XCode/DerivedData" -name "upload-symbols" -exec chmod +x {} \; -exec {} -gsp "./src/watchOS/bitwarden/GoogleService-Info.plist" -p ios "./bitwarden-export/Watch_dSYMs" \; + shell: bash - name: Deploy to App Store - if: | - (github.ref == 'refs/heads/main' - && needs.setup.outputs.rc_branch_exists == 0 - && needs.setup.outputs.hotfix_branch_exists == 0) - || (github.ref == 'refs/heads/rc' && needs.setup.outputs.hotfix_branch_exists == 0) - || github.ref == 'refs/heads/hotfix-rc' env: APPLE_ID_USERNAME: ${{ secrets.APPLE_ID_USERNAME }} APPLE_ID_PASSWORD: ${{ secrets.APPLE_ID_PASSWORD }} run: | xcrun altool --upload-app --type ios --file "./bitwarden-export/Bitwarden.ipa" \ --username "$APPLE_ID_USERNAME" --password "$APPLE_ID_PASSWORD" - - - crowdin-push: - name: Crowdin Push - if: github.ref == 'refs/heads/main' - needs: - - android - - f-droid - - ios - runs-on: ubuntu-22.04 - env: - _CROWDIN_PROJECT_ID: "269690" - steps: - - name: Checkout repo - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 - - - name: Login to Azure - CI Subscription - uses: Azure/login@e15b166166a8746d1a47596803bd8c1b595455cf # v1.6.0 - with: - creds: ${{ secrets.AZURE_KV_CI_SERVICE_PRINCIPAL }} - - - name: Retrieve secrets - id: retrieve-secrets - uses: bitwarden/gh-actions/get-keyvault-secrets@main - with: - keyvault: "bitwarden-ci" - secrets: "crowdin-api-token" - - - name: Upload Sources - uses: crowdin/github-action@6fb7e99759b996fd142995636fd8c88c1fb8ecd9 # v1.16.1 - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - CROWDIN_API_TOKEN: ${{ steps.retrieve-secrets.outputs.crowdin-api-token }} - with: - config: crowdin.yml - crowdin_branch_name: main - upload_sources: true - upload_translations: false - - - check-failures: - name: Check for failures - if: always() - runs-on: ubuntu-22.04 - needs: - - cloc - - android - - f-droid - - ios - - crowdin-push - steps: - - name: Check if any job failed - if: | - (github.ref == 'refs/heads/main') - || (github.ref == 'refs/heads/rc') - || (github.ref == 'refs/heads/hotfix-rc') - env: - CLOC_STATUS: ${{ needs.cloc.result }} - ANDROID_STATUS: ${{ needs.android.result }} - F_DROID_STATUS: ${{ needs.f-droid.result }} - IOS_STATUS: ${{ needs.ios.result }} - CROWDIN_PUSH_STATUS: ${{ needs.crowdin-push.result }} - run: | - if [ "$CLOC_STATUS" = "failure" ]; then - exit 1 - elif [ "$ANDROID_STATUS" = "failure" ]; then - exit 1 - elif [ "$F_DROID_STATUS" = "failure" ]; then - exit 1 - elif [ "$IOS_STATUS" = "failure" ]; then - exit 1 - elif [ "$CROWDIN_PUSH_STATUS" = "failure" ]; then - exit 1 - fi - - - name: Login to Azure - CI Subscription - uses: Azure/login@e15b166166a8746d1a47596803bd8c1b595455cf # v1.6.0 - if: failure() - with: - creds: ${{ secrets.AZURE_KV_CI_SERVICE_PRINCIPAL }} - - - name: Retrieve secrets - id: retrieve-secrets - uses: bitwarden/gh-actions/get-keyvault-secrets@main - if: failure() - with: - keyvault: "bitwarden-ci" - secrets: "devops-alerts-slack-webhook-url" - - - name: Notify Slack on failure - uses: act10ns/slack@ed1309ab9862e57e9e583e51c7889486b9a00b0f # v2.0.0 - if: failure() - env: - SLACK_WEBHOOK_URL: ${{ steps.retrieve-secrets.outputs.devops-alerts-slack-webhook-url }} - with: - status: ${{ job.status }} + shell: bash