Skip to content

akabanov/sneaky_bird_apps_template

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

New Flutter project template

This is a template for the upcoming https://sneakybird.app applications.

Audience

I'm crafting this project for personal use with two objectives in mind:

  • To be able to kick-start new Flutter projects with all the required integrations and boilerplate ready out of the box
  • Learn the production and maintenance process end-to-end

The snippets and the setup script are designed for Ubuntu 24.04. While some of these many may work in other environments, others may require tweaking.

I don't have a Mac, so the iOS building and publishing runs on Codemagic. I have configured Fastlane to run both on Codemagic and locally, but haven't tested the latter.

Licence

This template is available UNLICENSED.

Status

The template is ready to use:

  • Make sure you have all the prerequisites
  • Use this template to create your app GitHub repository
  • Run the setup script and follow the prompts
    allow up to an hour: you'll need to manually add a Play Store App and upload the initial build

The newly initialised project will have Fastlane targets to publish test builds both to App Store Connect and Google Play Console.

See the Roadmap section below for what's to come.

Quick actions

Release to Internal Google Play Console track:

bundle exec fastlane android internal

Release to Apple Test Flight (on Codemagic):

./ci.sh ios-beta

Quick release (no tests, no Shorebird) to Apple Test Flight (on Codemagic):

./ci.sh ios-beta true

Build Android app locally and submit to Test Lab to run integration tests:

pushd android
bundle exec fastlane android test_lab
popd

Set current project for gcloud tool:

gcloud config set project project-id-placeholder

Backup the source code:

mkdir -p ~/.backups
zip -r ~/.backups/$(basename "$PWD")-$(date +"%Y%m%d%H%M%S").zip ./

Application screen label

Application screen label (the text under the app icon) is set in APP_LABEL_SCREEN in the project's .env file. Just update this value and run:

pushd ios
bundle exec fastlane ios update_app_screen_label
popd
pushd android
bundle exec fastlane android update_app_screen_label
popd

Application icon

In order to change the app launch icon, create a master png icon, 1024 x 1024 px, save it as assets/dev/master_app_icon.png, and run:

. .env
dart run flutter_launcher_icons
cp -r web/icons/Icon-512.png "assets/dev/android/${PRIMARY_APP_LANGUAGE}/images/icon.png"
# Reverts AppIcon back to wider-scoped YES
sed -i 's/ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = AppIcon;/ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES;/' ios/Runner.xcodeproj/project.pbxproj

Permissions, capabilities and entitlements

If you're using XCode, you do not need to update the Info.plist and Runner.entitlements manually.

The checklist:

Resources

Local reference files:

External links:

Prerequisites

These are configured once (not per project).

Note: This instruction uses a convention of storing the secrets in .secrets directory in user's $HOME. The files layout is as follows:

  • ~/.secrets/{service-or-product}/{secret-file} for generic secrets (such as access tokens and passwords)
  • ~/.secrets/app/{app_name}/{secret-file} for application secrets (such as push certificates)

All env variables from this document (except PATH and related) are defined in ~/.secrets/.bashrc_creds. Call it from your .bashrc. For example source $HOME/.secrets/.bashrc_creds.

Create the directory, an empty env variables file, the script for backing up secrets, and a password for backups:

mkdir -p ~/.secrets
pushd ~/.secrets

# Create an empty file for the env variables
[ ! -f ".bashrc_creds" ] && touch ".bashrc_creds"

# Create password for secrets backups
[ ! -f "backup-pass" ] && openssl rand -base64 8 > "backup-pass"

# Create a backup script
echo 'pushd ~/.secrets; zip -r -P "$(<backup-pass)" ~/.backups/secrets-$(date +"%Y%m%d%H%M%S").zip ./; popd' > backup.sh
chmod +x backup.sh
popd 

Note the password from backup-pass somewhere safe and use backup.sh to back up your ~/.secrets directory content to ~/.backups directory as a password-protected zip file.

It is recommended to create a backup every time you add or update a secret. Rehearse the restoration at least once.

Do not change proposed variable names. Some tools, such as Fastlane and Sentry CLI, implicitly rely on some of them.

Tools

Install Flutter and Android Studio, if you haven't done it yet.

Make sure you have installed the following basic toolset:

