Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Setup CICD #133

Open
wants to merge 13 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
141 changes: 141 additions & 0 deletions .github/workflows/main.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,141 @@
on:
# action trigger
pull_request:
branches:
# - main
# - release/**
- develop
# action trigger
push:
branches:
# - main
# - release/**
- develop
name: "Build & Release"
jobs:
# build_ios:
# name: Build & Release IOS
# runs-on: macos-latest
#
# steps:
# - uses: actions/checkout@v2
#
# # - name: Select Xcode version
# # run: sudo xcode-select -s '/Applications/Xcode_11.3.app/Contents/Developer'
#
# - name: Bundle install
# run: cd ./ios && bundle install
#
# - name: Set up JDK
# uses: actions/setup-java@v1
# with:
# java-version: '12.x'
#
# - uses: subosito/flutter-action@v1
# with:
# flutter-version: '2.10.4'
# - name: Install tools
# run: |
# flutter pub get
# cd ./ios && pod install
#
# - name: Setup SSH Keys and known_hosts for fastlane match
# run: |
# SSH_PATH="$HOME/.ssh"
# mkdir -p "$SSH_PATH"
# touch "$HOME/.ssh/known_hosts"
#
# echo "$PRIVATE_KEY" > "$HOME/.ssh/id_rsa"
#
# chmod 700 "$HOME/.ssh"
# ssh-keyscan github.com >> ~/.ssh/known_hosts
# chmod 600 "$HOME/.ssh/known_hosts"
# chmod 600 "$HOME/.ssh/id_rsa"
#
# eval $(ssh-agent)
# ssh-add -K ~/.ssh/id_rsa
# env:
# PRIVATE_KEY: ${{ secrets.SSH_PRIVATE_KEY }}
#
# - name: Deploy to TestFlight
# run: |
# cd ./ios && bundle exec fastlane beta
# env:
# TEAM_ID: ${{ secrets.TEAM_ID }}
# ITC_TEAM_ID: ${{ secrets.ITC_TEAM_ID }}
# FASTLANE_USER: ${{ secrets.FASTLANE_USER }}
# FASTLANE_PASSWORD: ${{ secrets.FASTLANE_PASSWORD }}
# FASTLANE_APPLE_APPLICATION_SPECIFIC_PASSWORD: ${{ secrets.FASTLANE_APPLE_APPLICATION_SPECIFIC_PASSWORD }}
# FASTLANE_SESSION: ${{ secrets.FASTLANE_SESSION }}
# MATCH_PASSWORD: ${{ secrets.MATCH_PASSWORD }}
# MATCH_KEYCHAIN_NAME: ${{ secrets.MATCH_KEYCHAIN_NAME }}
# MATCH_KEYCHAIN_PASSWORD: ${{ secrets.MATCH_KEYCHAIN_PASSWORD }}
# DELIVER_ITMSTRANSPORTER_ADDITIONAL_UPLOAD_PARAMETERS: ${{ secrets.DELIVER_ITMSTRANSPORTER_ADDITIONAL_UPLOAD_PARAMETERS }}

build_web:
name: Build Flutter (Web)
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v1
- uses: subosito/flutter-action@v1
with:
flutter-version: '2.10.4'
- run: flutter pub get
- run: flutter config --enable-web
- run: flutter build web
- name: Deploy to Firebase
uses: w9jds/firebase-action@master
with:
args: deploy --only hosting --public build/web
env:
FIREBASE_TOKEN: ${{ secrets.FIREBASE_TOKEN }}
PROJECT_ID: default

build_android:
name: Build & Release Android
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v1
- uses: actions/setup-java@v1
with:
java-version: '12.x'
- uses: subosito/flutter-action@v1
with:
flutter-version: '2.10.4'
- run: flutter clean
- name: Cache pub dependencies
uses: actions/cache@v2
with:
path: ${{ env.FLUTTER_HOME }}/.pub-cache
key: ${{ runner.os }}-pub-${{ hashFiles('**/pubspec.lock') }}
restore-keys: ${{ runner.os }}-pub-
- run: flutter pub get
- name: Download Android keystore
id: android_keystore
uses: timheuer/[email protected]
with:
fileName: key.jks
encodedString: ${{ secrets.ANDROID_KEYSTORE_BASE64 }}

- name: Create key.properties
run: |
echo "storeFile=${{ steps.android_keystore.outputs.filePath }}" > android/key.properties
echo "storePassword=${{ secrets.ANDROID_KEYSTORE_PASSWORD }}" >> android/key.properties
echo "keyPassword=${{ secrets.ANDROID_KEY_PASSWORD }}" >> android/key.properties
echo "keyAlias=${{ secrets.ANDROID_KEY_ALIAS }}" >> android/key.properties
- run: flutter test // when have unit test


- run: flutter build appbundle
- name: Deploy to Play Store
uses: r0adkll/[email protected]
with:
serviceAccountJsonPlainText: ${{secrets.GOOGLE_SERVICE_ACCOUNT_KEY}}
packageName: ${{ secrets.ANDROID_PACKAGE_NAME }}
releaseFiles: build/app/outputs/bundle/release/app-release.aab
track: internal
status: draft
whatsNewDirectory: lib/whatsnew/

