diff --git a/Dockerfile b/Dockerfile index 40fb6cc..226758c 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,7 +1,22 @@ -FROM ubuntu:20.04 +FROM ubuntu:24.04 RUN apt-get update -RUN apt-get install --yes bzip2 wget libxext6 libllvm6.0 mesa-utils unzip rsync +RUN apt-get install --yes bzip2 wget libxext6 mesa-utils unzip rsync jq tree openjdk-21-jdk + +# Android SDK location inside container +ENV ANDROID_SDK_ROOT=/opt/android-sdk +ENV ANDROID_HOME=/opt/android-sdk +ENV PATH="${ANDROID_SDK_ROOT}/cmdline-tools/latest/bin:${ANDROID_SDK_ROOT}/platform-tools:${PATH}" + +# Install Android cmdline tools (sdkmanager) then required SDK packages +RUN mkdir -p ${ANDROID_SDK_ROOT}/cmdline-tools \ + && cd /tmp \ + && wget -q -O cmdline-tools.zip https://dl.google.com/android/repository/commandlinetools-linux-11076708_latest.zip \ + && unzip -q cmdline-tools.zip \ + && mv cmdline-tools ${ANDROID_SDK_ROOT}/cmdline-tools/latest \ + && rm -f cmdline-tools.zip \ + && yes | sdkmanager --licenses >/dev/null \ + && sdkmanager --install "platform-tools" COPY build.sh /build.sh diff --git a/README.md b/README.md index e453ab7..b55acc2 100644 --- a/README.md +++ b/README.md @@ -8,8 +8,11 @@ This GitHub action allows you to make distributable builds of a Ren'Py visual no - name: Build VN project uses: ProjectAliceDev/renpy-build-action@master with: - sdk-version: '6.99.12.4' + sdk-version: '8.5.2' project-dir: '.' + package: 'linux win mac' + add-steam-lib: false + output-dir: './dist' env: SDL_AUDIODRIVER: dummy SDL_VIDEODRIVER: dummy @@ -25,11 +28,32 @@ This GitHub action allows you to make distributable builds of a Ren'Py visual no **Optional Parameters:** -- `package`: Specific package to build for. Must be one of the following: `pc`, `win`, `mac`, `linux`, `market`, `web`, `android` or an array of options such as `['win','mac','linux']` Will build for all packages if value is not supported. +- `package`: Specific package(s) to build for. Supported values: `pc`, `win`, `mac`, `linux`, `market`, `web`, `android`. + You can provide multiple targets as a space-separated string (e.g. `linux win mac`). If omitted, it will build the default distribution. - `add-steam-lib`: Whether to include Steam lib. This is necessary if you want your build to work with Steam achievements. Defaults to `false`. +- `output-dir`: The directory where the built files will be placed. Defaults to `./dist`. + ### Outputs -- `dir`: The directory where the files were built to. -- `version`: The name of the project and version that was built. Often useful in cases where you don't know the version. +- `dir`: The directory where the files were built to (the `output-dir`). +- `version`: The project version detected from Ren'Py (from `build.version` or `config.version`). + +### Android Example + +This action automatically installs the Android SDK and all required packages for building Android apps, so you don't need to set up java JDK or Android SDK manually. + +```yml +- name: Build Android APK + id: build + uses: ProjectAliceDev/renpy-build-action@master + with: + sdk-version: '8.5.2' + package: android + env: + SDL_AUDIODRIVER: dummy + SDL_VIDEODRIVER: dummy +``` + +> :warning: In order to sign the Android APK, you must provide an `android.keystore` file in the project directory. The keystore file should be stored in GitHub Secrets and copied to a file in the project directory before building. See: https://www.renpy.org/doc/html/android.html \ No newline at end of file diff --git a/action.yml b/action.yml index a461ff7..ef51544 100644 --- a/action.yml +++ b/action.yml @@ -19,6 +19,10 @@ inputs: required: false default: false type: boolean + output-dir: + description: "The directory where the built files will be placed" + required: false + default: './dist' outputs: dir: description: "The directory where the distributed files exist" @@ -32,6 +36,7 @@ runs: - ${{ inputs.project-dir }} - ${{ inputs.package }} - ${{ inputs.add-steam-lib }} + - ${{ inputs.output-dir }} branding: color: 'gray-dark' icon: 'archive' diff --git a/build.sh b/build.sh index 7de2b4a..a492801 100755 --- a/build.sh +++ b/build.sh @@ -1,94 +1,131 @@ -#!/bin/sh +#!/usr/bin/env bash + +sdk_version="$1" +project_dir="$2" +targets="$3" +add_steam_lib="$4" +output_dir="$5" + +sdk_name="renpy-$sdk_version-sdk" +renpy_dir="../renpy" +renpy_sh="$renpy_dir/renpy.sh" +renpy_launcher="$renpy_dir/launcher" -sdk_name=renpy-$1-sdk echo "Downloading the specified SDK (${sdk_name})..." -wget -q https://www.renpy.org/dl/$1/${sdk_name}.tar.bz2 -clear +wget -q "https://www.renpy.org/dl/$sdk_version/${sdk_name}.tar.bz2" -echo "Downloaded SDK version (${sdk_name})." echo "Setting up the specified SDK (${sdk_name})..." tar -xf ./${sdk_name}.tar.bz2 rm ./${sdk_name}.tar.bz2 -mv ./${sdk_name} ../renpy +mv ./${sdk_name} "$renpy_dir" +echo "Setup SDK version (${sdk_name})." + +# Get the project version by using renpy's json-dump command +tmp="$(mktemp)" +"$renpy_sh" --json-dump "$tmp" "$project_dir" quit >/dev/null +project_version="$(jq -r '.build.version // .config.version // empty' "$tmp")" +rm -f "$tmp" -# used for steam and web +# used for steam, web, rapt install_lib() { - version="$1" - lib="$2" - name="renpy-$version-$lib" - - echo "Downloading ${lib} lib (${name})..." - wget -q "https://www.renpy.org/dl/${version}/${name}.zip" - clear - - echo "Downloaded ${lib} lib (${name})..." - echo "Adding Steam lib to Renpy" - unzip -qq ./${name} -d ${name} - rsync -a ${name}/ ../renpy - rm -rf ${name} ${name}.zip -} + local lib="$1" + local name="renpy-$sdk_version-$lib" -if [ $4 = "true" ]; then - install_lib "$1" steam -fi + echo "Downloading '${lib}' lib (${name})..." + wget -q "https://www.renpy.org/dl/${sdk_version}/${name}.zip" -# Note: This will be checked regardless of the version of Ren'Py. Caution is -# advised. -if [ -d "$2/old-game" ]; then - echo "old-game directory detected." - if [ -z "$(ls -A "$2/old-game")" ]; then - echo "ERROR: old-game is empty. This will cause incompatibility issues." - echo "For more information on how the old-game directory works and why" - echo "this directory should not be empty, please refer to the documentation" - echo "at: https://www.renpy.org/doc/html/build.html#old-game." - exit 1 - fi -fi + echo "Adding '${lib}' lib to Renpy..." + unzip -qq "./${name}.zip" -d "${name}" + rsync -a "${name}/" "$renpy_dir" + rm -rf "${name}" "${name}.zip" + echo "Added '${lib}' lib (${name})..." +} -if [[ "$(declare -p -- "$3")" == "declare -a "* ]]; then - for i in "${3[@]}" - do - if [ $i == 'android' ]; then - COMMAND="../renpy/renpy.sh ../renpy/launcher android_build $2" - elif [ $i == 'web' ]; then - install_lib "$1" web - COMMAND="../renpy/renpy.sh ../renpy/launcher web_build $2" - else - COMMAND="../renpy/renpy.sh ../renpy/launcher distribute --package $i $2" - fi - echo "Building $i" - if $COMMAND; then - built_dir=$(ls | grep '\-dists') - echo dir=$built_dir >> $GITHUB_OUTPUT - echo version=${built_dir%'-dists'} >> $GITHUB_OUTPUT - else - return 1 - fi - done -else - case $3 in +# Builds a Ren'Py distribution for a target platform +# +# Args: +# $1: Target platform (pc|win|mac|linux|market|web|android). Default: All. +# +# Outputs: +# Writes `dir` and `version` to $GITHUB_OUTPUT on success +build_platform() { + local target="$1" + local COMMAND=("$renpy_sh" "$renpy_launcher") + + case "$target" in pc|win|mac|linux|market) - COMMAND="../renpy/renpy.sh ../renpy/launcher distribute --package $3 $2" + COMMAND+=(distribute --package "$target" "$project_dir") ;; web) - install_lib "$1" web - COMMAND="../renpy/renpy.sh ../renpy/launcher web_build $2" + install_lib web + COMMAND+=(web_build "$project_dir") ;; android) - COMMAND="../renpy/renpy.sh ../renpy/launcher android_build $2" + install_lib rapt + echo "${ANDROID_SDK_ROOT}" > $renpy_dir/rapt/sdk.txt + COMMAND+=(android_build "$project_dir") ;; *) - COMMAND="../renpy/renpy.sh ../renpy/launcher distribute $2" + COMMAND+=(distribute "$project_dir") ;; esac - - echo "Building the project at $2..." - if $COMMAND; then - built_dir=$(ls | grep '\-dists') - echo dir=$built_dir >> $GITHUB_OUTPUT - echo version=${built_dir%'-dists'} >> $GITHUB_OUTPUT - else - return 1 + + echo "Building the project for platform '$target' at '$project_dir'..." + "${COMMAND[@]}" +} + +# Moves compiled distribution files to a single, pre-defined location +# +# Args: +# $1: Output folder +# +# Outputs: +# Writes `dir` and `version` to $GITHUB_OUTPUT +collect_distributions() { + local output_dir="$1" + local built_dir="$(find . -maxdepth 1 -type d -name '*-dists' -print -quit || true)" + + mkdir -p "$output_dir" + + if [[ -n "$built_dir" ]]; then + rsync -a --remove-source-files "$built_dir/" "$output_dir/" + rmdir "$built_dir" 2>/dev/null || true + fi + + if [[ -d "$renpy_dir/rapt/bin/" ]]; then + rsync -a -m --remove-source-files \ + --include='*/' \ + --include='*-release.apk' \ + --exclude='*' \ + "$renpy_dir/rapt/bin/" "$output_dir/" + fi + + echo "dir=$output_dir" >> $GITHUB_OUTPUT + echo "version=$project_version" >> $GITHUB_OUTPUT +} + +if [ "$add_steam_lib" = "true" ]; then + install_lib steam +fi + +# Note: This will be checked regardless of the version of Ren'Py. Caution is advised. +if [ -d "$project_dir/old-game" ]; then + echo "old-game directory detected." + if [ -z "$(ls -A "$project_dir/old-game")" ]; then + echo "ERROR: old-game is empty. This will cause incompatibility issues." + echo "For more information on how the old-game directory works and why" + echo "this directory should not be empty, please refer to the documentation" + echo "at: https://www.renpy.org/doc/html/build.html#old-game." + exit 1 fi fi +# Split $targets into an array of target platforms +[[ -n ${targets} ]] && read -r -a target_platforms <<<"$targets" || target_platforms=("all") + +# Build for listed platforms +for i in "${target_platforms[@]}"; do + build_platform "$i" +done + +collect_distributions "$output_dir" \ No newline at end of file