feat: Add flutter-build.sh
This commit is contained in:
commit
92687b6513
2
.gitignore
vendored
Normal file
2
.gitignore
vendored
Normal file
@ -0,0 +1,2 @@
|
||||
# NixOS artifacts
|
||||
result
|
22
LICENSE
Normal file
22
LICENSE
Normal file
@ -0,0 +1,22 @@
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2023 Alexander "PapaTutuWawa"
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
|
12
README.md
Normal file
12
README.md
Normal file
@ -0,0 +1,12 @@
|
||||
# bits-and-bytes
|
||||
|
||||
A collection of small scripts (and other stuff) that I want to reuse across
|
||||
my personal projects.
|
||||
|
||||
## Nix
|
||||
|
||||
For users of Nix, I also provide a Flake (see `flake.nix`).
|
||||
|
||||
## License
|
||||
|
||||
See `LICENSE`.
|
61
flake.lock
Normal file
61
flake.lock
Normal file
@ -0,0 +1,61 @@
|
||||
{
|
||||
"nodes": {
|
||||
"flake-utils": {
|
||||
"inputs": {
|
||||
"systems": "systems"
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1689068808,
|
||||
"narHash": "sha256-6ixXo3wt24N/melDWjq70UuHQLxGV8jZvooRanIHXw0=",
|
||||
"owner": "numtide",
|
||||
"repo": "flake-utils",
|
||||
"rev": "919d646de7be200f3bf08cb76ae1f09402b6f9b4",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "numtide",
|
||||
"repo": "flake-utils",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"nixpkgs": {
|
||||
"locked": {
|
||||
"lastModified": 1689935543,
|
||||
"narHash": "sha256-6GQ9ib4dA/r1leC5VUpsBo0BmDvNxLjKrX1iyL+h8mc=",
|
||||
"owner": "NixOS",
|
||||
"repo": "nixpkgs",
|
||||
"rev": "e43e2448161c0a2c4928abec4e16eae1516571bc",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "NixOS",
|
||||
"ref": "nixpkgs-unstable",
|
||||
"repo": "nixpkgs",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"root": {
|
||||
"inputs": {
|
||||
"flake-utils": "flake-utils",
|
||||
"nixpkgs": "nixpkgs"
|
||||
}
|
||||
},
|
||||
"systems": {
|
||||
"locked": {
|
||||
"lastModified": 1681028828,
|
||||
"narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=",
|
||||
"owner": "nix-systems",
|
||||
"repo": "default",
|
||||
"rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "nix-systems",
|
||||
"repo": "default",
|
||||
"type": "github"
|
||||
}
|
||||
}
|
||||
},
|
||||
"root": "root",
|
||||
"version": 7
|
||||
}
|
36
flake.nix
Normal file
36
flake.nix
Normal file
@ -0,0 +1,36 @@
|
||||
{
|
||||
description = "A collection of reusable scripts for various use-cases";
|
||||
inputs = {
|
||||
nixpkgs.url = "github:NixOS/nixpkgs/nixpkgs-unstable";
|
||||
flake-utils.url = "github:numtide/flake-utils";
|
||||
};
|
||||
|
||||
outputs = { self, nixpkgs, flake-utils }: flake-utils.lib.eachDefaultSystem (system: let
|
||||
pkgs = import nixpkgs { inherit system; };
|
||||
|
||||
flutterBuildRaw = {stdenv}: stdenv.mkDerivation {
|
||||
pname = "flutter-build";
|
||||
version = "0.1.0";
|
||||
src = ./.;
|
||||
|
||||
installPhase = ''
|
||||
mkdir -p $out/bin
|
||||
|
||||
install --mode 555 src/flutter-build.sh $out/bin/flutter-build
|
||||
'';
|
||||
};
|
||||
flutter-build-raw = pkgs.callPackage flutterBuildRaw {};
|
||||
in {
|
||||
packages = {
|
||||
# The raw flutter-build script
|
||||
inherit flutter-build-raw;
|
||||
|
||||
# A wrapper around the script that already provides the notify-send option
|
||||
flutter-build = pkgs.writeScriptBin "flutter-build" ''
|
||||
${flutter-build-raw}/bin/flutter-build \
|
||||
--notify-send ${pkgs.libnotify}/bin/notify-send \
|
||||
$@
|
||||
'';
|
||||
};
|
||||
});
|
||||
}
|
228
src/flutter-build.sh
Normal file
228
src/flutter-build.sh
Normal file
@ -0,0 +1,228 @@
|
||||
#!/bin/bash
|
||||
set -e
|
||||
|
||||
# Parse CLI arguments
|
||||
# (Thanks StackOverflow https://stackoverflow.com/questions/192249/how-do-i-parse-command-line-arguments-in-bash)
|
||||
while [[ $# -gt 0 ]]; do
|
||||
case $1 in
|
||||
--name)
|
||||
# The name of the application. Only useful for displaying in the script.
|
||||
# If not specified, will use the "name: " attribute from the pubspec.yaml
|
||||
NAME=$2
|
||||
shift
|
||||
shift
|
||||
;;
|
||||
--not-signed)
|
||||
# Tells the script that the APKs are *NOT* signed and have to be manually
|
||||
# signed.
|
||||
ALREADY_SIGNED=n
|
||||
shift
|
||||
;;
|
||||
--zipalign)
|
||||
# The path to the zipalign binary. If not specified, lets the shell resolve the path
|
||||
# itself.
|
||||
# Only useful with --not-signed.
|
||||
ZIPALIGN=$2
|
||||
shift
|
||||
shift
|
||||
;;
|
||||
--apksigner)
|
||||
# The path to the apksigner binary. If not specified, lets the shell resolve the path
|
||||
# itself.
|
||||
# Only useful with --not-signed.
|
||||
APKSIGNER=$2
|
||||
shift
|
||||
shift
|
||||
;;
|
||||
--notify-send)
|
||||
# The path to the notify-send binary. If not specified, lets the shell resolve the path
|
||||
# itself.
|
||||
# Only useful with --not-signed.
|
||||
NOTIFY_SEND=$2
|
||||
shift
|
||||
shift
|
||||
;;
|
||||
--provider-config)
|
||||
# The path to the provider config passed to apksigner via --provider-arg.
|
||||
# Only useful with --not-signed.
|
||||
PROVIDER_CONFIG=$2
|
||||
shift
|
||||
shift
|
||||
;;
|
||||
--no-clean)
|
||||
# Does not run "flutter clean" before running the build.
|
||||
CLEAN_BUILD=n
|
||||
shift
|
||||
;;
|
||||
--min-sdk-version)
|
||||
# The minimum SDK version that should be able to validate the APK signature.
|
||||
# Only useful with --not-signed.
|
||||
MIN_SDK_VERSION=$2
|
||||
shift
|
||||
shift
|
||||
;;
|
||||
--check)
|
||||
# Prints all parsed options and exits.
|
||||
JUST_CHECK=y
|
||||
shift
|
||||
;;
|
||||
--skip-build)
|
||||
# Skips the entire build but not the signing, if --not-signed is specified. If --not-signed
|
||||
# is not specified, then the build is skipped, but the APKs are copied into the correct folder.
|
||||
# This flag expects that the build has run at least once and the correct release directory
|
||||
# already exists.
|
||||
SKIP_BUILD=y
|
||||
shift
|
||||
;;
|
||||
--no-notification)
|
||||
# Does not create a notification when asking for the PIN of the Yubikey.
|
||||
# Only useful with --not-signed.
|
||||
SEND_NOTIFICATION=n
|
||||
shift
|
||||
;;
|
||||
*)
|
||||
echo "Unknown argument: $1"
|
||||
shift
|
||||
;;
|
||||
esac
|
||||
done
|
||||
|
||||
# Extract the name, if not passed
|
||||
if [[ -z "$NAME" ]]; then
|
||||
NAME=$(grep -E "^name: " pubspec.yaml | cut -b 6-)
|
||||
fi
|
||||
|
||||
# Default values
|
||||
APKSIGNER=${APKSIGNER:-apksigner}
|
||||
ZIPALIGN=${ZIPALIGN:-zipalign}
|
||||
ALREADY_SIGNED=${ALREADY_SIGNED:-y}
|
||||
MIN_SDK_VERSION=${MIN_SDK_VERSION:-24}
|
||||
CLEAN_BUILD=${CLEAN_BUILD:-y}
|
||||
SKIP_BUILD=${SKIP_BUILD:-n}
|
||||
NOTIFY_SEND=${NOTIFY_SEND:-notify-send}
|
||||
SEND_NOTIFICATION=${SEND_NOTIFICATION:-y}
|
||||
|
||||
# Parse version info
|
||||
version=$(grep -E "^version: " pubspec.yaml | cut -b 10-)
|
||||
IFS="+" read -ra version_parts <<< "$version"
|
||||
version_code="${version_parts[1]}"
|
||||
release_dir="./release-${version}"
|
||||
|
||||
# Print a header
|
||||
echo "===== ${NAME} ====="
|
||||
echo "Building version ${version}"
|
||||
echo "Moving APKs into ${release_dir} after build"
|
||||
echo "Clean build: ${CLEAN_BUILD}"
|
||||
echo "Skipping build: ${SKIP_BUILD}"
|
||||
echo "Sending notification: ${SEND_NOTIFICATION}"
|
||||
echo "APKs already signed: ${ALREADY_SIGNED}"
|
||||
if [[ "$ALREADY_SIGNED" = "n" ]]; then
|
||||
echo "Used zipalign: ${ZIPALIGN}"
|
||||
echo "Used apksigner: ${APKSIGNER}"
|
||||
echo "Provider config: ${PROVIDER_CONFIG}"
|
||||
echo "Minimum SDK verifiability: ${MIN_SDK_VERSION}"
|
||||
fi
|
||||
|
||||
if [[ "${JUST_CHECK}" = "y" ]]; then
|
||||
echo
|
||||
echo "Terminating here because --check was used"
|
||||
exit
|
||||
fi
|
||||
|
||||
# For better readability, print an empty line
|
||||
echo
|
||||
|
||||
# Check if we have a changelog file for that version
|
||||
if [[ ! -f "./fastlane/metadata/android/en-US/changelogs/$version_code.txt" ]]; then
|
||||
echo "Warning: No changelog item for $version_code"
|
||||
fi
|
||||
|
||||
if [[ "${SKIP_BUILD}" = "y" ]]; then
|
||||
echo "Skipping build because of --skip-build"
|
||||
else
|
||||
# Create the directory
|
||||
[[ -d "${release_dir}" ]] && echo "Warning: Release directory ${release_dir} already exists"
|
||||
mkdir "${release_dir}" || true
|
||||
|
||||
if [[ "${CLEAN_BUILD}" = "y" ]]; then
|
||||
# Clean flutter build
|
||||
flutter clean
|
||||
fi
|
||||
|
||||
# Get dependencies
|
||||
flutter pub get
|
||||
|
||||
# Build everything again
|
||||
flutter pub run build_runner build --delete-conflicting-outputs
|
||||
|
||||
# Build the release apk
|
||||
flutter build apk \
|
||||
--release \
|
||||
--split-per-abi \
|
||||
--split-debug-info="${release_dir}/debug-info"
|
||||
fi
|
||||
|
||||
# If we have to sign, ask for the PIN upfront
|
||||
if [[ "$ALREADY_SIGNED" = "n" ]]; then
|
||||
[[ "${SEND_NOTIFICATION}" = "y" ]] && ${NOTIFY_SEND} \
|
||||
--urgency normal \
|
||||
--app-name "Flutter Build" \
|
||||
--icon dialog-password \
|
||||
"Signing PIN required" \
|
||||
"The build is done and the PIN for manually signing the APKs must be entered"
|
||||
|
||||
# Thanks https://geoffreymetais.github.io/code/key-signing/#scripting
|
||||
echo "Please enter Yubikey PIN code "
|
||||
stty -echo
|
||||
trap 'stty echo' EXIT
|
||||
read -p 'PIN: ' YUBI_PIN
|
||||
stty echo
|
||||
trap - EXIT
|
||||
fi
|
||||
|
||||
# Move everything
|
||||
for platform in arm64-v8a armeabi-v7a x86_64; do
|
||||
echo "Processing the $platform release..."
|
||||
|
||||
raw_apk="build/app/outputs/flutter-apk/app-${platform}-release.apk"
|
||||
if [[ "$ALREADY_SIGNED" = "y" ]]; then
|
||||
# Simply copy artifacts
|
||||
cp -f "$raw_apk" "${release_dir}/${NAME}-${platform}-release.apk"
|
||||
else
|
||||
# https://developer.android.com/build/building-cmdline#sign_cmdline
|
||||
aligned_apk="${release_dir}/app-${platform}-release-aligned.apk"
|
||||
signed_apk="${release_dir}/app-${platform}-release.apk"
|
||||
${ZIPALIGN} -p 4 "$raw_apk" "${aligned_apk}"
|
||||
|
||||
# NOTE: "-J-add-exports jdk.crypto.cryptoki/sun.security.pkcs11=ALL-UNNAMED" tells the wrapper that is
|
||||
# `apksigner` to append "--add-exports jdk.[...]" as a parameter to the Java CLI. It is in
|
||||
# quotation marks such that it is passed with only one (1) dash (it would otherwise be "--add-exports -jdk.[...]",
|
||||
# which is wrong).
|
||||
# At least on NixOS, apksigner refuses to use the sun.security.pkcs11.SunPKCS11 provider because
|
||||
# it is not exported for its unnamed class. So, we have to do a little trickery to "export" the
|
||||
# class to apksigner.
|
||||
${APKSIGNER} "-J-add-exports jdk.crypto.cryptoki/sun.security.pkcs11=ALL-UNNAMED" sign \
|
||||
--ks NONE \
|
||||
--ks-pass "pass:$YUBI_PIN" \
|
||||
--provider-class sun.security.pkcs11.SunPKCS11 \
|
||||
--provider-arg "${PROVIDER_CONFIG}" \
|
||||
--ks-type PKCS11 \
|
||||
--min-sdk-version "${MIN_SDK_VERSION}" \
|
||||
--max-sdk-version 34 \
|
||||
--in "${aligned_apk}" \
|
||||
--out "${signed_apk}" \
|
||||
--v1-signing-enabled \
|
||||
--v2-signing-enabled \
|
||||
--v3-signing-enabled \
|
||||
--v4-signing-enabled
|
||||
|
||||
# Safety check
|
||||
${APKSIGNER} verify --min-sdk-version "${MIN_SDK_VERSION}" "${signed_apk}"
|
||||
|
||||
# Remove temporary artifact
|
||||
rm "${aligned_apk}"
|
||||
fi
|
||||
done
|
||||
|
||||
# Prevent leaking the PIN
|
||||
unset YUBI_PIN
|
Loading…
Reference in New Issue
Block a user