-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathaction.yml
More file actions
447 lines (385 loc) Β· 17.4 KB
/
action.yml
File metadata and controls
447 lines (385 loc) Β· 17.4 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
name: 'CodeBoarding [Diagram-First Documentation]'
description: 'Generates diagram-first visualizations of your codebase using static analysis and large language models.'
author: 'CodeBoarding'
branding:
icon: 'book-open' # or 'layers', 'git-branch', 'book-open', 'target'
color: 'blue'
inputs:
output_directory:
description: 'Directory where documentation files will be saved'
required: false
default: 'docs'
repository_url:
description: 'Repository URL to fetch documentation for (defaults to current repository)'
required: true
source_branch:
description: 'Source branch for comparison'
required: true
target_branch:
description: 'Target branch for comparison'
required: true
output_format:
description: 'Output format for documentation files (.md, .mdx, .rst, or .html)'
required: false
default: '.md'
outputs:
markdown_files_created:
description: 'Number of Markdown files created'
value: ${{ steps.process-docs.outputs.markdown_files_created }}
json_files_created:
description: 'Number of JSON files created'
value: ${{ steps.process-docs.outputs.json_files_created }}
output_directory:
description: 'Directory where Markdown files were saved'
value: ${{ steps.process-docs.outputs.output_directory }}
json_directory:
description: 'Directory where JSON files were saved (.codeboarding)'
value: ${{ steps.process-docs.outputs.json_directory }}
has_changes:
description: 'Whether any files were created or changed'
value: ${{ steps.process-docs.outputs.has_changes }}
repo_url:
description: 'Repository URL that was analyzed'
value: ${{ steps.repo-url.outputs.repo_url }}
runs:
using: 'composite'
steps:
- name: Determine repository URL
id: repo-url
shell: bash
run: |
# Use the provided repository URL if it's not empty
if [ -n "${{ inputs.repository_url }}" ]; then
REPO_URL="${{ inputs.repository_url }}"
echo "Using provided repository URL: $REPO_URL"
# Otherwise try to determine from git if we're in a git repository
elif git config --get remote.origin.url > /dev/null 2>&1; then
REPO_URL=$(git config --get remote.origin.url)
# Convert SSH URL to HTTPS if needed
if [[ $REPO_URL == git@* ]]; then
REPO_URL=$(echo $REPO_URL | sed 's|git@github.com:|https://github.com/|')
fi
echo "Using git remote URL: $REPO_URL"
else
REPO_URL="${{ github.server_url }}/${{ github.repository }}"
echo "Using GitHub context URL: $REPO_URL"
fi
echo "repo_url=$REPO_URL" >> $GITHUB_OUTPUT
- name: Create and poll documentation job
id: fetch-docs
shell: bash
run: |
CREATE_JOB_URL="https://server.codeboarding.org/github_action/jobs"
REPO_URL="${{ steps.repo-url.outputs.repo_url }}"
SOURCE_BRANCH="${{ inputs.source_branch }}"
TARGET_BRANCH="${{ inputs.target_branch }}"
OUTPUT_DIRECTORY="${{ inputs.output_directory }}"
OUTPUT_FORMAT="${{ inputs.output_format }}"
echo "π Creating CodeBoarding analysis job...$CREATE_JOB_URL"
echo "π Repository: $REPO_URL"
echo "πΏ Source branch: $SOURCE_BRANCH"
echo "π― Target branch: $TARGET_BRANCH"
echo "π Output format: $OUTPUT_FORMAT"
# Create JSON payload
JSON_PAYLOAD=$(jq -n \
--arg url "$REPO_URL" \
--arg source_branch "$SOURCE_BRANCH" \
--arg target_branch "$TARGET_BRANCH" \
--arg output_directory "$OUTPUT_DIRECTORY" \
--arg extension "$OUTPUT_FORMAT" \
'{
url: $url,
source_branch: $source_branch,
target_branch: $target_branch,
output_directory: $output_directory,
extension: $extension
}')
echo "π Request payload:"
echo "$JSON_PAYLOAD"
# Create temporary file for response
TEMP_FILE=$(mktemp)
echo "π Making API request to create job..."
# Make the API call to create job
response=$(curl -s -w "%{http_code}" -o "$TEMP_FILE" \
-X POST \
-H "Content-Type: application/json" \
-d "$JSON_PAYLOAD" \
--max-time 60 \
--connect-timeout 30 \
"$CREATE_JOB_URL")
curl_exit_code=$?
http_code=${response: -3}
echo "β
Job creation request completed!"
echo "π Response status code: $http_code"
echo "π§ Curl exit code: $curl_exit_code"
# Handle curl errors
if [ $curl_exit_code -ne 0 ]; then
echo "β Error: Curl failed with exit code $curl_exit_code"
case $curl_exit_code in
6) echo "π Couldn't resolve host - check network connectivity" ;;
7) echo "π Failed to connect to host - server might be down" ;;
28) echo "β° Request timed out - server might be busy" ;;
*) echo "β Unknown curl error - check network and server status" ;;
esac
rm -f "$TEMP_FILE"
exit 1
fi
if [ "$http_code" != "202" ]; then
echo "β Error: Job creation failed with status code $http_code"
echo "π Response content:"
cat "$TEMP_FILE"
# Try to parse as JSON for better error message
if jq -e '.detail' "$TEMP_FILE" > /dev/null 2>&1; then
echo "π Error details: $(jq -r '.detail' "$TEMP_FILE")"
fi
rm -f "$TEMP_FILE"
exit 1
fi
# Check if response is valid JSON
if ! jq empty "$TEMP_FILE" 2>/dev/null; then
echo "β Error: Invalid JSON response"
echo "π Response content:"
cat "$TEMP_FILE"
rm -f "$TEMP_FILE"
exit 1
fi
# Extract job_id from response
JOB_ID=$(jq -r '.job_id' "$TEMP_FILE")
if [ "$JOB_ID" = "null" ] || [ -z "$JOB_ID" ]; then
echo "β Error: No job_id found in response"
echo "π Response content:"
cat "$TEMP_FILE"
rm -f "$TEMP_FILE"
exit 1
fi
echo "β
Job created successfully!"
echo "π Job ID: $JOB_ID"
# Start polling job status
STATUS_URL="https://server.codeboarding.org/github_action/jobs/$JOB_ID"
echo "π Starting job status polling..."
echo "β° This may take 15-45 minutes for large repositories..."
echo "π‘ If your workflow times out, increase 'timeout-minutes' in your job configuration"
# Polling loop
POLL_COUNT=0
MAX_POLLS=90 # 90 minutes max (90 * 1 minute intervals)
while [ $POLL_COUNT -lt $MAX_POLLS ]; do
POLL_COUNT=$((POLL_COUNT + 1))
echo "π Polling attempt $POLL_COUNT of $MAX_POLLS ($(date '+%H:%M:%S'))"
# Make status check API call
response=$(curl -s -w "%{http_code}" -o "$TEMP_FILE" \
--max-time 30 \
--connect-timeout 10 \
"$STATUS_URL")
curl_exit_code=$?
http_code=${response: -3}
# Handle curl errors
if [ $curl_exit_code -ne 0 ]; then
echo "β οΈ Warning: Status check failed with curl exit code $curl_exit_code"
echo "π Retrying in 30 seconds..."
sleep 30
continue
fi
if [ "$http_code" != "200" ]; then
echo "β οΈ Warning: Status check failed with HTTP code $http_code"
echo "π Response content:"
cat "$TEMP_FILE"
echo "π Retrying in 30 seconds..."
sleep 30
continue
fi
# Check if response is valid JSON
if ! jq empty "$TEMP_FILE" 2>/dev/null; then
echo "β οΈ Warning: Invalid JSON response"
echo "π Response content:"
cat "$TEMP_FILE"
echo "π Retrying in 30 seconds..."
sleep 30
continue
fi
# Extract status from response
STATUS=$(jq -r '.status' "$TEMP_FILE")
echo "π Current job status: $STATUS"
if [ "$STATUS" = "COMPLETED" ]; then
echo "β
Job completed successfully!"
# Check if result field exists and contains files
if jq -e '.result' "$TEMP_FILE" > /dev/null; then
echo "π¦ Result field found, preparing output..."
# Check if result is a JSON string or already a JSON object
RESULT_TYPE=$(jq -r '.result | type' "$TEMP_FILE")
if [ "$RESULT_TYPE" = "string" ]; then
echo "π§ Result is a JSON string, parsing it..."
# Parse the JSON string in the result field
jq -r '.result' "$TEMP_FILE" | jq '.' > "${TEMP_FILE}_result"
else
echo "π§ Result is already a JSON object, extracting it..."
# Extract the result object directly
jq '.result' "$TEMP_FILE" > "${TEMP_FILE}_result"
fi
# Verify the extracted result
if jq -e '.files' "${TEMP_FILE}_result" > /dev/null; then
echo "β
Files extracted successfully"
mv "${TEMP_FILE}_result" "$TEMP_FILE"
echo "response_file=$TEMP_FILE" >> $GITHUB_OUTPUT
exit 0 # Successfully extracted files, exit with success
else
echo "β Error: Extracted result is missing files structure"
echo "π Extracted content:"
cat "${TEMP_FILE}_result"
rm -f "${TEMP_FILE}_result" "$TEMP_FILE"
exit 1
fi
else
echo "β Error: Job completed but no result or result.files found in response"
echo "π Response structure:"
jq '.' "$TEMP_FILE"
# If result exists, show what it contains
if jq -e '.result' "$TEMP_FILE" > /dev/null; then
echo "π Result field content:"
RESULT_TYPE=$(jq -r '.result | type' "$TEMP_FILE")
echo "Result type: $RESULT_TYPE"
if [ "$RESULT_TYPE" = "string" ]; then
echo "Result string content:"
jq -r '.result' "$TEMP_FILE"
else
echo "Result object content:"
jq '.result' "$TEMP_FILE"
fi
fi
rm -f "$TEMP_FILE"
exit 1
fi
elif [ "$STATUS" = "FAILED" ] || [ "$STATUS" = "ERROR" ]; then
echo "β Job failed with status: $STATUS"
echo "π Response content:"
cat "$TEMP_FILE"
rm -f "$TEMP_FILE"
exit 1
else
# Job still in progress
echo "β³ Job in progress (status: $STATUS)..."
# Show additional progress information if available
if jq -e '.updated_at' "$TEMP_FILE" > /dev/null; then
UPDATED_AT=$(jq -r '.updated_at' "$TEMP_FILE")
echo "π Last updated: $UPDATED_AT"
fi
echo "π€ Waiting 15 seconds before next check..."
sleep 15
fi
done
# Only reach here if we've exceeded max polls without completion
echo "β Error: Job polling timed out after $MAX_POLLS attempts"
echo "ποΈ The repository analysis is taking longer than expected."
echo "π This might be due to:"
echo " β’ Very large repository size (>10k files)"
echo " β’ Complex codebase requiring extensive analysis"
echo " β’ Server load or processing delays"
echo ""
echo "π‘ Suggestions:"
echo " β’ Try again later when server load might be lower"
echo " β’ Consider analyzing smaller branches or specific directories"
echo " β’ Increase your GitHub Actions job timeout-minutes to 120+"
echo " β’ Contact support if the issue persists"
rm -f "$TEMP_FILE"
exit 1
- name: Process documentation files
id: process-docs
shell: bash
run: |
RESPONSE_FILE="${{ steps.fetch-docs.outputs.response_file }}"
MD_OUTPUT_DIR="${{ inputs.output_directory }}"
JSON_OUTPUT_DIR=".codeboarding"
OUTPUT_FORMAT="${{ inputs.output_format }}"
# Validate output format
if [[ "$OUTPUT_FORMAT" != ".md" && "$OUTPUT_FORMAT" != ".mdx" && "$OUTPUT_FORMAT" != ".rst" && "$OUTPUT_FORMAT" != ".html" ]]; then
echo "Error: Invalid output format '$OUTPUT_FORMAT'. Must be either '.md', '.mdx', '.rst', or '.html'"
exit 1
fi
# Clean and create the output directories
mkdir -p "$MD_OUTPUT_DIR"
# Remove existing .codeboarding files before adding new ones
if [ -d "$JSON_OUTPUT_DIR" ]; then
echo "Cleaning existing JSON files from $JSON_OUTPUT_DIR"
rm -rf "$JSON_OUTPUT_DIR"
fi
mkdir -p "$JSON_OUTPUT_DIR"
# Initialize counters
MARKDOWN_FILES_CREATED=0
JSON_FILES_CREATED=0
echo "=== Processing Documentation Files ==="
echo "Response JSON structure:"
jq . "$RESPONSE_FILE"
echo "Using output format: $OUTPUT_FORMAT"
# Parse JSON response and create files using keys as filenames
if jq -e '.files' "$RESPONSE_FILE" > /dev/null; then
echo "Files key found, proceeding to create files..."
# Check if files object is empty
FILES_COUNT=$(jq '.files | length' "$RESPONSE_FILE")
if [ "$FILES_COUNT" -eq 0 ]; then
echo "βΉοΈ No documentation files were generated for this repository/branch combination."
echo "π This might be because:"
echo " β’ No changes were detected between the source and target branches"
echo " β’ The repository or branches don't exist or are not accessible"
echo " β’ No analyzable code files were found"
echo " β’ The branches are identical (no diff to analyze)"
else
# Get each key from files object and create a file with that name
while IFS= read -r filename; do
echo "Processing file: $filename"
# Get the content for this filename
content=$(jq -r ".files[\"$filename\"]" "$RESPONSE_FILE")
# Determine file type and destination
if [[ "$filename" == *.json ]]; then
# JSON file
output_dir="$JSON_OUTPUT_DIR"
output_filename="$filename"
echo "$content" > "$output_dir/$output_filename"
echo "Created JSON file: $output_dir/$output_filename"
JSON_FILES_CREATED=$((JSON_FILES_CREATED + 1))
else
# Documentation file - add appropriate extension if not present
output_dir="$MD_OUTPUT_DIR"
# Check if filename has an extension
if [[ "$filename" == *.* ]]; then
# Extract basename without extension
basename="${filename%.*}"
else
basename="$filename"
fi
# Add the selected output format extension
output_filename="${basename}${OUTPUT_FORMAT}"
echo "$content" > "$output_dir/$output_filename"
echo "Created documentation file: $output_dir/$output_filename"
MARKDOWN_FILES_CREATED=$((MARKDOWN_FILES_CREATED + 1))
fi
done < <(jq -r '.files | keys[]' "$RESPONSE_FILE")
fi
else
echo "No 'files' key found in response JSON - checking if job completed with no results"
fi
# Clean up temporary file
rm -f "$RESPONSE_FILE"
# Check if any files were created
TOTAL_FILES=$((MARKDOWN_FILES_CREATED + JSON_FILES_CREATED))
if [ "$TOTAL_FILES" -gt 0 ]; then
HAS_CHANGES="true"
echo "Created $MARKDOWN_FILES_CREATED Markdown files in $MD_OUTPUT_DIR"
echo "Created $JSON_FILES_CREATED JSON files in $JSON_OUTPUT_DIR"
# List created files
if [ "$MARKDOWN_FILES_CREATED" -gt 0 ]; then
echo "Markdown files created:"
ls -la "$MD_OUTPUT_DIR"
fi
if [ "$JSON_FILES_CREATED" -gt 0 ]; then
echo "JSON files created:"
ls -la "$JSON_OUTPUT_DIR"
fi
else
HAS_CHANGES="false"
echo "No files were created"
fi
# Set outputs
echo "markdown_files_created=$MARKDOWN_FILES_CREATED" >> $GITHUB_OUTPUT
echo "json_files_created=$JSON_FILES_CREATED" >> $GITHUB_OUTPUT
echo "output_directory=$MD_OUTPUT_DIR" >> $GITHUB_OUTPUT
echo "json_directory=$JSON_OUTPUT_DIR" >> $GITHUB_OUTPUT
echo "has_changes=$HAS_CHANGES" >> $GITHUB_OUTPUT