drush-ops / drush

Drush is a command-line shell and scripting interface for Drupal, a veritable Swiss Army knife designed to make life easier for those who spend their working hours hacking away at the command prompt.
https://www.drush.org
2.34k stars 1.08k forks source link

Ability to execute a config diff without exit status 1 or error messages #6162

Open jameswilson opened 1 week ago

jameswilson commented 1 week ago

Is your feature request related to a problem? Please describe. Currently, the drush config:import --no --diff command outputs a configuration diff and does not execute the import, as expected when the --no flag is used. However, the command still exits with status code 1, indicating a failure. This is problematic when the intent is to retrieve a config diff without performing an import or generating an error in scripts or logs.

Many users, including myself, are frustrated by this behavior because the command, in this context, performs exactly as intended—outputting a diff and abstaining from importing—yet it results in a "failed" exit status. This complicates scripting and logging when only a diff is needed without triggering a script failure.

Current output,

$ drush config:import --no --diff
diff --git a/tmp/drush_tmp_1731606322_67363732aed14/system.site.yml b/tmp/drush_tmp_1731606323_6736373347357/system.site.yml
index 0418eb8f19..7d88f504d7 100644
--- a/tmp/drush_tmp_1731606322_67363732aed14/system.site.yml
+++ b/tmp/drush_tmp_1731606323_6736373347357/system.site.yml
@@ -4,7 +4,7 @@ langcode: en
 uuid: XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX
 name: 'My Website'
 mail: admin@example.com
-slogan: 'CHANGED ON PROD'
+slogan: ''
 page:
   403: /node/3
   404: /node/4

 !
 ! [WARNING] Import the listed configuration changes?: no.
 !

In ConfigImportCommands.php line 228:

  Cancelled.

Failed to execute command drush config:import --no --diff: exit status 1

Describe the solution you'd like

  1. Introduce a dedicated command drush config:diff.

    A config:diff command will enable diff-only output without the failed exit code, WARNING, or error messages. This new command should allow users to view the configuration differences between the current and new config states without triggering an error status, ensuring compatibility with scripts or logging processes that expect a successful run. The command can be considered analogous to git diff and may in fact pass through status codes from the underlying command used internally to generate the diff.

    The desired behavior is for the diff command to exit with code 0 when it completes successfully, even if no import takes place, reflecting the intention of the --no or --dry-run (see below) functionality.

  2. Support --reverse flag.

    In the case of a new command drush config:diff should also allow a --reverse flag, analogous to the git diff -R flag to swap the two inputs; that is, show differences from staged config to the active config in the codebase (like config:export --diff) as opposed to the other way around (like config:import --diff).

  3. Support --quiet mode for scripting.

    git diff has a --quiet option that returns a status code of 0 or 1 as a quick way to detect if there are changes in the local working copy. Such a feature would be a useful addition for both drush config:diff and drush config:status

    if drush config:diff --quiet; then
      echo "Active config is in sync with codebase."
    else
      echo "Config changes detected in database."
    fi

    config:diff --quiet (or even config:status --quiet) could be a new-and-improved alternative to the currently documented approach of drush config:status 2>&1 | grep "No differences".

Describe alternatives you've considered

  1. Adding a --dry-run option to config:import (and config:export), to be used instead of the current --no flag, which is typically more consistent with other CLI conventions where a dry-run indicates no action will occur to avoid the exit code 1. I decided against this alternative for the proposal because the reasonable expectation of a dry-run flag on a configuration import or export task would be used to determine if the import/export would work without errors. While such a behavior might be useful, it seems potentially very hard to implement and lies outside the scope of this issue.
  2. Adding a --diff-only option to config:status, so that configuration differences can be reviewed independently of the import command, similar to git diff functionality. I decided against this alternative because it prevents future enhancements and options being added for just the diff functionality, such as the --reverse option mentioned above. Ultimately, a dedicated command makes the most sense here.

Additional context There’s a common use case where users need to see the config diff for validation or logging purposes without triggering a config import or an error. This feature would also align with common patterns in CLI tools like diff and grep, where exit code 1 is informational rather than an error. The current behavior complicates script automation, as adding || true after the command is required to prevent script termination, which is cumbersome and unintuitive.

weitzman commented 6 days ago

Seems like a reasonable feature request. I asked for this at https://github.com/drush-ops/drush/pull/2726#discussion_r113791118. I think config:status is a good place for this, or a new command as you've proposed.

FYI Drush already has --quiet and --simulate global options. Not all commands support them.