sudo apt-get install curl sed jq yq git ruby python3 python-is-python3 pipx uuidgen openjdk-17-jdk

Make sure you have correctly set JAVA_HOME (the path may differ, make sure you have correct one):

# ~/.bash_profile
export JAVA_HOME=/usr/lib/jvm/java-17-openjdk-amd64

Fastlane

Fastlane is a command-line tool written in Ruby that automates common tasks in iOS and Android development workflows, such as building, testing, code signing, and deploying apps to the App Store and Play Store.

Make sure your Ruby gems live in your local user space to avoid unexpected file permission issues:

# ~/.bash_profile
export GEM_HOME="$HOME/.gems"
export PATH="$HOME/.gems/bin:$PATH"

Then install Fastlane

gem install bundler fastlane

GitHub

Install GitHub CLI.

Login and add permissions:

gh auth login
gh auth refresh -h github.com -s delete_repo -s admin:public_key

Create your personal and CI/CD authentication keys:

# Personal
ssh-keygen -t ed25519 -P "" -C "$(gh api user --jq '.login')"
gh ssh-key add $HOME/.ssh/id_ed25519.pub --title 'Personal'

# CI/CD
mkdir -p $HOME/.secrets/github
ssh-keygen -t ed25519 -P "" -f $HOME/.secrets/github/cicd_id_ed25519 -C "$(gh api user --jq '.login')"
gh ssh-key add $HOME/.secrets/github/cicd_id_ed25519.pub --title 'CICD'

You can check your existing keys here.

Create a repository to store code signing keys for App Store applications and a password to protect the keys:

gh repo create fastlane_match_secrets --private
mkdir -p "$HOME/.secrets/fastlane"
openssl rand -base64 8 >> "$HOME/.secrets/fastlane/match_secrets_password"

Note: backup the password somewhere safe.

Store the SSH auth key path, repo SSH URL, and the code signing keys password in the env variables:

# ~/.secrets/.bashrc_creds
export MATCH_GIT_URL="[email protected]:{YOUR_NAMESPACE}/fastlane_match_secrets.git"
export CICD_GITHUB_SSH_KEY_PATH="$HOME/.secrets/github/cicd_id_ed25519"
export MATCH_PASSWORD_PATH="$HOME/.secrets/fastlane/match_secrets_password"

Slack

Slack is used to send build status notifications from Codemagic.

Create an account and install Slack application:

sudo snap install slack

Create #cicd-all public channel.

Apple

Assuming Apple Developer Program membership is active.

Get your "Team ID" from Apple Developer Portal.

Get your App Store Connect (former iTunes Connect - itc) team ID from App Store Connect.

Create and download App Store Connect API (team) key for CI/CD integration. Use App Manager role (or Admin if feeling lucky). Take note of the Issuer ID and the Key ID.

Store the key as $HOME/.secrets/apple/AuthKey_{YOUR_KEY_ID}.p8

Some fastlane actions still require username/password authentication. Save your iTunes password to $HOME/.secrets/apple/itunes-pass (in one line).

Set env variables:

# ~/.secrets/.bashrc_creds
export APPLE_DEV_TEAM_ID=...
export APP_STORE_CONNECT_TEAM_ID=...
export APP_STORE_CONNECT_ISSUER_ID=...
export APP_STORE_CONNECT_KEY_IDENTIFIER=...
export APP_STORE_CONNECT_PRIVATE_KEY_PATH="$HOME/.secrets/apple/AuthKey_${APP_STORE_CONNECT_KEY_IDENTIFIER}.p8"
# Your iTunes Id
export ITUNES_ID=...
export ITUNES_PASSWORD_PATH="$HOME/.secrets/apple/itunes-pass"
# This should be your full name if you are an individual developer
export APP_STORE_COMPANY_NAME=...

Google

Create a Google Cloud billing account if you don't have a suitable one.

Install gcloud CLI.

Use this instruction to create a service account and integrate it with Play Console (do nothing more from that instruction).

You can use your general administration Google Cloud project for the service account (not specific to the app).

Save your JSON access key to $HOME/.secrets/google/{YOUR_JSON_FILE_NAME}.

Generate code signing key pair for apps uploads to Play Console:

