Skip to content

Commit

Permalink
Merge pull request #32 from LucasXu0/code_magic
Browse files Browse the repository at this point in the history
Code magic
  • Loading branch information
LucasXu0 committed Nov 8, 2024
2 parents 4e1532a + 94f5e51 commit fe81551
Show file tree
Hide file tree
Showing 10 changed files with 218 additions and 44 deletions.
40 changes: 22 additions & 18 deletions .github/workflows/ios_ci.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -97,21 +97,25 @@ jobs:
cargo make --profile development-ios-arm64-sim appflowy-core-dev-ios
cargo make --profile development-ios-arm64-sim code_generation
# - uses: futureware-tech/simulator-action@v3
# id: simulator-action
# with:
# model: "iPhone 15"
# shutdown_after_job: false

# - name: Run AppFlowy on simulator
# working-directory: frontend/appflowy_flutter
# run: |
# flutter run -d ${{ steps.simulator-action.outputs.udid }} &
# pid=$!
# sleep 500
# kill $pid
# continue-on-error: true

# - name: Run integration tests
# working-directory: frontend/appflowy_flutter
# run: flutter test integration_test/runner.dart -d ${{ steps.simulator-action.outputs.udid }}
- uses: futureware-tech/simulator-action@v3
id: simulator-action
with:
model: "iPhone 15"
shutdown_after_job: false

- name: Run AppFlowy on simulator
working-directory: frontend/appflowy_flutter
run: |
flutter run -d ${{ steps.simulator-action.outputs.udid }} &
pid=$!
sleep 500
kill $pid
continue-on-error: true

- name: Run integration tests
working-directory: frontend/appflowy_flutter
# The integration tests are flaky and sometimes fail with "Connection timed out":
# Don't block the CI. If the tests fail, the CI will still pass.
# Instead, we're using Code Magic to re-run the tests to check if they pass.
continue-on-error: true
run: flutter test integration_test/runner.dart -d ${{ steps.simulator-action.outputs.udid }}
114 changes: 114 additions & 0 deletions .github/workflows/mobile_ci.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,114 @@
name: Mobile-CI

on:
workflow_dispatch:
inputs:
branch:
description: "Branch to build"
required: true
default: "main"
workflow_id:
description: "Codemagic workflow ID"
required: true
default: "ios-workflow"
type: choice
options:
- ios-workflow
- android-workflow

env:
CODEMAGIC_API_TOKEN: 3G8VZRVsbYPb5-RuFjw-xqqlyA7y-nfue-rmybupLZw
APP_ID: "64cb77ba5da3347bf6d22fba"

