Skip to content

Commit

Permalink
Set up CI/CD for iOS (#95)
Browse files Browse the repository at this point in the history
* Setup CI/CD for iOS

* Setup CI/CD for iOS

* Setup CI/CD for iOS

* Setup CI/CD for iOS

* Setup CI/CD for iOS

* Setup CI/CD for iOS

* Setup CI/CD for iOS

* Setup CI/CD for android build

* Setup CI/CD for android build

* Setup CI/CD for android build

* Setup CI/CD for android build

* Setup CI/CD for android build

* Setup CI/CD for android build

* Setup CI/CD for android build

* Fix apple sign in
  • Loading branch information
cp-sneha-s authored Apr 5, 2024
1 parent 1859590 commit 702cffe
Show file tree
Hide file tree
Showing 12 changed files with 109 additions and 72 deletions.
1 change: 0 additions & 1 deletion .github/script/install_secret_script.sh
Original file line number Diff line number Diff line change
Expand Up @@ -4,5 +4,4 @@ echo $GOOGLE_SERVICES_JSON_BASE64 | base64 -di > android/app/google-services.jso
echo $GOOGLE_SERVICES_PLIST_IOS_BASE64 | base64 -di > ios/Runner/GoogleService-Info.plist
echo $GOOGLE_SERVICES_PLIST_MACOS_BASE64 | base64 -di > macos/Runner/GoogleService-Info.plist
echo $DESKTOP_CREDENTIALS_BASE64 | base64 -di > lib/desktop_credentials.dart
echo $FIREBASE_OPTIONS_BASE64 | base64 -di > lib/firebase_options.dart
echo $WEB_INDEX_HTML_BASE64 | base64 -di > web/index.html
14 changes: 10 additions & 4 deletions .github/workflows/android_build.yml
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
name: Android Build

on: workflow_dispatch
on:
push:
branches:
- main
workflow_dispatch:

jobs:

Expand Down Expand Up @@ -30,7 +34,7 @@ jobs:
DESKTOP_CREDENTIALS_BASE64: ${{ secrets.DESKTOP_CREDENTIALS_BASE64 }}
FIREBASE_OPTIONS_BASE64: ${{ secrets.FIREBASE_OPTIONS_BASE64 }}
GOOGLE_SERVICES_JSON_BASE64: ${{ secrets.GOOGLE_SERVICES_JSON_BASE64 }}
run: ./install_secret_script.sh
run: .github/script/install_secret_script.sh

- name: Generate build
run: |
Expand All @@ -42,11 +46,12 @@ jobs:
IFS=''
buildName="${versionValue[0]}.${versionValue[1]}.${{ github.run_number }}"
echo "Generating android build $buildName $buildNumber"
echo $APKSIGN_KEYSTORE_PASS | base64 -di > release.jks
echo $APKSIGN_KEYSTORE_BASE64 | base64 -di > release.jks
export APKSIGN_KEYSTORE=`pwd`/release.jks
flutter build apk --release --build-number=$buildNumber --build-name=$buildName
mv build/app/outputs/apk/release/ProjectUnity*.apk .
env:
APKSIGN_KEYSTORE_BASE64: ${{ secrets.APKSIGN_KEYSTORE_BASE64 }}
APKSIGN_KEYSTORE_PASS: ${{ secrets.APKSIGN_KEYSTORE_PASS }}
APKSIGN_KEY_ALIAS: ${{ secrets.APKSIGN_KEY_ALIAS }}
APKSIGN_KEY_PASS: ${{ secrets.APKSIGN_KEY_PASS }}
Expand Down Expand Up @@ -97,11 +102,12 @@ jobs:
IFS=''
buildName="${versionValue[0]}.${versionValue[1]}.${{ github.run_number }}"
echo "Generating android build $buildName $buildNumber"
echo $APKSIGN_KEYSTORE_PASS | base64 -di > release.jks
echo $APKSIGN_KEYSTORE_BASE64 | base64 -di > release.jks
export APKSIGN_KEYSTORE=`pwd`/release.jks
flutter build appbundle --build-number=$buildNumber --build-name=$buildName
mv build/app/outputs/bundle/release/app-release.aab .
env:
APKSIGN_KEYSTORE_BASE64: ${{ secrets.APKSIGN_KEYSTORE_BASE64 }}
APKSIGN_KEYSTORE_PASS: ${{ secrets.APKSIGN_KEYSTORE_PASS }}
APKSIGN_KEY_ALIAS: ${{ secrets.APKSIGN_KEY_ALIAS }}
APKSIGN_KEY_PASS: ${{ secrets.APKSIGN_KEY_PASS }}
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/android_deploy.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ on:
push:
branches:
- main
workflow_dispatch:
workflow_dispatch:

jobs:
deploy_internal_android:
Expand Down
91 changes: 53 additions & 38 deletions .github/workflows/ios_deploy.yml
Original file line number Diff line number Diff line change
@@ -1,58 +1,75 @@
name: iOS build
name: Publish to App Store Connect

on:
push:
branches:
- main
workflow_dispatch:
workflow_dispatch:


jobs:
ios_deploy_testflight:
runs-on: macos-latest
runs-on: macos-13
env:
APP_STORE_CONNECT_ISSUER_ID: ${{ secrets.APP_STORE_CONNECT_ISSUER_ID }}
APP_STORE_CONNECT_KEY_IDENTIFIER: ${{ secrets.APP_STORE_CONNECT_KEY_IDENTIFIER }}
APP_STORE_CONNECT_PRIVATE_KEY: ${{ secrets.APP_STORE_CONNECT_PRIVATE_KEY }}
APP_STORE_APP_ID: ${{ secrets.APP_STORE_APP_ID }}
DIST_CERTIFICATE: ${{ secrets.DIST_CERTIFICATE_BASE64 }}
DIST_CERTIFICATE_PASSWORD: ${{ secrets.DIST_CERTIFICATE_PASSWORD }}
DIST_PROFILE: ${{ secrets.DIST_PROFILE_BASE64 }}

steps:

- name: Checkout
uses: actions/checkout@v2

- name: Install the Apple certificate and provisioning profile
env:
BUILD_CERTIFICATE_BASE64: ${{ secrets.BUILD_CERTIFICATE }}
P12_PASSWORD: ${{ secrets.P12_PASSWORD }}
BUILD_PROVISION_PROFILE_BASE64: ${{ secrets.PROVISIONING_PROFILE }}
KEYCHAIN_PASSWORD: ${{ secrets.KEYCHAIN_PASSWORD }}

run: |
# create variables
CERTIFICATE_PATH=$RUNNER_TEMP/build_certificate.p12
KEYCHAIN_PATH=$RUNNER_TEMP/app-signing.keychain-db
# import certificate and provisioning profile from secrets
echo -n "$BUILD_CERTIFICATE_BASE64" | base64 --decode > $CERTIFICATE_PATH
# create temporary keychain
security create-keychain -p "$KEYCHAIN_PASSWORD" $KEYCHAIN_PATH
security set-keychain-settings -lut 21600 $KEYCHAIN_PATH
security unlock-keychain -p "$KEYCHAIN_PASSWORD" $KEYCHAIN_PATH
# import certificate to keychain
security import $CERTIFICATE_PATH -P "$P12_PASSWORD" -A -t cert -f pkcs12 -k $KEYCHAIN_PATH
security set-key-partition-list -S apple-tool:,apple:,codesign: -s -k "$KEYCHAIN_PASSWORD" $KEYCHAIN_PATH
security list-keychain -d user -s $KEYCHAIN_PATH
chmod +x ios/install_dist_profile.sh && ./ios/install_dist_profile.sh
- name: Set up Flutter SDK
uses: subosito/flutter-action@v2
with:
channel: 'stable'
cache: true

- name: Retrieve the secret and decode it to file
env:
FIREABSE_APP_ID_JSON_BASE64: ${{ secrets.FIREBASE_APP_ID_JSON_BASE64 }}
DESKTOP_CREDENTIALS_BASE64: ${{ secrets.DESKTOP_CREDENTIALS_BASE64 }}
FIREBASE_OPTIONS_BASE64: ${{ secrets.FIREBASE_OPTIONS_BASE64 }}
GOOGLE_SERVICES_PLIST_IOS_BASE64: ${{ secrets.GOOGLE_SERVICES_PLIST_IOS_BASE64 }}
run: |
echo $FIREABSE_APP_ID_JSON_BASE64 | base64 --decode > ios/firebase_app_id_file.json
echo $FIREBASE_OPTIONS_BASE64 | base64 --decode > lib/firebase_options.dart
echo $GOOGLE_SERVICES_PLIST_IOS_BASE64 | base64 --decode > ios/Runner/GoogleService-Info.plist
echo $DESKTOP_CREDENTIALS_BASE64 | base64 --decode > lib/desktop_credentials.dart
- name: Install dependencies
run: |
flutter pub get
- name: Building ipa
- name: Install Codemagic CLI tools
run: pip install codemagic-cli-tools

- name: Set up keychain
run: keychain initialize

- name: Set up Provisioning Profiles
run: |
PROFILES_HOME="$HOME/Library/MobileDevice/Provisioning Profiles"
mkdir -p "$PROFILES_HOME"
PROFILE_PATH="$(mktemp "$PROFILES_HOME"/$(uuidgen).mobileprovision)"
echo ${DIST_PROFILE} | base64 --decode > "$PROFILE_PATH"
- name: Set up signing certificate
run: |
echo $DIST_CERTIFICATE | base64 --decode > /tmp/certificate.p12
keychain add-certificates --certificate /tmp/certificate.p12 --certificate-password $DIST_CERTIFICATE_PASSWORD
- name: Setup Code signing settings on Xcode project
run: xcode-project use-profiles


- name: Build ipa for Distribution
run: |
file='VERSION'
fileData=`cat $file`
Expand All @@ -62,12 +79,10 @@ jobs:
IFS=''
buildName="${versionValue[0]}.${versionValue[1]}.${{ github.run_number }}"
echo "Uploading build $buildName"
flutter build ipa --build-number=$buildNumber --build-name=$buildName --export-options-plist=ios/Runner/ExportOptions.plist
echo "Uploading app to iTC..."
xcrun altool --upload-app -t ios -f build/ios/ipa/*.ipa -u $ITC_USER_NAME -p $ITC_USER_PASSWORD
flutter build ipa --release --build-number=$buildNumber --build-name=$buildName --export-options-plist=$HOME/export_options.plist
- name: Clean up keychain and provisioning profile
if: ${{ always() }}
- name: Upload to App Store Connect
run: |
security delete-keychain $RUNNER_TEMP/app-signing.keychain-db
rm ~/Library/MobileDevice/Provisioning\ Profiles/build_pp.mobileprovision
APP_FILE=$(find $(pwd) -name "*.ipa")
app-store-connect publish \
--path "$APP_FILE"
2 changes: 1 addition & 1 deletion ios/Runner.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -247,7 +247,7 @@
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh;
shellScript = "\"$PODS_ROOT/FirebaseCrashlytics/upload-symbols\" --flutter-project \"$PROJECT_DIR/firebase_app_id_file.json\" ";
shellScript = "\"$PODS_ROOT/FirebaseCrashlytics/upload-symbols\" --flutter-project \"$PROJECT_DIR/firebase_app_id_file.json\" \n";
};
9740EEB61CF901F6004384FC /* Run Script */ = {
isa = PBXShellScriptBuildPhase;
Expand Down
11 changes: 0 additions & 11 deletions ios/install_dist_certs.sh

This file was deleted.

12 changes: 0 additions & 12 deletions ios/install_dist_profile.sh

This file was deleted.

1 change: 1 addition & 0 deletions lib/data/core/exception/error_const.dart
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ const String invalidLeaveDateError = 'invalid-leave_date_error';
const String alreadyLeaveAppliedError = 'already-applied';

const String somethingWentWrongError = 'something-went-wrong';
const String appleSigninError = 'apple-signin-error';

//Exception: when user don't provide all the required information in fields,
const String provideRequiredInformation = 'provide-required-information';
Expand Down
1 change: 1 addition & 0 deletions lib/data/l10n/app_en.arb
Original file line number Diff line number Diff line change
Expand Up @@ -427,6 +427,7 @@
"add_member_employee_exists_error": "Member already exists!",
"leave_already_applied_error_message": "Leave request has been already applied!",
"provide_required_information": "Please provide the required information to continue",
"apple_sign_in_error_message": "Oops! It looks like you haven't granted permission to access your email. Please check and grant permission to access your email address",

"sign_out_alert": "Are you sure you want to sign out?",

Expand Down
18 changes: 18 additions & 0 deletions lib/data/services/account_service.dart
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,24 @@ class AccountService {
return user;
}

Future<Account?> getAppleUser(firebase_auth.User authData) async {
final userDataDoc = await _accountsDb.doc(authData.uid).get();
final Account? userData = userDataDoc.data();
if (userData != null) {
await _setUserSession(authData.uid);
return userData;
} else if (authData.email != null) {
final user = Account(
uid: authData.uid,
email: authData.email!,
name: authData.displayName);
await _accountsDb.doc(authData.uid).set(user);
await _setUserSession(authData.uid);
return user;
}
return null;
}

Future<void> _setUserSession(String uid) async {
final Session? session = await deviceInfoProvider.getDeviceInfo();
if (session != null) {
Expand Down
17 changes: 15 additions & 2 deletions lib/ui/sign_in/bloc/sign_in_view_bloc.dart
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
import 'dart:async';
import 'package:firebase_auth/firebase_auth.dart' as firebase_auth;
import 'package:firebase_auth/firebase_auth.dart';
import 'package:firebase_crashlytics/firebase_crashlytics.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:injectable/injectable.dart';
import 'package:projectunity/data/services/account_service.dart';
Expand Down Expand Up @@ -49,13 +51,24 @@ class SignInBloc extends Bloc<SignInEvent, SignInState> {
emit(state.copyWith(appleSignInLoading: true));
firebase_auth.User? authUser = await _authService.signInWithApple();
if (authUser != null) {
final Account user = await _accountService.getUser(authUser);
final Account? user = await _accountService.getAppleUser(authUser);
if (user == null) {
emit(state.copyWith(
appleSignInLoading: false, error: appleSigninError));
return;
}
await _userStateNotifier.setUser(user);
emit(state.copyWith(appleSignInLoading: false, signInSuccess: true));
} else {
emit(state.copyWith(appleSignInLoading: false));
}
} on Exception {
} catch (e, stack) {
if (e is FirebaseAuthException && e.code == 'canceled') {
emit(state.copyWith(appleSignInLoading: false));
return;
}
FirebaseCrashlytics.instance
.recordError(e, stack, reason: 'Apple Sign In Error');
emit(state.copyWith(
appleSignInLoading: false, error: somethingWentWrongError));
}
Expand Down
11 changes: 9 additions & 2 deletions lib/ui/sign_in/sign_in_screen.dart
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import 'package:projectunity/style/app_text_style.dart';
import 'package:projectunity/style/other/smart_scroll_view.dart';
import 'package:projectunity/ui/sign_in/widget/apple_signin_button.dart';
import 'package:projectunity/ui/sign_in/widget/google_signin_button.dart';
import '../../data/core/exception/error_const.dart';
import '../../data/core/utils/const/image_constant.dart';
import '../../data/di/service_locator.dart';
import '../widget/error_snack_bar.dart';
Expand Down Expand Up @@ -61,7 +62,13 @@ class SignInScreenState extends State<SignInScreen> {
listenWhen: (previous, current) => current.error != null,
listener: (context, state) {
if (state.error != null) {
showSnackBar(context: context, error: state.error);
if (state.error == appleSigninError) {
showSnackBar(
context: context,
msg: context.l10n.apple_sign_in_error_message);
} else {
showSnackBar(context: context, error: state.error);
}
}
},
child: SafeArea(
Expand Down Expand Up @@ -108,7 +115,7 @@ class SignInScreenState extends State<SignInScreen> {
const SizedBox(
height: 20,
),
if (kIsWeb || Platform.isIOS) const AppleSignInButton()
if (!kIsWeb && Platform.isIOS) const AppleSignInButton()
],
),
),
Expand Down

0 comments on commit 702cffe

Please sign in to comment.