Skip to content

Commit 76f016c

Browse files
authored
feat(x2a): Error handling - error from python log (#2585)
* Error handling - error from python log * Simplify reporting by reading from file * applied review * changeset
1 parent de2a283 commit 76f016c

2 files changed

Lines changed: 48 additions & 24 deletions

File tree

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
'@red-hat-developer-hub/backstage-plugin-x2a-backend': patch
3+
---
4+
5+
Improve error propagation in job script: consolidate error handling into run_x2a function with default message and appended error details, add command logging, and refactor publish-aap to use the shared error handler.

workspaces/x2a/plugins/x2a-backend/templates/x2a-job-script.sh

Lines changed: 43 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,9 @@ PUSH_FAILED=""
1111
TERMINATED=false
1212
COMMIT_ID=""
1313

14+
# Path where x2a-convertor writes error details on failure
15+
export X2A_ERROR_FILE="/tmp/x2a-error.txt"
16+
1417
# Report job result back to the backend.
1518
report_result() {
1619
local status="$1"
@@ -74,6 +77,38 @@ sanitize_secrets() {
7477
fi
7578
}
7679

80+
# Run an x2a tool command with error reporting.
81+
# On failure, reads the error details file written by x2a-convertor and sets ERROR_MESSAGE.
82+
# On success, clears ERROR_MESSAGE.
83+
# Captured output is stored in X2A_OUTPUT for callers that need to parse it.
84+
# Usage: run_x2a uv run app.py <phase> [args...]
85+
run_x2a() {
86+
rm -f "${X2A_ERROR_FILE}"
87+
88+
echo "Command: $*"
89+
90+
local tmpfile
91+
tmpfile=$(mktemp)
92+
93+
set +e
94+
"$@" 2>&1 | tee "${tmpfile}"
95+
local rc=${PIPESTATUS[0]}
96+
set -e
97+
98+
X2A_OUTPUT=$(cat "${tmpfile}")
99+
rm -f "${tmpfile}"
100+
101+
if [ ${rc} -ne 0 ]; then
102+
ERROR_MESSAGE="Unexpected error during ${PHASE} phase. See the job log for details."
103+
if [ -f "${X2A_ERROR_FILE}" ]; then
104+
ERROR_MESSAGE+=" Message: $(cat "${X2A_ERROR_FILE}")"
105+
fi
106+
exit ${rc}
107+
fi
108+
109+
ERROR_MESSAGE=""
110+
}
111+
77112
# Cleanup trap: fires on every exit (success or failure).
78113
# Guarantees exactly one report_result call regardless of how the script ends.
79114
cleanup() {
@@ -232,10 +267,7 @@ case "${PHASE}" in
232267
# Usage: app.py init [OPTIONS] USER_REQUIREMENTS
233268
# --source-dir DIRECTORY Source directory to analyze
234269
USER_REQ="${USER_PROMPT:-Analyze the Chef cookbooks and create a migration plan}"
235-
echo "Command: uv run app.py init --source-dir ${SOURCE_BASE} \"${USER_REQ}\""
236-
ERROR_MESSAGE="Unexpected error during init phase. See the job log for details."
237-
uv run app.py init --source-dir "${SOURCE_BASE}" "${USER_REQ}"
238-
ERROR_MESSAGE=""
270+
run_x2a uv run app.py init --source-dir "${SOURCE_BASE}" "${USER_REQ}"
239271

240272
# Copy output to target location
241273
# Note: x2a tool writes files to the source directory (--source-dir)
@@ -296,10 +328,7 @@ case "${PHASE}" in
296328
echo "Working directory: $(pwd)"
297329

298330
USER_REQ="${USER_PROMPT:-Analyze the module '${MODULE_NAME}' for migration to Ansible}"
299-
echo "Command: uv run app.py analyze --source-dir ${SOURCE_BASE} \"${USER_REQ}\""
300-
ERROR_MESSAGE="Unexpected error during analyze phase. See the job log for details."
301-
uv run app.py analyze --source-dir "${SOURCE_BASE}" "${USER_REQ}"
302-
ERROR_MESSAGE=""
331+
run_x2a uv run app.py analyze --source-dir "${SOURCE_BASE}" "${USER_REQ}"
303332

304333
# Copy output to target location
305334
# Note: x2a tool produces migration-plan-{module_name}.md (spaces replaced with underscores)
@@ -365,15 +394,12 @@ case "${PHASE}" in
365394
echo "Working directory: $(pwd)"
366395

367396
USER_REQ="${USER_PROMPT:-Migrate this module to Ansible}"
368-
echo "Command: uv run app.py migrate --source-dir ${SOURCE_BASE} --source-technology Chef --high-level-migration-plan ${PROJECT_PATH}/migration-plan.md --module-migration-plan ${OUTPUT_DIR}/migration-plan-${MODULE_NAME_SANITIZED}.md \"${USER_REQ}\""
369-
ERROR_MESSAGE="Unexpected error during migrate phase. See the job log for details."
370-
uv run app.py migrate \
397+
run_x2a uv run app.py migrate \
371398
--source-dir "${SOURCE_BASE}" \
372399
--source-technology Chef \
373400
--high-level-migration-plan "${PROJECT_PATH}/migration-plan.md" \
374401
--module-migration-plan "${OUTPUT_DIR}/migration-plan-${MODULE_NAME_SANITIZED}.md" \
375402
"${USER_REQ}"
376-
ERROR_MESSAGE=""
377403

378404
# Copy output to target location
379405
# Note: x2a tool writes to ansible/roles/{module}/ in the source directory
@@ -414,15 +440,11 @@ case "${PHASE}" in
414440

415441
# Step 1: publish-project — assemble Ansible project from migrated role
416442
echo "=== Step 1: Assembling Ansible project ==="
417-
echo "Command: uv run app.py publish-project ${PROJECT_DIR} ${MODULE_NAME}"
418-
419443
# publish-project reads from {project_id}/modules/{module_name}/ansible/roles/{module_name}/
420444
# and writes to {project_id}/ansible-project/
421445
# It operates relative to CWD, so we run from TARGET_BASE
422446
pushd "${TARGET_BASE}"
423-
ERROR_MESSAGE="Unexpected error during publish phase (publish-project). See the job log for details."
424-
uv run --project /app /app/app.py publish-project "${PROJECT_DIR}" "${MODULE_NAME}"
425-
ERROR_MESSAGE=""
447+
run_x2a uv run --project /app /app/app.py publish-project "${PROJECT_DIR}" "${MODULE_NAME}"
426448
popd
427449

428450
# Verify ansible-project was created
@@ -439,17 +461,14 @@ case "${PHASE}" in
439461
# Step 2: publish-aap — register with AAP and sync
440462
echo ""
441463
echo "=== Step 2: Publishing to AAP ==="
442-
echo "Command: uv run app.py publish-aap --target-repo ${TARGET_REPO_URL} --target-branch ${TARGET_REPO_BRANCH} --project-id ${PROJECT_DIR}"
443464
cd /app
444-
ERROR_MESSAGE="Unexpected error during publish phase (publish-aap). See the job log for details."
445-
PUBLISH_OUTPUT=$(uv run app.py publish-aap \
465+
run_x2a uv run app.py publish-aap \
446466
--target-repo "${TARGET_REPO_URL}" \
447467
--target-branch "${TARGET_REPO_BRANCH}" \
448-
--project-id "${PROJECT_DIR}" 2>&1 | tee /dev/stderr)
449-
ERROR_MESSAGE=""
468+
--project-id "${PROJECT_DIR}"
450469

451-
# Parse AAP project ID from output and construct URL
452-
AAP_PROJECT_ID=$(echo "${PUBLISH_OUTPUT}" | grep -oP 'ID: \K[0-9]+' | tail -1)
470+
# Parse AAP project ID from captured output
471+
AAP_PROJECT_ID=$(echo "${X2A_OUTPUT}" | grep -oP 'ID: \K[0-9]+' | tail -1)
453472
if [ -n "${AAP_PROJECT_ID}" ]; then
454473
ARTIFACTS+=("ansible_project:${AAP_CONTROLLER_URL}/execution/projects/${AAP_PROJECT_ID}/details")
455474
else

0 commit comments

Comments
 (0)