diff --git a/.gemini/skills/async-pr-review/scripts/async-review.sh b/.gemini/skills/async-pr-review/scripts/async-review.sh index d408c5f2f1..51a9037efb 100755 --- a/.gemini/skills/async-pr-review/scripts/async-review.sh +++ b/.gemini/skills/async-pr-review/scripts/async-review.sh @@ -1,190 +1,202 @@ #!/bin/bash notify() { - local title="$1" - local message="$2" - local pr="$3" + local title="${1}" + local message="${2}" + local pr="${3}" # Terminal escape sequence - printf "\e]9;%s | PR #%s | %s\a" "$title" "$pr" "$message" + printf "\e]9;%s | PR #%s | %s\a" "${title}" "${pr}" "${message}" # Native macOS notification - if [[ "$(uname)" == "Darwin" ]]; then - osascript -e "display notification \"$message\" with title \"$title\" subtitle \"PR #$pr\"" + OS_TYPE=$(uname) + if [[ "${OS_TYPE}" == "Darwin" ]]; then + osascript -e "display notification \"${message}\" with title \"${title}\" subtitle \"PR #${pr}\"" fi } -pr_number=$1 -if [[ -z "$pr_number" ]]; then +pr_number="${1}" +if [[ -z "${pr_number}" ]]; then echo "Usage: async-review " exit 1 fi base_dir=$(git rev-parse --show-toplevel 2>/dev/null) -if [[ -z "$base_dir" ]]; then +if [[ -z "${base_dir}" ]]; then echo "โŒ Must be run from within a git repository." exit 1 fi # Use the repository's local .gemini/tmp directory for ephemeral worktrees and logs -pr_dir="$base_dir/.gemini/tmp/async-reviews/pr-$pr_number" -target_dir="$pr_dir/worktree" -log_dir="$pr_dir/logs" +pr_dir="${base_dir}/.gemini/tmp/async-reviews/pr-${pr_number}" +target_dir="${pr_dir}/worktree" +log_dir="${pr_dir}/logs" -cd "$base_dir" || exit 1 +cd "${base_dir}" || exit 1 -mkdir -p "$log_dir" -rm -f "$log_dir/setup.exit" "$log_dir/final-assessment.exit" "$log_dir/final-assessment.md" +mkdir -p "${log_dir}" +rm -f "${log_dir}/setup.exit" "${log_dir}/final-assessment.exit" "${log_dir}/final-assessment.md" -echo "๐Ÿงน Cleaning up previous worktree if it exists..." | tee -a "$log_dir/setup.log" -git worktree remove -f "$target_dir" >> "$log_dir/setup.log" 2>&1 || true -git branch -D "gemini-async-pr-$pr_number" >> "$log_dir/setup.log" 2>&1 || true -git worktree prune >> "$log_dir/setup.log" 2>&1 || true +echo "๐Ÿงน Cleaning up previous worktree if it exists..." | tee -a "${log_dir}/setup.log" +git worktree remove -f "${target_dir}" >> "${log_dir}/setup.log" 2>&1 || true +git branch -D "gemini-async-pr-${pr_number}" >> "${log_dir}/setup.log" 2>&1 || true +git worktree prune >> "${log_dir}/setup.log" 2>&1 || true -echo "๐Ÿ“ก Fetching PR #$pr_number..." | tee -a "$log_dir/setup.log" -if ! git fetch origin -f "pull/$pr_number/head:gemini-async-pr-$pr_number" >> "$log_dir/setup.log" 2>&1; then - echo 1 > "$log_dir/setup.exit" - echo "โŒ Fetch failed. Check $log_dir/setup.log" - notify "Async Review Failed" "Fetch failed." "$pr_number" +echo "๐Ÿ“ก Fetching PR #${pr_number}..." | tee -a "${log_dir}/setup.log" +if ! git fetch origin -f "pull/${pr_number}/head:gemini-async-pr-${pr_number}" >> "${log_dir}/setup.log" 2>&1; then + echo 1 > "${log_dir}/setup.exit" + echo "โŒ Fetch failed. Check ${log_dir}/setup.log" + notify "Async Review Failed" "Fetch failed." "${pr_number}" exit 1 fi -if [[ ! -d "$target_dir" ]]; then - echo "๐Ÿงน Pruning missing worktrees..." | tee -a "$log_dir/setup.log" - git worktree prune >> "$log_dir/setup.log" 2>&1 - echo "๐ŸŒฟ Creating worktree in $target_dir..." | tee -a "$log_dir/setup.log" - if ! git worktree add "$target_dir" "gemini-async-pr-$pr_number" >> "$log_dir/setup.log" 2>&1; then - echo 1 > "$log_dir/setup.exit" - echo "โŒ Worktree creation failed. Check $log_dir/setup.log" - notify "Async Review Failed" "Worktree creation failed." "$pr_number" +if [[ ! -d "${target_dir}" ]]; then + echo "๐Ÿงน Pruning missing worktrees..." | tee -a "${log_dir}/setup.log" + git worktree prune >> "${log_dir}/setup.log" 2>&1 + echo "๐ŸŒฟ Creating worktree in ${target_dir}..." | tee -a "${log_dir}/setup.log" + if ! git worktree add "${target_dir}" "gemini-async-pr-${pr_number}" >> "${log_dir}/setup.log" 2>&1; then + echo 1 > "${log_dir}/setup.exit" + echo "โŒ Worktree creation failed. Check ${log_dir}/setup.log" + notify "Async Review Failed" "Worktree creation failed." "${pr_number}" exit 1 fi else - echo "๐ŸŒฟ Worktree already exists." | tee -a "$log_dir/setup.log" + echo "๐ŸŒฟ Worktree already exists." | tee -a "${log_dir}/setup.log" fi -echo 0 > "$log_dir/setup.exit" +echo 0 > "${log_dir}/setup.exit" -cd "$target_dir" || exit 1 +cd "${target_dir}" || exit 1 -echo "๐Ÿš€ Launching background tasks. Logs saving to: $log_dir" +echo "๐Ÿš€ Launching background tasks. Logs saving to: ${log_dir}" echo " โ†ณ [1/5] Grabbing PR diff..." -rm -f "$log_dir/pr-diff.exit" -{ gh pr diff "$pr_number" > "$log_dir/pr-diff.diff" 2>&1; echo $? > "$log_dir/pr-diff.exit"; } & +rm -f "${log_dir}/pr-diff.exit" +{ gh pr diff "${pr_number}" > "${log_dir}/pr-diff.diff" 2>&1; echo $? > "${log_dir}/pr-diff.exit"; } & echo " โ†ณ [2/5] Starting build and lint..." -rm -f "$log_dir/build-and-lint.exit" -{ { npm run clean && npm ci && npm run format && npm run build && npm run lint:ci && npm run typecheck; } > "$log_dir/build-and-lint.log" 2>&1; echo $? > "$log_dir/build-and-lint.exit"; } & +rm -f "${log_dir}/build-and-lint.exit" +{ { npm run clean && npm ci && npm run format && npm run build && npm run lint:ci && npm run typecheck; } > "${log_dir}/build-and-lint.log" 2>&1; echo $? > "${log_dir}/build-and-lint.exit"; } & # Dynamically resolve gemini binary (fallback to your nightly path) -GEMINI_CMD=$(which gemini || echo "$HOME/.gcli/nightly/node_modules/.bin/gemini") -POLICY_PATH="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)/policy.toml" +GEMINI_CMD=$(command -v gemini || echo "${HOME}/.gcli/nightly/node_modules/.bin/gemini") +BASH_SOURCE_DIR=$(dirname "${BASH_SOURCE[0]}") +POLICY_PATH="$(cd "${BASH_SOURCE_DIR}/.." && pwd)/policy.toml" echo " โ†ณ [3/5] Starting Gemini code review..." -rm -f "$log_dir/review.exit" -{ "$GEMINI_CMD" --policy "$POLICY_PATH" -p "/review-frontend $pr_number" > "$log_dir/review.md" 2>&1; echo $? > "$log_dir/review.exit"; } & +rm -f "${log_dir}/review.exit" +{ "${GEMINI_CMD}" --policy "${POLICY_PATH}" -p "/review-frontend ${pr_number}" > "${log_dir}/review.md" 2>&1; echo $? > "${log_dir}/review.exit"; } & echo " โ†ณ [4/5] Starting automated tests (waiting for build and lint)..." -rm -f "$log_dir/npm-test.exit" +rm -f "${log_dir}/npm-test.exit" { - while [ ! -f "$log_dir/build-and-lint.exit" ]; do sleep 1; done - if [ "$(cat "$log_dir/build-and-lint.exit")" == "0" ]; then - gh pr checks "$pr_number" > "$log_dir/ci-checks.log" 2>&1 + while [[ ! -f "${log_dir}/build-and-lint.exit" ]]; do sleep 1; done + BUILD_LINT_EXIT_VAL=$(cat "${log_dir}/build-and-lint.exit") + if [[ "${BUILD_LINT_EXIT_VAL}" == "0" ]]; then + gh pr checks "${pr_number}" > "${log_dir}/ci-checks.log" 2>&1 ci_status=$? - if [ "$ci_status" -eq 0 ]; then - echo "CI checks passed. Skipping local npm tests." > "$log_dir/npm-test.log" - echo 0 > "$log_dir/npm-test.exit" - elif [ "$ci_status" -eq 8 ]; then - echo "CI checks are still pending. Skipping local npm tests to avoid duplicate work. Please check GitHub for final results." > "$log_dir/npm-test.log" - echo 0 > "$log_dir/npm-test.exit" + if [[ "${ci_status}" -eq 0 ]]; then + echo "CI checks passed. Skipping local npm tests." > "${log_dir}/npm-test.log" + echo 0 > "${log_dir}/npm-test.exit" + elif [[ "${ci_status}" -eq 8 ]]; then + echo "CI checks are still pending. Skipping local npm tests to avoid duplicate work. Please check GitHub for final results." > "${log_dir}/npm-test.log" + echo 0 > "${log_dir}/npm-test.exit" else - echo "CI checks failed. Failing checks:" > "$log_dir/npm-test.log" - gh pr checks "$pr_number" --json name,bucket -q '.[] | select(.bucket=="fail") | .name' >> "$log_dir/npm-test.log" 2>&1 + echo "CI checks failed. Failing checks:" > "${log_dir}/npm-test.log" + gh pr checks "${pr_number}" --json name,bucket -q '.[] | select(.bucket=="fail") | .name' >> "${log_dir}/npm-test.log" 2>&1 - echo "Attempting to extract failing test files from CI logs..." >> "$log_dir/npm-test.log" - pr_branch=$(gh pr view "$pr_number" --json headRefName -q '.headRefName' 2>/dev/null) - run_id=$(gh run list --branch "$pr_branch" --workflow ci.yml --json databaseId -q '.[0].databaseId' 2>/dev/null) + echo "Attempting to extract failing test files from CI logs..." >> "${log_dir}/npm-test.log" + PR_VIEW_DATA=$(gh pr view "${pr_number}" --json headRefName 2>/dev/null) + pr_branch=$(echo "${PR_VIEW_DATA}" | sed -n 's/.*"headRefName":"\([^"]*\)".*/\1/p') + RUN_LIST_DATA=$(gh run list --branch "${pr_branch}" --workflow ci.yml --json databaseId 2>/dev/null) + run_id_list=$(echo "${RUN_LIST_DATA}" | sed -n 's/.*"databaseId":\([0-9]*\).*/\1/p') + read -r run_id <<< "${run_id_list}" failed_files="" - if [[ -n "$run_id" ]]; then - failed_files=$(gh run view "$run_id" --log-failed 2>/dev/null | grep -o -E '(packages/[a-zA-Z0-9_-]+|integration-tests|evals)/[a-zA-Z0-9_/-]+\.test\.ts(x)?' | sort | uniq) + if [[ -n "${run_id}" ]]; then + RUN_VIEW_OUTPUT=$(gh run view "${run_id}" --log-failed 2>/dev/null) + # Split the pipeline to avoid SC2312 + failed_files_raw=$(echo "${RUN_VIEW_OUTPUT}" | grep -o -E '(packages/[a-zA-Z0-9_-]+|integration-tests|evals)/[a-zA-Z0-9_/-]+\.test\.ts(x)?') + failed_files_sorted=$(echo "${failed_files_raw}" | sort) + failed_files=$(echo "${failed_files_sorted}" | uniq) fi - if [[ -n "$failed_files" ]]; then - echo "Found failing test files from CI:" >> "$log_dir/npm-test.log" - for f in $failed_files; do echo " - $f" >> "$log_dir/npm-test.log"; done - echo "Running ONLY failing tests locally..." >> "$log_dir/npm-test.log" + if [[ -n "${failed_files}" ]]; then + echo "Found failing test files from CI:" >> "${log_dir}/npm-test.log" + for f in ${failed_files}; do echo " - ${f}" >> "${log_dir}/npm-test.log"; done + echo "Running ONLY failing tests locally..." >> "${log_dir}/npm-test.log" exit_code=0 - for file in $failed_files; do - if [[ "$file" == packages/* ]]; then - ws_dir=$(echo "$file" | cut -d'/' -f1,2) + for file in ${failed_files}; do + if [[ "${file}" == packages/* ]]; then + ws_dir=$(echo "${file}" | cut -d'/' -f1,2) else - ws_dir=$(echo "$file" | cut -d'/' -f1) + ws_dir=$(echo "${file}" | cut -d'/' -f1) fi - rel_file=${file#$ws_dir/} + rel_file=${file#"${ws_dir}/"} - echo "--- Running $rel_file in workspace $ws_dir ---" >> "$log_dir/npm-test.log" - if ! npm run test:ci -w "$ws_dir" -- "$rel_file" >> "$log_dir/npm-test.log" 2>&1; then + echo "--- Running ${rel_file} in workspace ${ws_dir} ---" >> "${log_dir}/npm-test.log" + if ! npm run test:ci -w "${ws_dir}" -- "${rel_file}" >> "${log_dir}/npm-test.log" 2>&1; then exit_code=1 fi done - echo $exit_code > "$log_dir/npm-test.exit" + echo "${exit_code}" > "${log_dir}/npm-test.exit" else - echo "Could not extract specific failing files. Skipping full local test suite as it takes too long. Please check CI logs manually." >> "$log_dir/npm-test.log" - echo 1 > "$log_dir/npm-test.exit" + echo "Could not extract specific failing files. Skipping full local test suite as it takes too long. Please check CI logs manually." >> "${log_dir}/npm-test.log" + echo 1 > "${log_dir}/npm-test.exit" fi fi else - echo "Skipped due to build-and-lint failure" > "$log_dir/npm-test.log" - echo 1 > "$log_dir/npm-test.exit" + echo "Skipped due to build-and-lint failure" > "${log_dir}/npm-test.log" + echo 1 > "${log_dir}/npm-test.exit" fi } & echo " โ†ณ [5/5] Starting Gemini test execution (waiting for build and lint)..." -rm -f "$log_dir/test-execution.exit" +rm -f "${log_dir}/test-execution.exit" { - while [ ! -f "$log_dir/build-and-lint.exit" ]; do sleep 1; done - if [ "$(cat "$log_dir/build-and-lint.exit")" == "0" ]; then - "$GEMINI_CMD" --policy "$POLICY_PATH" -p "Analyze the diff for PR $pr_number using 'gh pr diff $pr_number'. Instead of running the project's automated test suite (like 'npm test'), physically exercise the newly changed code in the terminal (e.g., by writing a temporary script to call the new functions, or testing the CLI command directly). Verify the feature's behavior works as expected. IMPORTANT: Do NOT modify any source code to fix errors. Just exercise the code and log the results, reporting any failures clearly. Do not ask for user confirmation." > "$log_dir/test-execution.log" 2>&1; echo $? > "$log_dir/test-execution.exit" + while [[ ! -f "${log_dir}/build-and-lint.exit" ]]; do sleep 1; done + BUILD_LINT_EXIT_CHECK=$(cat "${log_dir}/build-and-lint.exit") + if [[ "${BUILD_LINT_EXIT_CHECK}" == "0" ]]; then + "${GEMINI_CMD}" --policy "${POLICY_PATH}" -p "Analyze the diff for PR ${pr_number} using 'gh pr diff ${pr_number}'. Instead of running the project's automated test suite (like 'npm test'), physically exercise the newly changed code in the terminal (e.g., by writing a temporary script to call the new functions, or testing the CLI command directly). Verify the feature's behavior works as expected. IMPORTANT: Do NOT modify any source code to fix errors. Just exercise the code and log the results, reporting any failures clearly. Do not ask for user confirmation." > "${log_dir}/test-execution.log" 2>&1; echo $? > "${log_dir}/test-execution.exit" else - echo "Skipped due to build-and-lint failure" > "$log_dir/test-execution.log" - echo 1 > "$log_dir/test-execution.exit" + echo "Skipped due to build-and-lint failure" > "${log_dir}/test-execution.log" + echo 1 > "${log_dir}/test-execution.exit" fi } & echo "โœ… All tasks dispatched!" -echo "You can monitor progress with: tail -f $log_dir/*.log" -echo "Read your review later at: $log_dir/review.md" +echo "You can monitor progress with: tail -f ${log_dir}/*.log" +echo "Read your review later at: ${log_dir}/review.md" # Polling loop to wait for all background tasks to finish -tasks=("pr-diff" "build-and-lint" "review" "npm-test" "test-execution") -log_files=("pr-diff.diff" "build-and-lint.log" "review.md" "npm-test.log" "test-execution.log") +declare -a ASYNC_TASKS=("pr-diff" "build-and-lint" "review" "npm-test" "test-execution") +declare -a ASYNC_LOGS=("pr-diff.diff" "build-and-lint.log" "review.md" "npm-test.log" "test-execution.log") declare -A task_done -for t in "${tasks[@]}"; do task_done[$t]=0; done +for t in "${ASYNC_TASKS[@]}"; do task_done["${t}"]=0; done all_done=0 -while [[ $all_done -eq 0 ]]; do +while [[ "${all_done}" -eq 0 ]]; do clear echo "==================================================" - echo "๐Ÿš€ Async PR Review Status for PR #$pr_number" + echo "๐Ÿš€ Async PR Review Status for PR #${pr_number}" echo "==================================================" echo "" all_done=1 - for i in "${!tasks[@]}"; do - t="${tasks[$i]}" + for i in "${!ASYNC_TASKS[@]}"; do + t="${ASYNC_TASKS[${i}]}" - if [[ -f "$log_dir/$t.exit" ]]; then - exit_code=$(cat "$log_dir/$t.exit") - if [[ "$exit_code" == "0" ]]; then - echo " โœ… $t: SUCCESS" + EXIT_FILE_POLL="${log_dir}/${t}.exit" + if [[ -f "${EXIT_FILE_POLL}" ]]; then + EXIT_CODE_POLL=$(cat "${EXIT_FILE_POLL}") + if [[ "${EXIT_CODE_POLL}" == "0" ]]; then + echo " โœ… ${t}: SUCCESS" else - echo " โŒ $t: FAILED (exit code $exit_code)" + echo " โŒ ${t}: FAILED (exit code ${EXIT_CODE_POLL})" fi - task_done[$t]=1 + task_done["${t}"]=1 else - echo " โณ $t: RUNNING" + echo " โณ ${t}: RUNNING" all_done=0 fi done @@ -194,48 +206,51 @@ while [[ $all_done -eq 0 ]]; do echo "๐Ÿ“ Live Logs (Last 5 lines of running tasks)" echo "==================================================" - for i in "${!tasks[@]}"; do - t="${tasks[$i]}" - log_file="${log_files[$i]}" + for i in "${!ASYNC_TASKS[@]}"; do + t="${ASYNC_TASKS[${i}]}" + log_file="${ASYNC_LOGS[${i}]}" - if [[ ${task_done[$t]} -eq 0 ]]; then - if [[ -f "$log_dir/$log_file" ]]; then + if [[ ${task_done["${t}"]} -eq 0 ]]; then + LOG_PATH_POLL="${log_dir}/${log_file}" + if [[ -f "${LOG_PATH_POLL}" ]]; then echo "" - echo "--- $t ---" - tail -n 5 "$log_dir/$log_file" + echo "--- ${t} ---" + tail -n 5 "${LOG_PATH_POLL}" fi fi done - if [[ $all_done -eq 0 ]]; then + if [[ "${all_done}" -eq 0 ]]; then sleep 3 fi done clear echo "==================================================" -echo "๐Ÿš€ Async PR Review Status for PR #$pr_number" +echo "๐Ÿš€ Async PR Review Status for PR #${pr_number}" echo "==================================================" echo "" -for t in "${tasks[@]}"; do - exit_code=$(cat "$log_dir/$t.exit") - if [[ "$exit_code" == "0" ]]; then - echo " โœ… $t: SUCCESS" +for t in "${ASYNC_TASKS[@]}"; do + EXIT_FILE_FINAL="${log_dir}/${t}.exit" + EXIT_CODE_FINAL=$(cat "${EXIT_FILE_FINAL}") + if [[ "${EXIT_CODE_FINAL}" == "0" ]]; then + echo " โœ… ${t}: SUCCESS" else - echo " โŒ $t: FAILED (exit code $exit_code)" + echo " โŒ ${t}: FAILED (exit code ${EXIT_CODE_FINAL})" fi done echo "" echo "โณ Tasks complete! Synthesizing final assessment..." -if ! "$GEMINI_CMD" --policy "$POLICY_PATH" -p "Read the review at $log_dir/review.md, the automated test logs at $log_dir/npm-test.log, and the manual test execution logs at $log_dir/test-execution.log. Summarize the results, state whether the build and tests passed based on $log_dir/build-and-lint.exit and $log_dir/npm-test.exit, and give a final recommendation for PR $pr_number." > "$log_dir/final-assessment.md" 2>&1; then - echo $? > "$log_dir/final-assessment.exit" +if ! "${GEMINI_CMD}" --policy "${POLICY_PATH}" -p "Read the review at ${log_dir}/review.md, the automated test logs at ${log_dir}/npm-test.log, and the manual test execution logs at ${log_dir}/test-execution.log. Summarize the results, state whether the build and tests passed based on ${log_dir}/build-and-lint.exit and ${log_dir}/npm-test.exit, and give a final recommendation for PR ${pr_number}." > "${log_dir}/final-assessment.md" 2>&1; then + EXIT_SYNTHESIS=$? + echo "${EXIT_SYNTHESIS}" > "${log_dir}/final-assessment.exit" echo "โŒ Final assessment synthesis failed!" - echo "Check $log_dir/final-assessment.md for details." - notify "Async Review Failed" "Final assessment synthesis failed." "$pr_number" + echo "Check ${log_dir}/final-assessment.md for details." + notify "Async Review Failed" "Final assessment synthesis failed." "${pr_number}" exit 1 fi -echo 0 > "$log_dir/final-assessment.exit" -echo "โœ… Final assessment complete! Check $log_dir/final-assessment.md" -notify "Async Review Complete" "Review and test execution finished successfully." "$pr_number" +echo 0 > "${log_dir}/final-assessment.exit" +echo "โœ… Final assessment complete! Check ${log_dir}/final-assessment.md" +notify "Async Review Complete" "Review and test execution finished successfully." "${pr_number}" diff --git a/.gemini/skills/async-pr-review/scripts/check-async-review.sh b/.gemini/skills/async-pr-review/scripts/check-async-review.sh index fbb58c2b72..fca7706adf 100755 --- a/.gemini/skills/async-pr-review/scripts/check-async-review.sh +++ b/.gemini/skills/async-pr-review/scripts/check-async-review.sh @@ -1,22 +1,22 @@ #!/bin/bash -pr_number=$1 +pr_number="${1}" -if [[ -z "$pr_number" ]]; then +if [[ -z "${pr_number}" ]]; then echo "Usage: check-async-review " exit 1 fi base_dir=$(git rev-parse --show-toplevel 2>/dev/null) -if [[ -z "$base_dir" ]]; then +if [[ -z "${base_dir}" ]]; then echo "โŒ Must be run from within a git repository." exit 1 fi -log_dir="$base_dir/.gemini/tmp/async-reviews/pr-$pr_number/logs" +log_dir="${base_dir}/.gemini/tmp/async-reviews/pr-${pr_number}/logs" -if [[ ! -d "$log_dir" ]]; then +if [[ ! -d "${log_dir}" ]]; then echo "STATUS: NOT_FOUND" - echo "โŒ No logs found for PR #$pr_number in $log_dir" + echo "โŒ No logs found for PR #${pr_number} in ${log_dir}" exit 0 fi @@ -34,32 +34,32 @@ all_done=true echo "STATUS: CHECKING" for task_info in "${tasks[@]}"; do - IFS="|" read -r task_name log_file <<< "$task_info" + IFS="|" read -r task_name log_file <<< "${task_info}" - file_path="$log_dir/$log_file" - exit_file="$log_dir/$task_name.exit" + file_path="${log_dir}/${log_file}" + exit_file="${log_dir}/${task_name}.exit" - if [[ -f "$exit_file" ]]; then - exit_code=$(cat "$exit_file") - if [[ "$exit_code" == "0" ]]; then - echo "โœ… $task_name: SUCCESS" + if [[ -f "${exit_file}" ]]; then + EXIT_CODE_VAL=$(cat "${exit_file}") + if [[ "${EXIT_CODE_VAL}" == "0" ]]; then + echo "โœ… ${task_name}: SUCCESS" else - echo "โŒ $task_name: FAILED (exit code $exit_code)" - echo " Last lines of $file_path:" - tail -n 3 "$file_path" | sed 's/^/ /' + echo "โŒ ${task_name}: FAILED (exit code ${EXIT_CODE_VAL})" + echo " Last lines of ${file_path}:" + tail -n 3 "${file_path}" | sed 's/^/ /' || true fi - elif [[ -f "$file_path" ]]; then - echo "โณ $task_name: RUNNING" + elif [[ -f "${file_path}" ]]; then + echo "โณ ${task_name}: RUNNING" all_done=false else - echo "โž– $task_name: NOT STARTED" + echo "โž– ${task_name}: NOT STARTED" all_done=false fi done -if $all_done; then +if [[ "${all_done}" == "true" ]]; then echo "STATUS: COMPLETE" - echo "LOG_DIR: $log_dir" + echo "LOG_DIR: ${log_dir}" else echo "STATUS: IN_PROGRESS" -fi \ No newline at end of file +fi