Build #419
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: | |
workflow_dispatch: | |
inputs: | |
build-variant: | |
description: "Build Variant" | |
required: true | |
default: "Beta" | |
type: choice | |
options: | |
- Beta | |
- Production | |
build-version: | |
description: "Version Name Override - e.g. '2024.8.1'" | |
type: string | |
build-number: | |
description: "Version Number Override - e.g. '1021'" | |
type: string | |
xcode-version: | |
description: "Xcode Version Override - e.g. '15.2'" | |
type: string | |
compiler-flags: | |
description: "Compiler Flags - e.g. 'DEBUG_MENU FEATURE2'" | |
type: string | |
base_version_number: | |
description: "Base Version Number - Will be added to the calculated version number" | |
type: number | |
default: 1500 | |
patch_version: | |
description: "Patch Version Override - e.g. '999'" | |
type: string | |
distribute: | |
description: "Distribute to TestFlight" | |
type: boolean | |
default: true | |
workflow_call: | |
inputs: | |
build-variant: | |
description: "Build Variant" | |
type: string | |
build-version: | |
description: "Version Name Override - e.g. '2024.8.1'" | |
type: string | |
build-number: | |
description: "Version Number Override - e.g. '1021'" | |
type: string | |
xcode-version: | |
description: "Xcode Version Override - e.g. '15.2'" | |
type: string | |
compiler-flags: | |
description: "Compiler Flags - e.g. 'DEBUG_MENU FEATURE2'" | |
type: string | |
base_version_number: | |
description: "Base Version Number - Will be added to the calculated version number" | |
type: number | |
default: 1500 | |
patch_version: | |
description: "Patch Version Override - e.g. '999'" | |
type: string | |
distribute: | |
description: "Distribute to TestFlight" | |
type: boolean | |
upload_version_info: | |
description: "Upload version-info file - When false, caller may be handling it already" | |
type: boolean | |
env: | |
BUILD_VARIANT: ${{ inputs.build-variant || 'Beta' }} | |
XCODE_VERSION: ${{ inputs.xcode-version }} | |
jobs: | |
build: | |
name: Build | |
runs-on: macos-15 | |
env: | |
MINT_PATH: .mint/lib | |
MINT_LINK_PATH: .mint/bin | |
steps: | |
- name: Log inputs to job summary | |
run: | | |
echo "<details><summary>Build Workflow Inputs</summary>" >> $GITHUB_STEP_SUMMARY | |
echo "" >> $GITHUB_STEP_SUMMARY | |
echo '```json' >> $GITHUB_STEP_SUMMARY | |
echo '${{ toJson(inputs) }}' >> $GITHUB_STEP_SUMMARY | |
echo '```' >> $GITHUB_STEP_SUMMARY | |
echo "</details>" >> $GITHUB_STEP_SUMMARY | |
- name: Check out repo | |
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 | |
with: | |
fetch-depth: 0 | |
filter: tree:0 | |
- name: Calculate version | |
if: ${{ inputs.build-number == '' || inputs.build-version == '' }} | |
uses: bitwarden/ios/.github/actions/dispatch-and-download@main | |
id: dispatch-version | |
with: | |
token: ${{ secrets.GITHUB_TOKEN }} | |
owner: bitwarden | |
repo: ios | |
ref: main | |
workflow: _version.yml | |
workflow_inputs: '{"base_version_number": "${{ inputs.base_version_number }}", "version_name": "${{ inputs.build-version }}", "version_number": "${{ inputs.build-number }}", "patch_version": "${{ inputs.patch_version }}"}' | |
- name: Read version info | |
id: version_info | |
run: | | |
# test if dispatch-version was skipped. In that case, creates the same .json file expected by the Upload artifact step | |
if [ ! -f version-info/version_info.json ]; then | |
echo "::warning::version-version.json not found, was the previous step skipped? Creating a new file" | |
json='{ | |
"version_number": "${{ inputs.build-number }}", | |
"version_name": "${{ inputs.build-version }}" | |
}' | |
# file will be used by the upload step | |
mkdir version-info | |
echo "$json" > version-info/version_info.json | |
else | |
echo "::notice::version-version.json found!" | |
fi | |
content=$(cat version-info/version_info.json) | |
echo "version_name=$(echo $content | jq -r .version_name)" >> $GITHUB_OUTPUT | |
echo "version_number=$(echo $content | jq -r .version_number)" >> $GITHUB_OUTPUT | |
- name: Upload version info artifact | |
if: ${{ inputs.upload_version_info }} | |
uses: actions/upload-artifact@b4b15b8c7c6ac21ea08fcf65892d2ee8f75cf882 # v4.4.3 | |
with: | |
name: version-info | |
path: version-info/version_info.json | |
- name: Read default Xcode version | |
run: | | |
echo "DEFAULT_XCODE_VERSION=$(cat .xcode-version | tr -d '\n')" >> "$GITHUB_ENV" | |
- name: Set Xcode version | |
uses: maxim-lobanov/setup-xcode@60606e260d2fc5762a71e64e74b2174e8ea3c8bd # v1.6.0 | |
with: | |
xcode-version: ${{ env.XCODE_VERSION || env.DEFAULT_XCODE_VERSION }} | |
- name: Cache Mint packages | |
id: mint-cache | |
uses: actions/cache@6849a6489940f00c2f30c0fb92c6274307ccb58a # v4.1.2 | |
with: | |
path: .mint | |
key: ${{ runner.os }}-mint-${{ hashFiles('**/Mintfile') }} | |
restore-keys: | | |
${{ runner.os }}-mint- | |
- name: Log in to Azure | |
uses: Azure/login@cb79c773a3cfa27f31f25eb3f677781210c9ce3d # v1.6.1 | |
with: | |
creds: ${{ secrets.AZURE_KV_CI_SERVICE_PRINCIPAL }} | |
- name: Retrieve secrets | |
uses: bitwarden/gh-actions/get-keyvault-secrets@main | |
with: | |
keyvault: "bitwarden-ci" | |
secrets: "appcenter-ios-token" | |
- name: Retrieve production provisioning profiles | |
if: env.BUILD_VARIANT == 'Production' | |
env: | |
ACCOUNT_NAME: bitwardenci | |
CONTAINER_NAME: profiles | |
run: | | |
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" | |
"dist_bitwarden_watch_widget_extension.mobileprovision" | |
) | |
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 | |
- name: Retrieve beta provisioning profiles | |
if: env.BUILD_VARIANT == 'Beta' | |
env: | |
ACCOUNT_NAME: bitwardenci | |
CONTAINER_NAME: profiles | |
run: | | |
mkdir -p $HOME/secrets | |
profiles=( | |
"dist_beta_autofill.mobileprovision" | |
"dist_beta_bitwarden.mobileprovision" | |
"dist_beta_extension.mobileprovision" | |
"dist_beta_share_extension.mobileprovision" | |
"dist_beta_bitwarden_watch_app.mobileprovision" | |
"dist_beta_bitwarden_watch_app_extension.mobileprovision" | |
"dist_beta_bitwarden_watch_widget_extension.mobileprovision" | |
) | |
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 | |
- name: Retrieve production Google Services secret | |
if: env.BUILD_VARIANT == 'Production' | |
env: | |
ACCOUNT_NAME: bitwardenci | |
CONTAINER_NAME: mobile | |
SOURCE_FILE: GoogleService-Info.plist | |
TARGET_FILE: GoogleService-Info.plist | |
run: | | |
mkdir -p $HOME/secrets | |
az storage blob download --account-name $ACCOUNT_NAME --container-name $CONTAINER_NAME --name $SOURCE_FILE \ | |
--file Bitwarden/Application/Support/$TARGET_FILE --output none | |
- name: Retrieve watch production Google Services secret | |
if: env.BUILD_VARIANT == 'Production' | |
env: | |
ACCOUNT_NAME: bitwardenci | |
CONTAINER_NAME: mobile | |
SOURCE_FILE: GoogleService-Info.plist | |
TARGET_FILE: GoogleService-Info.plist | |
run: | | |
mkdir -p $HOME/secrets | |
az storage blob download --account-name $ACCOUNT_NAME --container-name $CONTAINER_NAME --name $SOURCE_FILE \ | |
--file BitwardenWatchApp/$TARGET_FILE --output none | |
plutil -replace BUNDLE_ID -string com.8bit.bitwarden.watchkitapp BitwardenWatchApp/$TARGET_FILE | |
- name: Retrieve beta Google Services secret | |
if: env.BUILD_VARIANT == 'Beta' | |
env: | |
ACCOUNT_NAME: bitwardenci | |
CONTAINER_NAME: mobile | |
SOURCE_FILE: GoogleService-Info-ios-pm-beta.plist | |
TARGET_FILE: GoogleService-Info.plist | |
run: | | |
mkdir -p $HOME/secrets | |
az storage blob download --account-name $ACCOUNT_NAME --container-name $CONTAINER_NAME --name $SOURCE_FILE \ | |
--file Bitwarden/Application/Support/$TARGET_FILE --output none | |
- name: Retrieve watch beta Google Services secret | |
if: env.BUILD_VARIANT == 'Beta' | |
env: | |
ACCOUNT_NAME: bitwardenci | |
CONTAINER_NAME: mobile | |
SOURCE_FILE: GoogleService-Info-ios-pm-beta.plist | |
TARGET_FILE: GoogleService-Info.plist | |
run: | | |
mkdir -p $HOME/secrets | |
az storage blob download --account-name $ACCOUNT_NAME --container-name $CONTAINER_NAME --name $SOURCE_FILE \ | |
--file BitwardenWatchApp/$TARGET_FILE --output none | |
plutil -replace BUNDLE_ID -string com.8bit.bitwarden.beta.watchkitapp BitwardenWatchApp/$TARGET_FILE | |
- name: Retrieve 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 | |
- name: Download Fastlane credentials | |
env: | |
ACCOUNT_NAME: bitwardenci | |
CONTAINER_NAME: mobile | |
FILE: appstoreconnect-fastlane.json | |
run: | | |
mkdir -p $HOME/secrets | |
az storage blob download --account-name $ACCOUNT_NAME --container-name $CONTAINER_NAME --name $FILE \ | |
--file $HOME/secrets/$FILE --output none | |
- name: Configure Keychain Access | |
env: | |
KEYCHAIN_PASSWORD: ${{ secrets.IOS_KEYCHAIN_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 $HOME/certificates/ios-distribution.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 | |
- name: Configure provisioning profiles | |
run: | | |
./Scripts/configure_provisioning_profiles.sh ${{ env.BUILD_VARIANT }} | |
- name: Update beta export compliance key | |
if: env.BUILD_VARIANT == 'Beta' | |
run: | | |
plutil -replace ITSEncryptionExportComplianceCode -string 3dd3e32f-efa6-4d99-b410-28aa28b1cb77 Bitwarden/Application/Support/Info.plist | |
- name: Update beta Fastlane Appfile | |
if: env.BUILD_VARIANT == 'Beta' | |
run: | | |
echo 'app_identifier "com.8bit.bitwarden.beta"' > fastlane/Appfile | |
- name: Update APNS entitlements | |
run: | | |
plutil -replace aps-environment -string production Bitwarden/Application/Support/Bitwarden.entitlements | |
- name: Configure Ruby | |
uses: ruby/setup-ruby@a2bbe5b1b236842c1cb7dd11e8e3b51e0a616acc # v1.202.0 | |
with: | |
bundler-cache: true | |
- name: Install Fastlane, Mint | |
run: | | |
brew update | |
brew install fastlane mint | |
- name: Install Mint packages | |
if: steps.mint-cache.outputs.cache-hit != 'true' | |
run: | | |
mint bootstrap | |
- name: Select variant | |
run: | | |
./Scripts/select_variant.sh ${{ env.BUILD_VARIANT }} "${{ inputs.compiler-flags }}" | |
- name: Update build version and number | |
run: | | |
yq -i '.settings.MARKETING_VERSION = "${{ steps.version_info.outputs.version_name }}"' 'project.yml' | |
yq -i '.settings.CURRENT_PROJECT_VERSION = "${{ steps.version_info.outputs.version_number }}"' 'project.yml' | |
- name: Update CI build info | |
run: | | |
./Scripts/update_app_ci_build_info.sh ${{ github.run_id }} ${{ github.run_number }} ${{ github.run_attempt }} "${{ inputs.compiler-flags }}" | |
- name: Build iOS app | |
run: | | |
./Scripts/build.sh | |
- name: Prepare IPA & dSYM files for upload to GitHub | |
run: | | |
mkdir -p export/dSYMs | |
cp build/Bitwarden/Bitwarden.ipa export | |
cp -rv build/Bitwarden.xcarchive/dSYMs/*.dSYM export/dSYMs | |
- name: Upload IPA & dSYM files | |
uses: actions/upload-artifact@b4b15b8c7c6ac21ea08fcf65892d2ee8f75cf882 # v4.4.3 | |
with: | |
name: Bitwarden iOS ${{ steps.version_info.outputs.version_name }} (${{ steps.version_info.outputs.version_number }}) ${{ env.BUILD_VARIANT }} ${{ env.XCODE_VERSION || env.DEFAULT_XCODE_VERSION }} | |
path: export | |
if-no-files-found: error | |
- name: Set up private auth key | |
run: | | |
mkdir ~/private_keys | |
cat << EOF > ~/private_keys/AuthKey_J46C83CB96.p8 | |
${{ secrets.APP_STORE_CONNECT_AUTH_KEY }} | |
EOF | |
- name: Validate app with App Store Connect | |
run: | | |
xcrun altool --validate-app \ | |
--type ios \ | |
--file "export/Bitwarden.ipa" \ | |
--apiKey "J46C83CB96" \ | |
--apiIssuer "${{ secrets.APP_STORE_CONNECT_TEAM_ISSUER }}" | |
- name: Upload app to TestFlight with Fastlane | |
if: ${{ inputs.distribute }} | |
run: | | |
CHANGELOG="$(git show -s --format=%s) | |
$GITHUB_REPOSITORY/$GITHUB_REF_NAME @ $GITHUB_SHA | |
Xcode ${{ env.XCODE_VERSION }} | |
Compiler Flags: ${{ inputs.compiler-flags }} | |
$GITHUB_SERVER_URL/$GITHUB_REPOSITORY/actions/runs/$GITHUB_RUN_ID" | |
fastlane upload_build \ | |
api_key_path:"$HOME/secrets/appstoreconnect-fastlane.json" \ | |
changelog:"$CHANGELOG" \ | |
ipa_path:"export/Bitwarden.ipa" |