diff --git a/.github/actions/build_android/action.yml b/.github/actions/build_android/action.yml new file mode 100644 index 000000000..7a3fb081a --- /dev/null +++ b/.github/actions/build_android/action.yml @@ -0,0 +1,48 @@ +name: Build Android app +description: Build and upload Android app +inputs: + version: + required: true + description: "App version" + build_version: + required: true + description: "Build version" + store_artifacts: + required: false + description: "Store artifact" + prod_release: + required: true + description: "Is prod release" + +runs: + using: "composite" + steps: + - name: Setup Java + uses: actions/setup-java@v3.13.0 + with: + distribution: "adopt" + java-version: 17 + + - name: Setup Flutter environment + uses: ./.github/actions/setup_flutter_environment + with: + prod_release: ${{ inputs.prod_release }} + + - name: Build appbundle (dev) + if: ${{ inputs.prod_release != 'true' }} + run: flutter build appbundle --flavor development --release --build-name ${{ inputs.version }} --build-number ${{ inputs.build_version }} --target lib/main_development.dart + shell: bash + + - name: Build appbundle (prod) + if: ${{ inputs.prod_release == 'true' }} + run: flutter build appbundle --flavor production --release --build-name ${{ inputs.version }} --build-number ${{ inputs.build_version }} --target lib/main_production.dart + shell: bash + + - name: Upload Android build + if: ${{ !!inputs.store_artifacts }} + uses: actions/upload-artifact@v3.1.3 + with: + name: android + path: build/app/outputs/bundle/release + retention-days: 1 + if-no-files-found: error diff --git a/.github/actions/build_ios/action.yml b/.github/actions/build_ios/action.yml new file mode 100644 index 000000000..663880699 --- /dev/null +++ b/.github/actions/build_ios/action.yml @@ -0,0 +1,64 @@ +name: Build iOS app +description: Build and upload iOS app +inputs: + version: + required: true + description: "App version" + build_version: + required: true + description: "Build version" + apple_ios_signing_cert: + required: true + description: "iOS signing certificate" + apple_ios_signing_cert_pw: + required: true + description: "iOS signing certificate password base 64 encoded" + apple_ios_provisioning_profile: + required: true + description: "Provisioning profile" + apple_keychain_pw: + required: true + description: "Keychain password" + store_artifacts: + required: true + description: "Store artifact" + prod_release: + required: true + description: "Is prod release" + +runs: + using: "composite" + steps: + - name: Install Apple certificate and provisioning profile + if: ${{ inputs.prod_release != 'true' }} + run: .github/scripts/setup_certs.sh + env: + APPLE_IOS_SIGNING_CERT: ${{ inputs.apple_ios_signing_cert }} + APPLE_IOS_SIGNING_CERT_PW: ${{ inputs.apple_ios_signing_cert_pw }} + APPLE_IOS_PROVISIONING_PROFILE: ${{ inputs.apple_ios_provisioning_profile }} + APPLE_KEYCHAIN_PW: ${{ inputs.apple_keychain_pw }} + shell: bash + + - name: Setup Flutter environment + uses: ./.github/actions/setup_flutter_environment + with: + prod_release: ${{ inputs.prod_release }} + + - name: Build iOS (dev) + if: ${{ inputs.prod_release != 'true' }} + run: .github/scripts/build_ios_dev.sh ${{ inputs.version }} ${{ inputs.build_version }} + shell: bash + + - name: Build iOS (prod) + if: ${{ inputs.prod_release == 'true' }} + run: .github/scripts/build_ios_prod.sh ${{ inputs.version }} ${{ inputs.build_version }} + shell: bash + + - name: Upload iOS build + if: ${{ inputs.store_artifacts }} + uses: actions/upload-artifact@v3.1.3 + with: + name: ios + path: build-output/ios + retention-days: 1 + if-no-files-found: error \ No newline at end of file diff --git a/.github/actions/setup_flutter_environment/action.yml b/.github/actions/setup_flutter_environment/action.yml new file mode 100644 index 000000000..93fdfa4df --- /dev/null +++ b/.github/actions/setup_flutter_environment/action.yml @@ -0,0 +1,32 @@ +name: Setup Flutter environment +description: Setup the Flutter environment +inputs: + prod_release: + required: false + default: 'false' + description: "Is prod release" + +env: + FLUTTER_VERSION: 3.13.7 + +runs: + using: "composite" + steps: + - name: Setup Flutter environment + uses: subosito/flutter-action@v2.11.0 + with: + flutter-version: ${{ env.FLUTTER_VERSION }} + channel: "stable" + + - name: Download dependencies + run: flutter pub get + shell: bash + + - name: Replace target URI in Production + if: ${{ inputs.prod_release == 'true' }} + run: sed -i'' -e 's/.env.develop/.env.production/' lib/env/env.dart + shell: bash + + - name: Generate code + run: dart run build_runner build + shell: bash \ No newline at end of file diff --git a/.github/scripts/build-dev.sh b/.github/scripts/build_ios_dev.sh similarity index 100% rename from .github/scripts/build-dev.sh rename to .github/scripts/build_ios_dev.sh diff --git a/.github/scripts/build-prod.sh b/.github/scripts/build_ios_prod.sh similarity index 100% rename from .github/scripts/build-prod.sh rename to .github/scripts/build_ios_prod.sh diff --git a/.github/scripts/setup-certs.sh b/.github/scripts/setup_certs.sh similarity index 100% rename from .github/scripts/setup-certs.sh rename to .github/scripts/setup_certs.sh diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index eda819db7..ead262534 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -1,4 +1,4 @@ -name: Build and test +name: Build application on: pull_request: @@ -8,22 +8,20 @@ on: workflow_call: inputs: - storeArtifacts: + store_artifacts: type: boolean required: false default: false - prodRelease: + prod_release: type: boolean required: false - tagName: + tag_name: type: string required: false env: - FLUTTER_VERSION: 3.13.1 - JAVA_VERSION: 17.x - PROD_RELEASE: ${{ inputs.prodRelease || 'false' }} - TAG_NAME: ${{ inputs.tagName || 'dev' }} + PROD_RELEASE: ${{ inputs.prod_release || 'false' }} + TAG_NAME: ${{ inputs.tag_name || 'dev' }} jobs: version: @@ -55,67 +53,35 @@ jobs: name: Build iOS App runs-on: macos-latest needs: [version] - steps: - name: Checkout code uses: actions/checkout@v4.1.0 - - name: Install Apple certificate and provisioning profile (dev) - if: env.PROD_RELEASE != 'true' - run: .github/scripts/setup-certs.sh - env: - APPLE_IOS_SIGNING_CERT: ${{ secrets.APPLE_IOS_SIGNING_CERTIFICATE_DEVELOPMENT }} - APPLE_IOS_SIGNING_CERT_PW: ${{ secrets.APPLE_IOS_SIGNING_CERTIFICATE_DEVELOPMENT_PASSWORD }} - APPLE_IOS_PROVISIONING_PROFILE: ${{ secrets.APPLE_IOS_PROVISIONING_PROFILE_DEVELOPMENT }} - APPLE_KEYCHAIN_PW: ${{ secrets.APPLE_KEYCHAIN_PW }} - - - name: Install Apple certificate and provisioning profile (prod) - if: env.PROD_RELEASE== 'true' - run: .github/scripts/setup-certs.sh - env: - APPLE_IOS_SIGNING_CERT: ${{ secrets.APPLE_IOS_SIGNING_CERT_PROD }} - APPLE_IOS_SIGNING_CERT_PW: ${{ secrets.APPLE_IOS_SIGNING_CERT_PW }} - APPLE_IOS_PROVISIONING_PROFILE: ${{ secrets.APPLE_IOS_PROVISIONING_PROFILE_PROD }} - APPLE_KEYCHAIN_PW: ${{ secrets.APPLE_KEYCHAIN_PW }} - - - name: Setup Java - uses: actions/setup-java@v3.13.0 + - name: Build iOS app (dev) + if: ${{ env.PROD_RELEASE != 'true' }} + uses: ./.github/actions/build_ios with: - distribution: "adopt" - java-version: ${{ env.JAVA_VERSION }} - - - name: Setup Flutter environment - uses: subosito/flutter-action@v2.11.0 + version: ${{ needs.version.outputs.version }} + build_version: ${{ needs.version.outputs.build_version }} + apple_ios_signing_cert: ${{ secrets.APPLE_IOS_SIGNING_CERTIFICATE_DEVELOPMENT }} + apple_ios_signing_cert_pw: ${{ secrets.APPLE_IOS_SIGNING_CERTIFICATE_DEVELOPMENT_PASSWORD }} + apple_ios_provisioning_profile: ${{ secrets.APPLE_IOS_PROVISIONING_PROFILE_DEVELOPMENT }} + apple_keychain_pw: ${{ secrets.APPLE_KEYCHAIN_PW }} + store_artifacts: ${{ inputs.store_artifacts }} + prod_release: ${{ env.PROD_RELEASE }} + + - name: Build iOS app (prod) + if: ${{ env.PROD_RELEASE == 'true' }} + uses: ./.github/actions/build_ios with: - flutter-version: ${{ env.FLUTTER_VERSION }} - channel: "stable" - - - name: Download dependencies - run: flutter pub get - - - name: Set URI (prod) - if: env.PROD_RELEASE == 'true' - run: sed -i '' 's/.env.develop/.env.production/' lib/env/env.dart - - - name: Generate code - run: dart run build_runner build - - - name: Create Development build - if: env.PROD_RELEASE != 'true' - run: .github/scripts/build-dev.sh ${{ needs.version.outputs.version }} ${{ needs.version.outputs.build_version }} - - - name: Create Production build - if: env.PROD_RELEASE == 'true' - run: .github/scripts/build-prod.sh ${{ needs.version.outputs.version }} ${{ needs.version.outputs.build_version }} - - - name: Upload iOS build - if: ${{ inputs.storeArtifacts }} - uses: actions/upload-artifact@v3.1.3 - with: - name: ios - path: build-output/ios - retention-days: 1 - if-no-files-found: error + version: ${{ needs.version.outputs.version }} + build_version: ${{ needs.version.outputs.build_version }} + apple_ios_signing_cert: ${{ secrets.APPLE_IOS_SIGNING_CERT_PROD }} + apple_ios_signing_cert_pw: ${{ secrets.APPLE_IOS_SIGNING_CERT_PW }} + apple_ios_provisioning_profile: ${{ secrets.APPLE_IOS_PROVISIONING_PROFILE_PROD }} + apple_keychain_pw: ${{ secrets.APPLE_KEYCHAIN_PW }} + store_artifacts: ${{ inputs.store_artifacts }} + prod_release: ${{ env.PROD_RELEASE }} build_android: name: Build Android App @@ -125,79 +91,10 @@ jobs: - name: Checkout code uses: actions/checkout@v4.1.0 - - name: Setup Java - uses: actions/setup-java@v3.13.0 - with: - distribution: "adopt" - java-version: ${{ env.JAVA_VERSION }} - - - name: Setup Flutter environment - uses: subosito/flutter-action@v2.11.0 - with: - flutter-version: ${{ env.FLUTTER_VERSION }} - channel: "stable" - - - name: Download dependencies - run: flutter pub get - - - name: Set URI (prod) - if: env.PROD_RELEASE == 'true' - run: sed -i 's/.env.develop/.env.production/' lib/env/env.dart - - - name: Generate code - run: dart run build_runner build - - - name: Build appbundle (dev) - if: env.PROD_RELEASE != 'true' - run: flutter build apk --flavor development --release --build-name ${{ needs.version.outputs.version }} --build-number ${{ needs.version.outputs.build_version }} --target lib/main_development.dart - - - name: Build appbundle (prod) - if: env.PROD_RELEASE== 'true' - run: flutter build apk --flavor production --release --dart-define=IS_PROD=true --build-name ${{ needs.version.outputs.version }} --build-number ${{ needs.version.outputs.build_version }} --target lib/main_production.dart - - - name: Upload Android build - if: ${{ inputs.storeArtifacts }} - uses: actions/upload-artifact@v3.1.3 - with: - name: android - path: build/app/outputs/flutter-apk - retention-days: 1 - if-no-files-found: error - - test: - name: Test Flutter app - runs-on: ubuntu-latest - - steps: - - name: Checkout code - uses: actions/checkout@v4.1.0 - - - name: Setup Flutter environment - uses: subosito/flutter-action@v2.11.0 - with: - flutter-version: ${{ env.FLUTTER_VERSION }} - channel: "stable" - - - name: Download dependencies - run: flutter pub get - - - name: Generate code - run: dart run build_runner build - - - name: Check formatting - run: dart format --set-exit-if-changed lib/ - - - name: Static Analysis - run: flutter analyze - - - name: Run Code Metrics - run: dart run dart_code_metrics:metrics --reporter=github lib - - - name: Run tests - run: flutter test --coverage - - - name: Upload test report to Codecov - uses: codecov/codecov-action@v3.1.4 + - name: Build Android app + uses: ./.github/actions/build_android with: - flags: unittests - file: coverage/lcov.info + version: ${{ needs.version.outputs.version }} + build_version: ${{ needs.version.outputs.build_version }} + store_artifacts: ${{ inputs.store_artifacts }} + prod_release: ${{ env.PROD_RELEASE }} diff --git a/.github/workflows/codesee-arch-diagram.yml b/.github/workflows/codesee.yml similarity index 87% rename from .github/workflows/codesee-arch-diagram.yml rename to .github/workflows/codesee.yml index 806d41d12..5e38b969b 100644 --- a/.github/workflows/codesee-arch-diagram.yml +++ b/.github/workflows/codesee.yml @@ -2,8 +2,7 @@ # This is v2.0 of this workflow file on: push: - branches: - - main + branches: [ main ] pull_request_target: types: [opened, synchronize, reopened] @@ -15,7 +14,7 @@ jobs: codesee: runs-on: ubuntu-latest continue-on-error: true - name: Analyze the repo with CodeSee + name: Analyze repository steps: - uses: Codesee-io/codesee-action@v2 with: diff --git a/.github/workflows/release-dev.yml b/.github/workflows/release-dev.yml index 9fe2f63b4..cbcfc326a 100644 --- a/.github/workflows/release-dev.yml +++ b/.github/workflows/release-dev.yml @@ -5,17 +5,20 @@ on: branches: [ main ] jobs: - build_and_test: + build: uses: ./.github/workflows/build.yml with: - storeArtifacts: true - prodRelease: false + store_artifacts: true + prod_release: false secrets: inherit - dev_upload_ios: + test: + uses: ./.github/workflows/test.yml + + upload_ios: name: Upload iOS build to Firebase App Distribution runs-on: ubuntu-latest - needs: [build_and_test] + needs: [build, test] steps: - name: Download Artifact @@ -33,10 +36,10 @@ jobs: groups: analogio-devs file: Analog.ipa - dev_upload_android: + upload_android: name: Upload Android build to Firebase App Distribution runs-on: ubuntu-latest - needs: [build_and_test] + needs: [build, test] steps: - name: Download artifact diff --git a/.github/workflows/release-prod.yml b/.github/workflows/release-prod.yml index fd207e87e..5f628d277 100644 --- a/.github/workflows/release-prod.yml +++ b/.github/workflows/release-prod.yml @@ -2,21 +2,24 @@ name: Release Production App on: release: - types: [created] + types: [ created ] jobs: - build_and_test: + build: uses: ./.github/workflows/build.yml with: - storeArtifacts: true - prodRelease: true - tagName: ${{ github.event.release.tag_name }} + store_artifacts: true + prod_release: true + tag_name: ${{ github.event.release.tag_name }} secrets: inherit - prod_release_ios: + test: + uses: ./.github/workflows/test.yml + + release_ios: name: Upload iOS build to App Store connect runs-on: macos-latest - needs: [build_and_test] + needs: [build, test] steps: - name: Download artifact @@ -31,10 +34,10 @@ jobs: run: | xcrun altool --upload-app -t ios -f "Analog.ipa" -u "$APP_STORE_CONNECT_USERNAME" -p "$APP_STORE_CONNECT_PASSWORD" - prod_release_android: + release_android: name: Upload Android build to Play Store runs-on: ubuntu-latest - needs: [build_and_test] + needs: [build, test] steps: - name: Download artifact diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml new file mode 100644 index 000000000..0ee0e0936 --- /dev/null +++ b/.github/workflows/test.yml @@ -0,0 +1,33 @@ +name: Test + +on: + pull_request: + branches: [ main ] + + workflow_call: + +jobs: + test: + name: Test app + runs-on: ubuntu-latest + steps: + - name: Checkout code + uses: actions/checkout@v3 + + - name: Setup Flutter environment + uses: ./.github/actions/setup_flutter_environment + + - name: Check formatting + run: dart format --set-exit-if-changed lib/ + + - name: Static Analysis + run: flutter analyze + + - name: Run tests + run: flutter test --coverage + + - name: Upload test report to Codecov + uses: codecov/codecov-action@v3.1.4 + with: + flags: unittests + file: coverage/lcov.info \ No newline at end of file