jobs:
trigger-mobile-build:
runs-on: ubuntu-latest
steps:
- name: Trigger Codemagic Build
id: trigger_build
run: |
RESPONSE=$(curl -X POST \
--header "Content-Type: application/json" \
--header "x-auth-token: $CODEMAGIC_API_TOKEN" \
--data '{
"appId": "${{ env.APP_ID }}",
"workflowId": "${{ github.event.inputs.workflow_id }}",
"branch": "${{ github.event.inputs.branch }}"
}' \
https://api.codemagic.io/builds)
BUILD_ID=$(echo $RESPONSE | jq -r '.buildId')
echo "build_id=$BUILD_ID" >> $GITHUB_OUTPUT
echo "build_id=$BUILD_ID"
- name: Wait for build and check status
id: check_status
run: |
while true; do
RESPONSE=$(curl -X GET \
--header "Content-Type: application/json" \
--header "x-auth-token: $CODEMAGIC_API_TOKEN" \
https://api.codemagic.io/builds/${{ steps.trigger_build.outputs.build_id }})
STATUS=$(echo $RESPONSE | jq -r '.build.status')
if [ "$STATUS" = "finished" ]; then
SUCCESS=$(echo $RESPONSE | jq -r '.success')
BUILD_URL=$(echo $RESPONSE | jq -r '.buildUrl')
echo "status=$STATUS" >> $GITHUB_OUTPUT
echo "success=$SUCCESS" >> $GITHUB_OUTPUT
echo "build_url=$BUILD_URL" >> $GITHUB_OUTPUT
break
elif [ "$STATUS" = "failed" ]; then
echo "status=failed" >> $GITHUB_OUTPUT
break
fi
sleep 60
done
- name: Send Slack Notification
if: always()
run: |
BUILD_STATUS="${{ steps.check_status.outputs.status }}"
SUCCESS="${{ steps.check_status.outputs.success }}"
BUILD_URL="${{ steps.check_status.outputs.build_url }}"
if [ "$SUCCESS" = "true" ]; then
COLOR="#36a64f"
STATUS_TEXT="✅ Success"
else
COLOR="#ff0000"
STATUS_TEXT="❌ Failed"
fi
echo "build_status=$BUILD_STATUS"
echo "success=$SUCCESS"
echo "build_url=$BUILD_URL"
# send the result to slack
# curl -X POST -H 'Content-type: application/json' \
# --data "{
# \"attachments\": [
# {
# \"color\": \"$COLOR\",
# \"blocks\": [
# {
# \"type\": \"section\",
# \"text\": {
# \"type\": \"mrkdwn\",
# \"text\": \"*Mobile CI Build Result*\n$STATUS_TEXT\"
# }
# },
# {
# \"type\": \"section\",
# \"text\": {
# \"type\": \"mrkdwn\",
# \"text\": \"*Branch:* ${{ github.event.inputs.branch }}\n*Workflow:* ${{ github.event.inputs.workflow_id }}\n*Build URL:* $BUILD_URL\"
# }
# }
# ]
# }
# ]
# }" \
# ${{ secrets.RELEASE_SLACK_WEBHOOK }}
47 changes: 47 additions & 0 deletions codemagic.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
workflows:
ios-workflow:
name: iOS Workflow
instance_type: mac_mini_m2
max_build_duration: 30
environment:
flutter: 3.22.3
xcode: latest
cocoapods: default

scripts:
- name: Build Flutter
script: |
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y
source "$HOME/.cargo/env"
rustc --version
cargo --version
cd frontend
rustup target install aarch64-apple-ios-sim
cargo install --force cargo-make
cargo install --force duckscript_cli
cargo install --force cargo-lipo
cargo make appflowy-flutter-deps-tools
cargo make --profile development-ios-arm64-sim appflowy-core-dev-ios
cargo make --profile development-ios-arm64-sim code_generation
- name: iOS integration tests
script: |
cd frontend/appflowy_flutter
flutter emulators --launch apple_ios_simulator
flutter -d iPhone test integration_test/runner.dart
artifacts:
- build/ios/ipa/*.ipa
- /tmp/xcodebuild_logs/*.log
- flutter_drive.log

publishing:
email:
recipients:
- lucas.xu@appflowy.io
notify:
success: true
failure: true
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ import '../../shared/util.dart';
void main() {
IntegrationTestWidgetsFlutterBinding.ensureInitialized();

group('document page style', () {
group('document page style:', () {
double getCurrentEditorFontSize() {
final editorPage = find
.byType(AppFlowyEditorPage)
Expand All @@ -57,11 +57,9 @@ void main() {
.single
.widget as AppFlowyEditorPage;
return editorPage.styleCustomizer
.style()
.textStyleConfiguration
.text
.height ??
PageStyleLineHeightLayout.normal.lineHeight;
.style()
.textStyleConfiguration
.lineHeight;
}

testWidgets('change font size in page style settings', (tester) async {
Expand All @@ -87,20 +85,24 @@ void main() {
await tester.openPage(gettingStarted);
// click the layout button
await tester.tapButton(find.byType(MobileViewPageLayoutButton));
var lineHeight = getCurrentEditorLineHeight();
expect(
getCurrentEditorLineHeight(),
lineHeight,
PageStyleLineHeightLayout.normal.lineHeight,
);
// change line height from normal to large
await tester.tapSvgButton(FlowySvgs.m_layout_large_s);
await tester.pumpAndSettle();
lineHeight = getCurrentEditorLineHeight();
expect(
getCurrentEditorLineHeight(),
lineHeight,
PageStyleLineHeightLayout.large.lineHeight,
);
// change line height from large to small
await tester.tapSvgButton(FlowySvgs.m_layout_small_s);
lineHeight = getCurrentEditorLineHeight();
expect(
getCurrentEditorLineHeight(),
lineHeight,
PageStyleLineHeightLayout.small.lineHeight,
);
});
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,19 +29,18 @@ import '../../shared/util.dart';
void main() {
IntegrationTestWidgetsFlutterBinding.ensureInitialized();

group('create new page', () {
group('create new page in home page:', () {
testWidgets('create document', (tester) async {
await tester.initializeAppFlowy(
cloudType: AuthenticatorType.local,
);
await tester.launchInAnonymousMode();

// tap the create page button
final createPageButton = find.byWidgetPredicate(
(widget) =>
widget is FlowySvg &&
widget.svg.path == FlowySvgs.m_home_unselected_m.path,
widget.svg.path == FlowySvgs.m_home_add_m.path,
);
await tester.tapButton(createPageButton);
await tester.pumpAndSettle();
expect(find.byType(MobileDocumentScreen), findsOneWidget);
});
});
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,9 +25,9 @@ import '../../shared/util.dart';
void main() {
IntegrationTestWidgetsFlutterBinding.ensureInitialized();

group('anonymous sign in on mobile', () {
group('anonymous sign in on mobile:', () {
testWidgets('anon user and then sign in', (tester) async {
await tester.initializeAppFlowy();
await tester.launchInAnonymousMode();

// expect to see the home page
expect(find.byType(MobileHomeScreen), findsOneWidget);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,13 @@ import 'mobile/document/page_style_test.dart' as page_style_test;
import 'mobile/home_page/create_new_page_test.dart' as create_new_page_test;
import 'mobile/sign_in/anonymous_sign_in_test.dart' as anonymous_sign_in_test;

Future<void> runIntegrationOnMobile() async {
Future<void> main() async {
Log.shared.disableLog = true;

await runIntegration1OnMobile();
}

Future<void> runIntegration1OnMobile() async {
IntegrationTestWidgetsFlutterBinding.ensureInitialized();

anonymous_sign_in_test.main();
Expand Down
4 changes: 2 additions & 2 deletions frontend/appflowy_flutter/integration_test/runner.dart
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import 'desktop_runner_5.dart';
import 'desktop_runner_6.dart';
import 'desktop_runner_7.dart';
import 'desktop_runner_8.dart';
import 'mobile_runner.dart';
import 'mobile_runner_1.dart';

/// The main task runner for all integration tests in AppFlowy.
///
Expand All @@ -28,7 +28,7 @@ Future<void> main() async {
await runIntegration7OnDesktop();
await runIntegration8OnDesktop();
} else if (Platform.isIOS || Platform.isAndroid) {
await runIntegrationOnMobile();
await runIntegration1OnMobile();
} else {
throw Exception('Unsupported platform');
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,10 @@ class _MobileViewPageState extends State<MobileViewPage> {
@override
void dispose() {
_appBarOpacity.dispose();
_scrollNotificationObserver?.removeListener(_onScrollNotification);

// there's no need to remove the listener, because the observer will be disposed when the widget is unmounted.
// inside the observer, the listener will be removed automatically.
// _scrollNotificationObserver?.removeListener(_onScrollNotification);
_scrollNotificationObserver = null;

super.dispose();
Expand Down
12 changes: 6 additions & 6 deletions frontend/appflowy_flutter/pubspec.lock
Original file line number Diff line number Diff line change
Expand Up @@ -1543,10 +1543,10 @@ packages:
dependency: transitive
description:
name: platform
sha256: "12220bb4b65720483f8fa9450b4332347737cf8213dd2840d8b2c823e47243ec"
sha256: "9b71283fc13df574056616011fb138fd3b793ea47cc509c189a6c3fa5f8a1a65"
url: "https://pub.dev"
source: hosted
version: "3.1.4"
version: "3.1.5"
plugin_platform_interface:
dependency: "direct dev"
description:
Expand Down Expand Up @@ -1941,10 +1941,10 @@ packages:
dependency: transitive
description:
name: string_scanner
sha256: "556692adab6cfa87322a115640c11f13cb77b3f076ddcc5d6ae3c20242bedcde"
sha256: "688af5ed3402a4bde5b3a6c15fd768dbf2621a614950b17f04626c431ab3c4c3"
url: "https://pub.dev"
source: hosted
version: "1.2.0"
version: "1.3.0"
string_validator:
dependency: "direct main"
description:
Expand Down Expand Up @@ -2246,10 +2246,10 @@ packages:
dependency: transitive
description:
name: vm_service
sha256: "3923c89304b715fb1eb6423f017651664a03bf5f4b29983627c4da791f74a4ec"
sha256: "5c5f338a667b4c644744b661f309fb8080bb94b18a7e91ef1dbd343bed00ed6d"
url: "https://pub.dev"
source: hosted
version: "14.2.1"
version: "14.2.5"
watcher:
dependency: transitive
description:
Expand Down

0 comments on commit fe81551

Please sign in to comment.