@@ -14,30 +14,176 @@ jobs:
1414 - name : Checkout code
1515 uses : actions/checkout@v5
1616 with :
17- token : ${{ secrets.GITHUB_TOKEN }}
17+ token : ${{ secrets.PAT_TOKEN || secrets. GITHUB_TOKEN }}
1818 ref : ${{ github.head_ref || github.ref }}
1919 fetch-depth : 0
2020
2121 - name : Update docblocks
2222 run : |
23- set -e
24- SOURCE_URL=$(jq -r '.support.source' composer.json)
25- if [ ! -d ./src ]; then
26- echo "Source directory ./src does not exist!"
27- exit 1
28- fi
29- docker run --rm -v "$PWD/src:/app/run" davidsmith3/docblock-annotator-cli \
30- docblock-annotator-cli:update-directory /app/run "@link $SOURCE_URL"
23+ set -euo pipefail
24+
25+ # Constants
26+ readonly COMPOSER_JSON="composer.json"
27+ readonly DOCBLOCK_DOCKER_IMAGE="davidsmith3/docblock-annotator-cli"
28+ readonly DOCBLOCK_COMMAND="docblock-annotator-cli:update-file"
29+
30+ # Execute docblock annotator via Docker for a specific file
31+ execute_docblock_annotator() {
32+ local file_path="$1"
33+ shift
34+
35+ docker run \
36+ --rm \
37+ --volume "$(pwd):/app/run" \
38+ "${DOCBLOCK_DOCKER_IMAGE}" \
39+ "${DOCBLOCK_COMMAND}" \
40+ "/app/run/${file_path}" \
41+ "$@"
42+ }
43+
44+ # Validate required dependencies are available
45+ validate_dependencies() {
46+ if ! command -v jq &> /dev/null; then
47+ echo "Error: jq is required but not installed." >&2
48+ return 1
49+ fi
50+
51+ if [[ ! -f "${COMPOSER_JSON}" ]]; then
52+ echo "Error: ${COMPOSER_JSON} not found in current directory." >&2
53+ return 1
54+ fi
55+ }
56+
57+ # Extract the main PHP class file path from composer.json PSR-4 autoload configuration
58+ get_main_class_file() {
59+ local namespace directory class_name php_file
60+
61+ namespace=$(jq -r '.autoload."psr-4" | keys[0] // empty' "${COMPOSER_JSON}")
62+ directory=$(jq -r --arg ns "$namespace" '.autoload."psr-4"[$ns] // empty' "${COMPOSER_JSON}")
63+
64+ if [[ -z "$namespace" || -z "$directory" ]]; then
65+ echo "Error: Could not extract PSR-4 namespace or directory from ${COMPOSER_JSON}." >&2
66+ return 1
67+ fi
68+
69+ # Remove trailing backslash from namespace
70+ namespace="${namespace%\\}"
71+
72+ # Extract class name from namespace (last segment)
73+ class_name=$(echo "$namespace" | awk -F'\\\\' '{print $NF}')
74+
75+ # Construct PHP file path
76+ php_file="${directory}${class_name}.php"
77+
78+ # Convert backslashes to forward slashes for file path
79+ php_file=$(echo "$php_file" | sed 's/\\/\//g')
80+
81+ if [[ ! -f "$php_file" ]]; then
82+ echo "Warning: Main class file '$php_file' not found. Trying to find an alternative..." >&2
83+
84+ # Try to find the first PHP class file in the directory
85+ local alternative_file
86+ alternative_file=$(find "$directory" -maxdepth 1 -name "*.php" -type f | head -1)
87+
88+ if [[ -n "$alternative_file" ]]; then
89+ echo "Using alternative file: $alternative_file" >&2
90+ echo "$alternative_file"
91+ return 0
92+ else
93+ echo "Error: No PHP class files found in directory '$directory'." >&2
94+ return 1
95+ fi
96+ fi
97+
98+ echo "$php_file"
99+ }
100+
101+ # Extract package description from composer.json
102+ get_package_description() {
103+ local description
104+ description=$(jq -r '.description // empty' "${COMPOSER_JSON}")
105+
106+ if [[ -z "$description" ]]; then
107+ echo "Error: Could not extract package description from ${COMPOSER_JSON}." >&2
108+ return 1
109+ fi
110+
111+ echo "$description"
112+ }
113+
114+ # Extract package homepage from composer.json
115+ get_package_homepage() {
116+ local homepage
117+ homepage=$(jq -r '.homepage // empty' "${COMPOSER_JSON}")
118+
119+ if [[ -z "$homepage" ]]; then
120+ echo "Error: Could not extract package homepage from ${COMPOSER_JSON}." >&2
121+ return 1
122+ fi
123+
124+ echo "$homepage"
125+ }
126+
127+ # Update docblock with package description
128+ update_docblock_with_description() {
129+ local php_file description
130+
131+ php_file=$(get_main_class_file) || return 1
132+ description=$(get_package_description) || return 1
133+
134+ execute_docblock_annotator "$php_file" "$description" "--statements=class"
135+ }
136+
137+ # Update docblock with homepage link
138+ update_docblock_with_link() {
139+ local php_file homepage
140+
141+ php_file=$(get_main_class_file) || return 1
142+ homepage=$(get_package_homepage) || return 1
143+
144+ execute_docblock_annotator "$php_file" "@link $homepage"
145+ }
146+
147+ # Main function to update all docblocks
148+ update_package_docblocks() {
149+ validate_dependencies || return 1
150+
151+ echo "Updating docblocks with package description..."
152+ update_docblock_with_description || return 1
153+
154+ echo "Updating docblocks with homepage link..."
155+ update_docblock_with_link || return 1
156+
157+ echo "Docblock updates completed successfully."
158+ }
159+
160+ # Execute the main function
161+ update_package_docblocks
31162
32163 - name : Commit and push changes (if any)
33164 run : |
34- set -e
165+ set -euo pipefail
166+
167+ # Configure git user for commits
35168 git config --local user.email "action@github.com"
36169 git config --local user.name "GitHub Action"
170+
171+ # Stage all changes
37172 git add -A
173+
174+ # Check if there are any changes to commit
38175 if ! git diff --cached --quiet; then
39- git commit -m "Update docblocks with @link annotations" --no-verify
176+ echo "Changes detected, committing docblock updates..."
177+
178+ # Commit without skip-ci to allow other workflows to run
179+ git commit -m "Update docblocks with @link annotations" \
180+ --no-verify
181+
182+ # Push changes - using PAT_TOKEN if available to trigger workflows properly
40183 git push
184+
185+ echo "Docblock updates committed and pushed successfully."
186+ echo "Other workflows will run on the new commit."
41187 else
42188 echo "No changes to commit."
43189 fi
0 commit comments