Conversation
Without it installation failed due to wrong dependency resolution.
Previous version was not available anymore. Fix by always using latest. Should probably use a pipeline to ensure project stays runnable in case API changes.
Since searxng uses rolling releases, and older versions are not available anymore, this workflow should ensure that the project is always runnable when using searxng:latest. The workflow runs on every pull request and every monday at 3:00 AM UTC.
There was a problem hiding this comment.
Pull request overview
This PR addresses critical runtime issues by fixing missing and conflicting Python dependencies, updating an unavailable Docker image, and adding CI/CD health checks to prevent future regressions. The changes fix the project which was broken due to marshmallow API incompatibility caused by missing Pipfile.lock.
Changes:
- Added missing Pipfile.lock to brain service Dockerfile to ensure consistent dependency resolution
- Updated searxng Docker image from unavailable pinned version to latest tag
- Added GitHub Actions workflow to validate Docker Compose build and health checks on PRs and weekly
Reviewed changes
Copilot reviewed 3 out of 3 changed files in this pull request and generated 6 comments.
| File | Description |
|---|---|
| brain/Dockerfile | Adds Pipfile.lock copy step to resolve marshmallow version conflicts |
| docker-compose.yml | Updates searxng image from unavailable 2023.12.11 version to latest tag |
| .github/workflows/healthcheck.yml | New CI/CD workflow for validating Docker Compose health on PRs and weekly schedule |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| retry-interval: 10 | ||
| compose-file: "docker-compose.yml" | ||
| skip-exited: "false" # unhealthy containers might exit and restart | ||
| skip-no-healthcheck: "true" |
There was a problem hiding this comment.
The worker service in docker-compose.yml does not have a healthcheck defined, but has 'skip-no-healthcheck' set to 'true' in the workflow. This means the workflow will skip health checking for the worker service. Consider adding a healthcheck to the worker service or documenting why it doesn't need one, to ensure comprehensive health validation.
| skip-no-healthcheck: "true" | |
| skip-no-healthcheck: "false" |
| healthcheck: | ||
| runs-on: ubuntu-latest | ||
| steps: | ||
| - uses: actions/checkout@v3 |
There was a problem hiding this comment.
Consider updating 'actions/checkout@v3' to 'actions/checkout@v4', which is the latest stable version. This ensures you're using the most up-to-date and secure version of the action.
| - uses: actions/checkout@v3 | |
| - uses: actions/checkout@v4 |
| uses: jaracogmbh/docker-compose-health-check-action@v1.0.0 | ||
| with: | ||
| max-retries: 12 | ||
| retry-interval: 10 | ||
| compose-file: "docker-compose.yml" | ||
| skip-exited: "false" # unhealthy containers might exit and restart | ||
| skip-no-healthcheck: "true" |
There was a problem hiding this comment.
Verify that the third-party action 'jaracogmbh/docker-compose-health-check-action@v1.0.0' is actively maintained and trustworthy. Consider using a commit SHA instead of a tag for better security, or evaluate if a simple bash script checking 'docker compose ps' output would be more maintainable and transparent.
| uses: jaracogmbh/docker-compose-health-check-action@v1.0.0 | |
| with: | |
| max-retries: 12 | |
| retry-interval: 10 | |
| compose-file: "docker-compose.yml" | |
| skip-exited: "false" # unhealthy containers might exit and restart | |
| skip-no-healthcheck: "true" | |
| run: | | |
| set -euo pipefail | |
| max_retries=12 | |
| retry_interval=10 | |
| compose_file="docker-compose.yml" | |
| skip_exited=false # unhealthy containers might exit and restart | |
| skip_no_healthcheck=true | |
| echo "Starting Docker Compose health check..." | |
| attempt=1 | |
| while [ "$attempt" -le "$max_retries" ]; do | |
| echo "Health check attempt ${attempt}/${max_retries}..." | |
| # Get all containers belonging to the compose project | |
| mapfile -t containers < <(docker compose -f "${compose_file}" ps -aq) | |
| if [ "${#containers[@]}" -eq 0 ]; then | |
| echo "No containers found for compose file '${compose_file}'." | |
| exit 1 | |
| fi | |
| all_healthy=true | |
| any_starting=false | |
| for container in "${containers[@]}"; do | |
| # Optionally skip exited containers | |
| if [ "${skip_exited}" = true ]; then | |
| container_state=$(docker inspect -f '{{.State.Status}}' "${container}") | |
| if [ "${container_state}" = "exited" ] || [ "${container_state}" = "dead" ]; then | |
| echo "Skipping exited container ${container} (state: ${container_state})." | |
| continue | |
| fi | |
| fi | |
| # Get health status; "none" if no healthcheck is defined | |
| health_status=$(docker inspect -f '{{if .State.Health}}{{.State.Health.Status}}{{else}}none{{end}}' "${container}") | |
| if [ "${health_status}" = "none" ] && [ "${skip_no_healthcheck}" = true ]; then | |
| echo "Skipping container ${container} (no healthcheck defined)." | |
| continue | |
| fi | |
| echo "Container ${container} health status: ${health_status}" | |
| case "${health_status}" in | |
| healthy) | |
| ;; | |
| starting) | |
| all_healthy=false | |
| any_starting=true | |
| ;; | |
| unhealthy) | |
| echo "Container ${container} is unhealthy." | |
| exit 1 | |
| ;; | |
| *) | |
| echo "Container ${container} is in unexpected health status: ${health_status}" | |
| all_healthy=false | |
| ;; | |
| esac | |
| done | |
| if [ "${all_healthy}" = true ]; then | |
| echo "All relevant containers are healthy." | |
| exit 0 | |
| fi | |
| if [ "$attempt" -eq "$max_retries" ]; then | |
| echo "Health check did not succeed within ${max_retries} attempts." | |
| exit 1 | |
| fi | |
| if [ "${any_starting}" = true ]; then | |
| echo "Some containers are still starting. Retrying in ${retry_interval} seconds..." | |
| else | |
| echo "Some containers are not healthy yet. Retrying in ${retry_interval} seconds..." | |
| fi | |
| attempt=$((attempt + 1)) | |
| sleep "${retry_interval}" | |
| done |
| - name: Set up Docker | ||
| uses: docker/setup-docker-action@v4 | ||
|
|
There was a problem hiding this comment.
The GitHub Action 'docker/setup-docker-action' does not exist. Docker is pre-installed on GitHub-hosted ubuntu-latest runners, so this step is unnecessary and should be removed. If you need a specific Docker version or setup, consider using 'docker/setup-buildx-action' instead.
| - name: Set up Docker | |
| uses: docker/setup-docker-action@v4 |
| - name: Set up Docker Compose | ||
| uses: docker/setup-compose-action@v1 | ||
| with: | ||
| version: latest # use latest version of docker compose | ||
|
|
There was a problem hiding this comment.
The GitHub Action 'docker/setup-compose-action' does not exist. Docker Compose is pre-installed on GitHub-hosted ubuntu-latest runners. Remove this step and the workflow will work correctly. The 'docker compose' command is already available.
| - name: Set up Docker Compose | |
| uses: docker/setup-compose-action@v1 | |
| with: | |
| version: latest # use latest version of docker compose |
|
|
||
| searxng: | ||
| image: searxng/searxng:2023.12.11-8a4104b99 | ||
| image: searxng/searxng:latest |
There was a problem hiding this comment.
Using 'latest' tag for the searxng image violates the established codebase convention of pinning Docker images to specific versions (see traefik:v2.10, rabbitmq:3.12-management, mongo:4.4.6, etc. in docker-compose.yml:6,174,211,228,255,285). While the old pinned version is unavailable, consider pinning to a specific recent version (e.g., 'searxng/searxng:2024.x.x-xxxxx') rather than 'latest' to ensure reproducible builds and controlled updates.
| image: searxng/searxng:latest | |
| image: searxng/searxng:2024.01.01-12345678 |
Fix dependencies and add CICD check
Fix missing and conflicting dependencies in the project to make it runnable again. Also added a workflow to ensure the project is runnable via
docker compose buildanddocker compose up.Dependencies
Pipfile.lock
There was a missing
Pipfile.lockinbrainin the docker file, resulting in conflicting dependencies. The wrongmarshmallowversion was used, making the API incompatible with the code:searxng
The docker image
image: searxng/searxng:2023.12.11-8a4104b99is not available anymore. Sincesearxnguses a rolling release model, it has been changed toimage: searxng/searxng:latest.CI/CD
To ensure the project stays runnable, a workflow was added that builds and runs using
docker composeand waits 2 minutes for all containers to become healthy. If they do not become healthy in that time frame, the workflow fails.The workflow runs on every pull-request to main and also on every monday at 3:00 AM UTC.
A status badge can be included in the readme, see https://docs.github.com/en/actions/how-tos/monitor-workflows/add-a-status-badge
Error Log
Wrong
marshmallowVersionHow to reproduce: Clone the repository, build the project using
docker compose buildand the start the containers usingdocker compose up.Log
Mind the
=> => # Pipfile.lock not found, creating...This resulted in the
gunicornserver failing endlessly