diff --git a/.github/dependabot.yml b/.github/dependabot.yml new file mode 100644 index 0000000..7f8966d --- /dev/null +++ b/.github/dependabot.yml @@ -0,0 +1,12 @@ +--- +# Set update schedule for GitHub Actions + +version: 2 +updates: + # See documentation for possible values + - package-ecosystem: "github-actions" + # Location of package manifests + directory: "/" + schedule: + # Check for updates to GitHub Actions every month + interval: "monthly" diff --git a/.github/linters/.markdown-lint.yml b/.github/linters/.markdown-lint.yml new file mode 100644 index 0000000..871f112 --- /dev/null +++ b/.github/linters/.markdown-lint.yml @@ -0,0 +1,41 @@ +--- +########################### +########################### +## Markdown Linter rules ## +########################### +########################### + +# Linter rules doc: +# - https://github.com/DavidAnson/markdownlint +# +# Note: +# To comment out a single error: +# +# any violations you want +# +# + +############################ +# Super-linter Rules by id # +############################ +MD004: false # Unordered list style +MD007: + indent: 2 # Unordered list indentation +MD013: + line_length: 808 # Line length 80 is far too short +MD026: + punctuation: ".,;:!。,;:" # List of not allowed +MD029: false # Ordered list item prefix +MD033: false # Allow inline HTML +MD036: false # Emphasis used instead of a heading + +############################## +# Super-linter Rules by tags # +############################## +blank_lines: false # Error on blank lines + +######################## +# Seablast Rules by id # +######################## +# Multiple heading with the same content (in CHANGELOG.md) +MD024: false # No-duplicate-heading diff --git a/.github/linters/super-linter-templates-phpcs.xml b/.github/linters/super-linter-templates-phpcs.xml new file mode 100644 index 0000000..27cefdd --- /dev/null +++ b/.github/linters/super-linter-templates-phpcs.xml @@ -0,0 +1,6 @@ + + + + The default coding standard for usage with Super-Linter. It just includes PSR12. + + diff --git a/.github/workflows/phpcs-phpcbf.yml b/.github/workflows/phpcs-phpcbf.yml new file mode 100644 index 0000000..f1947a0 --- /dev/null +++ b/.github/workflows/phpcs-phpcbf.yml @@ -0,0 +1,18 @@ +--- +name: Phpcs-fix +on: [pull_request, push] + +permissions: + contents: write + +jobs: + phpcs-phpcbf: + runs-on: ubuntu-latest + # Limit the running time + timeout-minutes: 10 + steps: + - name: Invoke the PHPCS check and PHPCBF fix + # Use the latest commit in the main branch. + uses: WorkOfStan/phpcs-fix@main + with: + commit-changes: true diff --git a/.github/workflows/polish-the-code.yml b/.github/workflows/polish-the-code.yml new file mode 100644 index 0000000..d259027 --- /dev/null +++ b/.github/workflows/polish-the-code.yml @@ -0,0 +1,37 @@ +--- +name: Polish the code + +on: + push: + branches-ignore: + # notest branches to ignore testing of partial online commits + - "notest/**" + + pull_request: + branches-ignore: + # notest branches to ignore testing of partial online commits + - "notest/**" + +permissions: + # only prettier-fix needs write permission, for others read is enough + contents: read + +jobs: + prettier-fix: + # Note: runs-on doesn't accept all expressions, so a string is used + runs-on: "ubuntu-24.04" + permissions: + contents: write + # Limit the running time + timeout-minutes: 10 + steps: + - name: Invoke the Prettier fix + uses: WorkOfStan/prettier-fix@v1.1.0 + with: + commit-changes: true + + super-linter: + needs: prettier-fix + uses: WorkOfStan/seablast-actions/.github/workflows/linter.yml@v0.2.1 + with: + runs-on: "ubuntu-24.04" diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..ec7cf8b --- /dev/null +++ b/.gitignore @@ -0,0 +1,6 @@ +#disable dependency files +/composer.lock + +#disable IDE files +/nbproject/ +/.idea/ diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 0000000..c50511a --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,34 @@ +# Changelog + +All notable changes to this project will be documented in this file. + +The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), +and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). + +## [Unreleased] + +### `Added` for new features + +### `Changed` for changes in existing functionality + +### `Deprecated` for soon-to-be removed features + +### `Removed` for now removed features + +### `Fixed` for any bugfixes + +### `Security` in case of vulnerabilities + +## [1.0.0] - 2025-01-18 + +- This GitHub Action automates PHPCS formatting across your project, ensuring consistent code styling by creating a new branch for review when necessary. It simplifies integrating PHPCS/PHPCBF into your workflow. +- A warning appears in the GitHub Actions Annotations section if changes occur and therefore a new branch is created. +- A proposed manual changed linked from the warning in the GitHub Actions Annotations section. +- The input parameter `commit-changes: true` to commit to the current branch. +- **Customizable Commit Message**: Introduced an input `commit-message` to allow users to specify a custom commit message. +- **Branch Name Output**: The `branch-name` is provided as an output for downstream workflows. +- Notice about a successful commit. +- **Checkout code**: Fetches the latest changes so that modifications from a previous job are included, enabling seamless job chaining. + +[Unreleased]: https://github.com/WorkOfStan/phpcs-fix/compare/v1.0.0...HEAD?w=1 +[1.0.0]: https://github.com/WorkOfStan/phpcs-fix/releases/tag/v1.0.0 diff --git a/README.md b/README.md index 990d842..a4b4e04 100644 --- a/README.md +++ b/README.md @@ -1,2 +1,45 @@ -# phpcs-fix -Automatically apply PHP coding standard formatting and create a pull request to fix code style issues, ensuring compatibility with Super-Linter. +# PHPCS-Fix + +**PHP Code Beautifier and Fixer** is a GitHub Action that checks your PHP code for style issues using the supported [PHPCSStandards/PHP_CodeSniffer](https://github.com/PHPCSStandards/PHP_CodeSniffer/) and automatically attempts to fix them using phpcbf ensuring compatibility with [Super-Linter](https://github.com/super-linter/super-linter). +(Note that the original [squizlabs/PHP_CodeSniffer](https://github.com/squizlabs/PHP_CodeSniffer) was abandoned.) +This action can either commit changes directly to the current branch or create a new branch if you prefer manual review via pull request. + +## Features + +- **Automatic Fixes:** Check PHP files for coding standard violations and attempts to automatically fix them when possible. +- **Flexible Committing:** Creates a new branch (prefixed with `phpcbf/fix`) if changes are required, making it easy to review and merge. Or you can set the input parameter `commit-changes: true` to commit to the current branch. (Recommendation: start with committing to another branch and review in order to avoid surprises. Then commit to the same branch for incremental changes.) +- **Configurable:** Adjust extensions, ignore and standard parameters of phpcs. Adjust PHP version, or commit-message. + +## Usage + +This action is designed to be used as a _reusable workflow_. You can call it from another workflow in your repository or simply add [the provided YAML configuration](.github/workflows/phpcs-phpcbf.yml) to your repository. + +By default, if needed, a new branch with a name starting with `prettier/fix` will be created, making it easy to review and merge the fixes into your main branch. + +Note: This action is not blocking, so the status remains green even if changes are proposed in the form of a new branch. Then it’s up to you to either create a pull request to merge the changes or delete the branch. + +### Permissions + +This action requires the following permissions: + +```yaml +permissions: + contents: write +``` + +### Inputs (all optional) + +| Input | Description | Type | Default | +| ---------------- | ---------------------------------------------------------------------------------------------------------------------------- | ------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| `commit-changes` | If set to `true`, the action will commit changes to the current branch; otherwise a new branch is created for manual review. | Boolean | `false` | +| `commit-message` | Commit message to use if the action commits changes. | String | `"PHP Code Beautifier fixes applied automatically"` | +| `extensions` | Comma-delimited list of file extensions to be sniffed. Note: an empty value will disable checking. | String | `"php"` (defaults to PHP only; other file types must be specified) | +| `ignore` | Ignore files based on a comma-separated list of patterns matching files and/or directories. | String | `vendor/` | +| `php-version` | The PHP version to use, e.g. `"8.2"`. | String | `"8.2"` | +| `standard` | The name of, or the path to, the coding standard to use. Can be a comma-separated list specifying multiple standards. | String | The project's `.github/linters/phpcs.xml` (where Super-linter expects it) with fallback to copied to [.github/linters/super-linter-templates-phpcs.xml](.github/linters/super-linter-templates-phpcs.xml) will be used. | + +### Outputs + +| Output | Description | +| ------------- | ----------------------------------- | +| `branch-name` | The name of the branch created/used | diff --git a/action.yml b/action.yml new file mode 100644 index 0000000..3cc2134 --- /dev/null +++ b/action.yml @@ -0,0 +1,145 @@ +--- +name: "PHP Code Beautifier and Fixer" +description: Sniff the PHP code and beautify it if necessary. + +author: + name: "Stanislav Rejthar" + email: "rejthar@stanislavrejthar.com" + url: "https://github.com/WorkOfStan" + +branding: + icon: "check-circle" + color: "blue" + +inputs: + commit-changes: + description: "If true, commit changes to the current branch" + type: boolean + default: false + commit-message: + description: "Commit message for the changes" + type: string + default: "PHP Code Beautifier fixes applied automatically" + # https://github.com/PHPCSStandards/PHP_CodeSniffer/wiki/Advanced-Usage#specifying-valid-file-extensions + # By default, PHP_CodeSniffer will check any file it finds with a .inc, .php, .js or .css extension, although not all standards will actually check all these file types. + # Empty value means no checking at all. + # The default is `php` as js and css are handled by prettier. + # Btw: JS/CSS support will be removed from PHP_CodeSniffer in PHPCS 4.x. Source: https://phpcsutils.com/ + extensions: + description: "Comma delimited list of extensions to be sniffed" + required: false + type: string + default: "php" # "php,inc,lib" + ignore: + description: "Ignore files based on a comma-separated list of patterns matching files and/or directories." + required: false + type: string + default: "vendor/" + php-version: + description: "PHP version to be used for running phpcs and phpcbf" + required: false + type: string + default: "8.2" + standard: + description: "The name of, or the path to, the coding standard to use. Can be a comma-separated list specifying multiple standards." + required: false + type: string + default: "" # if left empty, .github/linters/phpcs.xml or https://github.com/super-linter/super-linter/blob/main/TEMPLATES/phpcs.xml will be used + +outputs: + branch-name: + description: "The branch where changes were committed" + +runs: + using: "composite" + steps: + - name: Checkout code + uses: actions/checkout@v4 + with: + ref: ${{ github.ref }} # Fetch latest changes (even by previous job) + fetch-depth: 0 # Fetch all history for all branches and tags. Otherwise github.event.pull_request.base.ref SHA isn't found. + + # Fetch latest changes (even by previous job) + - name: Fetch latest changes + run: git pull origin ${{ github.ref }} + shell: bash + + - name: Set up PHP + uses: shivammathur/setup-php@v2 + with: + php-version: "${{ inputs.php-version }}" + tools: composer:v2 + + # todo consider using cache + - name: "Use the latest PHPCS version" + run: composer require --dev squizlabs/php_codesniffer --prefer-dist --no-progress + shell: bash + + - name: Run PHP Code Sniffer + id: phpcs + run: | + # Determine which coding standard to use. + # Priority: + # 1. Use inputs.standard if provided (non-empty). + # 2. If not, use the repository's own phpcs.xml if available. + # 3. Otherwise, fall back to the action's default template. Which is a copy of https://github.com/super-linter/super-linter/blob/main/TEMPLATES/phpcs.xml + if [ -n "${{ inputs.standard }}" ]; then + use_standard="${{ inputs.standard }}" + elif [ -f .github/linters/phpcs.xml ]; then + use_standard=".github/linters/phpcs.xml" + else + use_standard="$GITHUB_ACTION_PATH/.github/linters/super-linter-templates-phpcs.xml" + fi + echo "USE_STANDARD=$use_standard" >> "$GITHUB_ENV" # for subsequent steps + echo "phpcs standard=$use_standard" + vendor/bin/phpcs --extensions="${{ inputs.extensions }}" . --standard="$use_standard" --ignore="${{ inputs.ignore }}" || HAS_ISSUES=true + # because of `||`, the previous command always exit 0 + + # Default the variable if no issues were found + : "${HAS_ISSUES:=false}" + echo "HAS_ISSUES=$HAS_ISSUES" >> "$GITHUB_ENV" + shell: bash + + - name: Run PHP Code Beautifier if needed + if: env.HAS_ISSUES == 'true' + run: | + echo "phpcbf standard=${{ env.USE_STANDARD }}" + vendor/bin/phpcbf --extensions="${{ inputs.extensions }}" . --standard="${{ env.USE_STANDARD }}" --ignore="${{ inputs.ignore }}" || echo "::warning title=Some phpcs issues remained::Manual fix necessary. Compare to the PHP Code Sniffer section above." + + # restore composer.json before staging the changes + git checkout composer.json + + # Check for fixable changes + if [ -z "$(git status --porcelain)" ]; then + echo "::warning title=No fixable errors were found by phpcbf::Manual fix necessary. Compare to the PHP Code Sniffer section above." + # Exiting gracefully + exit 0 + # The rest of the script must still be within the same step to really stop the execution + fi + + git add . + + # Determine branch name based on commit-changes input + if ${{ inputs.commit-changes }}; then + BRANCH_NAME=$(git branch --show-current) + NOTICE_MESSAGE="A PHPCBF commit was successfully added to the current branch: $BRANCH_NAME" + else + # name includes timestamp and short_hash + BRANCH_NAME="phpcbf/fix-$(date +'%y%m%d%H%M%S')-$(git rev-parse --short HEAD)" + git checkout -b "$BRANCH_NAME" + echo "::warning title=New branch created::Consider pull request for a new branch: $BRANCH_NAME (or delete it)" + NOTICE_MESSAGE="A PHPCBF commit was successfully added to the new branch: $BRANCH_NAME" + fi + + # Configure Git user + git config user.name "github-actions[bot]" + git config user.email "41898282+github-actions[bot]@users.noreply.github.com" + + # Commit and push changes with custom message + git commit -m "${{ inputs.commit-message }} on $(date +'%Y-%m-%d %H:%M:%S') UTC" + git push origin "$BRANCH_NAME" + echo "::notice title=Commit added::$NOTICE_MESSAGE" + + # Set branch name as output + echo "branch-name=$BRANCH_NAME" >> $GITHUB_OUTPUT + shell: bash