144 lines
4.6 KiB
YAML
144 lines
4.6 KiB
YAML
# Ultralytics 🚀 AGPL-3.0 License - https://ultralytics.com/license
|
|
|
|
# Example usage:
|
|
#
|
|
# Basic usage (will retry failed step 3 times):
|
|
# steps:
|
|
# - uses: ultralytics/actions/retry@main
|
|
# with:
|
|
# run: python train.py
|
|
#
|
|
# Advanced usage:
|
|
# steps:
|
|
# - uses: ultralytics/actions/retry@main
|
|
# with:
|
|
# run: |
|
|
# python setup.py install
|
|
# pytest tests/
|
|
# retries: 2 # Retry twice after initial attempt (3 total runs)
|
|
# timeout_minutes: 30 # Total timeout for all attempts combined
|
|
# retry_delay_seconds: 60 # Wait 60 seconds between retries
|
|
# shell: bash # Use python or bash shell
|
|
|
|
name: "Step-Level Retry"
|
|
description: "Retries a step while preserving its full context"
|
|
inputs:
|
|
timeout_minutes:
|
|
description: "Maximum total time in minutes for all attempts"
|
|
required: false
|
|
default: "360"
|
|
retries:
|
|
description: "Number of retry attempts after initial run"
|
|
required: false
|
|
default: "3"
|
|
retry_delay_seconds:
|
|
description: "Delay between retries in seconds"
|
|
required: false
|
|
default: "30"
|
|
run:
|
|
description: "Command to run"
|
|
required: true
|
|
shell:
|
|
description: "Shell to use (bash or python)"
|
|
required: false
|
|
default: "bash"
|
|
|
|
runs:
|
|
using: "composite"
|
|
steps:
|
|
- name: Execute with retry
|
|
shell: bash
|
|
env:
|
|
# Note: Workflow env vars are automatically inherited. Only RETRY_COMMANDS is added here.
|
|
RETRY_COMMANDS: ${{ inputs.run }}
|
|
run: |
|
|
set +e # Don't exit on error - we handle errors manually
|
|
|
|
start_time=$(date +%s)
|
|
timeout_seconds=$(( ${{ inputs.timeout_minutes }} * 60 ))
|
|
attempt=1
|
|
max_attempts=$(( 1 + ${{ inputs.retries }} )) # Initial run + retries
|
|
retries=${{ inputs.retries }}
|
|
retry_delay=${{ inputs.retry_delay_seconds }}
|
|
timeout_mins=${{ inputs.timeout_minutes }}
|
|
shell_type="${{ inputs.shell }}"
|
|
exit_code=0
|
|
|
|
# Create temporary script file with appropriate extension
|
|
if [ "$shell_type" = "python" ]; then
|
|
if ! TEMP_SCRIPT=$(mktemp --suffix=.py 2>/dev/null); then
|
|
# Fallback: create temp file then rename it
|
|
if ! TEMP_SCRIPT=$(mktemp 2>/dev/null); then
|
|
echo "::error::Failed to create temporary file"
|
|
exit 1
|
|
fi
|
|
if ! mv "$TEMP_SCRIPT" "${TEMP_SCRIPT}.py"; then
|
|
rm -f "$TEMP_SCRIPT"
|
|
echo "::error::Failed to rename temporary file"
|
|
exit 1
|
|
fi
|
|
TEMP_SCRIPT="${TEMP_SCRIPT}.py"
|
|
fi
|
|
else
|
|
if ! TEMP_SCRIPT=$(mktemp 2>/dev/null); then
|
|
echo "::error::Failed to create temporary file"
|
|
exit 1
|
|
fi
|
|
fi
|
|
|
|
# Ensure cleanup on exit
|
|
trap 'rm -f "$TEMP_SCRIPT"' EXIT
|
|
|
|
# Write the user's commands to the temp script
|
|
printf '%s\n' "$RETRY_COMMANDS" > "$TEMP_SCRIPT"
|
|
|
|
# Validate script was written
|
|
if [ ! -s "$TEMP_SCRIPT" ]; then
|
|
echo "::error::No commands provided to execute"
|
|
exit 1
|
|
fi
|
|
|
|
while [ "$attempt" -le "$max_attempts" ]; do
|
|
if [ "$attempt" -gt 1 ]; then
|
|
echo "::group::Retry $((attempt - 1)) of $retries"
|
|
fi
|
|
|
|
current_time=$(date +%s)
|
|
elapsed=$((current_time - start_time))
|
|
if [ "$elapsed" -gt "$timeout_seconds" ]; then
|
|
echo "::error::Step timed out after $timeout_mins minutes"
|
|
[ "$attempt" -gt 1 ] && echo "::endgroup::"
|
|
exit 1
|
|
fi
|
|
|
|
# Execute the script with appropriate interpreter
|
|
if [ "$shell_type" = "python" ]; then
|
|
python3 "$TEMP_SCRIPT"
|
|
else
|
|
bash -e "$TEMP_SCRIPT"
|
|
fi
|
|
exit_code=$?
|
|
|
|
if [ "$exit_code" -eq 0 ]; then
|
|
[ "$attempt" -gt 1 ] && echo "::endgroup::"
|
|
exit 0
|
|
fi
|
|
|
|
# Handle failure
|
|
if [ "$attempt" -gt 1 ]; then
|
|
echo "Retry $((attempt - 1)) failed with exit code $exit_code"
|
|
echo "::endgroup::"
|
|
else
|
|
echo "Initial attempt failed with exit code $exit_code"
|
|
fi
|
|
|
|
if [ "$attempt" -eq "$max_attempts" ]; then
|
|
echo "::error::Step failed after initial attempt and $((attempt - 1)) retries"
|
|
exit "$exit_code"
|
|
fi
|
|
|
|
echo "Retrying in $retry_delay seconds..."
|
|
sleep "$retry_delay"
|
|
attempt=$((attempt + 1))
|
|
done
|