Last active
November 19, 2024 13:56
-
-
Save logickoder/67978325e23d0df326db2d263e6349c0 to your computer and use it in GitHub Desktop.
My Flutter CI/CD Workflow
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# From .github/workflows/build-production.yml | |
name: Build and upload android app to Google Play Store | |
on: | |
push: | |
branches: | |
- main | |
paths: | |
- 'android/**' | |
- 'lib/**' | |
- 'pubspec.yaml' | |
workflow_dispatch: | |
concurrency: | |
group: ${{ github.workflow }}-${{ github.ref }} | |
cancel-in-progress: true | |
jobs: | |
build: | |
runs-on: ubuntu-latest | |
steps: | |
- uses: actions/checkout@v4 | |
- name: Set up Python | |
uses: actions/setup-python@v5 | |
with: | |
python-version: '3.x' | |
- name: Install dependencies | |
run: | | |
python -m pip install --upgrade pip | |
pip install -r ./.github/scripts/requirements.txt | |
- name: set up JDK 17 | |
uses: actions/setup-java@v4 | |
with: | |
java-version: '17' | |
distribution: 'temurin' | |
cache: 'gradle' | |
- name: Set up Flutter | |
uses: subosito/flutter-action@v2 | |
with: | |
channel: "stable" | |
- run: flutter --version | |
- name: Install dependencies | |
run: flutter pub get | |
- name: Run build runner | |
run: flutter pub run build_runner build --delete-conflicting-outputs | |
- name: Build production aab | |
run: | | |
python -u .github/scripts/build_android_production.py | |
- name: Upload aab to Google Drive | |
uses: logickoder/g-drive-upload@main | |
with: | |
credentials: ${{ secrets.GCP_CREDENTIAL }} | |
filename: app-production.aab | |
folderId: ${{ secrets.DRIVE_FOLDER_ID }} | |
overwrite: "true" | |
mimeType: "application/vnd.android.package-archive" | |
- name: Deploy aab to Play Store | |
uses: r0adkll/upload-google-play@v1 | |
with: | |
serviceAccountJsonPlainText: ${{ secrets.GCP_CREDENTIAL }} | |
packageName: 'dev.logickoder.app' | |
releaseFiles: app-production.aab | |
mappingFile: build/app/outputs/mapping/release/mapping.txt | |
debugSymbols: build/app/intermediates/merged_native_libs/release/out/lib | |
inAppUpdatePriority: 5 | |
track: production | |
status: completed |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# From .github/workflows/build-staging.yml | |
name: Build and upload staging app to Google Drive | |
on: | |
push: | |
branches: | |
- staging | |
paths: | |
- 'android/**' | |
- 'lib/**' | |
- 'pubspec.yaml' | |
workflow_dispatch: | |
concurrency: | |
group: ${{ github.workflow }}-${{ github.ref }} | |
cancel-in-progress: true | |
jobs: | |
build: | |
runs-on: ubuntu-latest | |
steps: | |
- uses: actions/checkout@v4 | |
- name: Set up Python | |
uses: actions/setup-python@v5 | |
with: | |
python-version: '3.x' | |
- name: Install dependencies | |
run: | | |
python -m pip install --upgrade pip | |
pip install -r ./.github/scripts/requirements.txt | |
- name: set up JDK 17 | |
uses: actions/setup-java@v4 | |
with: | |
java-version: '17' | |
distribution: 'temurin' | |
cache: 'gradle' | |
- name: Set up Flutter | |
uses: subosito/flutter-action@v2 | |
with: | |
channel: "stable" | |
- run: flutter --version | |
- name: Install dependencies | |
run: flutter pub get | |
- name: Run build runner | |
run: flutter pub run build_runner build --delete-conflicting-outputs | |
- name: Build staging apk | |
run: | | |
python -u .github/scripts/build_android_staging.py | |
- name: Upload staging apk to Google Drive | |
uses: logickoder/g-drive-upload@main | |
with: | |
credentials: ${{ secrets.GCP_CREDENTIAL }} | |
filename: ${{ env.FILE_NAME }} | |
folderId: ${{ secrets.DRIVE_FOLDER_ID }} | |
overwrite: "true" | |
mimeType: "application/vnd.android.package-archive" |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# From .github/scripts/build_android.py | |
import os | |
import subprocess | |
from dotenv import load_dotenv | |
def build(extension=None, environment=None, version_name=None, version_code=None): | |
'''Builds the android app based on the extension (apk or aab), environment (production or staging) and the version information''' | |
load_dotenv() | |
workspace = os.getenv('GITHUB_WORKSPACE') | |
os.chdir(workspace) | |
is_actions = os.getenv('GITHUB_ACTIONS') == 'true' | |
extension = extension or os.getenv('EXTENSION') or 'apk' | |
environment = environment or os.getenv('ENVIRONMENT') or 'staging' | |
# Determine the build params from the extension and environment | |
config_file = "config.staging.json" if environment == "staging" else "config.json" | |
build_format = "apk" if extension == "apk" else "appbundle" | |
app_name = "app-staging" if environment == "staging" else "app-production" | |
version_name = version_name or os.getenv('VERSION_NAME') or "1.0.0" | |
version_code = version_code or os.getenv('VERSION_CODE') or "1" | |
# print all the calculated values | |
print( | |
f"Build extension: {extension}, Environment: {environment}, Config file: {config_file}, Build format: {build_format}, App name: {app_name}, Version name: {version_name}, Version code: {version_code}") | |
# Construct the build command | |
build_command = [ | |
"flutter", "build", build_format, | |
f"--dart-define-from-file={config_file}", | |
f"--build-name={version_name}", | |
f"--build-number={version_code}" | |
] | |
if not is_actions: | |
build_command.insert(0, "/c") | |
build_command.insert(0, "cmd") | |
subprocess.run(build_command, check=True) | |
# Determine the output file paths | |
if extension == "apk": | |
file_path = f"build/app/outputs/flutter-apk/app-release.apk" | |
else: | |
file_path = f"build/app/outputs/bundle/release/app-release.aab" | |
# Set the FILE_NAME and move the file | |
os.rename(file_path, f"{workspace}/{app_name}.{extension}") | |
with open(os.getenv('GITHUB_ENV') or f"{workspace}\\.github\\env", "a") as env_file: | |
env_file.write(f"FILE_NAME={app_name}.{extension}\n") | |
if __name__ == '__main__': | |
build() |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# From .github/scripts/build_android_production.py | |
from build_android import build | |
from get_version import get_version | |
if __name__ == '__main__': | |
version_name, version_code = get_version() | |
build(extension='aab', environment='production', version_name=version_name, version_code=version_code) |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# From .github/scripts/build_android_staging.py | |
from build_android import build | |
from get_version import get_version | |
if __name__ == '__main__': | |
version_name, version_code = get_version() | |
build(extension='apk', environment='staging', version_name=version_name, version_code=version_code) |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/bin/sh | |
# From ios/ci_scripts/ci_post_clone.sh | |
# Runner | |
# Make sure to setup XCode Cloud and link your repo to trigger the build | |
# Created by logickoder on 17/09/2024 with help from Dirisu Jesse | |
# | |
# Fail this script if any subcommand fails. | |
#set -e | |
# The default execution directory of this script is the ci_scripts directory. | |
cd $CI_PRIMARY_REPOSITORY_PATH # change working directory to the root of your cloned repo. | |
# Install Flutter using git. | |
git clone https://github.com/flutter/flutter.git --depth 1 -b stable $HOME/flutter | |
export PATH="$PATH:$HOME/flutter/bin" | |
# Install FlutterFire CLI | |
echo "Installing FlutterFire CLI..." | |
dart pub global activate flutterfire_cli | |
export PATH="$PATH":"$HOME/.pub-cache/bin" | |
# Install Flutter artifacts for iOS (--ios) platform. | |
flutter precache --ios | |
# Install Flutter dependencies. | |
flutter pub get | |
# Generate files | |
flutter packages pub run build_runner build --delete-conflicting-outputs | |
# Install CocoaPods using Homebrew. | |
HOMEBREW_NO_AUTO_UPDATE=1 # disable homebrew's automatic updates. | |
brew install cocoapods | |
# Install CocoaPods dependencies. | |
pod install # run `pod install` in the `ios` directory. | |
# Check flutter installation health | |
flutter doctor -v | |
# Build iOS app | |
# xcodebuild -project Runner.xcodeproj -archivePath ../../build/ios/archive/Runner.xcarchive | |
if [ "$ENVIRONMENT" = "production" ]; then | |
flutter build ios --release --dart-define-from-file=config.json | |
else | |
flutter build ios --release --dart-define-from-file=config.staging.json | |
fi | |
# Close out successfully | |
exit 0 |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# From .github/scripts/get_version.py | |
import os | |
import yaml | |
from dotenv import load_dotenv | |
def get_version(): | |
'''Fetches the current app version from pubspec.yaml or 1.0.0+1 if it can't retrieve it''' | |
load_dotenv() | |
os.chdir(os.getenv('GITHUB_WORKSPACE')) | |
with open("pubspec.yaml", 'r') as stream: | |
try: | |
pubspec = yaml.safe_load(stream) | |
version = pubspec.get('version', '1.0.0+1') | |
version_name, version_code = version.split('+') | |
return version_name, version_code | |
except yaml.YAMLError as exc: | |
print(f"::error ::{exc}") | |
return "1.0.0", "1" | |
if __name__ == '__main__': | |
get_version() |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# From .github/scripts/requirements.txt | |
python-dotenv==1.0.1 | |
PyYAML==6.0.2 |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
My complete pipeline for building and pushing my flutter app to play and app store.
You can tweak to your usecase.
iOS is run with only the ci_post_clone.sh, you have to link the repo to Xcode Cloud for it to work.
Android is run with the other files.
You can notice at the top of each file a comment #From ${path}, path represents where the files should be placed relative to the root of your flutter project