From 4343f98cebadb363b7968335a47daece3ac895bc Mon Sep 17 00:00:00 2001 From: Robert Kirkman Date: Wed, 9 Apr 2025 20:47:22 -0500 Subject: [PATCH] chore(scripts/run-docker): implement dry run simulation to skip launching container if no packages would have been built - Fixes termux#24116 - adds a new script to `scripts/bin`, `build-package-dry-run-simulation.sh`, which is used to test whether the entire `build-package.sh` command would have both proceeded beyond this point, https://github.com/termux/termux-packages/blob/040710f4927fc42cb74a85911e42da0a3f2e1f39/scripts/build/termux_step_start_build.sh#L13-L16 - and also proceeded beyond this point, https://github.com/termux/termux-packages/blob/040710f4927fc42cb74a85911e42da0a3f2e1f39/scripts/build/termux_step_start_build.sh#L42-L47 - or if it would have skipped all packages in the list of packages to build without building anything. - if the build would have continued or an unknown situation occurs, zero is returned, but if all packages in the list of packages to build would have been skipped, 85 (`C_EX__NOOP`) is returned. - if an error handled by this script, such as a syntax error in the `-a` argument or the package name argument list occurs, a similar error message to what `build-package.sh` would have printed is shown, and 1 is returned. - in `run-docker.sh`, the command passed to `run-docker.sh` is run in `build-package-dry-run-simulation.sh` before doing anything else only if the command passed has `build-package.sh` in its first argument, and only continues if a zero value is returned by `build-package-dry-run-simulation.sh`, which indicates either that at least one package will be built, or that the passed command is empty or not `build-package.sh`. --- .github/workflows/package_updates.yml | 1 + .github/workflows/packages.yml | 1 + .../bin/build-package-dry-run-simulation.sh | 87 +++++++++++++++++++ scripts/run-docker.sh | 28 ++++++ 4 files changed, 117 insertions(+) create mode 100755 scripts/bin/build-package-dry-run-simulation.sh diff --git a/.github/workflows/package_updates.yml b/.github/workflows/package_updates.yml index 0484b3e28755a20..887252aefaeaf8b 100644 --- a/.github/workflows/package_updates.yml +++ b/.github/workflows/package_updates.yml @@ -112,6 +112,7 @@ jobs: env: GITHUB_TOKEN: ${{ secrets.TERMUXBOT2_TOKEN }} BUILD_PACKAGES: "true" + TERMUX_DOCKER__CONTAINER_EXEC_COMMAND__PRE_CHECK_IF_WILL_BUILD_PACKAGES: "true" CREATE_ISSUE: "true" GIT_COMMIT_PACKAGES: "true" GIT_PUSH_PACKAGES: "true" diff --git a/.github/workflows/packages.yml b/.github/workflows/packages.yml index db8759555776735..88425013790aa92 100644 --- a/.github/workflows/packages.yml +++ b/.github/workflows/packages.yml @@ -238,6 +238,7 @@ jobs: if: ${{ steps.build-info.outputs.skip-building != 'true' }} env: DOCKER_BUILD: ${{ steps.build-info.outputs.docker-build }} + TERMUX_DOCKER__CONTAINER_EXEC_COMMAND__PRE_CHECK_IF_WILL_BUILD_PACKAGES: "true" run: | declare -a packages=() for repo_path in $(jq --raw-output 'del(.pkg_format) | keys | .[]' repo.json); do diff --git a/scripts/bin/build-package-dry-run-simulation.sh b/scripts/bin/build-package-dry-run-simulation.sh new file mode 100755 index 000000000000000..3258366d62cce4c --- /dev/null +++ b/scripts/bin/build-package-dry-run-simulation.sh @@ -0,0 +1,87 @@ +#!/bin/bash + +set -e -u + +# This script is in '$TERMUX_SCRIPTDIR/scripts/bin/'. +TERMUX_SCRIPTDIR=$(cd "$(realpath "$(dirname "$0")")"; cd ../..; pwd) +DRY_RUN_SCRIPT_NAME=$(basename "$0") +BUILDSCRIPT_NAME="build-package.sh" +TERMUX_ARCH="aarch64" +TERMUX_DEBUG_BUILD="false" +TERMUX_PACKAGES_DIRECTORIES=" +packages +root-packages +x11-packages +" + +# Please keep synchronized with the logic of lines 468-547 of 'build-package.sh'. +declare -a PACKAGE_LIST=() +while (($# >= 1)); do + case "$1" in + *"/$BUILDSCRIPT_NAME") ;; + -a) + if [ $# -lt 2 ]; then + echo "$DRY_RUN_SCRIPT_NAME: Option '-a' requires an argument" + exit 1 + fi + shift 1 + if [ -z "$1" ]; then + echo "$DRY_RUN_SCRIPT_NAME: Argument to '-a' should not be empty." + exit 1 + fi + TERMUX_ARCH="$1" + ;; + -d) TERMUX_DEBUG_BUILD="true" ;; + -*) ;; + *) PACKAGE_LIST+=("$1") ;; + esac + shift 1 +done + +# Please keep synchronized with the logic of lines 592-656 of 'build-package.sh'. +for ((i=0; i<${#PACKAGE_LIST[@]}; i++)); do + TERMUX_PKG_NAME=$(basename "${PACKAGE_LIST[i]}") + TERMUX_PKG_BUILDER_DIR= + for package_directory in $TERMUX_PACKAGES_DIRECTORIES; do + if [ -d "${TERMUX_SCRIPTDIR}/${package_directory}/${TERMUX_PKG_NAME}" ]; then + TERMUX_PKG_BUILDER_DIR="${TERMUX_SCRIPTDIR}/$package_directory/$TERMUX_PKG_NAME" + break + fi + done + if [ -z "${TERMUX_PKG_BUILDER_DIR}" ]; then + echo "$DRY_RUN_SCRIPT_NAME: No package $TERMUX_PKG_NAME found in any of the enabled repositories. Are you trying to set up a custom repository?" + exit 1 + fi + TERMUX_PKG_BUILDER_SCRIPT="$TERMUX_PKG_BUILDER_DIR/build.sh" + + # Please keep synchronized with the logic of lines 2-50 of 'scripts/build/termux_step_start_build.sh'. + if [ "${TERMUX_ARCH}" != "all" ] && \ + grep -qE "^TERMUX_PKG_EXCLUDED_ARCHES=.*${TERMUX_ARCH}" "$TERMUX_PKG_BUILDER_SCRIPT"; then + echo "$DRY_RUN_SCRIPT_NAME: Skipping building $TERMUX_PKG_NAME for arch $TERMUX_ARCH" + continue + fi + + if [ "${TERMUX_DEBUG_BUILD}" = "true" ] && \ + grep -qE "^TERMUX_PKG_HAS_DEBUG=.*false" "$TERMUX_PKG_BUILDER_SCRIPT"; then + echo "$DRY_RUN_SCRIPT_NAME: Skipping building debug build for $TERMUX_PKG_NAME" + continue + fi + + echo "$DRY_RUN_SCRIPT_NAME: Ending dry run simulation ($BUILDSCRIPT_NAME would have continued building $TERMUX_PKG_NAME)" + exit 0 +done + +if [ ${#PACKAGE_LIST[@]} -gt 0 ]; then + # At least one package name was parsed, but none of them reached "exit 0", + # so exit with return value 85 (EX_C__NOOP) to indicate that no packages would have been built. + echo "$DRY_RUN_SCRIPT_NAME: Ending dry run simulation ($BUILDSCRIPT_NAME would not have built any packages)" + exit 85 # EX_C__NOOP +fi + +# If this point is reached, assume that a combination of arguments +# that is either invalid or is not implemented in this script +# has been used, and that the real 'build-package.sh' +# needs to be run so that its own parser can interpret the arguments +# and display the appropriate message. +echo "$DRY_RUN_SCRIPT_NAME: Ending dry run simulation (unknown arguments, pass to the real $BUILDSCRIPT_NAME for more information)" +exit 0 diff --git a/scripts/run-docker.sh b/scripts/run-docker.sh index 97b2d099cbefde2..c706b9cdda2bfbb 100755 --- a/scripts/run-docker.sh +++ b/scripts/run-docker.sh @@ -3,6 +3,34 @@ set -e -u TERMUX_SCRIPTDIR=$(cd "$(realpath "$(dirname "$0")")"; cd ..; pwd) +BUILDSCRIPT_NAME="build-package.sh" + +if [ "${1:-}" = "-p" ] || [ "${1:-}" = "--pre-check-if-will-build-packages" ]; then + shift 1 + TERMUX_DOCKER__CONTAINER_EXEC_COMMAND__PRE_CHECK_IF_WILL_BUILD_PACKAGES="true" +fi + +# If 'build-package-dry-run-simulation.sh' does not return 85 (EX_C__NOOP), or if +# $1 (the first argument passed to this script which runs docker) does not contain +# $BUILDSCRIPT_NAME, this condition will evaluate false and this script which +# runs docker will continue. +if [ "${TERMUX_DOCKER__CONTAINER_EXEC_COMMAND__PRE_CHECK_IF_WILL_BUILD_PACKAGES:-}" = "true" ]; then + case "${1:-}" in + *"/$BUILDSCRIPT_NAME") + RETURN_VALUE=0 + OUTPUT="$("$TERMUX_SCRIPTDIR/scripts/bin/build-package-dry-run-simulation.sh" "$@" 2>&1)" || RETURN_VALUE=$? + if [ $RETURN_VALUE -ne 0 ]; then + echo "$OUTPUT" 1>&2 + if [ $RETURN_VALUE -eq 85 ]; then # EX_C__NOOP + echo "$0: Exiting since '$BUILDSCRIPT_NAME' would not have built any packages" + exit 0 + fi + exit $RETURN_VALUE + fi + ;; + esac +fi + CONTAINER_HOME_DIR=/home/builder UNAME=$(uname) if [ "$UNAME" = Darwin ]; then