Build #420
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-mode: | |
description: "Build Mode" | |
required: true | |
default: "Device" | |
type: choice | |
options: | |
- Device | |
- Simulator | |
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-mode: | |
description: "Build Mode" | |
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' }} | |
BUILD_MODE: ${{ inputs.build-mode || 'Device' }} | |
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 | |
if: env.BUILD_MODE != 'Simulator' | |
uses: Azure/login@cb79c773a3cfa27f31f25eb3f677781210c9ce3d # v1.6.1 | |
with: | |
creds: ${{ secrets.AZURE_KV_CI_SERVICE_PRINCIPAL }} | |
- name: Retrieve secrets | |
if: env.BUILD_MODE != 'Simulator' | |
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 | |
if: env.BUILD_MODE != 'Simulator' | |
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 | |
if: env.BUILD_MODE != 'Simulator' | |
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 | |
if: env.BUILD_MODE != 'Simulator' | |
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 | |
if: env.BUILD_MODE != 'Simulator' | |
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 | |
if: env.BUILD_MODE != 'Simulator' | |
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: Update homebrew | |
run: | | |
brew update | |
- name: Install Fastlane | |
if: env.BUILD_MODE != 'Simulator' | |
run: | | |
brew install fastlane | |
- name: Install Mint | |
run: | | |
brew install 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 ${{ env.BUILD_MODE }} | |
- name: Prepare artifacts for upload to GitHub | |
run: | | |
if [ "$BUILD_MODE" == "Simulator" ]; then | |
app_path="build/DerivedData/Build/Products/Debug-iphonesimulator/Bitwarden.app" | |
watchapp_path="build/DerivedData/Build/Products/Debug-watchsimulator/BitwardenWatchApp.app" | |
#dsym_path="build/DerivedData/Build/Products/Debug-iphonesimulator/Bitwarden.app/dSYMs/*.dSYM" | |
else | |
app_path="build/Bitwarden/Bitwarden.ipa" | |
dsym_path="build/Bitwarden.xcarchive/dSYMs/*.dSYM" | |
fi | |
mkdir -p export | |
mkdir -p export/dSYMs | |
zip -r "export/$(basename "$app_path").zip" "$app_path" | |
cp $dsym_path export/dSYMs | |
zip -r "export/dSYMs.zip" "export/dSYMs" | |
if [ "$BUILD_MODE" == "Simulator" ]; then | |
zip -r "export/$(basename "$watchapp_path").zip" "$watchapp_path" | |
else | |
# Copy uncompressed .ipa file.Required for App Store Connect upload step | |
cp $app_path export/ | |
fi | |
- name: Upload artifacts to GitHub | |
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 | |
if: env.BUILD_MODE != 'Simulator' | |
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 | |
if: env.BUILD_MODE != 'Simulator' | |
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 && env.BUILD_MODE == 'Device' }} | |
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" |