mkdir -p "$HOME/.secrets/google"

openssl rand -base64 8 >> "$HOME/.secrets/google/play-upload-keystore-pass"

keytool -genkeypair \
  -keyalg RSA \
  -keysize 2048 \
  -validity 10000 \
  -alias upload \
  -keystore "$HOME/.secrets/google/play-upload-keystore.jks" \
  -storepass $(cat "$HOME/.secrets/google/play-upload-keystore-pass") \
  -keypass $(cat "$HOME/.secrets/google/play-upload-keystore-pass")

Add env variables:

# ~/.secrets/.bashrc_creds
export GCLOUD_BILLING_ACCOUNT_ID=...
export SUPPLY_JSON_KEY="$HOME/.secrets/google/{YOUR_JSON_FILE_NAME}"
export PLAY_CONSOLE_UPLOAD_KEYSTORE="$HOME/.secrets/google/play-upload-keystore.jks"
export PLAY_CONSOLE_UPLOAD_KEYSTORE_PASS="$HOME/.secrets/google/play-upload-keystore-pass"

OneSignal

Register with OneSignal.

Do not create an app - the template setup script will do this for you.

Open you organisation in the organisation dashboard, and copy the org ID from the URL (must be something like a123456f-42cd-3e14-a360-123ab456cdef).

Go to "Keys & IDs", create an API Key and store it in $HOME/.secrets/onesignal/api-token file.

Add env variables:

# ~/.secrets/.bashrc_creds
export ONESIGNAL_ORG_ID=...
export ONESIGNAL_API_KEY_PATH="$HOME/.secrets/onesignal/api-token"

Codemagic

Go to your account setting and enable Slack integration.

Save Codemagic API token to $HOME/.secrets/codemagic/auth-token file and add env variable:

# ~/.secrets/.bashrc_creds
export CM_API_TOKEN_PATH="$HOME/.secrets/codemagic/auth-token"

Install Codemagic CLI suite:

pipx install codemagic-cli-tools
pipx ensurepath

Sentry

Register with Sentry.

Create two auth tokens in User Auth Tokens, and save them in $HOME/.secrets/sentry directory:

  • api-token-dev file; roles: Projects: Admin; Organisation: Read (used locally for initial project setup)
  • api-token-ci file; roles: Release: Admin; Organisation: Read (used locally and on CI server)

Add variables:

# ~/.secrets/.bashrc_creds
export SENTRY_PROJECTS_ADMIN_TOKEN_PATH="$HOME/.secrets/sentry/api-token-dev"
export SENTRY_CI_TOKEN_PATH="$HOME/.secrets/sentry/api-token-ci"
export SENTRY_ORG="{organization-slug}"
export SENTRY_TEAM="{default-team-slug}"

Install GitHub integration.

Install Sentry command line tool:

curl -sL https://sentry.io/get-cli/ | SENTRY_CLI_VERSION="2.40.0" INSTALL_DIR="$HOME/tools/sentry" sh

Add $HOME/tools/sentry to your $PATH.

Shorebird

Shorebird is a service that allows patching production apps without going through the app store review process.

Create a dev account with Shorebird.

Install Shorebird CLI.

Create CI auth token:

shorebird login:ci

Save the token to your $HOME/.secrets/shorebird/auth-token and add an env variable:

# ~/.secrets/.bashrc_creds
export SHOREBIRD_TOKEN_PATH="$HOME/.secrets/shorebird/auth-token"

Miscellaneous

Export your contact details for submission to App and Play store. Also export the timezone for your build number timestamps.

# ~/.secrets/.bashrc_creds
export DEV_FIRST_NAME=...
export DEV_LAST_NAME=...
export DEV_PHONE=...
export DEV_EMAIL=...
export DEV_WEBSITE=...
export DEV_FULL_NAME=...
export DEV_ADDRESS_LINE_1=...
export DEV_ADDRESS_LINE_2=...
export DEV_CITY=...
export DEV_STATE=...
export DEV_COUNTRY=...
export DEV_ZIP=...

# Use the timezone string which is compatible with the `date` command
export TZ="Pacific/Auckland"

That's it. Now you're ready to use the template to set up a project.

Roadmap

About

Flutter app template for SneakyBird Apps

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published