diff --git a/.github/scripts/get_changed_php.sh b/.github/scripts/get_changed_php.sh new file mode 100755 index 00000000000..1b9ad4734ae --- /dev/null +++ b/.github/scripts/get_changed_php.sh @@ -0,0 +1,86 @@ +#!/bin/bash +# Copyright (C) 2025 MDW + +set -euo pipefail + +# This script retrieves the list of changed PHP files for a pull request +# using the GitHub API and sets two outputs: +# - any_changed: "true" if at least one PHP file changed, "false" otherwise +# - all_changed_files: space-separated list of changed PHP file paths +# +# Required environment variables: +# GITHUB_TOKEN - GitHub token with repo access +# GITHUB_REPOSITORY - "owner/repo" +# GITHUB_EVENT_PATH - Path to the event JSON payload + +# Verify required environment variables are set +if [[ -z "${GITHUB_TOKEN:-}" ]]; then + echo "GITHUB_TOKEN is not set" >&2 + exit 1 +fi +if [[ -z "${GITHUB_REPOSITORY:-}" ]]; then + echo "GITHUB_REPOSITORY is not set" >&2 + exit 1 +fi +if [[ -z "${GITHUB_EVENT_PATH:-}" ]]; then + echo "GITHUB_EVENT_PATH is not set" >&2 + exit 1 +fi + +# Extract the pull request number from the event payload +pr_number=$(jq --raw-output '.pull_request.number' "$GITHUB_EVENT_PATH") +if [[ "$pr_number" == "null" ]]; then + echo "Not a pull request event" + exit 0 +fi + +# Split repository into owner and repo name +# Split repository into owner and repo name using Bash parameter expansion +owner="${GITHUB_REPOSITORY%%/*}" # Extract text before the first '/' +repo="${GITHUB_REPOSITORY##*/}" # Extract text after the last '/' + +page=1 +per_page=100 +changed_php_files=() + +# Loop through all pages to gather changed files +while true; do + response=$(curl -s -H "Authorization: token ${GITHUB_TOKEN}" \ + "https://api.github.com/repos/${owner}/${repo}/pulls/${pr_number}/files?per_page=${per_page}&page=${page}") + + # Filter for files ending with .php and add them to the list + mapfile -t files < <(echo "$response" | jq -r '.[] | select(.filename | test("\\.php$")) | .filename') + changed_php_files+=("${files[@]}") + + # Check if we have reached the last page (less than per_page results) + count=$(echo "$response" | jq 'length') + if (( count < per_page )); then + break + fi + ((page++)) +done + + +# Build a space-separated string of changed PHP files +# This does not cope with files that have spaces. +# But such files do not exist in the project (at least not for the +# files we are filtering). +all_changed_files=$(IFS=" " ; echo "${changed_php_files[*]}") + + +# Determine changed files flag +if [ -z "$all_changed_files" ]; then + any_changed="false" +else + any_changed="true" +fi + +# Set outputs for GitHub Actions if GITHUB_OUTPUT is available +if [ -n "${GITHUB_OUTPUT:-}" ]; then + echo "any_changed=${any_changed}" >> "$GITHUB_OUTPUT" + echo "all_changed_files=${all_changed_files}" >> "$GITHUB_OUTPUT" +else + # Otherwise, print the outputs + echo "any_changed=${any_changed}" + echo "all_changed_files=${all_changed_files}" +fi diff --git a/.github/workflows/pre-commit.yml b/.github/workflows/pre-commit.yml index ddf13c8a070..171d494b411 100644 --- a/.github/workflows/pre-commit.yml +++ b/.github/workflows/pre-commit.yml @@ -14,18 +14,18 @@ jobs: run: sudo apt-get update && sudo apt-get install cppcheck if: false + # Checkout git sources to analyze + - uses: actions/checkout@v4 + # The next uses the git API because there is no clone yet. # This is faster for a big repo. - name: Get all changed php files (if PR) id: changed-php - uses: tj-actions/changed-files@v42 - if: github.event_name == 'pull_request' - with: - files: | - **.php + if: env.gh_event == 'pull_request' + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + run: ./.github/scripts/get_changed_php.sh - # Checkout git sources to analyze - - uses: actions/checkout@v4 # Action setup-python needs a requirements.txt or pyproject.toml # This ensures one of them exists. - name: Create requirements.txt if no requirements.txt or pyproject.toml