#!/bin/bash # Copyright (C) 2025-2026 MDW # shellcheck disable=2129,2128,2034,2016 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 2 fi if [[ -z "${GITHUB_EVENT_PATH:-}" ]]; then echo "GITHUB_EVENT_PATH is not set" >&2 exit 3 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 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=() changed_phan_files=() changed_lang_files=() # Get phan path configuration phan_directory_list=$(php -r '$config = require("dev/tools/phan/config.php"); echo "^".implode("|",$config["directory_list"]);') phan_exclude_directory=$(php -r '$config = require("dev/tools/phan/config.php"); echo "^".implode("|",$config["exclude_analysis_directory_list"]);') phan_exclude_file_regex=$(php -r '$config = require("dev/tools/phan/config.php"); echo $config["exclude_file_regex"];') phan_exclude_file_regex=${phan_exclude_file_regex#@} phan_exclude_file_regex=${phan_exclude_file_regex%@} # 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$")) and (.filename | test("^dev/") | not)) | .filename') changed_php_files+=("${files[@]}") mapfile -t files < <(echo "$response" | jq -r '.[] | select((.filename | test("\\.php$")) and (.filename | test("'"$phan_directory_list"'"))) | .filename' | grep -vP "$phan_exclude_file_regex") changed_phan_files+=("${files[@]}") mapfile -t files < <(echo "$response" | jq -r '.[] | select(.filename | test("\\.lang$")) | .filename') changed_lang_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 and lang 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[*]}") all_changed_lang=$(IFS=" " ; echo "${changed_lang_files[*]}") phan_changed_files=$(IFS=" " ; echo "${changed_phan_files[*]}") forbidden_files="" #forbidden_files=$(echo "$all_changed_lang" | grep -E 'htdocs/langs/([^/]+)/.*\.lang$' | grep -v 'htdocs/langs/en_US/') #if [ -n "$forbidden_files" ]; then # echo "You tried to modify one or more language files that are not allowed to be modified in Pull requests." # echo "$forbidden_files" # echo "To modify translations that are not the source language (en_US), you must modify them from transifex.com" # exit 10 #fi # Determine changed files flags if [ -z "${all_changed_files}" ]; then any_changed="false" else any_changed="true" fi if [ -z "${phan_changed_files}" ]; then phan_changed="false" else phan_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 "phan_changed=${phan_changed}" >> "$GITHUB_OUTPUT" echo "all_changed_files=${all_changed_files}" >> "$GITHUB_OUTPUT" echo "phan_changed_files=${phan_changed_files[*]}" >> "$GITHUB_OUTPUT" echo "forbidden_files=${forbidden_files}" >> "$GITHUB_OUTPUT" else # Otherwise, print the outputs echo "any_changed=${any_changed}" echo "phan_changed=${phan_changed}" echo "phan_changed_files=${phan_changed_files[*]}" echo "all_changed_files=${all_changed_files}" echo "forbidden_files=${forbidden_files}" fi