diff --git a/.github/workflows/callable-fabbot.yml b/.github/workflows/callable-fabbot.yml deleted file mode 100644 index 26da75921a7bc..0000000000000 --- a/.github/workflows/callable-fabbot.yml +++ /dev/null @@ -1,247 +0,0 @@ -name: Fabbot - -on: - workflow_call: - inputs: - package: - required: true - type: string - check_license: - required: false - type: boolean - default: false - -env: - GH_TOKEN: ${{ github.token }} - -jobs: - check: - name: Checks - runs-on: ubuntu-24.04 - steps: - - name: Checkout code - run: | - # Checkout patched files using the REST API and install dependencies concurrently - PR_NUMBER="${{ github.event.pull_request.number }}" - PR_HEAD_SHA="${{ github.event.pull_request.head.sha }}" - REPO_OWNER="${{ github.repository_owner }}" - REPO_NAME="${{ github.event.repository.name }}" - - pip install codespell & - composer global require -q friendsofphp/php-cs-fixer seld/jsonlint symfony/yaml & - - mkdir a - - gh api -H "Accept: application/vnd.github.v3.raw" \ - "/repos/$REPO_OWNER/$REPO_NAME/contents/.php-cs-fixer.dist.php?ref=$PR_HEAD_SHA" \ - > a/.php-cs-fixer.dist.php || rm a/.php-cs-fixer.dist.php & - - gh api --paginate "/repos/$REPO_OWNER/$REPO_NAME/pulls/$PR_NUMBER/files" \ - | jq -c '.[] | select(.status != "removed") | {filename, sha}' \ - | while read -r FILE_OBJ; do - FILENAME=$(echo "$FILE_OBJ" | jq -r '.filename') - FILE_SHA=$(echo "$FILE_OBJ" | jq -r '.sha') - - mkdir -p "a/$(dirname "$FILENAME")" - gh api -H "Accept: application/vnd.github.raw" \ - "/repos/$REPO_OWNER/$REPO_NAME/git/blobs/$FILE_SHA" \ - > "a/$FILENAME" & - done - - wait - - - name: Check code style - if: always() - run: | - # Run PHP-CS-Fixer - cp -a a b && cd b - ~/.composer/vendor/bin/php-cs-fixer fix --using-cache no --show-progress none - cd .. - - if ! diff -qr --no-dereference a/ b/ >/dev/null; then - echo "::error::PHP-CS-Fixer found style issues. Please apply the patch below." - echo -e "\n \n git apply - <<'EOF_PATCH'" - diff -pru2 --no-dereference --color=always a/ b/ || true - echo -e "EOF_PATCH\n \n" - echo "Then commit the changes and push to your PR branch." - exit 1 - fi - - - name: Check for common typos - if: always() - run: | - # Run codespell - rm -rf b && cp -a a b && cd b - codespell -L invokable --check-filenames -w || true - cd .. - - if ! diff -qr --no-dereference a/ b/ >/dev/null; then - echo "::error::PHP-CS-Fixer found typos. Please apply the patch below." - echo -e "\n \n git apply - <<'EOF_PATCH'" - diff -pru2 --no-dereference --color=always a/ b/ || true - echo -e "EOF_PATCH\n \n" - echo "Then commit the changes and push to your PR branch." - exit 1 - fi - - - name: Check for merge commits - if: always() - run: | - # If a PR contains merge commits, fail the job - gh api -H "Accept: application/vnd.github.v3+json" \ - "/repos/${{ github.repository_owner }}/${{ github.event.repository.name }}/pulls/${{ github.event.pull_request.number }}/commits" \ - | jq -r '.[].parents | length > 1' | grep true > /dev/null && { - echo "::error::Merge commits are not allowed in pull requests." - echo "Please rebase your branch." - exit 1 - } || true - - - name: Check test-case methods - if: always() - run: | - # Test method names should not have a return type - rm -rf b && cp -a a b && cd b - find -wholename '**/Tests/**.php' \ - | while read -r FILE; do - sed -i -E 's/^( public function test.*): void$/\1/' "$FILE" - done - cd .. - - if ! diff -qr --no-dereference a/ b/ >/dev/null; then - echo "::error::Test case methods should not have a return type. Please apply the patch below." - echo -e "\n \n git apply - <<'EOF_PATCH'" - diff -pru2 --no-dereference --color=always a/ b/ || true - echo -e "EOF_PATCH\n \n" - echo "Then commit the changes and push to your PR branch." - exit 1 - fi - - - name: Check @deprecated annotations - if: always() - run: | - # @deprecated annotations should mention ${{ inputs.package }} - rm -rf b && cp -a a b && cd b - find -name '*.php' \ - | while read -r FILE; do - sed -i -E 's/(@deprecated since )([0-9])/\1${{ inputs.package }} \2/' "$FILE" - done - cd .. - - if ! diff -qr --no-dereference a/ b/ >/dev/null; then - echo "::error::@deprecated annotations should mention ${{ inputs.package }}. Please apply the patch below." - echo -e "\n \n git apply - <<'EOF_PATCH'" - diff -pru2 --no-dereference --color=always a/ b/ || true - echo -e "EOF_PATCH\n \n" - echo "Then commit the changes and push to your PR branch." - exit 1 - fi - - - name: Check PR header - if: always() - run: | - # Check if the PR title and body follow the Symfony contribution guidelines - PR_TITLE="${{ github.event.pull_request.title }}" - PR_BODY="${{ github.event.pull_request.body }}" - - if [[ "${{ inputs.check_license }}" == "true" ]]; then - if [[ ! "$PR_BODY" =~ \|\ License[\ ]+\|\ MIT ]]; then - echo "::error::You must add the standard contribution header in the PR description" - echo "See https://symfony.com/doc/current/contributing/code/patches.html#make-a-pull-request" - exit 1 - fi - fi - - if [[ "$PR_TITLE" =~ (feat|fix|docs|style|refactor|perf|test|chore|revert|build|ci|types?|wip)[:()] ]]; then - echo "::error::Don't use conventional commits in PR titles." - echo "We'll add the appropriate prefix while merging." - echo "Use the component name instead, e.g., [Component] Description." - exit 1 - fi - - - name: Check YAML files - if: always() - run: | - # Check YAML files for syntax errors - rm -rf b && cp -a a b && cd b - find . -name '*.yml' -o -name '*.yaml' \ - | while read -r FILE; do php -r ' - use Symfony\Component\Yaml\{Parser,Yaml}; - require $_SERVER["HOME"]."/.composer/vendor/autoload.php"; - try { (new Parser())->parse(file_get_contents($argv[1]), Yaml::PARSE_CUSTOM_TAGS); } - catch (Exception $e) { echo "::error::in $argv[1]:\n{$e->getMessage()}\n"; exit(1); } - ' "$FILE" - done - cd .. - - - name: Check JSON files - if: always() - run: | - # Check JSON files for syntax errors - rm -rf b && cp -a a b && cd b - find . -name '*.json' \ - | while read -r FILE; do php -r ' - use Seld\JsonLint\JsonParser; - require $_SERVER["HOME"]."/.composer/vendor/autoload.php"; - try { (new JsonParser())->parse(file_get_contents($argv[1])); } - catch (Exception $e) { echo "::error:: in $argv[1]: {$e->getMessage()}\n"; exit(1); } - ' "$FILE" - done - cd .. - - - name: Check exception messages - if: always() - run: | - # Placeholders should be enclosed in double-quotes and messages should end with a dot - rm -rf b && cp -a a b && cd b - find -name '*.php' \ - | while read -r FILE; do php -r "$(cat <<'EOF' - $new = preg_replace_callback('{throw new ([^\(]+)\((.+?)\);}', function ($match) { - $contents = $match[2]; - - // %s::%s() -> "%s::%s()" - $contents = preg_replace('{(?<= )%s\:\:%s(\(\))?}', '"%s::%s()"', $contents); - $contents = preg_replace('{\(\'%s\:\:%s(\(\))?}', '(\'"%s::%s()"', $contents); - - // %s() -> "%s()" - $contents = preg_replace('{(?<= )%s(\(\))}', '"%s$1"', $contents); - $contents = preg_replace('{\(\'%s(\(\))}', '(\'"%s$1"', $contents); - - // %s -> "%s" after a space - $contents = preg_replace('{(?<= )%s}', '"%s"', $contents); - $contents = preg_replace('{\(\'%s}', '(\'"%s"', $contents); - - return sprintf('throw new %s(%s);', $match[1], $contents); - }, $old = file_get_contents($argv[1])); - - // ensure there is a dot at the end of the exception message - // except for files under Tests/ - if (false === strpos($argv[1], '/Tests/')) { - $new = preg_replace_callback('{throw new ([^\(]+)\((sprintf\()?(\'|")(.+?)(?/dev/null; then - echo "::error::Some exception messages might need a tweak. Please consider the patch below." - echo -e "\n \n git apply - <<'EOF_PATCH'" - diff -pru2 --no-dereference --color=always a/ b/ || true - echo -e "EOF_PATCH\n \n" - echo "Then commit the changes and push to your PR branch." - exit 1 - fi - - - name: 🧠 Fabbot can generate false-positives. Cherry-pick as fits 🍒. Reviewers will help. - if: always() - run: exit 0 diff --git a/.github/workflows/fabbot.yml b/.github/workflows/fabbot.yml index b62f36fde840f..a187b49ee6991 100644 --- a/.github/workflows/fabbot.yml +++ b/.github/workflows/fabbot.yml @@ -9,7 +9,7 @@ permissions: jobs: call-fabbot: name: Fabbot - uses: ./.github/workflows/callable-fabbot.yml + uses: symfony-tools/fabbot/.github/workflows/fabbot.yml@main with: package: Symfony check_license: true