diff --git a/doc/release-notes/rl-2605.section.md b/doc/release-notes/rl-2605.section.md index 3a3977ffb779..01f7347d7600 100644 --- a/doc/release-notes/rl-2605.section.md +++ b/doc/release-notes/rl-2605.section.md @@ -82,4 +82,4 @@ ### Additions and Improvements {#sec-nixpkgs-release-26.05-lib-additions-improvements} -- Create the first release note entry in this section! +- The builder `php.buildComposerProject2` for PHP applications has been improved for better reliability and stability. diff --git a/pkgs/build-support/php/builders/v2/hooks/composer-install-hook.sh b/pkgs/build-support/php/builders/v2/hooks/composer-install-hook.sh index 4e3eba5f0785..19783d08fb1c 100644 --- a/pkgs/build-support/php/builders/v2/hooks/composer-install-hook.sh +++ b/pkgs/build-support/php/builders/v2/hooks/composer-install-hook.sh @@ -5,6 +5,16 @@ declare -g pname declare -g composerVendor declare -g -i composerStrictValidation="${composerStrictValidation:-0}" +declare -g composerNoDev +declare -g composerNoPlugins +declare -g composerNoScripts + +declare -ga composerFlags=() + +[[ 1 == "${composerNoDev:-1}" ]] && composerFlags+=(--no-dev) +[[ 1 == "${composerNoPlugins:-1}" ]] && composerFlags+=(--no-plugins) +[[ 1 == "${composerNoScripts:-1}" ]] && composerFlags+=(--no-scripts) + preConfigureHooks+=(composerInstallConfigureHook) preBuildHooks+=(composerInstallBuildHook) preCheckHooks+=(composerInstallCheckHook) @@ -14,12 +24,12 @@ preInstallHooks+=(composerInstallInstallHook) source @phpScriptUtils@ composerInstallConfigureHook() { - echo "Executing composerInstallConfigureHook" + echo "Running phase: composerInstallConfigureHook" setComposerRootVersion if [[ ! -e "${composerVendor}" ]]; then - echo "No local composer vendor found." >&2 + echo -e "\e[31mERROR: The 'composerVendor' attribute is missing or invalid.\e[0m" >&2 exit 1 fi @@ -35,27 +45,39 @@ composerInstallConfigureHook() { chmod +w composer.json - echo "Finished composerInstallConfigureHook" + echo "Finished phase: composerInstallConfigureHook" } composerInstallBuildHook() { - echo "Executing composerInstallBuildHook" + echo "Running phase: composerInstallBuildHook" - echo "Finished composerInstallBuildHook" + setComposerEnvVariables + + echo -e "\e[32mRestoring Composer vendor directory to '${COMPOSER_VENDOR_DIR}'...\e[0m" + cp -r "${composerVendor}/${COMPOSER_VENDOR_DIR}" . + chmod -R +w "${COMPOSER_VENDOR_DIR}" + + echo -e "\e[32mGenerating optimized autoloader and restoring 'bin' directory...\e[0m" + COMPOSER_DISABLE_NETWORK=1 composer \ + "${composerFlags[@]}" \ + --no-interaction \ + --no-progress \ + --optimize-autoloader \ + install + + echo "Finished phase: composerInstallBuildHook" } composerInstallCheckHook() { - echo "Executing composerInstallCheckHook" + echo "Running phase: composerInstallCheckHook" checkComposerValidate - echo "Finished composerInstallCheckHook" + echo "Finished phase: composerInstallCheckHook" } composerInstallInstallHook() { - echo "Executing composerInstallInstallHook" - - cp -ar "${composerVendor}"/* . + echo "Running phase: composerInstallInstallHook" # Copy the relevant files only in the store. mkdir -p "$out"/share/php/"${pname}" @@ -64,10 +86,10 @@ composerInstallInstallHook() { # Create symlinks for the binaries. mapfile -t BINS < <(jq -r -c 'try (.bin[] | select(test(".bat$")? | not) )' composer.json) for bin in "${BINS[@]}"; do - echo -e "\e[32mCreating symlink ${bin}...\e[0m" + echo -e "\e[32mInstalling binary: ${bin}\e[0m" mkdir -p "$out/bin" ln -s "$out/share/php/${pname}/${bin}" "$out/bin/$(basename "$bin")" done - echo "Finished composerInstallInstallHook" + echo "Finished phase: composerInstallInstallHook" } diff --git a/pkgs/build-support/php/builders/v2/hooks/composer-vendor-hook.sh b/pkgs/build-support/php/builders/v2/hooks/composer-vendor-hook.sh index 83dda99f33cd..f14a53778a90 100644 --- a/pkgs/build-support/php/builders/v2/hooks/composer-vendor-hook.sh +++ b/pkgs/build-support/php/builders/v2/hooks/composer-vendor-hook.sh @@ -10,9 +10,9 @@ declare -g composerNoPlugins declare -g composerNoScripts declare -ga composerFlags=() -[[ -n "${composerNoDev-}" ]] && composerFlags+=(--no-dev) -[[ -n "${composerNoPlugins-}" ]] && composerFlags+=(--no-plugins) -[[ -n "${composerNoScripts-}" ]] && composerFlags+=(--no-scripts) +[[ 1 == "${composerNoDev:-1}" ]] && composerFlags+=(--no-dev) +[[ 1 == "${composerNoPlugins:-1}" ]] && composerFlags+=(--no-plugins) +[[ 1 == "${composerNoScripts:-1}" ]] && composerFlags+=(--no-scripts) preConfigureHooks+=(composerVendorConfigureHook) preBuildHooks+=(composerVendorBuildHook) @@ -20,20 +20,21 @@ preCheckHooks+=(composerVendorCheckHook) preInstallHooks+=(composerVendorInstallHook) composerVendorConfigureHook() { - echo "Executing composerVendorConfigureHook" + echo "Running phase: composerVendorConfigureHook" setComposerRootVersion if [[ -f "composer.lock" ]]; then - echo -e "\e[32mUsing \`composer.lock\` file from the source package\e[0m" + echo -e "\e[32mFound 'composer.lock' in source root.\e[0m" fi if [[ -e "$composerLock" ]]; then - echo -e "\e[32mUsing user provided \`composer.lock\` file from \`$composerLock\`\e[0m" + echo -e "\e[32mUsing provided 'composer.lock' from: $composerLock\e[0m" install -Dm644 "$composerLock" ./composer.lock fi if [[ ! -f "composer.lock" ]]; then + echo "No 'composer.lock' found. Updating dependencies to generate one..." composer \ --no-cache \ --no-install \ @@ -47,16 +48,17 @@ composerVendorConfigureHook() { install -Dm644 composer.lock -t "$out"/ echo - echo -e "\e[31mERROR: No composer.lock found\e[0m" + echo -e "\e[31mERROR: Missing 'composer.lock' file.\e[0m" echo - echo -e '\e[31mNo composer.lock file found, consider adding one to your repository to ensure reproducible builds.\e[0m' - echo -e "\e[31mIn the meantime, a composer.lock file has been generated for you in $out/composer.lock\e[0m" + echo -e "\e[31mA 'composer.lock' file is required to ensure reproducible builds, but it was not found in the source.\e[0m" + echo -e "\e[31mA temporary lock file has been generated for you at:\e[0m" + echo -e "\e[31m $out/composer.lock\e[0m" echo - echo -e '\e[31mTo fix the issue:\e[0m' - echo -e "\e[31m1. Copy the composer.lock file from $out/composer.lock to the project's source:\e[0m" - echo -e "\e[31m cp $out/composer.lock \e[0m" - echo -e '\e[31m2. Add the composerLock attribute, pointing to the copied composer.lock file:\e[0m' - echo -e '\e[31m composerLock = ./composer.lock;\e[0m' + echo -e "\e[31mTo fix this issue:\e[0m" + echo -e "\e[31m1. Copy the generated lock file to your project source:\e[0m" + echo -e "\e[31m cp $out/composer.lock /\e[0m" + echo -e "\e[31m2. Register the lock file in your Nix expression:\e[0m" + echo -e "\e[31m composerLock = ./composer.lock;\e[0m" echo exit 1 @@ -69,39 +71,45 @@ composerVendorConfigureHook() { chmod +w composer.json - echo "Finished composerVendorConfigureHook" + echo "Finished phase: composerVendorConfigureHook" } composerVendorBuildHook() { - echo "Executing composerVendorBuildHook" + echo "Running phase: composerVendorBuildHook" setComposerEnvVariables + echo -e "\e[32mInstalling Composer dependencies to '${COMPOSER_VENDOR_DIR}'...\e[0m" composer \ --no-cache \ --no-interaction \ --no-progress \ - --optimize-autoloader \ + --no-autoloader \ "${composerFlags[@]}" \ install - echo "Finished composerVendorBuildHook" + # Clarified: We remove it because we only want the 'vendor' folder here, not the bins yet. + echo -e "\e[32mCleaning up Composer 'bin' directory (will be regenerated during install).\e[0m" + rm -rf "$(composer config bin-dir)" + + echo "Finished phase: composerVendorBuildHook" } composerVendorCheckHook() { - echo "Executing composerVendorCheckHook" + echo "Running phase: composerVendorCheckHook" checkComposerValidate - echo "Finished composerVendorCheckHook" + echo "Finished phase: composerVendorCheckHook" } composerVendorInstallHook() { - echo "Executing composerVendorInstallHook" + echo "Running phase: composerVendorInstallHook" mkdir -p "$out" - cp -ar composer.json "$(composer config vendor-dir)" "$out"/ + echo -e "\e[32mPreserving Composer vendor directory from '${COMPOSER_VENDOR_DIR}'...\e[0m" + cp -ar composer.json "${COMPOSER_VENDOR_DIR}" "$out"/ mapfile -t installer_paths < <(jq -r -c 'try((.extra."installer-paths") | keys[])' composer.json) for installer_path in "${installer_paths[@]}"; do @@ -111,7 +119,7 @@ composerVendorInstallHook() { # Copy the installer path if it exists if [[ -d "$installer_path" ]]; then mkdir -p "$(dirname "$out_installer_path")" - echo -e "\e[32mCopying installer path $installer_path to $out_installer_path\e[0m" + echo -e "\e[32mPreserving custom installer path: $installer_path\e[0m" cp -ar "$installer_path" "$out_installer_path" # Strip out the git repositories find "$out_installer_path" -name .git -type d -prune -print -exec rm -rf {} ";" @@ -122,5 +130,5 @@ composerVendorInstallHook() { cp -ar composer.lock "$out"/ fi - echo "Finished composerVendorInstallHook" + echo "Finished phase: composerVendorInstallHook" } diff --git a/pkgs/build-support/php/builders/v2/hooks/php-script-utils.bash b/pkgs/build-support/php/builders/v2/hooks/php-script-utils.bash index bec552bfaa46..83dce2e9715a 100644 --- a/pkgs/build-support/php/builders/v2/hooks/php-script-utils.bash +++ b/pkgs/build-support/php/builders/v2/hooks/php-script-utils.bash @@ -15,6 +15,8 @@ setComposerEnvVariables() { export COMPOSER_MIRROR_PATH_REPOS=1 export COMPOSER_HTACCESS_PROTECT=0 export COMPOSER_FUND=0 + COMPOSER_VENDOR_DIR=$(composer config vendor-dir) + export COMPOSER_VENDOR_DIR } checkComposerValidate() {