Unverified Commit 726417aa authored by Pol Dellaiera's avatar Pol Dellaiera Committed by GitHub
Browse files

build-support/php: improve PHP builder stability (#459254)

parents 9bd74d88 b19a7ee9
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -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.
+34 −12
Original line number Diff line number Diff line
@@ -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"

  setComposerEnvVariables

  echo "Finished composerInstallBuildHook"
  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"
}
+32 −24
Original line number Diff line number Diff line
@@ -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 <path>\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 <path/to/project_root>/\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"
}
+2 −0
Original line number Diff line number Diff line
@@ -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() {
+3 −3
Original line number Diff line number Diff line
@@ -6,22 +6,22 @@
php.buildComposerProject2 (finalAttrs: {
  pname = "baikal";
  version = "0.10.1";

  src = fetchFromGitHub {
    owner = "sabre-io";
    repo = "Baikal";
    tag = finalAttrs.version;
    hash = "sha256-YQQwTdwfHQZdUhO5HbScj/Bl8ype7TtPI3lHjvz2k04=";
  };

  # It doesn't provide a composer.lock file, we have to generate manually.
  composerLock = ./composer.lock;
  vendorHash = "sha256-dYg7cULL4gquR5EenA0lD9ZC9Ge4qNwFFDNhELKgSso=";
  vendorHash = "sha256-TM0dyr90bUDxUwywwkeHh0pAWkTB8FV3ricWCHGxA7k=";

  meta = {
    description = "Lightweight CalDAV+CardDAV server that offers an extensive web interface with easy management of users, address books and calendars";
    homepage = "https://sabre.io/baikal/";
    license = lib.licenses.gpl3Only;
    maintainers = with lib.maintainers; [ wrvsrx ];
    # vendorHash non-reproducible
    broken = true;
  };
})
Loading