From 63e4610f22effa6a9ef122e5ab2d23ee3456c7b7 Mon Sep 17 00:00:00 2001 From: Florent Morselli Date: Fri, 11 Nov 2022 13:39:14 +0100 Subject: [PATCH 1/2] New pipeline + ECS + Rector (#167) * New pipeline + ECS + Rector * parallel-lint * CI/CD fixes * Deptrac * Exported files * Error fixed --- .editorconfig | 29 +++ .gitattributes | 4 +- .github/CONTRIBUTING.md | 13 +- .github/ISSUE_TEMPLATE/1_Bug_report.yaml | 77 +++--- .github/ISSUE_TEMPLATE/2_Feature_request.yaml | 28 +-- .github/ISSUE_TEMPLATE/3_Documentation.yaml | 14 +- .github/ISSUE_TEMPLATE/config.yml | 9 +- .github/PULL_REQUEST_TEMPLATE.md | 32 ++- .github/dependabot.yml | 23 +- .github/stale.yml | 8 +- .github/workflows/coding-standards.yml | 32 --- .github/workflows/gitsplit.yml | 18 ++ .github/workflows/integrate.yml | 230 ++++++++++++++++++ .github/workflows/merge-me.yml | 28 +++ .github/workflows/mutation-tests.yml | 35 --- .github/workflows/rector_checkstyle.yaml | 30 --- .../workflows/release-on-milestone-closed.yml | 72 ++++++ .github/workflows/static-analyze.yml | 33 --- .github/workflows/tests.yml | 32 --- .github/workflows/tweet.yml | 23 ++ .gitignore | 2 +- Makefile | 72 +++--- composer.json | 6 +- deptrac.yaml | 14 ++ infection.json.dist | 11 +- phpstan.neon | 19 +- phpunit.xml.dist | 48 ++-- src/HOTP.php | 11 +- src/OTP.php | 4 +- src/ParameterTrait.php | 4 +- src/Url.php | 2 +- tests/TOTPTest.php | 15 +- 32 files changed, 642 insertions(+), 336 deletions(-) create mode 100644 .editorconfig delete mode 100644 .github/workflows/coding-standards.yml create mode 100644 .github/workflows/gitsplit.yml create mode 100644 .github/workflows/integrate.yml create mode 100644 .github/workflows/merge-me.yml delete mode 100644 .github/workflows/mutation-tests.yml delete mode 100644 .github/workflows/rector_checkstyle.yaml create mode 100644 .github/workflows/release-on-milestone-closed.yml delete mode 100644 .github/workflows/static-analyze.yml delete mode 100644 .github/workflows/tests.yml create mode 100644 .github/workflows/tweet.yml create mode 100644 deptrac.yaml diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 0000000..f329996 --- /dev/null +++ b/.editorconfig @@ -0,0 +1,29 @@ +# https://EditorConfig.org + +root = true + +[*] +indent_style = space +# Reduce tab size on GitHub +indent_size = 4 +end_of_line = lf +charset = utf-8 +trim_trailing_whitespace = true +insert_final_newline = true +block_comment_start = /* +block_comment = * +block_comment_end = */ + +[{*.yml,*.yaml}] +indent_size = 2 + +[*.md] +trim_trailing_whitespace = false + +[Makefile] +indent_style = tab + +# Generated file +[infection.txt] +indent_size = unset +trim_trailing_whitespace = unset diff --git a/.gitattributes b/.gitattributes index cea09fc..de25e8f 100644 --- a/.gitattributes +++ b/.gitattributes @@ -3,14 +3,14 @@ /.github export-ignore /doc export-ignore /tests export-ignore +/.editorconfig export-ignore /.gitattributes export-ignore /.gitignore export-ignore /CODE_OF_CONDUCT.md export-ignore +/deptrac.yaml export-ignore /ecs.php export-ignore /infection.json.dist export-ignore /Makefile export-ignore /phpstan.neon export-ignore /phpunit.xml.dist export-ignore -/README.md export-ignore /rector.php export-ignore -/SECURITY.md export-ignore diff --git a/.github/CONTRIBUTING.md b/.github/CONTRIBUTING.md index 2b7c6aa..7cc67ce 100644 --- a/.github/CONTRIBUTING.md +++ b/.github/CONTRIBUTING.md @@ -11,9 +11,14 @@ Few rules to ease code reviews and merges: - You MUST write (or update) unit tests when bugs are fixed or features are added. - You SHOULD write documentation. -To contribute use [Pull Requests](https://help.github.com/articles/using-pull-requests), please, write commit messages that make sense, and rebase your branch before submitting your PR. +We use [Git-Flow](http://jeffkreeftmeijer.com/2010/why-arent-you-using-git-flow/) to automate our git branching +workflow. -May be asked to squash your commits too. This is used to "clean" your Pull Request before merging it, avoiding commits such as fix tests, fix 2, fix 3, etc. +To contribute use [Pull Requests](https://help.github.com/articles/using-pull-requests), please, write commit messages +that make sense, and rebase your branch before submitting your PR. + +May be asked to squash your commits too. This is used to "clean" your Pull Request before merging it, avoiding commits +such as fix tests, fix 2, fix 3, etc. Run test suite ------------ @@ -21,7 +26,3 @@ Run test suite * install composer: `curl -s http://getcomposer.org/installer | php` * install dependencies: `php composer.phar install` * run tests: `vendor/bin/phpunit` -* check and fix coding standards: - * `vendor/bin/phpstan analyse` - * `vendor/bin/rector process` - * `vendor/bin/ecs check --fix` diff --git a/.github/ISSUE_TEMPLATE/1_Bug_report.yaml b/.github/ISSUE_TEMPLATE/1_Bug_report.yaml index 841cfdc..d3f26cf 100644 --- a/.github/ISSUE_TEMPLATE/1_Bug_report.yaml +++ b/.github/ISSUE_TEMPLATE/1_Bug_report.yaml @@ -1,43 +1,42 @@ name: 🐛 Bug Report description: ⚠️ NEVER report security issues, email security AT spomky-labs.com instead labels: Bug - body: - - type: input - id: affected-versions - attributes: - label: Version(s) affected - placeholder: x.y.z - validations: - required: true - - type: textarea - id: description - attributes: - label: Description - description: A clear and concise description of the problem - validations: - required: true - - type: textarea - id: how-to-reproduce - attributes: - label: How to reproduce - description: | - ⚠️ This is the most important part of the report ⚠️ - Without a way to easily reproduce your issue, there is little chance we will be able to help you and work on a fix. - Please, take the time to show us some code and/or config that is needed for others to reproduce the problem easily. - Most of the time, creating a "bug reproducer" is the best way to help us and increases the chances someone - will have a look at it. - validations: - required: true - - type: textarea - id: possible-solution - attributes: - label: Possible Solution - description: | - Optional: only if you have suggestions on a fix/reason for the bug - Don't hesitate to create a pull request with your solution, it helps get faster feedback. - - type: textarea - id: additional-context - attributes: - label: Additional Context - description: "Optional: any other context about the problem: log messages, screenshots, etc." + - type: input + id: affected-versions + attributes: + label: Version(s) affected + placeholder: x.y.z + validations: + required: true + - type: textarea + id: description + attributes: + label: Description + description: A clear and concise description of the problem + validations: + required: true + - type: textarea + id: how-to-reproduce + attributes: + label: How to reproduce + description: | + ⚠️ This is the most important part of the report ⚠️ + Without a way to easily reproduce your issue, there is little chance we will be able to help you and work on a fix. + Please, take the time to show us some code and/or config that is needed for others to reproduce the problem easily. + Most of the time, creating a "bug reproducer" is the best way to help us and increases the chances someone + will have a look at it. + validations: + required: true + - type: textarea + id: possible-solution + attributes: + label: Possible Solution + description: | + Optional: only if you have suggestions on a fix/reason for the bug + Don't hesitate to create a pull request with your solution, it helps get faster feedback. + - type: textarea + id: additional-context + attributes: + label: Additional Context + description: "Optional: any other context about the problem: log messages, screenshots, etc." diff --git a/.github/ISSUE_TEMPLATE/2_Feature_request.yaml b/.github/ISSUE_TEMPLATE/2_Feature_request.yaml index bd300eb..52b3de7 100644 --- a/.github/ISSUE_TEMPLATE/2_Feature_request.yaml +++ b/.github/ISSUE_TEMPLATE/2_Feature_request.yaml @@ -1,17 +1,17 @@ name: 🚀 Feature Request description: RFC and ideas for new features and improvements body: - - type: textarea - id: description - attributes: - label: Description - description: A clear and concise description of the new feature - validations: - required: true - - type: textarea - id: example - attributes: - label: Example - description: | - A simple example of the new feature in action (include PHP code, YAML config, etc.) - If the new feature changes an existing feature, include a simple before/after comparison. + - type: textarea + id: description + attributes: + label: Description + description: A clear and concise description of the new feature + validations: + required: true + - type: textarea + id: example + attributes: + label: Example + description: | + A simple example of the new feature in action (include PHP code, YAML config, etc.) + If the new feature changes an existing feature, include a simple before/after comparison. diff --git a/.github/ISSUE_TEMPLATE/3_Documentation.yaml b/.github/ISSUE_TEMPLATE/3_Documentation.yaml index 7a3dc17..1c5ac89 100644 --- a/.github/ISSUE_TEMPLATE/3_Documentation.yaml +++ b/.github/ISSUE_TEMPLATE/3_Documentation.yaml @@ -1,10 +1,10 @@ name: 📖 Documentation Issue description: To report typo or obsolete section in the documentation body: - - type: textarea - id: description - attributes: - label: Description - description: A clear and concise description of the error you found in the documentation - validations: - required: true + - type: textarea + id: description + attributes: + label: Description + description: A clear and concise description of the error you found in the documentation + validations: + required: true diff --git a/.github/ISSUE_TEMPLATE/config.yml b/.github/ISSUE_TEMPLATE/config.yml index 1181241..6d11ce2 100644 --- a/.github/ISSUE_TEMPLATE/config.yml +++ b/.github/ISSUE_TEMPLATE/config.yml @@ -1,5 +1,8 @@ blank_issues_enabled: false contact_links: - - name: Support Question - url: https://spomky-labs.com/contact/ - about: We use GitHub issues only to discuss about bugs and new features. For this kind of questions about using the library, please use Stackoverflow (or similar) or send a quote request at https://spomky-labs.com/contact/ + - name: Support Question + url: https://spomky-labs.com/contact/ + about:| + We use GitHub issues only to discuss about bugs and new features. + For this kind of questions about using the framework or third-party bundles, + please email us contact AT spomky-labs.com for quoting diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md index 1beb0a3..029817b 100644 --- a/.github/PULL_REQUEST_TEMPLATE.md +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -1,19 +1,17 @@ -| Q | A -| ------------- | --- -| Branch? | -| Bug fix? | yes/no -| New feature? | yes/no -| Deprecations? | yes/no -| Tickets | Fix #... -| License | MIT +Target branch: +Resolves issue # + + +- [ ] It is a Bug fix +- [ ] It is a New feature +- [ ] Breaks BC +- [ ] Includes Deprecations + \ No newline at end of file +Please consider the following requirement: +* Modification of existing tests should be avoided unless deemed necessary. +* You MUST never open a PR related to a security issue. Contact Spomky in private at https://gitter.im/Spomky/ +--> diff --git a/.github/dependabot.yml b/.github/dependabot.yml index 75436e4..ae2faa4 100644 --- a/.github/dependabot.yml +++ b/.github/dependabot.yml @@ -1,8 +1,19 @@ version: 2 updates: -- package-ecosystem: composer - directory: "/" - schedule: - interval: daily - time: "11:00" - open-pull-requests-limit: 10 + - package-ecosystem: "composer" + directory: "/" + schedule: + interval: "weekly" + day: "friday" + versioning-strategy: "widen" + open-pull-requests-limit: 20 + allow: + - dependency-type: all + labels: [ "Dependencies" ] + + - package-ecosystem: "github-actions" + directory: "/" + schedule: + interval: "monthly" + open-pull-requests-limit: 20 + labels: [ "Dependencies" ] diff --git a/.github/stale.yml b/.github/stale.yml index 98284be..19367a6 100644 --- a/.github/stale.yml +++ b/.github/stale.yml @@ -1,8 +1,8 @@ -daysUntilStale: 60 +daysUntilStale: 30 daysUntilClose: 7 staleLabel: wontfix markComment: > - Ce problème a été automatiquement marqué comme périmé car il n'a pas eu - d’activité récente. Il sera fermé dans 7 jours si aucune autre activité ne se produit. Merci - pour votre contribution. + This issue has been automatically marked as stale because it has not had + recent activity. It will be closed if no further activity occurs. Thank you + for your contributions. closeComment: false diff --git a/.github/workflows/coding-standards.yml b/.github/workflows/coding-standards.yml deleted file mode 100644 index 584b524..0000000 --- a/.github/workflows/coding-standards.yml +++ /dev/null @@ -1,32 +0,0 @@ -name: Coding Standards - -on: [push] - -jobs: - tests: - runs-on: ${{ matrix.operating-system }} - strategy: - matrix: - operating-system: [ubuntu-latest] - php-versions: ['8.1'] - name: PHP ${{ matrix.php-versions }} Test on ${{ matrix.operating-system }} - - steps: - - name: Checkout - uses: actions/checkout@v2 - with: - ref: ${{ github.head_ref }} - - - name: Setup PHP, with composer and extensions - uses: shivammathur/setup-php@v2 - with: - php-version: ${{ matrix.php-versions }} - extensions: mbstring - coverage: xdebug - - - name: Install the application - run: | - composer install --no-progress --prefer-dist --optimize-autoloader - - - name: Coding Standards Checks - run: make ci-cs diff --git a/.github/workflows/gitsplit.yml b/.github/workflows/gitsplit.yml new file mode 100644 index 0000000..0677186 --- /dev/null +++ b/.github/workflows/gitsplit.yml @@ -0,0 +1,18 @@ +name: gitsplit +on: + push: + tags: + - '*' + release: + types: [ published ] + +jobs: + gitsplit: + runs-on: ubuntu-latest + steps: + - name: checkout + run: git clone https://github.com/web-auth/webauthn-framework /home/runner/work/web-auth/webauthn-framework && cd /home/runner/work/web-auth/webauthn-framework + - name: Split repositories + run: docker run --rm -t -e GH_TOKEN -v /cache/gitsplit:/cache/gitsplit -v /home/runner/work/web-auth/webauthn-framework:/srv jderusse/gitsplit gitsplit + env: + GH_TOKEN: ${{ secrets.GITSPLIT_TOKEN }} diff --git a/.github/workflows/integrate.yml b/.github/workflows/integrate.yml new file mode 100644 index 0000000..5578d06 --- /dev/null +++ b/.github/workflows/integrate.yml @@ -0,0 +1,230 @@ +# yaml-language-server: $schema=https://json.schemastore.org/github-workflow + +name: "Integrate" + +on: + push: + branches: + - "*.x" + pull_request: null + +jobs: + byte_level: + name: "0️⃣ Byte-level" + runs-on: "ubuntu-latest" + steps: + - name: "Checkout code" + uses: "actions/checkout@v3" + + - name: "Check file permissions" + run: | + test "$(find . -type f -not -path './.git/*' -executable)" == "" + + - name: "Find non-printable ASCII characters" + run: | + ! LC_ALL=C.UTF-8 find . -type f -name "*.php" -print0 | xargs -0 -- grep -PHn "[^ -~]" + + syntax_errors: + name: "1️⃣ Syntax errors" + runs-on: "ubuntu-latest" + steps: + - name: "Set up PHP" + uses: "shivammathur/setup-php@v2" + with: + php-version: "8.1" + coverage: "none" + + - name: "Checkout code" + uses: "actions/checkout@v3" + + - name: "Install dependencies" + uses: "ramsey/composer-install@v2" + with: + dependency-versions: "highest" + + - name: "Check source code for syntax errors" + run: "composer exec -- parallel-lint src/ tests/" + + unit_tests: + name: "2️⃣ Unit and functional tests" + needs: + - "byte_level" + - "syntax_errors" + strategy: + matrix: + operating-system: + - "ubuntu-latest" + php-version: + - "8.1" + dependencies: + - "lowest" + - "highest" + runs-on: ${{ matrix.operating-system }} + steps: + - name: "Set up PHP" + uses: "shivammathur/setup-php@v2" + with: + php-version: "${{ matrix.php-version }}" + extensions: "mbstring" + coverage: "xdebug" + + - name: "Checkout code" + uses: "actions/checkout@v3" + + - name: "Install dependencies" + uses: "ramsey/composer-install@v2" + with: + dependency-versions: "${{ matrix.dependencies }}" + composer-options: "--optimize-autoloader" + + - name: "Execute tests (PHP)" + run: "make ci-cc" + + # - name: Send coverage to Coveralls + # if: "matrix.php-version == '8.1' && matrix.dependencies == 'highest'" + # env: + # COVERALLS_REPO_TOKEN: "${{ secrets.GITHUB_TOKEN }}" + # run: | + # wget "https://github.com/php-coveralls/php-coveralls/releases/download/v2.5.2/php-coveralls.phar" + # php ./php-coveralls.phar -v + + static_analysis: + name: "3️⃣ Static Analysis" + needs: + - "byte_level" + - "syntax_errors" + runs-on: "ubuntu-latest" + steps: + - name: "Set up PHP" + uses: "shivammathur/setup-php@v2" + with: + php-version: "8.1" + extensions: "mbstring" + coverage: "none" + + - name: "Checkout code" + uses: "actions/checkout@v3" + + - name: "Validate Composer configuration" + run: "composer validate --strict" + + - name: "Install dependencies" + uses: "ramsey/composer-install@v2" + with: + dependency-versions: "highest" + composer-options: "--optimize-autoloader" + + - name: "Check PSR-4 mapping" + run: "composer dump-autoload --optimize --strict-psr" + + - name: "Execute static analysis" + run: "make st" + + coding_standards: + name: "4️⃣ Coding Standards" + needs: + - "byte_level" + - "syntax_errors" + runs-on: "ubuntu-latest" + steps: + - name: "Set up PHP" + uses: "shivammathur/setup-php@v2" + with: + php-version: "8.1" + extensions: "mbstring" + coverage: "none" + + - name: "Checkout code" + uses: "actions/checkout@v3" + + - name: "Check adherence to EditorConfig" + uses: "greut/eclint-action@v0" + + - name: "Install dependencies" + uses: "ramsey/composer-install@v2" + with: + dependency-versions: "highest" + composer-options: "--optimize-autoloader" + + - name: "Check coding style" + run: "make ci-cs" + + - name: "Deptrac" + run: | + vendor/bin/deptrac analyse --fail-on-uncovered --no-cache + + mutation_testing: + name: "5️⃣ Mutation Testing" + needs: + - "byte_level" + - "syntax_errors" + runs-on: "ubuntu-latest" + steps: + - name: "Set up PHP" + uses: "shivammathur/setup-php@v2" + with: + php-version: "8.1" + extensions: "mbstring" + coverage: "xdebug" + + - name: "Checkout code" + uses: "actions/checkout@v3" + + - name: "Fetch Git base reference" + run: "git fetch --depth=1 origin ${GITHUB_BASE_REF}" + + - name: "Install dependencies" + uses: "ramsey/composer-install@v2" + with: + dependency-versions: "highest" + composer-options: "--optimize-autoloader" + + - name: "Execute Infection" + run: "make ci-mu" + + rector_checkstyle: + name: "6️⃣ Rector Checkstyle" + needs: + - "byte_level" + - "syntax_errors" + runs-on: "ubuntu-latest" + steps: + - name: "Set up PHP" + uses: "shivammathur/setup-php@v2" + with: + php-version: "8.1" + extensions: "mbstring" + coverage: "xdebug" + + - name: "Checkout code" + uses: "actions/checkout@v3" + + - name: "Fetch Git base reference" + run: "git fetch --depth=1 origin ${GITHUB_BASE_REF}" + + - name: "Install dependencies" + uses: "ramsey/composer-install@v2" + with: + dependency-versions: "highest" + composer-options: "--optimize-autoloader" + + - name: "Execute Rector" + run: "make rector" + + exported_files: + name: "7️⃣ Exported files" + needs: + - "byte_level" + - "syntax_errors" + runs-on: "ubuntu-20.04" + steps: + - name: "Checkout code" + uses: "actions/checkout@v3" + + - name: "Check exported files" + run: | + EXPECTED="LICENSE,README.md,SECURITY.md,composer.json" + CURRENT="$(git archive HEAD | tar --list --exclude="src" --exclude="src/*" | paste -s -d ",")" + echo "CURRENT =${CURRENT}" + echo "EXPECTED=${EXPECTED}" + test "${CURRENT}" == "${EXPECTED}" diff --git a/.github/workflows/merge-me.yml b/.github/workflows/merge-me.yml new file mode 100644 index 0000000..77e8f7d --- /dev/null +++ b/.github/workflows/merge-me.yml @@ -0,0 +1,28 @@ +name: Merge me! + +on: + check_suite: + types: + - completed + +jobs: + merge-me: + name: Merge me! + runs-on: ubuntu-latest + steps: + - name: Merge me! + uses: ridedott/merge-me-action@v2.10.19 + with: + # Depending on branch protection rules, a manually populated + # `GITHUB_TOKEN_WORKAROUND` environment variable with permissions to + # push to a protected branch must be used. This variable can have an + # arbitrary name, as an example, this repository uses + # `GITHUB_TOKEN_DOTTBOTT`. + # + # When using a custom token, it is recommended to leave the following + # comment for other developers to be aware of the reasoning behind it: + # + # This must be used as GitHub Actions token does not support + # pushing to protected branches. + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + MERGE_METHOD: MERGE diff --git a/.github/workflows/mutation-tests.yml b/.github/workflows/mutation-tests.yml deleted file mode 100644 index 2277a98..0000000 --- a/.github/workflows/mutation-tests.yml +++ /dev/null @@ -1,35 +0,0 @@ -name: Mutation Testing - -on: [push] - -jobs: - tests: - runs-on: ${{ matrix.operating-system }} - strategy: - matrix: - operating-system: [ubuntu-latest] - php-versions: ['8.1'] - name: PHP ${{ matrix.php-versions }} Test on ${{ matrix.operating-system }} - - steps: - - name: Checkout - uses: actions/checkout@v2 - with: - ref: ${{ github.head_ref }} - - - name: Setup PHP, with composer and extensions - uses: shivammathur/setup-php@v2 - with: - php-version: ${{ matrix.php-versions }} - extensions: mbstring - coverage: xdebug - - - name: Install the application - run: | - composer install --no-progress --prefer-dist --optimize-autoloader - - - name: Fetch Git base reference - run: git fetch --depth=1 origin $GITHUB_BASE_REF - - - name: Infection - run: make ci-mu diff --git a/.github/workflows/rector_checkstyle.yaml b/.github/workflows/rector_checkstyle.yaml deleted file mode 100644 index 53f8d36..0000000 --- a/.github/workflows/rector_checkstyle.yaml +++ /dev/null @@ -1,30 +0,0 @@ -name: Rector Checkstyle - -on: [push] - -jobs: - tests: - runs-on: ${{ matrix.operating-system }} - strategy: - matrix: - operating-system: [ ubuntu-latest ] - php-versions: ['8.1'] - steps: - - name: Checkout - uses: actions/checkout@v2 - with: - ref: ${{ github.head_ref }} - - - name: Setup PHP, with composer and extensions - uses: shivammathur/setup-php@v2 - with: - php-version: ${{ matrix.php-versions }} - extensions: mbstring - coverage: none - - - name: Install the application - run: | - composer install --no-progress --prefer-dist --optimize-autoloader - - - name: Rector - run: make ci-rector diff --git a/.github/workflows/release-on-milestone-closed.yml b/.github/workflows/release-on-milestone-closed.yml new file mode 100644 index 0000000..babdc09 --- /dev/null +++ b/.github/workflows/release-on-milestone-closed.yml @@ -0,0 +1,72 @@ +# https://help.github.com/en/categories/automating-your-workflow-with-github-actions + +name: "Automatic Releases" + +on: + milestone: + types: + - "closed" + +jobs: + release: + name: "GIT tag, release & create merge-up PR" + runs-on: ubuntu-latest + + steps: + - name: "Checkout" + uses: "actions/checkout@v3" + + - name: "Release" + uses: "laminas/automatic-releases@1.17.0" + with: + command-name: "laminas:automatic-releases:release" + env: + "SHELL_VERBOSITY": "3" + "GITHUB_TOKEN": ${{ secrets.ORGANIZATION_ADMIN_TOKEN }} + "SIGNING_SECRET_KEY": ${{ secrets.SIGNING_SECRET_KEY }} + "GIT_AUTHOR_NAME": ${{ secrets.GIT_AUTHOR_NAME }} + "GIT_AUTHOR_EMAIL": ${{ secrets.GIT_AUTHOR_EMAIL }} + + - name: "Create Merge-Up Pull Request" + uses: "laminas/automatic-releases@1.17.0" + with: + command-name: "laminas:automatic-releases:create-merge-up-pull-request" + env: + "SHELL_VERBOSITY": "3" + "GITHUB_TOKEN": ${{ secrets.GITHUB_TOKEN }} + "SIGNING_SECRET_KEY": ${{ secrets.SIGNING_SECRET_KEY }} + "GIT_AUTHOR_NAME": ${{ secrets.GIT_AUTHOR_NAME }} + "GIT_AUTHOR_EMAIL": ${{ secrets.GIT_AUTHOR_EMAIL }} + + - name: "Create and/or Switch to new Release Branch" + uses: "laminas/automatic-releases@1.17.0" + with: + command-name: "laminas:automatic-releases:switch-default-branch-to-next-minor" + env: + "SHELL_VERBOSITY": "3" + "GITHUB_TOKEN": ${{ secrets.ORGANIZATION_ADMIN_TOKEN }} + "SIGNING_SECRET_KEY": ${{ secrets.SIGNING_SECRET_KEY }} + "GIT_AUTHOR_NAME": ${{ secrets.GIT_AUTHOR_NAME }} + "GIT_AUTHOR_EMAIL": ${{ secrets.GIT_AUTHOR_EMAIL }} + + - name: "Bump Changelog Version On Originating Release Branch" + uses: "laminas/automatic-releases@1.17.0" + with: + command-name: "laminas:automatic-releases:bump-changelog" + env: + "SHELL_VERBOSITY": "3" + "GITHUB_TOKEN": ${{ secrets.GITHUB_TOKEN }} + "SIGNING_SECRET_KEY": ${{ secrets.SIGNING_SECRET_KEY }} + "GIT_AUTHOR_NAME": ${{ secrets.GIT_AUTHOR_NAME }} + "GIT_AUTHOR_EMAIL": ${{ secrets.GIT_AUTHOR_EMAIL }} + + - name: "Create new milestones" + uses: "laminas/automatic-releases@1.17.0" + with: + command-name: "laminas:automatic-releases:create-milestones" + env: + "SHELL_VERBOSITY": "3" + "GITHUB_TOKEN": ${{ secrets.GITHUB_TOKEN }} + "SIGNING_SECRET_KEY": ${{ secrets.SIGNING_SECRET_KEY }} + "GIT_AUTHOR_NAME": ${{ secrets.GIT_AUTHOR_NAME }} + "GIT_AUTHOR_EMAIL": ${{ secrets.GIT_AUTHOR_EMAIL }} diff --git a/.github/workflows/static-analyze.yml b/.github/workflows/static-analyze.yml deleted file mode 100644 index 91154b0..0000000 --- a/.github/workflows/static-analyze.yml +++ /dev/null @@ -1,33 +0,0 @@ -name: Static Analyze - -on: [push] - -jobs: - tests: - runs-on: ${{ matrix.operating-system }} - strategy: - matrix: - operating-system: [ubuntu-latest] - php-versions: ['8.1'] - name: PHP ${{ matrix.php-versions }} Test on ${{ matrix.operating-system }} - - steps: - - name: Checkout - uses: actions/checkout@v2 - with: - ref: ${{ github.head_ref }} - - - name: Setup PHP, with composer and extensions - uses: shivammathur/setup-php@v2 - with: - php-version: ${{ matrix.php-versions }} - extensions: mbstring - coverage: xdebug - tools: cs2pr - - - name: Install the application - run: | - composer install --no-progress --prefer-dist --optimize-autoloader - - - name: Static Analyze Checks - run: make ci-st diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml deleted file mode 100644 index 71f18a4..0000000 --- a/.github/workflows/tests.yml +++ /dev/null @@ -1,32 +0,0 @@ -name: Unit and Functional Tests - -on: [push] - -jobs: - tests: - runs-on: ${{ matrix.operating-system }} - strategy: - matrix: - operating-system: [ ubuntu-latest ] - php-versions: ['8.1'] - name: PHP ${{ matrix.php-versions }} Test on ${{ matrix.operating-system }} - - steps: - - name: Checkout - uses: actions/checkout@v2 - with: - ref: ${{ github.head_ref }} - - - name: Setup PHP, with composer and extensions - uses: shivammathur/setup-php@v2 - with: - php-version: ${{ matrix.php-versions }} - extensions: mbstring - coverage: xdebug - - - name: Install the application - run: | - composer install --no-progress --prefer-dist --optimize-autoloader - - - name: Run tests - run: make all diff --git a/.github/workflows/tweet.yml b/.github/workflows/tweet.yml new file mode 100644 index 0000000..5f9acda --- /dev/null +++ b/.github/workflows/tweet.yml @@ -0,0 +1,23 @@ +name: tweet +on: + push: + tags: + - '*' + release: + types: [ published ] + +jobs: + tweet: + runs-on: ubuntu-latest + steps: + - name: Tweet + uses: snow-actions/tweet@v1.3.0 + with: + status: | + We are proud to announce that ${{ github.repository }} · ${{ github.event.release.name }} + ${{ github.event.release.html_url }} is now released 🚀. #php #totp #hotp + env: + CONSUMER_API_KEY: ${{ secrets.TWITTER_CONSUMER_API_KEY }} + CONSUMER_API_SECRET_KEY: ${{ secrets.TWITTER_CONSUMER_API_SECRET }} + ACCESS_TOKEN: ${{ secrets.TWITTER_ACCESS_TOKEN }} + ACCESS_TOKEN_SECRET: ${{ secrets.TWITTER_ACCESS_TOKEN_SECRET }} diff --git a/.gitignore b/.gitignore index 9c4be60..757b917 100644 --- a/.gitignore +++ b/.gitignore @@ -2,4 +2,4 @@ /vendor/ .phpunit.result.cache /phpunit.xml -/infection.log \ No newline at end of file +/infection.log diff --git a/Makefile b/Makefile index 529b80e..159530a 100644 --- a/Makefile +++ b/Makefile @@ -1,63 +1,69 @@ ######################## -# CI/CD # +# Everyday # ######################## -ci-cs: vendor ## Check all files using defined rules (CI/CD) - vendor/bin/ecs check +.PHONY: mu +mu: vendor ## Mutation tests + vendor/bin/infection -s --threads=$$(nproc) --min-msi=30 --min-covered-msi=50 -ci-st: vendor ## Run static analyse (CI/CD) - vendor/bin/phpstan analyse --error-format=checkstyle | cs2pr +.PHONY: tests +tests: vendor ## Run all tests + vendor/bin/phpunit --color + yarn test -ci-rector: vendor ## Check all files using Rector (CI/CD) - vendor/bin/rector process --ansi --dry-run +.PHONY: cc +cc: vendor ## Show test coverage rates (HTML) + vendor/bin/phpunit --coverage-html ./build -ci-mu: vendor ## Mutation tests (CI/CD) - vendor/bin/infection --logger-github -s --threads=$$(nproc) --min-msi=70 --min-covered-msi=50 --test-framework-options="--exclude-group=Performance" +.PHONY: cs +cs: vendor ## Fix all files using defined ECS rules + vendor/bin/ecs check --fix -######################## -# Everyday # -######################## +.PHONY: tu +tu: vendor ## Run only unit tests + vendor/bin/phpunit --color --group Unit -all: vendor ## Run all tests - vendor/bin/phpunit --color +.PHONY: ti +ti: vendor ## Run only integration tests + vendor/bin/phpunit --color --group Integration -tu: vendor ## Run only unit tests - vendor/bin/phpunit --color tests +.PHONY: tf +tf: vendor ## Run only functional tests + vendor/bin/phpunit --color --group Functional +.PHONY: st st: vendor ## Run static analyse - vendor/bin/phpstan analyse + XDEBUG_MODE=off vendor/bin/phpstan analyse ######################## -# Every PR # +# CI/CD # ######################## -cs: vendor ## Fix all files using defined rules - vendor/bin/ecs check --fix +.PHONY: ci-mu +ci-mu: vendor ## Mutation tests (for CI/CD only) + vendor/bin/infection --logger-github -s --threads=$$(nproc) --min-msi=30 --min-covered-msi=50 -rector: vendor ## Check all files using Rector - vendor/bin/rector process +.PHONY: ci-cc +ci-cc: vendor ## Show test coverage rates (for CI/CD only) + vendor/bin/phpunit --coverage-text +.PHONY: ci-cs +ci-cs: vendor ## Check all files using defined ECS rules (for CI/CD only) + XDEBUG_MODE=off vendor/bin/ecs check ######################## # Others # ######################## -mu: vendor ## Mutation tests - vendor/bin/infection -s --threads=$$(nproc) --min-msi=70 --min-covered-msi=50 --test-framework-options="--exclude-group=Performance" - -cc: vendor ## Show test coverage rates (HTML) - vendor/bin/phpunit --coverage-html ./build +.PHONY: rector +rector: vendor ## Check all files using Rector + XDEBUG_MODE=off vendor/bin/rector process --ansi --dry-run --xdebug -vendor: composer.json composer.lock +vendor: composer.json composer validate composer install - -######################## -# Default # -######################## - .DEFAULT_GOAL := help help: @grep -E '(^[a-zA-Z_-]+:.*?##.*$$)|(^##)' $(MAKEFILE_LIST) | awk 'BEGIN {FS = ":.*?## "}; {printf "\033[32m%-30s\033[0m %s\n", $$1, $$2}' | sed -e 's/\[32m##/[33m/' diff --git a/composer.json b/composer.json index bff24fa..30db972 100644 --- a/composer.json +++ b/composer.json @@ -23,13 +23,15 @@ "require-dev": { "ekino/phpstan-banned-code": "^1.0", "infection/infection": "^0.26", + "php-parallel-lint/php-parallel-lint": "^1.3", "phpstan/phpstan": "^1.0", "phpstan/phpstan-deprecation-rules": "^1.0", "phpstan/phpstan-phpunit": "^1.0", "phpstan/phpstan-strict-rules": "^1.0", - "phpunit/phpunit": "^9.5", + "phpunit/phpunit": "^9.5.26", + "qossmic/deptrac-shim": "^1.0", "rector/rector": "^0.14", - "symfony/phpunit-bridge": "^6.0", + "symfony/phpunit-bridge": "^6.1", "symplify/easy-coding-standard": "^11.0" }, "autoload": { diff --git a/deptrac.yaml b/deptrac.yaml new file mode 100644 index 0000000..1986e15 --- /dev/null +++ b/deptrac.yaml @@ -0,0 +1,14 @@ +parameters: + paths: + - './src' + layers: + - name: 'OTP' + collectors: + - type: 'directory' + regex: 'src/.*' + - name: 'Vendors' + collectors: + - { type: className, regex: '^ParagonIE\\' } + ruleset: + OTP: + - 'Vendors' diff --git a/infection.json.dist b/infection.json.dist index f02cbf8..00a3453 100644 --- a/infection.json.dist +++ b/infection.json.dist @@ -9,8 +9,11 @@ }, "mutators": { "@default": true, - "global-ignoreSourceCodeByRegex": [ - "\\$this->logger.*" - ] + "MBString": { + "settings": { + "mb_substr": false, + "mb_strlen": false + } + } } -} \ No newline at end of file +} diff --git a/phpstan.neon b/phpstan.neon index e55b635..2ce3a2c 100644 --- a/phpstan.neon +++ b/phpstan.neon @@ -4,10 +4,25 @@ parameters: - src - tests ignoreErrors: - - '#Variable property access on \$this\(OTPHP\\OTP\)\.#' - - '#^Method OTPHP\\OTP::generateSecret\(\) should return non-empty-string but returns string\.$#' + - + message: '#Variable property access on \$this\(OTPHP\\OTP\)\.#' + path: src/ParameterTrait.php + count: 1 + - + message: '#^Method OTPHP\\OTP::generateSecret\(\) should return non-empty-string but returns string\.$#' + path: src/OTP.php + count: 1 + - + message: '#^Cannot cast mixed to int\.$#' + path: src/HOTP.php + count: 1 + - + message: '#^Parameter \#\d .* of class OTPHP\\Url constructor expects .*\, .* given\.$#' + path: src/Url.php + count: 2 includes: + - vendor/phpstan/phpstan/conf/bleedingEdge.neon - vendor/phpstan/phpstan-strict-rules/rules.neon - vendor/phpstan/phpstan-phpunit/extension.neon - vendor/phpstan/phpstan-deprecation-rules/rules.neon diff --git a/phpunit.xml.dist b/phpunit.xml.dist index d4bd675..e52c02c 100644 --- a/phpunit.xml.dist +++ b/phpunit.xml.dist @@ -1,24 +1,28 @@ - - - - ./src - - - - - ./tests - - - - - - - OTPHP - OTPHP\TOTP - - - - - + + + + ./src + + + + + ./tests + + + + + + + OTPHP\TOTP + + + + diff --git a/src/HOTP.php b/src/HOTP.php index 8dc18d3..aa5a227 100644 --- a/src/HOTP.php +++ b/src/HOTP.php @@ -12,6 +12,8 @@ */ final class HOTP extends OTP implements HOTPInterface { + private const DEFAULT_WINDOW = 0; + public static function create( null|string $secret = null, int $counter = self::DEFAULT_COUNTER, @@ -86,10 +88,11 @@ public function setCounter(int $counter): void protected function getParameterMap(): array { return [...parent::getParameterMap(), ...[ - 'counter' => static function ($value): int { - (int) $value >= 0 || throw new InvalidArgumentException('Counter must be at least 0.'); + 'counter' => static function (mixed $value): int { + $value = (int) $value; + $value >= 0 || throw new InvalidArgumentException('Counter must be at least 0.'); - return (int) $value; + return $value; }, ]]; } @@ -101,7 +104,7 @@ private function updateCounter(int $counter): void private function getWindow(null|int $window): int { - return abs($window ?? 0); + return abs($window ?? self::DEFAULT_WINDOW); } private function verifyOtpWithWindow(string $otp, int $counter, null|int $window): bool diff --git a/src/OTP.php b/src/OTP.php index ba640a3..2cba067 100644 --- a/src/OTP.php +++ b/src/OTP.php @@ -17,6 +17,8 @@ abstract class OTP implements OTPInterface { use ParameterTrait; + private const DEFAULT_SECRET_SIZE = 64; + /** * @param non-empty-string $secret */ @@ -42,7 +44,7 @@ public function at(int $input): string */ final protected static function generateSecret(): string { - return Base32::encodeUpper(random_bytes(64)); + return Base32::encodeUpper(random_bytes(self::DEFAULT_SECRET_SIZE)); } /** diff --git a/src/ParameterTrait.php b/src/ParameterTrait.php index 80d3888..b050923 100644 --- a/src/ParameterTrait.php +++ b/src/ParameterTrait.php @@ -149,9 +149,7 @@ protected function getParameterMap(): array return $value; }, - 'secret' => static function ($value): string { - return mb_strtoupper(trim($value, '=')); - }, + 'secret' => static fn ($value): string => mb_strtoupper(trim((string) $value, '=')), 'algorithm' => static function ($value): string { $value = mb_strtolower($value); in_array($value, hash_algos(), true) || throw new InvalidArgumentException(sprintf( diff --git a/src/Url.php b/src/Url.php index 387d54f..56ad979 100644 --- a/src/Url.php +++ b/src/Url.php @@ -15,13 +15,13 @@ final class Url { /** * @param non-empty-string $secret + * @param array $query */ public function __construct( private readonly string $scheme, private readonly string $host, private readonly string $path, private readonly string $secret, - /** @var array $query */ private readonly array $query ) { } diff --git a/tests/TOTPTest.php b/tests/TOTPTest.php index 03691da..53d7284 100644 --- a/tests/TOTPTest.php +++ b/tests/TOTPTest.php @@ -164,9 +164,12 @@ public function wrongSizeOtp(): void */ public function generateOtpNow(): void { + ClockMock::register(TOTP::class); + $time = time(); + ClockMock::withClockMock($time); $otp = $this->createTOTP(6, 'sha1', 30); - static::assertSame($otp->now(), $otp->at(time())); + static::assertSame($otp->now(), $otp->at($time)); } /** @@ -174,7 +177,9 @@ public function generateOtpNow(): void */ public function verifyOtpNow(): void { + ClockMock::register(TOTP::class); $time = time(); + ClockMock::withClockMock($time); $otp = $this->createTOTP(6, 'sha1', 30); $totp = $otp->at($time); @@ -308,8 +313,12 @@ public function verifyOtpInWindow(int $timestamp, string $input, int $leeway, bo * @test * @dataProvider dataLeewayWithEpoch */ - public function verifyOtpWithEpochInWindow(int $timestamp, string $input, int $leeway, bool $expectedResult): void - { + public function verifyOtpWithEpochInWindow( + int $timestamp, + string $input, + int $leeway, + bool $expectedResult + ): void { ClockMock::register(TOTP::class); ClockMock::withClockMock($timestamp); $otp = $this->createTOTP(6, 'sha1', 30, 'JDDK4U6G3BJLEZ7Y', 'alice@foo.bar', 'My Project', 100); From 28d9ec3e7d886f12b888071ca314ddda94f6877b Mon Sep 17 00:00:00 2001 From: Florent Morselli Date: Fri, 11 Nov 2022 13:40:54 +0100 Subject: [PATCH 2/2] Revert "New pipeline + ECS + Rector (#167)" This reverts commit 63e4610f22effa6a9ef122e5ab2d23ee3456c7b7. --- .editorconfig | 29 --- .gitattributes | 4 +- .github/CONTRIBUTING.md | 13 +- .github/ISSUE_TEMPLATE/1_Bug_report.yaml | 77 +++--- .github/ISSUE_TEMPLATE/2_Feature_request.yaml | 28 +-- .github/ISSUE_TEMPLATE/3_Documentation.yaml | 14 +- .github/ISSUE_TEMPLATE/config.yml | 9 +- .github/PULL_REQUEST_TEMPLATE.md | 32 +-- .github/dependabot.yml | 23 +- .github/stale.yml | 8 +- .github/workflows/coding-standards.yml | 32 +++ .github/workflows/gitsplit.yml | 18 -- .github/workflows/integrate.yml | 230 ------------------ .github/workflows/merge-me.yml | 28 --- .github/workflows/mutation-tests.yml | 35 +++ .github/workflows/rector_checkstyle.yaml | 30 +++ .../workflows/release-on-milestone-closed.yml | 72 ------ .github/workflows/static-analyze.yml | 33 +++ .github/workflows/tests.yml | 32 +++ .github/workflows/tweet.yml | 23 -- .gitignore | 2 +- Makefile | 72 +++--- composer.json | 6 +- deptrac.yaml | 14 -- infection.json.dist | 11 +- phpstan.neon | 19 +- phpunit.xml.dist | 48 ++-- src/HOTP.php | 11 +- src/OTP.php | 4 +- src/ParameterTrait.php | 4 +- src/Url.php | 2 +- tests/TOTPTest.php | 15 +- 32 files changed, 336 insertions(+), 642 deletions(-) delete mode 100644 .editorconfig create mode 100644 .github/workflows/coding-standards.yml delete mode 100644 .github/workflows/gitsplit.yml delete mode 100644 .github/workflows/integrate.yml delete mode 100644 .github/workflows/merge-me.yml create mode 100644 .github/workflows/mutation-tests.yml create mode 100644 .github/workflows/rector_checkstyle.yaml delete mode 100644 .github/workflows/release-on-milestone-closed.yml create mode 100644 .github/workflows/static-analyze.yml create mode 100644 .github/workflows/tests.yml delete mode 100644 .github/workflows/tweet.yml delete mode 100644 deptrac.yaml diff --git a/.editorconfig b/.editorconfig deleted file mode 100644 index f329996..0000000 --- a/.editorconfig +++ /dev/null @@ -1,29 +0,0 @@ -# https://EditorConfig.org - -root = true - -[*] -indent_style = space -# Reduce tab size on GitHub -indent_size = 4 -end_of_line = lf -charset = utf-8 -trim_trailing_whitespace = true -insert_final_newline = true -block_comment_start = /* -block_comment = * -block_comment_end = */ - -[{*.yml,*.yaml}] -indent_size = 2 - -[*.md] -trim_trailing_whitespace = false - -[Makefile] -indent_style = tab - -# Generated file -[infection.txt] -indent_size = unset -trim_trailing_whitespace = unset diff --git a/.gitattributes b/.gitattributes index de25e8f..cea09fc 100644 --- a/.gitattributes +++ b/.gitattributes @@ -3,14 +3,14 @@ /.github export-ignore /doc export-ignore /tests export-ignore -/.editorconfig export-ignore /.gitattributes export-ignore /.gitignore export-ignore /CODE_OF_CONDUCT.md export-ignore -/deptrac.yaml export-ignore /ecs.php export-ignore /infection.json.dist export-ignore /Makefile export-ignore /phpstan.neon export-ignore /phpunit.xml.dist export-ignore +/README.md export-ignore /rector.php export-ignore +/SECURITY.md export-ignore diff --git a/.github/CONTRIBUTING.md b/.github/CONTRIBUTING.md index 7cc67ce..2b7c6aa 100644 --- a/.github/CONTRIBUTING.md +++ b/.github/CONTRIBUTING.md @@ -11,14 +11,9 @@ Few rules to ease code reviews and merges: - You MUST write (or update) unit tests when bugs are fixed or features are added. - You SHOULD write documentation. -We use [Git-Flow](http://jeffkreeftmeijer.com/2010/why-arent-you-using-git-flow/) to automate our git branching -workflow. +To contribute use [Pull Requests](https://help.github.com/articles/using-pull-requests), please, write commit messages that make sense, and rebase your branch before submitting your PR. -To contribute use [Pull Requests](https://help.github.com/articles/using-pull-requests), please, write commit messages -that make sense, and rebase your branch before submitting your PR. - -May be asked to squash your commits too. This is used to "clean" your Pull Request before merging it, avoiding commits -such as fix tests, fix 2, fix 3, etc. +May be asked to squash your commits too. This is used to "clean" your Pull Request before merging it, avoiding commits such as fix tests, fix 2, fix 3, etc. Run test suite ------------ @@ -26,3 +21,7 @@ Run test suite * install composer: `curl -s http://getcomposer.org/installer | php` * install dependencies: `php composer.phar install` * run tests: `vendor/bin/phpunit` +* check and fix coding standards: + * `vendor/bin/phpstan analyse` + * `vendor/bin/rector process` + * `vendor/bin/ecs check --fix` diff --git a/.github/ISSUE_TEMPLATE/1_Bug_report.yaml b/.github/ISSUE_TEMPLATE/1_Bug_report.yaml index d3f26cf..841cfdc 100644 --- a/.github/ISSUE_TEMPLATE/1_Bug_report.yaml +++ b/.github/ISSUE_TEMPLATE/1_Bug_report.yaml @@ -1,42 +1,43 @@ name: 🐛 Bug Report description: ⚠️ NEVER report security issues, email security AT spomky-labs.com instead labels: Bug + body: - - type: input - id: affected-versions - attributes: - label: Version(s) affected - placeholder: x.y.z - validations: - required: true - - type: textarea - id: description - attributes: - label: Description - description: A clear and concise description of the problem - validations: - required: true - - type: textarea - id: how-to-reproduce - attributes: - label: How to reproduce - description: | - ⚠️ This is the most important part of the report ⚠️ - Without a way to easily reproduce your issue, there is little chance we will be able to help you and work on a fix. - Please, take the time to show us some code and/or config that is needed for others to reproduce the problem easily. - Most of the time, creating a "bug reproducer" is the best way to help us and increases the chances someone - will have a look at it. - validations: - required: true - - type: textarea - id: possible-solution - attributes: - label: Possible Solution - description: | - Optional: only if you have suggestions on a fix/reason for the bug - Don't hesitate to create a pull request with your solution, it helps get faster feedback. - - type: textarea - id: additional-context - attributes: - label: Additional Context - description: "Optional: any other context about the problem: log messages, screenshots, etc." + - type: input + id: affected-versions + attributes: + label: Version(s) affected + placeholder: x.y.z + validations: + required: true + - type: textarea + id: description + attributes: + label: Description + description: A clear and concise description of the problem + validations: + required: true + - type: textarea + id: how-to-reproduce + attributes: + label: How to reproduce + description: | + ⚠️ This is the most important part of the report ⚠️ + Without a way to easily reproduce your issue, there is little chance we will be able to help you and work on a fix. + Please, take the time to show us some code and/or config that is needed for others to reproduce the problem easily. + Most of the time, creating a "bug reproducer" is the best way to help us and increases the chances someone + will have a look at it. + validations: + required: true + - type: textarea + id: possible-solution + attributes: + label: Possible Solution + description: | + Optional: only if you have suggestions on a fix/reason for the bug + Don't hesitate to create a pull request with your solution, it helps get faster feedback. + - type: textarea + id: additional-context + attributes: + label: Additional Context + description: "Optional: any other context about the problem: log messages, screenshots, etc." diff --git a/.github/ISSUE_TEMPLATE/2_Feature_request.yaml b/.github/ISSUE_TEMPLATE/2_Feature_request.yaml index 52b3de7..bd300eb 100644 --- a/.github/ISSUE_TEMPLATE/2_Feature_request.yaml +++ b/.github/ISSUE_TEMPLATE/2_Feature_request.yaml @@ -1,17 +1,17 @@ name: 🚀 Feature Request description: RFC and ideas for new features and improvements body: - - type: textarea - id: description - attributes: - label: Description - description: A clear and concise description of the new feature - validations: - required: true - - type: textarea - id: example - attributes: - label: Example - description: | - A simple example of the new feature in action (include PHP code, YAML config, etc.) - If the new feature changes an existing feature, include a simple before/after comparison. + - type: textarea + id: description + attributes: + label: Description + description: A clear and concise description of the new feature + validations: + required: true + - type: textarea + id: example + attributes: + label: Example + description: | + A simple example of the new feature in action (include PHP code, YAML config, etc.) + If the new feature changes an existing feature, include a simple before/after comparison. diff --git a/.github/ISSUE_TEMPLATE/3_Documentation.yaml b/.github/ISSUE_TEMPLATE/3_Documentation.yaml index 1c5ac89..7a3dc17 100644 --- a/.github/ISSUE_TEMPLATE/3_Documentation.yaml +++ b/.github/ISSUE_TEMPLATE/3_Documentation.yaml @@ -1,10 +1,10 @@ name: 📖 Documentation Issue description: To report typo or obsolete section in the documentation body: - - type: textarea - id: description - attributes: - label: Description - description: A clear and concise description of the error you found in the documentation - validations: - required: true + - type: textarea + id: description + attributes: + label: Description + description: A clear and concise description of the error you found in the documentation + validations: + required: true diff --git a/.github/ISSUE_TEMPLATE/config.yml b/.github/ISSUE_TEMPLATE/config.yml index 6d11ce2..1181241 100644 --- a/.github/ISSUE_TEMPLATE/config.yml +++ b/.github/ISSUE_TEMPLATE/config.yml @@ -1,8 +1,5 @@ blank_issues_enabled: false contact_links: - - name: Support Question - url: https://spomky-labs.com/contact/ - about:| - We use GitHub issues only to discuss about bugs and new features. - For this kind of questions about using the framework or third-party bundles, - please email us contact AT spomky-labs.com for quoting + - name: Support Question + url: https://spomky-labs.com/contact/ + about: We use GitHub issues only to discuss about bugs and new features. For this kind of questions about using the library, please use Stackoverflow (or similar) or send a quote request at https://spomky-labs.com/contact/ diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md index 029817b..1beb0a3 100644 --- a/.github/PULL_REQUEST_TEMPLATE.md +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -1,17 +1,19 @@ -Target branch: -Resolves issue # - - -- [ ] It is a Bug fix -- [ ] It is a New feature -- [ ] Breaks BC -- [ ] Includes Deprecations - +| Q | A +| ------------- | --- +| Branch? | +| Bug fix? | yes/no +| New feature? | yes/no +| Deprecations? | yes/no +| Tickets | Fix #... +| License | MIT +Additionally: + - Always add tests and ensure they pass. + - Never break backward compatibility (unless you are working on the next major release branch). + - Bug fixes must be submitted against the lowest maintained branch where they apply + (lowest branches are regularly merged to upper ones so they get the fixes too.) + - Features and deprecations must be submitted against the last major branch (e.g. 1.x). +--> \ No newline at end of file diff --git a/.github/dependabot.yml b/.github/dependabot.yml index ae2faa4..75436e4 100644 --- a/.github/dependabot.yml +++ b/.github/dependabot.yml @@ -1,19 +1,8 @@ version: 2 updates: - - package-ecosystem: "composer" - directory: "/" - schedule: - interval: "weekly" - day: "friday" - versioning-strategy: "widen" - open-pull-requests-limit: 20 - allow: - - dependency-type: all - labels: [ "Dependencies" ] - - - package-ecosystem: "github-actions" - directory: "/" - schedule: - interval: "monthly" - open-pull-requests-limit: 20 - labels: [ "Dependencies" ] +- package-ecosystem: composer + directory: "/" + schedule: + interval: daily + time: "11:00" + open-pull-requests-limit: 10 diff --git a/.github/stale.yml b/.github/stale.yml index 19367a6..98284be 100644 --- a/.github/stale.yml +++ b/.github/stale.yml @@ -1,8 +1,8 @@ -daysUntilStale: 30 +daysUntilStale: 60 daysUntilClose: 7 staleLabel: wontfix markComment: > - This issue has been automatically marked as stale because it has not had - recent activity. It will be closed if no further activity occurs. Thank you - for your contributions. + Ce problème a été automatiquement marqué comme périmé car il n'a pas eu + d’activité récente. Il sera fermé dans 7 jours si aucune autre activité ne se produit. Merci + pour votre contribution. closeComment: false diff --git a/.github/workflows/coding-standards.yml b/.github/workflows/coding-standards.yml new file mode 100644 index 0000000..584b524 --- /dev/null +++ b/.github/workflows/coding-standards.yml @@ -0,0 +1,32 @@ +name: Coding Standards + +on: [push] + +jobs: + tests: + runs-on: ${{ matrix.operating-system }} + strategy: + matrix: + operating-system: [ubuntu-latest] + php-versions: ['8.1'] + name: PHP ${{ matrix.php-versions }} Test on ${{ matrix.operating-system }} + + steps: + - name: Checkout + uses: actions/checkout@v2 + with: + ref: ${{ github.head_ref }} + + - name: Setup PHP, with composer and extensions + uses: shivammathur/setup-php@v2 + with: + php-version: ${{ matrix.php-versions }} + extensions: mbstring + coverage: xdebug + + - name: Install the application + run: | + composer install --no-progress --prefer-dist --optimize-autoloader + + - name: Coding Standards Checks + run: make ci-cs diff --git a/.github/workflows/gitsplit.yml b/.github/workflows/gitsplit.yml deleted file mode 100644 index 0677186..0000000 --- a/.github/workflows/gitsplit.yml +++ /dev/null @@ -1,18 +0,0 @@ -name: gitsplit -on: - push: - tags: - - '*' - release: - types: [ published ] - -jobs: - gitsplit: - runs-on: ubuntu-latest - steps: - - name: checkout - run: git clone https://github.com/web-auth/webauthn-framework /home/runner/work/web-auth/webauthn-framework && cd /home/runner/work/web-auth/webauthn-framework - - name: Split repositories - run: docker run --rm -t -e GH_TOKEN -v /cache/gitsplit:/cache/gitsplit -v /home/runner/work/web-auth/webauthn-framework:/srv jderusse/gitsplit gitsplit - env: - GH_TOKEN: ${{ secrets.GITSPLIT_TOKEN }} diff --git a/.github/workflows/integrate.yml b/.github/workflows/integrate.yml deleted file mode 100644 index 5578d06..0000000 --- a/.github/workflows/integrate.yml +++ /dev/null @@ -1,230 +0,0 @@ -# yaml-language-server: $schema=https://json.schemastore.org/github-workflow - -name: "Integrate" - -on: - push: - branches: - - "*.x" - pull_request: null - -jobs: - byte_level: - name: "0️⃣ Byte-level" - runs-on: "ubuntu-latest" - steps: - - name: "Checkout code" - uses: "actions/checkout@v3" - - - name: "Check file permissions" - run: | - test "$(find . -type f -not -path './.git/*' -executable)" == "" - - - name: "Find non-printable ASCII characters" - run: | - ! LC_ALL=C.UTF-8 find . -type f -name "*.php" -print0 | xargs -0 -- grep -PHn "[^ -~]" - - syntax_errors: - name: "1️⃣ Syntax errors" - runs-on: "ubuntu-latest" - steps: - - name: "Set up PHP" - uses: "shivammathur/setup-php@v2" - with: - php-version: "8.1" - coverage: "none" - - - name: "Checkout code" - uses: "actions/checkout@v3" - - - name: "Install dependencies" - uses: "ramsey/composer-install@v2" - with: - dependency-versions: "highest" - - - name: "Check source code for syntax errors" - run: "composer exec -- parallel-lint src/ tests/" - - unit_tests: - name: "2️⃣ Unit and functional tests" - needs: - - "byte_level" - - "syntax_errors" - strategy: - matrix: - operating-system: - - "ubuntu-latest" - php-version: - - "8.1" - dependencies: - - "lowest" - - "highest" - runs-on: ${{ matrix.operating-system }} - steps: - - name: "Set up PHP" - uses: "shivammathur/setup-php@v2" - with: - php-version: "${{ matrix.php-version }}" - extensions: "mbstring" - coverage: "xdebug" - - - name: "Checkout code" - uses: "actions/checkout@v3" - - - name: "Install dependencies" - uses: "ramsey/composer-install@v2" - with: - dependency-versions: "${{ matrix.dependencies }}" - composer-options: "--optimize-autoloader" - - - name: "Execute tests (PHP)" - run: "make ci-cc" - - # - name: Send coverage to Coveralls - # if: "matrix.php-version == '8.1' && matrix.dependencies == 'highest'" - # env: - # COVERALLS_REPO_TOKEN: "${{ secrets.GITHUB_TOKEN }}" - # run: | - # wget "https://github.com/php-coveralls/php-coveralls/releases/download/v2.5.2/php-coveralls.phar" - # php ./php-coveralls.phar -v - - static_analysis: - name: "3️⃣ Static Analysis" - needs: - - "byte_level" - - "syntax_errors" - runs-on: "ubuntu-latest" - steps: - - name: "Set up PHP" - uses: "shivammathur/setup-php@v2" - with: - php-version: "8.1" - extensions: "mbstring" - coverage: "none" - - - name: "Checkout code" - uses: "actions/checkout@v3" - - - name: "Validate Composer configuration" - run: "composer validate --strict" - - - name: "Install dependencies" - uses: "ramsey/composer-install@v2" - with: - dependency-versions: "highest" - composer-options: "--optimize-autoloader" - - - name: "Check PSR-4 mapping" - run: "composer dump-autoload --optimize --strict-psr" - - - name: "Execute static analysis" - run: "make st" - - coding_standards: - name: "4️⃣ Coding Standards" - needs: - - "byte_level" - - "syntax_errors" - runs-on: "ubuntu-latest" - steps: - - name: "Set up PHP" - uses: "shivammathur/setup-php@v2" - with: - php-version: "8.1" - extensions: "mbstring" - coverage: "none" - - - name: "Checkout code" - uses: "actions/checkout@v3" - - - name: "Check adherence to EditorConfig" - uses: "greut/eclint-action@v0" - - - name: "Install dependencies" - uses: "ramsey/composer-install@v2" - with: - dependency-versions: "highest" - composer-options: "--optimize-autoloader" - - - name: "Check coding style" - run: "make ci-cs" - - - name: "Deptrac" - run: | - vendor/bin/deptrac analyse --fail-on-uncovered --no-cache - - mutation_testing: - name: "5️⃣ Mutation Testing" - needs: - - "byte_level" - - "syntax_errors" - runs-on: "ubuntu-latest" - steps: - - name: "Set up PHP" - uses: "shivammathur/setup-php@v2" - with: - php-version: "8.1" - extensions: "mbstring" - coverage: "xdebug" - - - name: "Checkout code" - uses: "actions/checkout@v3" - - - name: "Fetch Git base reference" - run: "git fetch --depth=1 origin ${GITHUB_BASE_REF}" - - - name: "Install dependencies" - uses: "ramsey/composer-install@v2" - with: - dependency-versions: "highest" - composer-options: "--optimize-autoloader" - - - name: "Execute Infection" - run: "make ci-mu" - - rector_checkstyle: - name: "6️⃣ Rector Checkstyle" - needs: - - "byte_level" - - "syntax_errors" - runs-on: "ubuntu-latest" - steps: - - name: "Set up PHP" - uses: "shivammathur/setup-php@v2" - with: - php-version: "8.1" - extensions: "mbstring" - coverage: "xdebug" - - - name: "Checkout code" - uses: "actions/checkout@v3" - - - name: "Fetch Git base reference" - run: "git fetch --depth=1 origin ${GITHUB_BASE_REF}" - - - name: "Install dependencies" - uses: "ramsey/composer-install@v2" - with: - dependency-versions: "highest" - composer-options: "--optimize-autoloader" - - - name: "Execute Rector" - run: "make rector" - - exported_files: - name: "7️⃣ Exported files" - needs: - - "byte_level" - - "syntax_errors" - runs-on: "ubuntu-20.04" - steps: - - name: "Checkout code" - uses: "actions/checkout@v3" - - - name: "Check exported files" - run: | - EXPECTED="LICENSE,README.md,SECURITY.md,composer.json" - CURRENT="$(git archive HEAD | tar --list --exclude="src" --exclude="src/*" | paste -s -d ",")" - echo "CURRENT =${CURRENT}" - echo "EXPECTED=${EXPECTED}" - test "${CURRENT}" == "${EXPECTED}" diff --git a/.github/workflows/merge-me.yml b/.github/workflows/merge-me.yml deleted file mode 100644 index 77e8f7d..0000000 --- a/.github/workflows/merge-me.yml +++ /dev/null @@ -1,28 +0,0 @@ -name: Merge me! - -on: - check_suite: - types: - - completed - -jobs: - merge-me: - name: Merge me! - runs-on: ubuntu-latest - steps: - - name: Merge me! - uses: ridedott/merge-me-action@v2.10.19 - with: - # Depending on branch protection rules, a manually populated - # `GITHUB_TOKEN_WORKAROUND` environment variable with permissions to - # push to a protected branch must be used. This variable can have an - # arbitrary name, as an example, this repository uses - # `GITHUB_TOKEN_DOTTBOTT`. - # - # When using a custom token, it is recommended to leave the following - # comment for other developers to be aware of the reasoning behind it: - # - # This must be used as GitHub Actions token does not support - # pushing to protected branches. - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - MERGE_METHOD: MERGE diff --git a/.github/workflows/mutation-tests.yml b/.github/workflows/mutation-tests.yml new file mode 100644 index 0000000..2277a98 --- /dev/null +++ b/.github/workflows/mutation-tests.yml @@ -0,0 +1,35 @@ +name: Mutation Testing + +on: [push] + +jobs: + tests: + runs-on: ${{ matrix.operating-system }} + strategy: + matrix: + operating-system: [ubuntu-latest] + php-versions: ['8.1'] + name: PHP ${{ matrix.php-versions }} Test on ${{ matrix.operating-system }} + + steps: + - name: Checkout + uses: actions/checkout@v2 + with: + ref: ${{ github.head_ref }} + + - name: Setup PHP, with composer and extensions + uses: shivammathur/setup-php@v2 + with: + php-version: ${{ matrix.php-versions }} + extensions: mbstring + coverage: xdebug + + - name: Install the application + run: | + composer install --no-progress --prefer-dist --optimize-autoloader + + - name: Fetch Git base reference + run: git fetch --depth=1 origin $GITHUB_BASE_REF + + - name: Infection + run: make ci-mu diff --git a/.github/workflows/rector_checkstyle.yaml b/.github/workflows/rector_checkstyle.yaml new file mode 100644 index 0000000..53f8d36 --- /dev/null +++ b/.github/workflows/rector_checkstyle.yaml @@ -0,0 +1,30 @@ +name: Rector Checkstyle + +on: [push] + +jobs: + tests: + runs-on: ${{ matrix.operating-system }} + strategy: + matrix: + operating-system: [ ubuntu-latest ] + php-versions: ['8.1'] + steps: + - name: Checkout + uses: actions/checkout@v2 + with: + ref: ${{ github.head_ref }} + + - name: Setup PHP, with composer and extensions + uses: shivammathur/setup-php@v2 + with: + php-version: ${{ matrix.php-versions }} + extensions: mbstring + coverage: none + + - name: Install the application + run: | + composer install --no-progress --prefer-dist --optimize-autoloader + + - name: Rector + run: make ci-rector diff --git a/.github/workflows/release-on-milestone-closed.yml b/.github/workflows/release-on-milestone-closed.yml deleted file mode 100644 index babdc09..0000000 --- a/.github/workflows/release-on-milestone-closed.yml +++ /dev/null @@ -1,72 +0,0 @@ -# https://help.github.com/en/categories/automating-your-workflow-with-github-actions - -name: "Automatic Releases" - -on: - milestone: - types: - - "closed" - -jobs: - release: - name: "GIT tag, release & create merge-up PR" - runs-on: ubuntu-latest - - steps: - - name: "Checkout" - uses: "actions/checkout@v3" - - - name: "Release" - uses: "laminas/automatic-releases@1.17.0" - with: - command-name: "laminas:automatic-releases:release" - env: - "SHELL_VERBOSITY": "3" - "GITHUB_TOKEN": ${{ secrets.ORGANIZATION_ADMIN_TOKEN }} - "SIGNING_SECRET_KEY": ${{ secrets.SIGNING_SECRET_KEY }} - "GIT_AUTHOR_NAME": ${{ secrets.GIT_AUTHOR_NAME }} - "GIT_AUTHOR_EMAIL": ${{ secrets.GIT_AUTHOR_EMAIL }} - - - name: "Create Merge-Up Pull Request" - uses: "laminas/automatic-releases@1.17.0" - with: - command-name: "laminas:automatic-releases:create-merge-up-pull-request" - env: - "SHELL_VERBOSITY": "3" - "GITHUB_TOKEN": ${{ secrets.GITHUB_TOKEN }} - "SIGNING_SECRET_KEY": ${{ secrets.SIGNING_SECRET_KEY }} - "GIT_AUTHOR_NAME": ${{ secrets.GIT_AUTHOR_NAME }} - "GIT_AUTHOR_EMAIL": ${{ secrets.GIT_AUTHOR_EMAIL }} - - - name: "Create and/or Switch to new Release Branch" - uses: "laminas/automatic-releases@1.17.0" - with: - command-name: "laminas:automatic-releases:switch-default-branch-to-next-minor" - env: - "SHELL_VERBOSITY": "3" - "GITHUB_TOKEN": ${{ secrets.ORGANIZATION_ADMIN_TOKEN }} - "SIGNING_SECRET_KEY": ${{ secrets.SIGNING_SECRET_KEY }} - "GIT_AUTHOR_NAME": ${{ secrets.GIT_AUTHOR_NAME }} - "GIT_AUTHOR_EMAIL": ${{ secrets.GIT_AUTHOR_EMAIL }} - - - name: "Bump Changelog Version On Originating Release Branch" - uses: "laminas/automatic-releases@1.17.0" - with: - command-name: "laminas:automatic-releases:bump-changelog" - env: - "SHELL_VERBOSITY": "3" - "GITHUB_TOKEN": ${{ secrets.GITHUB_TOKEN }} - "SIGNING_SECRET_KEY": ${{ secrets.SIGNING_SECRET_KEY }} - "GIT_AUTHOR_NAME": ${{ secrets.GIT_AUTHOR_NAME }} - "GIT_AUTHOR_EMAIL": ${{ secrets.GIT_AUTHOR_EMAIL }} - - - name: "Create new milestones" - uses: "laminas/automatic-releases@1.17.0" - with: - command-name: "laminas:automatic-releases:create-milestones" - env: - "SHELL_VERBOSITY": "3" - "GITHUB_TOKEN": ${{ secrets.GITHUB_TOKEN }} - "SIGNING_SECRET_KEY": ${{ secrets.SIGNING_SECRET_KEY }} - "GIT_AUTHOR_NAME": ${{ secrets.GIT_AUTHOR_NAME }} - "GIT_AUTHOR_EMAIL": ${{ secrets.GIT_AUTHOR_EMAIL }} diff --git a/.github/workflows/static-analyze.yml b/.github/workflows/static-analyze.yml new file mode 100644 index 0000000..91154b0 --- /dev/null +++ b/.github/workflows/static-analyze.yml @@ -0,0 +1,33 @@ +name: Static Analyze + +on: [push] + +jobs: + tests: + runs-on: ${{ matrix.operating-system }} + strategy: + matrix: + operating-system: [ubuntu-latest] + php-versions: ['8.1'] + name: PHP ${{ matrix.php-versions }} Test on ${{ matrix.operating-system }} + + steps: + - name: Checkout + uses: actions/checkout@v2 + with: + ref: ${{ github.head_ref }} + + - name: Setup PHP, with composer and extensions + uses: shivammathur/setup-php@v2 + with: + php-version: ${{ matrix.php-versions }} + extensions: mbstring + coverage: xdebug + tools: cs2pr + + - name: Install the application + run: | + composer install --no-progress --prefer-dist --optimize-autoloader + + - name: Static Analyze Checks + run: make ci-st diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml new file mode 100644 index 0000000..71f18a4 --- /dev/null +++ b/.github/workflows/tests.yml @@ -0,0 +1,32 @@ +name: Unit and Functional Tests + +on: [push] + +jobs: + tests: + runs-on: ${{ matrix.operating-system }} + strategy: + matrix: + operating-system: [ ubuntu-latest ] + php-versions: ['8.1'] + name: PHP ${{ matrix.php-versions }} Test on ${{ matrix.operating-system }} + + steps: + - name: Checkout + uses: actions/checkout@v2 + with: + ref: ${{ github.head_ref }} + + - name: Setup PHP, with composer and extensions + uses: shivammathur/setup-php@v2 + with: + php-version: ${{ matrix.php-versions }} + extensions: mbstring + coverage: xdebug + + - name: Install the application + run: | + composer install --no-progress --prefer-dist --optimize-autoloader + + - name: Run tests + run: make all diff --git a/.github/workflows/tweet.yml b/.github/workflows/tweet.yml deleted file mode 100644 index 5f9acda..0000000 --- a/.github/workflows/tweet.yml +++ /dev/null @@ -1,23 +0,0 @@ -name: tweet -on: - push: - tags: - - '*' - release: - types: [ published ] - -jobs: - tweet: - runs-on: ubuntu-latest - steps: - - name: Tweet - uses: snow-actions/tweet@v1.3.0 - with: - status: | - We are proud to announce that ${{ github.repository }} · ${{ github.event.release.name }} - ${{ github.event.release.html_url }} is now released 🚀. #php #totp #hotp - env: - CONSUMER_API_KEY: ${{ secrets.TWITTER_CONSUMER_API_KEY }} - CONSUMER_API_SECRET_KEY: ${{ secrets.TWITTER_CONSUMER_API_SECRET }} - ACCESS_TOKEN: ${{ secrets.TWITTER_ACCESS_TOKEN }} - ACCESS_TOKEN_SECRET: ${{ secrets.TWITTER_ACCESS_TOKEN_SECRET }} diff --git a/.gitignore b/.gitignore index 757b917..9c4be60 100644 --- a/.gitignore +++ b/.gitignore @@ -2,4 +2,4 @@ /vendor/ .phpunit.result.cache /phpunit.xml -/infection.log +/infection.log \ No newline at end of file diff --git a/Makefile b/Makefile index 159530a..529b80e 100644 --- a/Makefile +++ b/Makefile @@ -1,69 +1,63 @@ ######################## -# Everyday # +# CI/CD # ######################## -.PHONY: mu -mu: vendor ## Mutation tests - vendor/bin/infection -s --threads=$$(nproc) --min-msi=30 --min-covered-msi=50 +ci-cs: vendor ## Check all files using defined rules (CI/CD) + vendor/bin/ecs check -.PHONY: tests -tests: vendor ## Run all tests - vendor/bin/phpunit --color - yarn test +ci-st: vendor ## Run static analyse (CI/CD) + vendor/bin/phpstan analyse --error-format=checkstyle | cs2pr -.PHONY: cc -cc: vendor ## Show test coverage rates (HTML) - vendor/bin/phpunit --coverage-html ./build +ci-rector: vendor ## Check all files using Rector (CI/CD) + vendor/bin/rector process --ansi --dry-run -.PHONY: cs -cs: vendor ## Fix all files using defined ECS rules - vendor/bin/ecs check --fix +ci-mu: vendor ## Mutation tests (CI/CD) + vendor/bin/infection --logger-github -s --threads=$$(nproc) --min-msi=70 --min-covered-msi=50 --test-framework-options="--exclude-group=Performance" -.PHONY: tu -tu: vendor ## Run only unit tests - vendor/bin/phpunit --color --group Unit +######################## +# Everyday # +######################## -.PHONY: ti -ti: vendor ## Run only integration tests - vendor/bin/phpunit --color --group Integration +all: vendor ## Run all tests + vendor/bin/phpunit --color -.PHONY: tf -tf: vendor ## Run only functional tests - vendor/bin/phpunit --color --group Functional +tu: vendor ## Run only unit tests + vendor/bin/phpunit --color tests -.PHONY: st st: vendor ## Run static analyse - XDEBUG_MODE=off vendor/bin/phpstan analyse + vendor/bin/phpstan analyse ######################## -# CI/CD # +# Every PR # ######################## -.PHONY: ci-mu -ci-mu: vendor ## Mutation tests (for CI/CD only) - vendor/bin/infection --logger-github -s --threads=$$(nproc) --min-msi=30 --min-covered-msi=50 +cs: vendor ## Fix all files using defined rules + vendor/bin/ecs check --fix -.PHONY: ci-cc -ci-cc: vendor ## Show test coverage rates (for CI/CD only) - vendor/bin/phpunit --coverage-text +rector: vendor ## Check all files using Rector + vendor/bin/rector process -.PHONY: ci-cs -ci-cs: vendor ## Check all files using defined ECS rules (for CI/CD only) - XDEBUG_MODE=off vendor/bin/ecs check ######################## # Others # ######################## -.PHONY: rector -rector: vendor ## Check all files using Rector - XDEBUG_MODE=off vendor/bin/rector process --ansi --dry-run --xdebug +mu: vendor ## Mutation tests + vendor/bin/infection -s --threads=$$(nproc) --min-msi=70 --min-covered-msi=50 --test-framework-options="--exclude-group=Performance" -vendor: composer.json +cc: vendor ## Show test coverage rates (HTML) + vendor/bin/phpunit --coverage-html ./build + +vendor: composer.json composer.lock composer validate composer install + +######################## +# Default # +######################## + .DEFAULT_GOAL := help help: @grep -E '(^[a-zA-Z_-]+:.*?##.*$$)|(^##)' $(MAKEFILE_LIST) | awk 'BEGIN {FS = ":.*?## "}; {printf "\033[32m%-30s\033[0m %s\n", $$1, $$2}' | sed -e 's/\[32m##/[33m/' diff --git a/composer.json b/composer.json index 30db972..bff24fa 100644 --- a/composer.json +++ b/composer.json @@ -23,15 +23,13 @@ "require-dev": { "ekino/phpstan-banned-code": "^1.0", "infection/infection": "^0.26", - "php-parallel-lint/php-parallel-lint": "^1.3", "phpstan/phpstan": "^1.0", "phpstan/phpstan-deprecation-rules": "^1.0", "phpstan/phpstan-phpunit": "^1.0", "phpstan/phpstan-strict-rules": "^1.0", - "phpunit/phpunit": "^9.5.26", - "qossmic/deptrac-shim": "^1.0", + "phpunit/phpunit": "^9.5", "rector/rector": "^0.14", - "symfony/phpunit-bridge": "^6.1", + "symfony/phpunit-bridge": "^6.0", "symplify/easy-coding-standard": "^11.0" }, "autoload": { diff --git a/deptrac.yaml b/deptrac.yaml deleted file mode 100644 index 1986e15..0000000 --- a/deptrac.yaml +++ /dev/null @@ -1,14 +0,0 @@ -parameters: - paths: - - './src' - layers: - - name: 'OTP' - collectors: - - type: 'directory' - regex: 'src/.*' - - name: 'Vendors' - collectors: - - { type: className, regex: '^ParagonIE\\' } - ruleset: - OTP: - - 'Vendors' diff --git a/infection.json.dist b/infection.json.dist index 00a3453..f02cbf8 100644 --- a/infection.json.dist +++ b/infection.json.dist @@ -9,11 +9,8 @@ }, "mutators": { "@default": true, - "MBString": { - "settings": { - "mb_substr": false, - "mb_strlen": false - } - } + "global-ignoreSourceCodeByRegex": [ + "\\$this->logger.*" + ] } -} +} \ No newline at end of file diff --git a/phpstan.neon b/phpstan.neon index 2ce3a2c..e55b635 100644 --- a/phpstan.neon +++ b/phpstan.neon @@ -4,25 +4,10 @@ parameters: - src - tests ignoreErrors: - - - message: '#Variable property access on \$this\(OTPHP\\OTP\)\.#' - path: src/ParameterTrait.php - count: 1 - - - message: '#^Method OTPHP\\OTP::generateSecret\(\) should return non-empty-string but returns string\.$#' - path: src/OTP.php - count: 1 - - - message: '#^Cannot cast mixed to int\.$#' - path: src/HOTP.php - count: 1 - - - message: '#^Parameter \#\d .* of class OTPHP\\Url constructor expects .*\, .* given\.$#' - path: src/Url.php - count: 2 + - '#Variable property access on \$this\(OTPHP\\OTP\)\.#' + - '#^Method OTPHP\\OTP::generateSecret\(\) should return non-empty-string but returns string\.$#' includes: - - vendor/phpstan/phpstan/conf/bleedingEdge.neon - vendor/phpstan/phpstan-strict-rules/rules.neon - vendor/phpstan/phpstan-phpunit/extension.neon - vendor/phpstan/phpstan-deprecation-rules/rules.neon diff --git a/phpunit.xml.dist b/phpunit.xml.dist index e52c02c..d4bd675 100644 --- a/phpunit.xml.dist +++ b/phpunit.xml.dist @@ -1,28 +1,24 @@ - - - - ./src - - - - - ./tests - - - - - - - OTPHP\TOTP - - - - + + + + ./src + + + + + ./tests + + + + + + + OTPHP + OTPHP\TOTP + + + + + diff --git a/src/HOTP.php b/src/HOTP.php index aa5a227..8dc18d3 100644 --- a/src/HOTP.php +++ b/src/HOTP.php @@ -12,8 +12,6 @@ */ final class HOTP extends OTP implements HOTPInterface { - private const DEFAULT_WINDOW = 0; - public static function create( null|string $secret = null, int $counter = self::DEFAULT_COUNTER, @@ -88,11 +86,10 @@ public function setCounter(int $counter): void protected function getParameterMap(): array { return [...parent::getParameterMap(), ...[ - 'counter' => static function (mixed $value): int { - $value = (int) $value; - $value >= 0 || throw new InvalidArgumentException('Counter must be at least 0.'); + 'counter' => static function ($value): int { + (int) $value >= 0 || throw new InvalidArgumentException('Counter must be at least 0.'); - return $value; + return (int) $value; }, ]]; } @@ -104,7 +101,7 @@ private function updateCounter(int $counter): void private function getWindow(null|int $window): int { - return abs($window ?? self::DEFAULT_WINDOW); + return abs($window ?? 0); } private function verifyOtpWithWindow(string $otp, int $counter, null|int $window): bool diff --git a/src/OTP.php b/src/OTP.php index 2cba067..ba640a3 100644 --- a/src/OTP.php +++ b/src/OTP.php @@ -17,8 +17,6 @@ abstract class OTP implements OTPInterface { use ParameterTrait; - private const DEFAULT_SECRET_SIZE = 64; - /** * @param non-empty-string $secret */ @@ -44,7 +42,7 @@ public function at(int $input): string */ final protected static function generateSecret(): string { - return Base32::encodeUpper(random_bytes(self::DEFAULT_SECRET_SIZE)); + return Base32::encodeUpper(random_bytes(64)); } /** diff --git a/src/ParameterTrait.php b/src/ParameterTrait.php index b050923..80d3888 100644 --- a/src/ParameterTrait.php +++ b/src/ParameterTrait.php @@ -149,7 +149,9 @@ protected function getParameterMap(): array return $value; }, - 'secret' => static fn ($value): string => mb_strtoupper(trim((string) $value, '=')), + 'secret' => static function ($value): string { + return mb_strtoupper(trim($value, '=')); + }, 'algorithm' => static function ($value): string { $value = mb_strtolower($value); in_array($value, hash_algos(), true) || throw new InvalidArgumentException(sprintf( diff --git a/src/Url.php b/src/Url.php index 56ad979..387d54f 100644 --- a/src/Url.php +++ b/src/Url.php @@ -15,13 +15,13 @@ final class Url { /** * @param non-empty-string $secret - * @param array $query */ public function __construct( private readonly string $scheme, private readonly string $host, private readonly string $path, private readonly string $secret, + /** @var array $query */ private readonly array $query ) { } diff --git a/tests/TOTPTest.php b/tests/TOTPTest.php index 53d7284..03691da 100644 --- a/tests/TOTPTest.php +++ b/tests/TOTPTest.php @@ -164,12 +164,9 @@ public function wrongSizeOtp(): void */ public function generateOtpNow(): void { - ClockMock::register(TOTP::class); - $time = time(); - ClockMock::withClockMock($time); $otp = $this->createTOTP(6, 'sha1', 30); - static::assertSame($otp->now(), $otp->at($time)); + static::assertSame($otp->now(), $otp->at(time())); } /** @@ -177,9 +174,7 @@ public function generateOtpNow(): void */ public function verifyOtpNow(): void { - ClockMock::register(TOTP::class); $time = time(); - ClockMock::withClockMock($time); $otp = $this->createTOTP(6, 'sha1', 30); $totp = $otp->at($time); @@ -313,12 +308,8 @@ public function verifyOtpInWindow(int $timestamp, string $input, int $leeway, bo * @test * @dataProvider dataLeewayWithEpoch */ - public function verifyOtpWithEpochInWindow( - int $timestamp, - string $input, - int $leeway, - bool $expectedResult - ): void { + public function verifyOtpWithEpochInWindow(int $timestamp, string $input, int $leeway, bool $expectedResult): void + { ClockMock::register(TOTP::class); ClockMock::withClockMock($timestamp); $otp = $this->createTOTP(6, 'sha1', 30, 'JDDK4U6G3BJLEZ7Y', 'alice@foo.bar', 'My Project', 100);