Repository: bmitch/churn-php (php)

Issue:
"commitsSince" not recognized
When I drop in the example config (modified or verbatim) I get the following warning on launch:
```console
Unrecognized configuration keys: commitsSince
```
Fresh install of `church` as `composer require --dev`, both pulled version `1.7.0`. I don't see any other reports of this so far; I will dig through the config code and bit and see if anything is apparent.


Discussion:
It is because the configuration string is actual the singular `commitSince`: https://github.com/bmitch/churn-php/blob/fca48716d5b958a3bd87ed80adefdf87e0e63f27/src/Configuration/Validator/CommitsSince.php#L20

The Validator is actually the plural though as well. Need a maintainer to advise, then I can send a PR one way or another.
Thank you for the report!

The right key is `commitsSince`.
This regression exists since `1.6.0` and has been introduced by [1b59a42](https://github.com/bmitch/churn-php/commit/1b59a427afda35f93ca145f7c5afed010f9cbf6a).

In my opinion we should support the 2 spellings just in case some users already use the singular form.
However the usage of `commitSince` must trigger a deprecation message indicating it won't be supported in the next major version.

Patch:
diff --git a/.github/workflows/pull-request.yml b/.github/workflows/pull-request.yml
--- a/.github/workflows/pull-request.yml
+++ b/.github/workflows/pull-request.yml
@@ -31,4 +31,4 @@ jobs:
       - name: "Run Infection"
         run: |
           git fetch --depth=1 origin $GITHUB_BASE_REF
-          infection -j$(nproc) --logger-github --git-diff-filter=AM --git-diff-base=origin/$GITHUB_BASE_REF --ignore-msi-with-no-mutations --min-msi=76 --min-covered-msi=82
+          infection -j$(nproc) --logger-github --show-mutations --git-diff-filter=AM --git-diff-base=origin/$GITHUB_BASE_REF --ignore-msi-with-no-mutations --min-msi=75 --min-covered-msi=80
diff --git a/bin/bootstrap.php b/bin/bootstrap.php
--- a/bin/bootstrap.php
+++ b/bin/bootstrap.php
@@ -4,6 +4,7 @@
 
 error_reporting(E_ALL);
 ini_set('display_errors', 'stderr');
+ini_set('log_errors', 'Off');
 
 foreach (
     [
diff --git a/infection.json b/infection.json
--- a/infection.json
+++ b/infection.json
@@ -6,7 +6,7 @@
         ]
     },
     "logs": {
-        "text": "infection.log"
+        "text": "php://stdout"
     },
     "mutators": {
         "@default": true,
diff --git a/src/Configuration/Validator/CommitsSince.php b/src/Configuration/Validator/CommitsSince.php
--- a/src/Configuration/Validator/CommitsSince.php
+++ b/src/Configuration/Validator/CommitsSince.php
@@ -17,7 +17,23 @@ final class CommitsSince extends BaseValidator
      */
     public function __construct()
     {
-        parent::__construct('commitSince');
+        parent::__construct('commitsSince');
+    }
+
+    /**
+     * @param EditableConfig $config The configuration object.
+     * @param array<mixed> $configuration The array containing the configuration values.
+     */
+    public function validate(EditableConfig $config, array $configuration): void
+    {
+        if (!$this->hasConfigurationKey($configuration)) {
+            return;
+        }
+
+        /** @var mixed $value */
+        $value = $configuration[$this->key];
+
+        $this->validateValue($config, $value);
     }
 
     /**
@@ -30,4 +46,27 @@ protected function validateValue(EditableConfig $config, $value): void
 
         $config->setCommitsSince($value);
     }
+
+    /**
+     * @param array<mixed> $configuration The array containing the configuration values.
+     */
+    private function hasConfigurationKey(array $configuration): bool
+    {
+        if (\array_key_exists($this->key, $configuration)) {
+            return true;
+        }
+
+        if (\array_key_exists('commitSince', $configuration)) {
+            $this->key = 'commitSince';
+            \trigger_error(
+                'The "commitSince" configuration key is deprecated and won\'t be supported'
+                . ' in the next major version anymore. Use "commitsSince" instead.',
+                \E_USER_DEPRECATED
+            );
+
+            return true;
+        }
+
+        return false;
+    }
 }


Test patch:
diff --git a/tests/Integration/Command/config/unrecognized-keys.yml b/tests/Integration/Command/config/unrecognized-keys.yml
--- a/tests/Integration/Command/config/unrecognized-keys.yml
+++ b/tests/Integration/Command/config/unrecognized-keys.yml
@@ -1,2 +1,17 @@
 foo: ~
-bar: baz
\ No newline at end of file
+bar: baz
+
+# The following keys must not be reported as unrecognized
+filesToShow: 10
+minScoreToShow: 0.1
+maxScoreThreshold: null
+parallelJobs: 10
+commitsSince: One year ago
+filesToIgnore: []
+fileExtensions:
+ - php
+directoriesToScan:
+ - src
+hooks: []
+vcs: git
+cachePath: null
diff --git a/tests/Unit/Configuration/ValidatorTest.php b/tests/Unit/Configuration/ValidatorTest.php
--- a/tests/Unit/Configuration/ValidatorTest.php
+++ b/tests/Unit/Configuration/ValidatorTest.php
@@ -134,4 +134,34 @@ public function provide_validators_with_invalid_value(): iterable
         yield 'Vcs / int' => [new Vcs(), 123, 'VCS should be a string'];
         yield 'Vcs / null' => [new Vcs(), null, 'VCS should be a string'];
     }
+
+    /**
+     * @test
+     */
+    public function it_emits_a_deprecation_warning_for_commit_since(): void
+    {
+        $deprecationMessage = null;
+        set_error_handler(function ($_, $errstr) use (&$deprecationMessage) {
+            $deprecationMessage = $errstr;
+
+            return true;
+        }, \E_USER_DEPRECATED);
+
+        try {
+            $config = new EditableConfig();
+            $validator = new CommitsSince();
+            $validator->validate($config, ['commitSince' => 'one day ago']);
+
+            $this->assertEquals('one day ago', $config->getCommitsSince());
+            $this->assertEquals('commitSince', $validator->getKey());
+	} finally {
+            restore_error_handler();
+        }
+
+        $this->assertEquals(
+            'The "commitSince" configuration key is deprecated and won\'t be supported'
+            . ' in the next major version anymore. Use "commitsSince" instead.',
+            $deprecationMessage
+        );
+    }
 }