AppResource #8
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
--- | |
name: Build | |
on: | |
push: | |
branches-ignore: | |
- "l10n_master" | |
- "gh-pages" | |
paths-ignore: | |
- ".github/workflows/**" | |
workflow_dispatch: | |
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 = "io.cozy.pass.mobile"; | |
if ("${{ matrix.variant }}" -ne "prod") | |
{ | |
$packageName = "io.cozy.pass.mobile.${{ 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: io.cozy.pass.mobile.aab | |
path: ./io.cozy.pass.mobile.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: io.cozy.pass.mobile.apk | |
path: ./io.cozy.pass.mobile.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: io.cozy.pass.mobile.${{ matrix.variant }}.apk | |
path: ./io.cozy.pass.mobile.${{ matrix.variant }}.apk | |
if-no-files-found: error | |
- name: Create checksum for Prod .apk artifact | |
if: ${{ matrix.variant == 'prod' }} | |
run: | | |
checksum -f="./io.cozy.pass.mobile.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="./io.cozy.pass.mobile.${{ 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/io.cozy.pass.mobile.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/io.cozy.pass.mobile-Signed.apk"); | |
$signedApkDestPath = $($env:GITHUB_WORKSPACE + "/io.cozy.pass.mobile-fdroid.apk"); | |
Copy-Item $signedApkPath $signedApkDestPath | |
- name: Upload F-Droid .apk artifact | |
uses: actions/upload-artifact@26f96dfa697d77e81fd5907df203aa23a56210a8 # v4.3.0 | |
with: | |
name: io.cozy.pass.mobile-fdroid.apk | |
path: ./io.cozy.pass.mobile-fdroid.apk | |
if-no-files-found: error | |
- name: Create checksum for F-Droid artifact | |
run: | | |
checksum -f="./io.cozy.pass.mobile-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 | |
steps: | |
- name: Setup NuGet | |
uses: nuget/setup-nuget@296fd3ccf8528660c91106efefe2364482f86d6f # v1.2.0 | |
with: | |
nuget-version: 5.9.0 | |
- 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: | |
submodules: 'true' | |
- 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: "appcenter-ios-token" | |
- 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 $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 | |
- name: Increment version | |
run: | | |
BUILD_NUMBER=$((100 + $GITHUB_RUN_NUMBER)) | |
echo "########################################" | |
echo "##### Setting CFBundleVersion $BUILD_NUMBER" | |
echo "########################################" | |
perl -0777 -pi.bak -e 's/<key>CFBundleVersion<\/key>\s*<string>1<\/string>/<key>CFBundleVersion<\/key>\n\t<string>'"$BUILD_NUMBER"'<\/string>/' ./src/iOS/Info.plist | |
perl -0777 -pi.bak -e 's/<key>CFBundleVersion<\/key>\s*<string>1<\/string>/<key>CFBundleVersion<\/key>\n\t<string>'"$BUILD_NUMBER"'<\/string>/' ./src/iOS.Extension/Info.plist | |
perl -0777 -pi.bak -e 's/<key>CFBundleVersion<\/key>\s*<string>1<\/string>/<key>CFBundleVersion<\/key>\n\t<string>'"$BUILD_NUMBER"'<\/string>/' ./src/iOS.Autofill/Info.plist | |
perl -0777 -pi.bak -e 's/<key>CFBundleVersion<\/key>\s*<string>1<\/string>/<key>CFBundleVersion<\/key>\n\t<string>'"$BUILD_NUMBER"'<\/string>/' ./src/iOS.ShareExtension/Info.plist | |
cd src/watchOS/bitwarden | |
agvtool new-version -all $BUILD_NUMBER | |
- name: Update Entitlements | |
run: | | |
echo "########################################" | |
echo "##### Updating Entitlements" | |
echo "########################################" | |
perl -0777 -pi.bak -e 's/<key>aps-environment<\/key>\s*<string>development<\/string>/<key>aps-environment<\/key>\n\t<string>production<\/string>/' ./src/iOS/Entitlements.plist | |
- 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 \ | |
-T /usr/bin/codesign -T /usr/bin/security | |
security set-key-partition-list -S apple-tool:,apple:,codesign: -s -k $KEYCHAIN_PASSWORD build.keychain | |
- name: Set up provisioning profiles | |
run: | | |
AUTOFILL_PROFILE_PATH=$HOME/secrets/dist_autofill.mobileprovision | |
BITWARDEN_PROFILE_PATH=$HOME/secrets/dist_bitwarden.mobileprovision | |
EXTENSION_PROFILE_PATH=$HOME/secrets/dist_extension.mobileprovision | |
SHARE_EXTENSION_PROFILE_PATH=$HOME/secrets/dist_share_extension.mobileprovision | |
WATCH_APP_PROFILE_PATH=$HOME/secrets/dist_watch_app.mobileprovision | |
WATCH_APP_EXTENSION_PROFILE_PATH=$HOME/secrets/dist_watch_app_extension.mobileprovision | |
PROFILES_DIR_PATH=$HOME/Library/MobileDevice/Provisioning\ Profiles | |
mkdir -p "$PROFILES_DIR_PATH" | |
AUTOFILL_UUID=$(grep UUID -A1 -a $AUTOFILL_PROFILE_PATH | grep -io "[-A-F0-9]\{36\}") | |
cp $AUTOFILL_PROFILE_PATH "$PROFILES_DIR_PATH/$AUTOFILL_UUID.mobileprovision" | |
BITWARDEN_UUID=$(grep UUID -A1 -a $BITWARDEN_PROFILE_PATH | grep -io "[-A-F0-9]\{36\}") | |
cp $BITWARDEN_PROFILE_PATH "$PROFILES_DIR_PATH/$BITWARDEN_UUID.mobileprovision" | |
EXTENSION_UUID=$(grep UUID -A1 -a $EXTENSION_PROFILE_PATH | grep -io "[-A-F0-9]\{36\}") | |
cp $EXTENSION_PROFILE_PATH "$PROFILES_DIR_PATH/$EXTENSION_UUID.mobileprovision" | |
SHARE_EXTENSION_UUID=$(grep UUID -A1 -a $SHARE_EXTENSION_PROFILE_PATH | grep -io "[-A-F0-9]\{36\}") | |
cp $SHARE_EXTENSION_PROFILE_PATH "$PROFILES_DIR_PATH/$SHARE_EXTENSION_UUID.mobileprovision" | |
WATCH_APP_UUID=$(grep UUID -A1 -a $WATCH_APP_PROFILE_PATH | grep -io "[-A-F0-9]\{36\}") | |
cp $WATCH_APP_PROFILE_PATH "$PROFILES_DIR_PATH/$WATCH_APP_UUID.mobileprovision" | |
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" | |
- name: Bulid WatchApp | |
run: | | |
echo "########################################" | |
echo "##### Build WatchApp with Release Configuration" | |
echo "########################################" | |
xcodebuild archive -workspace ./src/watchOS/bitwarden/bitwarden.xcodeproj/project.xcworkspace -configuration Release -scheme bitwarden\ WatchKit\ App -archivePath ./src/watchOS/bitwarden | |
echo "########################################" | |
echo "##### Done" | |
echo "########################################" | |
- name: Restore packages | |
run: nuget restore | |
- name: Archive Build for App Store | |
run: | | |
$configuration = "AppStore"; | |
$platform = "iPhone"; | |
Write-Output "########################################" | |
Write-Output "##### Archive $configuration Configuration for $platform Platform" | |
Write-Output "########################################" | |
msbuild "$($env:GITHUB_WORKSPACE + "/src/iOS/iOS.csproj")" "/p:Platform=$platform" ` | |
"/p:Configuration=$configuration" "/p:ArchiveOnBuild=true" "/t:`"Build`"" | |
Write-Output "########################################" | |
Write-Output "##### Done" | |
Write-Output "########################################" | |
shell: pwsh | |
- name: Archive Build for Mobile Automation | |
run: | | |
$configuration = "Release"; | |
$platform = "iPhoneSimulator"; | |
Write-Output "########################################" | |
Write-Output "##### Archive $configuration Configuration for $platform Platform" | |
Write-Output "########################################" | |
msbuild "$($env:GITHUB_WORKSPACE + "/src/iOS/iOS.csproj")" "/p:Platform=$platform" ` | |
"/p:Configuration=$configuration" "/p:ArchiveOnBuild=true" "/t:`"Build`"" | |
Write-Output "########################################" | |
Write-Output "##### Done" | |
Write-Output "########################################" | |
ls ~/Library/Developer/Xcode/Archives | |
shell: pwsh | |
- name: Export .ipa for App Store | |
run: | | |
EXPORT_OPTIONS_PATH="./.github/resources/export-options-app-store.plist" | |
ARCHIVE_PATH="$HOME/Library/Developer/Xcode/Archives/*/*.xcarchive" | |
EXPORT_PATH="./bitwarden-export" | |
xcodebuild -exportArchive -archivePath $ARCHIVE_PATH -exportPath $EXPORT_PATH \ | |
-exportOptionsPlist $EXPORT_OPTIONS_PATH | |
- name: Export .app for Automation CI | |
run: | | |
ARCHIVE_PATH="./src/iOS/bin/iPhoneSimulator/Release/BitwardeniOS.app" | |
EXPORT_PATH="./bitwarden-export" | |
zip -r -q BitwardeniOS.app.zip $ARCHIVE_PATH | |
mv BitwardeniOS.app.zip $EXPORT_PATH | |
- name: Copy all dSYMs files to upload | |
run: | | |
ARCHIVE_DSYMS_PATH="$HOME/Library/Developer/Xcode/Archives/*/*.xcarchive/dSYMs" | |
EXPORT_PATH="./bitwarden-export" | |
WATCH_ARCHIVE_DSYMS_PATH="./src/watchOS/bitwarden.xcarchive/dSYMs/" | |
WATCH_DSYMS_EXPORT_PATH="$EXPORT_PATH/Watch_dSYMs" | |
cp -r -v $ARCHIVE_DSYMS_PATH $EXPORT_PATH | |
mkdir $WATCH_DSYMS_EXPORT_PATH | |
cp -r -v $WATCH_ARCHIVE_DSYMS_PATH $WATCH_DSYMS_EXPORT_PATH | |
- name: Upload App Store .ipa & dSYMs artifacts | |
uses: actions/upload-artifact@26f96dfa697d77e81fd5907df203aa23a56210a8 # v4.3.0 | |
with: | |
name: Bitwarden iOS | |
path: | | |
./bitwarden-export/Bitwarden.ipa | |
./bitwarden-export/dSYMs/*.* | |
if-no-files-found: error | |
- name: Upload .app file for Automation CI | |
uses: actions/upload-artifact@26f96dfa697d77e81fd5907df203aa23a56210a8 # v4.3.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 | |
- 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" \; | |
- 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 }} |