https://github.com/sgaunet/retry
simple and flexible command-line tool that retries a given command until it succeeds or a maximum number of attempts is reached. Ideal for automating workflows, handling flaky commands in CI/CD pipelines, and improving reliability in development and testing environments.
https://github.com/sgaunet/retry
automation binary ci cli command-line devops flaky-tests golang linux retry task-runner testing utility
Last synced: 2 months ago
JSON representation
simple and flexible command-line tool that retries a given command until it succeeds or a maximum number of attempts is reached. Ideal for automating workflows, handling flaky commands in CI/CD pipelines, and improving reliability in development and testing environments.
- Host: GitHub
- URL: https://github.com/sgaunet/retry
- Owner: sgaunet
- License: mit
- Created: 2023-11-09T20:10:22.000Z (over 2 years ago)
- Default Branch: main
- Last Pushed: 2026-03-31T19:22:49.000Z (3 months ago)
- Last Synced: 2026-03-31T21:28:31.523Z (3 months ago)
- Topics: automation, binary, ci, cli, command-line, devops, flaky-tests, golang, linux, retry, task-runner, testing, utility
- Language: Go
- Homepage:
- Size: 873 KB
- Stars: 1
- Watchers: 1
- Forks: 0
- Open Issues: 2
-
Metadata Files:
- Readme: README.md
- Funding: .github/FUNDING.yml
- License: LICENSE
Awesome Lists containing this project
README
[](https://goreportcard.com/report/github.com/sgaunet/retry)



[](https://github.com/sgaunet/retry/actions/workflows/linter.yml)
[](https://github.com/sgaunet/retry/actions/workflows/vulnerability-scan.yml)
[](https://github.com/sgaunet/retry/actions/workflows/coverage.yml)
[](https://github.com/sgaunet/retry/actions/workflows/snapshot.yml)
[](https://github.com/sgaunet/retry/actions/workflows/release.yml)
# retry
retry command will execute X times a failed command until it's successful. Supports both fixed delays and exponential backoff strategies. Useful for flaky tests, waiting for services to become available, or handling transient failures.
## Features
- **Fixed delay**: Traditional constant delay between retries
- **Exponential backoff**: Smart retry strategy that increases delays exponentially
- **Configurable**: Customize retry count, delays, multipliers, and maximum delays
- **Backward compatible**: Existing scripts continue to work unchanged
- **Environment variables**: Configure via environment variables
# Getting started
## Basic Usage
```bash
# Basic retry with default settings (3 attempts, fixed delay)
retry "flaky-command"
# Custom retry count and fixed delay
retry --max-tries 5 --delay 2s "curl https://api.example.com"
# Exponential backoff (recommended for network operations)
retry --backoff exponential --base-delay 1s --max-delay 30s "curl https://api.example.com"
```
## Exponential Backoff Examples
```bash
# Basic exponential backoff (1s, 2s, 4s, 8s, ...)
retry --backoff exponential "make test"
# Custom exponential backoff with shorter delays
retry --backoff exp --base-delay 100ms --multiplier 1.5 --max-delay 10s "flaky-service-check"
# Short form flags
retry -B exp -b 500ms -M 1m -t 10 "network-dependent-command"
```
## All Available Options
```
$ ./retry --help
Usage:
retry [flags] "command"
Flags:
-B, --backoff string backoff strategy (fixed, exponential) (default "fixed")
-b, --base-delay string base delay for exponential backoff (default "1s")
-d, --delay string delay between retries (e.g., 1s, 500ms, 2m) (default "0s")
-h, --help help for retry
-M, --max-delay string maximum delay for exponential backoff (default "5m")
-t, --max-tries uint maximum number of retry attempts (0 for infinite) (default 3)
--multiplier float multiplier for exponential backoff (default 2)
-v, --verbose enable verbose output
```
## Environment Variables
```bash
export RETRY_MAX_TRIES=5
export RETRY_BACKOFF=exponential
export RETRY_BASE_DELAY=500ms
export RETRY_MAX_DELAY=30s
retry "your-command"
```
Demo:

## Using as a Go Library
In addition to the CLI tool, you can use `retry` as a Go library in your own applications.
### Installation
```bash
go get github.com/sgaunet/retry
```
### Basic Usage
```go
import (
"context"
"time"
"github.com/sgaunet/retry/pkg/logger"
"github.com/sgaunet/retry/pkg/retry"
)
func main() {
// Create retry with max 5 attempts
r, _ := retry.NewRetry("your-command", retry.NewStopOnMaxTries(5))
// Add exponential backoff
r.SetBackoffStrategy(retry.NewExponentialBackoff(
time.Second, // base delay
time.Minute, // max delay
2.0, // multiplier
))
// Run with context and logger
appLogger := logger.NewLogger("info")
err := r.RunWithLogger(context.Background(), appLogger)
if err != nil {
// handle error
}
}
```
### Composite Conditions
Combine multiple stop conditions with AND/OR logic:
```go
// Stop after 10 tries OR after 5 minutes
condition := retry.NewCompositeCondition(
retry.LogicOR,
retry.NewStopOnMaxTries(10),
retry.NewStopOnTimeout(5 * time.Minute),
)
r, _ := retry.NewRetry("curl -sf https://api.example.com/health", condition)
```
### Success Conditions
Define custom success criteria beyond just exit code 0:
```go
r, _ := retry.NewRetry("curl https://api.example.com", retry.NewStopOnMaxTries(10))
// Consider successful if output contains "healthy"
successCond, _ := retry.NewSuccessContains("healthy")
r.SetSuccessConditions([]retry.ConditionRetryer{successCond})
```
### Available Backoff Strategies
- **Fixed**: Constant delay between retries
- **Exponential**: Delay doubles (or multiplies) each attempt
- **Linear**: Delay increases by a fixed increment
- **Fibonacci**: Delay follows the Fibonacci sequence
- **Jitter**: Wraps any strategy with randomness to avoid thundering herd
- **Custom**: User-defined delay sequence
### API Documentation
Full API documentation is available at: https://pkg.go.dev/github.com/sgaunet/retry/pkg/retry
See [examples/](examples/) for complete runnable examples.
## Real-World Examples
For comprehensive CLI usage examples, see the [examples/](examples/) directory:
- **CI/CD Integration**: [GitHub Actions](examples/ci-cd/github-actions.yml), [GitLab CI](examples/ci-cd/gitlab-ci.yml)
- **Docker & Containers**: [Health checks](examples/docker/healthcheck.sh), [Dockerfile](examples/docker/Dockerfile.example), [Compose](examples/docker/docker-compose.yml)
- **Databases**: [Migrations](examples/databases/migration-retry.sh), [Connection waiting](examples/databases/connection-wait.sh)
- **Networking**: [API health checks](examples/networking/api-endpoint-check.sh), [Downloads](examples/networking/download-with-retry.sh)
- **Kubernetes**: [Init containers](examples/kubernetes/init-container.yaml), [Jobs](examples/kubernetes/job-with-retry.yaml)
- **Testing**: [Flaky tests](examples/testing/flaky-tests.sh), [E2E tests](examples/testing/e2e-with-retry.sh)
- **Services**: [Startup waiting](examples/services/service-startup-wait.sh), [Dependencies](examples/services/dependency-check.sh)
# Install
## From binary
Download the binary in the release section.
## From Docker image
Docker registry is: ghcr.io/sgaunet/retry
The docker image is only interesting to copy the binary in your docker image.
# Development
This project is using :
* golang
* [task for development](https://taskfile.dev/#/)
* docker
* [docker buildx](https://github.com/docker/buildx)
* docker manifest
* [goreleaser](https://goreleaser.com/)
* [pre-commit](https://pre-commit.com/)
There are hooks executed in the precommit stage. Once the project cloned on your disk, please install pre-commit:
```
brew install pre-commit
```
Install tools:
```
task dev:install-prereq
```
And install the hooks:
```
task dev:install-pre-commit
```
If you like to launch manually the pre-commmit hook:
```
task dev:pre-commit
```