initialize variables, cli>env>defaults, modern install/packaging, db migration script guard+logging

This commit is contained in:
tooomm 2026-07-25 19:29:16 +02:00
parent cb2d0c484b
commit 065924a729
2 changed files with 91 additions and 78 deletions

View file

@ -1,13 +1,21 @@
#!/bin/bash #!/usr/bin/env bash
## This script is to be used by the CI environment from the project root directory, do not use it from somewhere else set -euo pipefail
# Compiles Cockatrice inside a CI environment ### Compiles Cockatrice inside GitHub Actions CI, run only from project root directory (GITHUB_WORKSPACE)
# #
# Supported options: # Build flow and script structure:
# - Read options
# - Pre-checks (CI, Servatrice schema)
# - Prepare compilation (CMake options, OS-specific configuration)
# - Pre-buld (ccache)
# - Build (Configure, Compile)
# - Post-build (ccache, Inspect, Test, Install, Package)
### Supported command-line options:
# --ccache [<size>] Use ccache (USE_CCACHE) (optionally: provide cache size, e.g. "500M" or "1G" (CCACHE_SIZE)) # --ccache [<size>] Use ccache (USE_CCACHE) (optionally: provide cache size, e.g. "500M" or "1G" (CCACHE_SIZE))
# --cmake-generator <generator> Sets the CMake generator (CMAKE_GENERATOR), e.g. "Ninja", "Visual Studio 18 2026" # --cmake-generator <generator> Sets the CMake generator (CMAKE_GENERATOR), e.g. "Ninja", "Visual Studio 18 2026"
# --debug / --release Sets the build type (BUILDTYPE --> CMAKE_BUILD_TYPE) # --debug Sets the build type (BUILDTYPE --> CMAKE_BUILD_TYPE)
# --dir <dir> Sets the name of the build dir (BUILD_DIR) # --dir <dir> Sets the name of the build dir (BUILD_DIR)
# --evict-ccache <age> Evicts compiler cache older than <age> after build (CCACHE_EVICTION_AGE), e.g. "7d" # --evict-ccache <age> Evicts compiler cache older than <age> after build (CCACHE_EVICTION_AGE), e.g. "7d"
# --install Runs cmake install (MAKE_INSTALL) # --install Runs cmake install (MAKE_INSTALL)
@ -19,35 +27,31 @@
# --target-macos-version <version> Sets the min OS version (TARGET_MACOS_VERSION), e.g. "14" [macOS only] # --target-macos-version <version> Sets the min OS version (TARGET_MACOS_VERSION), e.g. "14" [macOS only]
# --test Runs tests (MAKE_TEST) # --test Runs tests (MAKE_TEST)
# --vcpkg Use vcpkg package manager to resolve dependencies (USE_VCPKG) # --vcpkg Use vcpkg package manager to resolve dependencies (USE_VCPKG)
#
# Used environment variables: ### Initialize configuration variables:
# BUILDTYPE Build type to be used by CMake and buildsystem (defaults to "Release" if omitted) # Precedence: command-line options > environment variables > built-in script defaults
# See "--debug" and "--release" flags BUILDTYPE="${BUILDTYPE:-Release}" # See "--debug" and "--release" flags (defaults to "Release" if omitted)
# BUILD_DIR See value for "--dir" option (defaults to "build" if omitted) BUILD_DIR="${BUILD_DIR:-build}" # See value for "--dir" option (defaults to "build" if omitted)
# CCACHE_EVICTION_AGE See value for "--evict-ccache" option CCACHE_EVICTION_AGE="${CCACHE_EVICTION_AGE:-}" # See value for "--evict-ccache" option
# CCACHE_SIZE See value for "--ccache" option CCACHE_SIZE="${CCACHE_SIZE:-}" # See value for "--ccache" option
# CMAKE_GENERATOR See "--cmake-generator" option CMAKE_GENERATOR="${CMAKE_GENERATOR:-}" # See "--cmake-generator" option
# MAKE_INSTALL See "--install" flag MAKE_INSTALL="${MAKE_INSTALL:-0}" # See "--install" flag
# MAKE_NO_CLIENT See "--no-client" flag MAKE_NO_CLIENT="${MAKE_NO_CLIENT:-0}" # See "--no-client" flag
# MAKE_PACKAGE See "--package" option MAKE_PACKAGE="${MAKE_PACKAGE:-0}" # See "--package" option
# MAKE_SERVER See "--server" flag MAKE_SERVER="${MAKE_SERVER:-0}" # See "--server" flag
# MAKE_TEST See "--test" flag MAKE_TEST="${MAKE_TEST:-0}" # See "--test" flag
# PACKAGE_SUFFIX See "--suffix" option PACKAGE_SUFFIX="${PACKAGE_SUFFIX:-}" # See "--suffix" option
# PACKAGE_TYPE See value for "--package" option PACKAGE_TYPE="${PACKAGE_TYPE:-}" # See value for "--package" option
# TARGET_MACOS_VERSION See "--target-macos-version" option TARGET_MACOS_VERSION="${TARGET_MACOS_VERSION:-}" # See "--target-macos-version" option
# USE_CCACHE See "--ccache" option USE_CCACHE="${USE_CCACHE:-0}" # See "--ccache" option
# USE_VCPKG See "--vcpkg" flag USE_VCPKG="${USE_VCPKG:-0}" # See "--vcpkg" flag
#
# Exit codes: ### Exit codes:
# 1 --> Failure # 1 --> Failure
# 3 --> Invalid argument(s) # 3 --> Invalid argument(s)
# TODO flags/options and env variables are doubled (and just proxying some tool variables) and are not used uniformly between Linux and macOS/Windows builds which adds complexity
set -e ### Read options
## Read options
#TODO group only alphabetically and put flag/option to comments above with no "argument"/"boolean flag" and "accept an argument"/"options with values"?
while [[ $# != 0 ]]; do while [[ $# != 0 ]]; do
case "$1" in case "$1" in
@ -96,7 +100,7 @@ while [[ $# != 0 ]]; do
echo "::error file=$0::--cmake-generator expects an argument" echo "::error file=$0::--cmake-generator expects an argument"
exit 3 exit 3
fi fi
export CMAKE_GENERATOR=$1 CMAKE_GENERATOR="$1"
shift shift
;; ;;
'--dir') '--dir')
@ -114,7 +118,7 @@ while [[ $# != 0 ]]; do
echo "::error file=$0::--evict-ccache expects an argument" echo "::error file=$0::--evict-ccache expects an argument"
exit 3 exit 3
fi fi
CCACHE_EVICTION_AGE=$1 CCACHE_EVICTION_AGE="$1"
shift shift
;; ;;
'--package') '--package')
@ -144,74 +148,81 @@ while [[ $# != 0 ]]; do
shift shift
;; ;;
# Positional arguments are not supported
'--')
shift
if [[ $# != 0 ]]; then
echo "::error file=$0::Unexpected positional arguments: $*"
exit 3
fi
break
;;
# Unknown options # Unknown options
*) *)
echo "::error file=$0::unrecognized option: $1" echo "::error file=$0::Unrecognized option: $1"
exit 3 exit 3
;; ;;
esac esac
done done
## Set defaults ### Pre-checks
#TODO comment on script
./servatrice/check_schema_version.sh
if [[ -z $BUILDTYPE ]]; then # CI context (GitHub Actions provided environment variable)
BUILDTYPE="Release" if [[ -z ${RUNNER_OS:-} ]]; then
echo "This script requires GitHub Actions environment variable RUNNER_OS"
exit 1
fi fi
if [[ -z $BUILD_DIR ]]; then # Schema version consistency
BUILD_DIR="build" if [[ $MAKE_SERVER == 1 ]]; then
./servatrice/check_schema_version.sh
fi fi
## Prepare compilation ### Prepare compilation
# Prepare CMake options # CMake options
flags=("-DCMAKE_BUILD_TYPE=$BUILDTYPE") flags=("-DCMAKE_BUILD_TYPE=$BUILDTYPE")
if [[ -n $CMAKE_GENERATOR ]]; then
flags+=(-G "$CMAKE_GENERATOR")
fi
if [[ $MAKE_NO_CLIENT == 1 ]]; then if [[ $MAKE_NO_CLIENT == 1 ]]; then
flags+=("-DWITH_CLIENT=0" "-DWITH_ORACLE=0") flags+=("-DWITH_CLIENT=0" "-DWITH_ORACLE=0")
fi fi
if [[ $MAKE_SERVER == 1 ]]; then if [[ $MAKE_SERVER == 1 ]]; then
flags+=("-DWITH_SERVER=1") flags+=("-DWITH_SERVER=1")
fi fi
if [[ $MAKE_TEST == 1 ]]; then if [[ $MAKE_TEST == 1 ]]; then
flags+=("-DTEST=1") flags+=("-DTEST=1")
fi fi
if [[ -n $PACKAGE_TYPE ]]; then if [[ -n $PACKAGE_TYPE ]]; then
flags+=("-DCPACK_GENERATOR=$PACKAGE_TYPE") flags+=("-DCPACK_GENERATOR=$PACKAGE_TYPE")
fi fi
if [[ $USE_CCACHE == 1 ]]; then
if [[ $USE_CCACHE == 1]]; then
flags+=("-DUSE_CCACHE=1") flags+=("-DUSE_CCACHE=1")
if [[ -n $CCACHE_SIZE ]]; then if [[ -n $CCACHE_SIZE ]]; then
# Note: Setting persists after running the script # Note: Setting persists after running the script
ccache --max-size "$CCACHE_SIZE" ccache --max-size "$CCACHE_SIZE"
fi fi
fi fi
if [[ $USE_VCPKG == 1 ]]; then if [[ $USE_VCPKG == 1 ]]; then
flags+=("-DUSE_VCPKG=1") flags+=("-DUSE_VCPKG=1")
fi fi
# Prepare CMake --build options # CMake --build options
buildflags=(--config "$BUILDTYPE") buildflags=(--config "$BUILDTYPE")
if [[ $RUNNER_OS == Windows ]]; then if [[ ${RUNNER_OS:-} == "Windows" ]]; then
# Enable MSBuild switches for MTT, see https://devblogs.microsoft.com/cppblog/improved-parallelism-in-msbuild/ # Enable MSBuild switches for MTT, see https://devblogs.microsoft.com/cppblog/improved-parallelism-in-msbuild/
# and https://devblogs.microsoft.com/cppblog/cpp-build-throughput-investigation-and-tune-up/#multitooltask-mtt # and https://devblogs.microsoft.com/cppblog/cpp-build-throughput-investigation-and-tune-up/#multitooltask-mtt
buildflags+=(-- -p:UseMultiToolTask=true -p:EnableClServerMode=true) buildflags+=(-- -p:UseMultiToolTask=true -p:EnableClServerMode=true)
fi fi
# Other OS-specific configuration (GitHub runner) # Other OS-specific configuration (GitHub Actions runner)
if [[ $RUNNER_OS == macOS ]]; then if [[ ${RUNNER_OS:-} == "macOS" ]]; then
# TODO qtdir
# QTDIR is needed for macOS since we actually only use the cached thin Qt binaries instead of the install-qt-action, # QTDIR is needed for macOS since we actually only use the cached thin Qt binaries instead of the install-qt-action,
# which sets a few environment variables # which sets a few environment variables
if QTDIR=$(find "$GITHUB_WORKSPACE/Qt" -depth -maxdepth 2 -name macos -type d -print -quit); then if QTDIR=$(find "$GITHUB_WORKSPACE/Qt" -depth -maxdepth 2 -name macos -type d -print -quit); then
@ -264,9 +275,8 @@ if [[ $RUNNER_OS == macOS ]]; then
fi fi
fi fi
echo "::group::Signing Certificate" echo "::group::Setup signing certificate"
if [[ -n $MACOS_CERTIFICATE_NAME ]]; then
if [[ -n "$MACOS_CERTIFICATE_NAME" ]]; then
echo "$MACOS_CERTIFICATE" | base64 --decode >"certificate.p12" echo "$MACOS_CERTIFICATE" | base64 --decode >"certificate.p12"
security create-keychain -p "$MACOS_CI_KEYCHAIN_PWD" build.keychain security create-keychain -p "$MACOS_CI_KEYCHAIN_PWD" build.keychain
security default-keychain -s build.keychain security default-keychain -s build.keychain
@ -278,7 +288,6 @@ if [[ $RUNNER_OS == macOS ]]; then
else else
echo "No signing certificate configured. Skipping set up of keychain in macOS environment." echo "No signing certificate configured. Skipping set up of keychain in macOS environment."
fi fi
echo "::endgroup::" echo "::endgroup::"
if [[ $MAKE_PACKAGE == 1 ]]; then if [[ $MAKE_PACKAGE == 1 ]]; then
@ -299,16 +308,16 @@ if [[ $RUNNER_OS == macOS ]]; then
flags+=(-DCPACK_COMMAND_HDIUTIL="$hdiutil_script") flags+=(-DCPACK_COMMAND_HDIUTIL="$hdiutil_script")
fi fi
elif [[ $RUNNER_OS == Windows ]]; then elif [[ ${RUNNER_OS:-} == "Windows" ]]; then
: :
elif [[ $RUNNER_OS == Linux ]]; then elif [[ ${RUNNER_OS:-} == "Linux" ]]; then
: :
fi fi
## Pre-build ### Pre-build
# ccache # ccache
if [[ $USE_CCACHE == 1 ]]; then if [[ $USE_CCACHE == 1 ]]; then
@ -324,14 +333,13 @@ if [[ $USE_CCACHE == 1 ]]; then
fi fi
## Build ### Build
# Configure CMake # Configure CMake
echo "::group::Configure CMake" echo "::group::Configure CMake"
cmake --version cmake --version
echo "Running CMake configuration with following flags: ${flags[*]}" echo "Running CMake configuration with following flags: ${flags[*]}"
cmake -S . -B "$BUILD_DIR" "${flags[@]}" cmake -S . -B "$BUILD_DIR" "${flags[@]}"
# cmake -S .. -B "$BUILD_DIR" "${flags[@]}"
echo "::endgroup::" echo "::endgroup::"
# Compile # Compile
@ -341,7 +349,7 @@ cmake --build "$BUILD_DIR" "${buildflags[@]}"
echo "::endgroup::" echo "::endgroup::"
## Post-build ### Post-build
# ccache # ccache
if [[ $USE_CCACHE == 1 ]]; then if [[ $USE_CCACHE == 1 ]]; then
@ -362,8 +370,8 @@ elif [[ -n $CCACHE_EVICTION_AGE ]]; then
echo "::error file=$0::ccache eviction is enabled while ccache is disabled!" echo "::error file=$0::ccache eviction is enabled while ccache is disabled!"
fi fi
# Inspect binaries # Inspect
if [[ $RUNNER_OS == macOS ]]; then if [[ ${RUNNER_OS:-} == "macOS" ]]; then
echo "::group::Inspect Mach-O binaries" echo "::group::Inspect Mach-O binaries"
for app in cockatrice oracle servatrice; do for app in cockatrice oracle servatrice; do
@ -378,7 +386,6 @@ if [[ $RUNNER_OS == macOS ]]; then
echo "::endgroup::" echo "::endgroup::"
fi fi
# Test # Test
if [[ $MAKE_TEST == 1 ]]; then if [[ $MAKE_TEST == 1 ]]; then
echo "::group::Run tests" echo "::group::Run tests"
@ -390,8 +397,7 @@ fi
# Install # Install
if [[ $MAKE_INSTALL == 1 ]]; then if [[ $MAKE_INSTALL == 1 ]]; then
echo "::group::Install" echo "::group::Install"
cmake --build "$BUILD_DIR" --target install --config "$BUILDTYPE" cmake --install "$BUILD_DIR" --config "$BUILDTYPE"
# cmake --install "$BUILD_DIR" --config "$BUILDTYPE"
echo "::endgroup::" echo "::endgroup::"
fi fi
@ -399,7 +405,7 @@ fi
if [[ $MAKE_PACKAGE == 1 ]]; then if [[ $MAKE_PACKAGE == 1 ]]; then
echo "::group::Create package" echo "::group::Create package"
cpack --version cpack --version
cmake --build "$BUILD_DIR" --target package --config "$BUILDTYPE" cpack --config "$BUILD_DIR/CPackConfig.cmake"
echo "::endgroup::" echo "::endgroup::"
if [[ -n $PACKAGE_SUFFIX ]]; then if [[ -n $PACKAGE_SUFFIX ]]; then

View file

@ -2,6 +2,7 @@
set -e set -e
echo "::group::Check Servatrice database schema version"
version_line="$(grep 'INSERT INTO cockatrice_schema_version' servatrice/servatrice.sql)" version_line="$(grep 'INSERT INTO cockatrice_schema_version' servatrice/servatrice.sql)"
version_line="${version_line#*VALUES(}" version_line="${version_line#*VALUES(}"
declare -i schema_ver="${version_line%%)*}" declare -i schema_ver="${version_line%%)*}"
@ -13,24 +14,30 @@ xtoy="${xtoysql%.sql}"
declare -i old_ver="10#${xtoy%_to_*}" # declare as integer with base 10, numbers with a leading 0 are normally interpreted as base 16 declare -i old_ver="10#${xtoy%_to_*}" # declare as integer with base 10, numbers with a leading 0 are normally interpreted as base 16
declare -i new_ver="10#${xtoy#*_to_}" declare -i new_ver="10#${xtoy#*_to_}"
echo "Schema version: $schema_ver"
echo "Latest migration: $latest_migration ($old_ver → $new_ver)"
if ((old_ver >= new_ver)); then if ((old_ver >= new_ver)); then
echo "New version $new_ver is not newer than $old_ver" echo "New version $new_ver is not newer than $old_ver"
exit 1 exit 1
fi fi
if ((schema_ver != new_ver)); then if ((schema_ver != new_ver)); then
echo "Schema version $schema_ver does not equal new version $new_ver" echo "Schema version $schema_ver does not match new version $new_ver"
exit 1 exit 1
fi fi
expected_sql="^UPDATE cockatrice_schema_version SET version=${new_ver} WHERE version=${old_ver};$" expected_sql="^UPDATE cockatrice_schema_version SET version=${new_ver} WHERE version=${old_ver};$"
if ! grep -q "$expected_sql" "servatrice/migrations/$latest_migration"; then if ! grep -q "$expected_sql" "servatrice/migrations/$latest_migration"; then
echo "$latest_migration does not contain expected sql: $expected_sql" echo "$latest_migration does not contain expected sql: $expected_sql"
exit 1 exit 1
fi fi
expected_define="^#define DATABASE_SCHEMA_VERSION $new_ver$" expected_define="^#define DATABASE_SCHEMA_VERSION $new_ver$"
if ! grep -q "$expected_define" servatrice/src/servatrice_database_interface.h; then if ! grep -q "$expected_define" servatrice/src/servatrice_database_interface.h; then
echo "servatrice_database_interface.h does not contain expected #define: $expected_define" echo "servatrice_database_interface.h does not contain expected #define: $expected_define"
exit 1 exit 1
fi fi
echo " ✓ Database schema version is consistent"
echo "::endgroup::