#push code to develop
#pull request on develop
5 changes: 5 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -71,3 +71,8 @@ build/
!/packages/flutter_tools/test/data/dart_dependencies_test/**/.packages
.flutter-plugins-dependencies
ios/Flutter/flutter_export_environment.sh

# Generated mobx file
*.inject.summary
*.inject.dart
*.g.dart
131 changes: 128 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,28 @@ A boilerplate project created in flutter using MobX and Provider. Boilerplate su
* For Mobile: https://github.com/zubairehman/flutter-boilerplate-project/tree/master (stable channel)
* For Web: https://github.com/zubairehman/flutter-boilerplate-project/tree/feature/web-support (beta channel)

# The difference with the original boilerplate

1. Enhance navigation using the package `page_transition` for more customizable transitions.
2. Integrate Sentry for error reporting.
3. Add utils class to show common messages and dialogs.
4. Add Lint to the project and fix all the linting issues.
5. Enhance localization using the package `intl`. This will allow you to easily localize your app with more customization.
6. Simple folder structure when using firebase (Firestore).

**Firebase:**

Checkout branch `feature/firebase` for firebase support.

# Contents
- [Getting Started](#getting-started)
- [How to Use](#how-to-use)
- [Hide Generated Files](#hide-generated-files)
- [Boilerplate Features](#boilerplate-features)
- [Wiki](#wiki)
- [Conclusion](#conclusion)
- [Setting CI-CD](#setting-ci-cd)

## Getting Started

The Boilerplate contains the minimal implementation required to create a new library or project. The repository code is preloaded with some basic components like basic app architecture, app theme, constants and required dependencies to create a new project. By using boiler plate code as standard initializer, we can have same patterns in all the projects that will inherit it. This will also help in reducing setup & development time by allowing you to use same code pattern and avoid re-writing from scratch.
Expand All @@ -16,7 +38,7 @@ The Boilerplate contains the minimal implementation required to create a new lib
Download or clone this repo by using the link below:

```
https://github.com/zubairehman/flutter-boilerplate-project.git
https://github.com/kitemetric/flutter-boilerplate-project.git
```

**Step 2:**
Expand All @@ -41,6 +63,18 @@ or watch command in order to keep the source code synced automatically:
flutter packages pub run build_runner watch
```

**Step 4: intl (l10n)**

This project uses `l10n` library that works with code generation, execute the following command to generate files:

```
flutter gen-l10n
```

**Step 5: Setup Sentry**

This project uses `Sentry` so you have to add Sentry DNS to be able to use Sentry in the project. Change the ```option.dns``` in `main.dart` or disable all Sentry related code in `main.dart` to disable Sentry.

## Hide Generated Files

In-order to hide generated files, navigate to `Android Studio` -> `Preferences` -> `Editor` -> `File Types` and paste the below lines under `ignore files and folders` section:
Expand All @@ -56,7 +90,7 @@ In Visual Studio Code, navigate to `Preferences` -> `Settings` and search for `F
**/*.g.dart
```

## Boilerplate Features:
## Boilerplate Features

* Splash
* Login
Expand All @@ -74,8 +108,9 @@ In Visual Studio Code, navigate to `Preferences` -> `Settings` and search for `F
* Logging
* Dependency Injection
* Dark Theme Support (new)
* Multilingual Support (new)
* Provider example (new)
* Sentry (new)
* intl (new)

### Up-Coming Features:

Expand All @@ -88,6 +123,7 @@ In Visual Studio Code, navigate to `Preferences` -> `Settings` and search for `F
* [Database](https://github.com/tekartik/sembast.dart)
* [MobX](https://github.com/mobxjs/mobx.dart) (to connect the reactive data of your application with the UI)
* [Provider](https://github.com/rrousselGit/provider) (State Management)
* [intl] (https://github.com/dart-lang/intl)
* [Encryption](https://github.com/xxtea/xxtea-dart)
* [Validation](https://github.com/dart-league/validators)
* [Logging](https://github.com/zubairehman/Flogs)
Expand Down Expand Up @@ -294,3 +330,92 @@ I will be happy to answer any questions that you may have on this approach, and

Again to note, this is example can appear as over-architectured for what it is - but it is an example only. If you liked my work, don’t forget to ⭐ star the repo to show your support.


## Setting CI-CD
Web-Android using github actions, iOS using Codemagic

**Web and Android auto build and deploy/public to Firebase hosting/Internal Testing CH Play when trigger occurred, the only thing have to do is config env (only git repo owner can do that)**

### Web
**Config env**

You have to set the values below to GitHub secrets. [How to set the value to GitHub secrets.](https://github.com/Azure/actions-workflow-samples/blob/master/assets/create-secrets-for-GitHub-workflows.md)

`FIREBASE_TOKEN`

How to get FIREBASE_TOKEN: run cmd `firebase login:ci`

### Android
You have to set the value to GitHub secrets. [How to set the value to GitHub secrets.](https://github.com/Azure/actions-workflow-samples/blob/master/assets/create-secrets-for-GitHub-workflows.md)

`ANDROID_KEYSTORE_BASE64`

`ANDROID_KEYSTORE_PASSWORD`

`ANDROID_KEY_PASSWORD`

`ANDROID_KEY_ALIAS`

`GOOGLE_SERVICE_ACCOUNT_KEY`

`ANDROID_PACKAGE_NAME`

[How to get the above values.](https://viblo.asia/p/cai-dat-don-gian-automating-publishing-flutter-app-len-google-play-bang-github-actions-63vKjg1dZ2R)

### iOS
To automatic build and deploy new version to TestFlight, we using **CodeMagic**

**Step 1: Register**

Register your app on Codemagic, fetch your codemagic.yaml to Codemagic

**Step 2: Setup**

*Environment*: need to provide the following values:
```yaml
PROVISIONING_PROFILE: # A file prefixed with .mobileprovision
CERTIFICATE: #A file prefixed with .p12
CERTIFICATE_PASSWORD: #When you create a certificate, it will include a password for this certificate, remember it
flutter: #Target flutter version
xcode: #Target xcode version
cocoapods: #Target cocoapods version
```
[What's Provision Profile and How to get?](https://viblo.asia/p/phan-3-provisioning-profiles-gAm5yjqLKdb)

[What's Certificate and How to get?](https://stackoverflow.com/questions/9418661/how-to-create-p12-certificate-for-ios-distribution)

*Trigger*: When the trigger occurs, the application will automatically build
```yaml
triggering:
events:
- tag
branch_patterns:
- pattern: '*'
include: true
source: true
tag_patterns:
- pattern: release-production*
include: true
```
Current trigger: push tag with tag's name: `release-production*` or `release-staging*`, `*` can be version name like `-v2.1.0`

*Publishing*: need to provide some information to be able to automatically publish the app to testflight
```yaml
publishing:
# have to config
app_store_connect:
api_key:
key_id:
issuer_id:
submit_to_testflight: false
submit_to_app_store: false
```
Only role `ADMIN` in `User and Access` can create new api key and get them [Setup App Store Connect API key](https://support.appmachine.com/support/solutions/articles/80001023345-v2-how-to-setup-app-store-connect-api-key)

However, you still have to manual the last step at testflight to roll out for testers.


CodeMagic provides 2 ways for setup the workflow, above I mentioned how to use .yaml file to write workflow.
In addition, you can refer to how to use Workflow Editor to create your workflow at [Easy to setup CodeMagic!](https://docs.codemagic.io/yaml-quick-start/building-a-flutter-app/)


33 changes: 33 additions & 0 deletions analysis_options.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
# This file configures the analyzer to use the lint rule set from `package:lint`

# For apps, use the default set
include: package:lint/analysis_options.yaml

# Packages, that may be distributed (i.e. via pub.dev) should use the package
# version, resulting in a better pub score.
# include: package:lint/analysis_options_package.yaml

# You might want to exclude auto-generated files from dart analysis
analyzer:
exclude:
- '**.g.dart'

# You can customize the lint rules set to your own liking. A list of all rules
# can be found at https://dart-lang.github.io/linter/lints/options/options.html
linter:
rules:
# Util classes are awesome!
throw_of_invalid_type: false
avoid_classes_with_only_static_members: false
require_trailing_commas: false
sort_pub_dependencies: false
use_setters_to_change_properties: false
avoid_print: false
constant_identifier_names: false

# Make constructors the first thing in every class
# sort_constructors_first: true

# Choose wisely, but you don't have to
# prefer_double_quotes: true
# prefer_single_quotes: true
4 changes: 4 additions & 0 deletions assets/lang/da.json → assets/lang/app_da.arb
Original file line number Diff line number Diff line change
@@ -1,4 +1,8 @@
{
"message_success": "Succes",
"message_error": "Fejl",
"message_information": "Information",

"login_start": "Below are list of strings for login da ",
"login_et_user_email": "Brugernavn",
"login_et_user_password": "Adgangskode",
Expand Down
4 changes: 4 additions & 0 deletions assets/lang/en.json → assets/lang/app_en.arb
Original file line number Diff line number Diff line change
@@ -1,4 +1,8 @@
{
"message_success": "Success",
"message_error": "Error",
"message_information": "Information",

"login_start": "Below are list of strings for login",
"login_et_user_email": "Enter user email",
"login_et_user_password": "Enter password",
Expand Down
4 changes: 4 additions & 0 deletions assets/lang/es.json → assets/lang/app_es.arb
Original file line number Diff line number Diff line change
@@ -1,4 +1,8 @@
{
"message_success": "Éxito",
"message_error": "Error",
"message_information": "Información",

"login_start": "Below are list of strings for login es ",
"login_et_user_email": "Ingrese el correo electrónico del usuario",
"login_et_user_password": "Introducir la contraseña",
Expand Down
Loading