Skip to content

Update permissions to make scripts executable (#815) #298

Update permissions to make scripts executable (#815)

Update permissions to make scripts executable (#815) #298

Workflow file for this run

name: Build
on:
push:
branches:
- main
workflow_dispatch:
inputs:
build-variant:
description: "Which variant of the app to build"
required: true
type: choice
options:
- Beta
- Production
build-version:
description: "Optional. Version string to use, in X.Y.Z format. Overrides default in the project."
required: false
type: string
build-number:
description: "Optional. Build number to use. Overrides default of GitHub run number."
required: false
type: number
xcode-version:
description: "Optional. Xcode version to use. Overrides default."
required: false
type: string
env:
BUILD_VARIANT: ${{ inputs.build-variant || 'Beta' }}
XCODE_VERSION: ${{ inputs.xcode-version || '15.4' }}
jobs:
build:
name: Build
runs-on: macos-14
env:
MINT_PATH: .mint/lib
MINT_LINK_PATH: .mint/bin
steps:
- name: Check out repo
uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7
with:
fetch-depth: 0
filter: tree:0
- name: Set Xcode version
uses: maxim-lobanov/setup-xcode@60606e260d2fc5762a71e64e74b2174e8ea3c8bd # v1.6.0
with:
xcode-version: ${{ env.XCODE_VERSION }}
- name: Cache Mint packages
id: mint-cache
uses: actions/cache@0c45773b623bea8c8e75f6c82b208c3cf94ea4f9 # v4.0.2
with:
path: .mint
key: ${{ runner.os }}-mint-${{ hashFiles('**/Mintfile') }}
restore-keys: |
${{ runner.os }}-mint-
- name: Install yeetd
run: |
wget https://github.com/biscuitehh/yeetd/releases/download/1.0/yeetd-normal.pkg
sudo installer -pkg yeetd-normal.pkg -target /
yeetd &
- 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"
)
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"
)
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 production provisioning profiles
if: env.BUILD_VARIANT == 'Production'
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_bitwarden_watch_app.mobileprovision
WATCH_APP_EXTENSION_PROFILE_PATH=$HOME/secrets/dist_bitwarden_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: Configure beta provisioning profiles
if: env.BUILD_VARIANT == 'Beta'
run: |
AUTOFILL_PROFILE_PATH=$HOME/secrets/dist_beta_autofill.mobileprovision
BITWARDEN_PROFILE_PATH=$HOME/secrets/dist_beta_bitwarden.mobileprovision
EXTENSION_PROFILE_PATH=$HOME/secrets/dist_beta_extension.mobileprovision
SHARE_EXTENSION_PROFILE_PATH=$HOME/secrets/dist_beta_share_extension.mobileprovision
WATCH_APP_PROFILE_PATH=$HOME/secrets/dist_beta_bitwarden_watch_app.mobileprovision
WATCH_APP_EXTENSION_PROFILE_PATH=$HOME/secrets/dist_beta_bitwarden_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: 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@a6e6f86333f0a2523ece813039b8b4be04560854 # v1.190.0
with:
bundler-cache: true
- name: Install Fastlane, Mint, xcbeautify, and yq
run: |
brew install fastlane mint xcbeautify yq
- 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 }}
- name: Calculate build version
id: calculate
run: |
if [[ ! -z "${{ inputs.build-version }}" ]]; then
echo -e "\nApplying version override"
next_version=${{ inputs.build-version }}
else
echo -e "\nCalculating next version..."
current_year=$(date +%Y)
current_month=$(date +%-m)
latest_tag_version=$(git tag --sort=committerdate --list | tail -1)
latest_version=${latest_tag_version:1} # remove 'v' from tag version
latest_major_version=$(echo $latest_version | cut -d "." -f 1)
latest_minor_version=$(echo $latest_version | cut -d "." -f 2)
latest_patch_version=$(echo $latest_version | cut -d "." -f 3)
echo " Current Year: $current_year"
echo " Current Month: $current_month"
echo " Latest Version: $latest_version"
echo " Latest Major Version: $latest_major_version"
echo " Latest Minor Version: $latest_minor_version"
echo " Latest Patch Version: $latest_patch_version"
if [[ "$current_year" == "$latest_major_version" && "$current_month" == "$latest_minor_version" ]]; then
next_version="${latest_major_version}.${latest_minor_version}.$(($latest_patch_version + 1))"
else
next_version="${current_year}.${current_month}.0"
fi
fi
echo "Next Version: $next_version"
echo "version=$next_version" >> $GITHUB_OUTPUT
- name: Update build version
env:
build_version: ${{ steps.calculate.outputs.version }}
run: |
yq -i '.settings.MARKETING_VERSION = "${{ env.build_version }}"' 'project.yml'
- name: Update build number
run: |
BUILD_NUMBER=$(($GITHUB_RUN_NUMBER))
yq -i ".settings.CURRENT_PROJECT_VERSION = ${{ inputs.build-number || '$BUILD_NUMBER' }}" 'project.yml'
- name: Update app CI Build info
run: |
./Scripts/update_app_ci_build_info.sh ${{ github.run_id }} ${{ github.run_number }} ${{ github.run_attempt }}
- name: Build iOS app
run: |
BUILD_NUMBER=$(($GITHUB_RUN_NUMBER))
./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@89ef406dd8d7e03cfd12d9e0a4a378f454709029 # v4.3.5
with:
name: Bitwarden iOS
path: export
if-no-files-found: error
- name: Validate app with App Store Connect
env:
APPLE_ID_USERNAME: ${{ secrets.APPLE_ID_USERNAME }}
APPLE_ID_PASSWORD: ${{ secrets.APPLE_ID_PASSWORD }}
run: |
xcrun altool --validate-app \
--type ios \
--file "export/Bitwarden.ipa" \
--username "$APPLE_ID_USERNAME" \
--password @env:APPLE_ID_PASSWORD
- name: Upload app to TestFlight with Fastlane
run: |
NEWLINE=$'\n'
fastlane upload_build \
api_key_path:"$HOME/secrets/appstoreconnect-fastlane.json" \
changelog:"$(git show -s --format=%s)$NEWLINE$GITHUB_REPOSITORY/$GITHUB_REF_NAME @ $GITHUB_SHA$NEWLINE$NEWLINE$GITHUB_SERVER_URL/$GITHUB_REPOSITORY/actions/runs/$GITHUB_RUN_ID" \
ipa_path:"export/Bitwarden.ipa"