Skip to content

fix: resolve multiple bugs found during comprehensive code review#23

Merged
SimplicityGuy merged 17 commits intomainfrom
fix/comprehensive-bug-fixes
Apr 4, 2026
Merged

fix: resolve multiple bugs found during comprehensive code review#23
SimplicityGuy merged 17 commits intomainfrom
fix/comprehensive-bug-fixes

Conversation

@SimplicityGuy
Copy link
Copy Markdown
Owner

@SimplicityGuy SimplicityGuy commented Apr 4, 2026

Summary

Comprehensive bug fixes, dependency modernization, security improvements, logging improvements, and documentation updates.

Dependency Replacement

Logging Improvements

  • Cron job output now visible in docker logs — Replaced broken 2>&1 | cat with /proc/1/fd/1 redirect (BusyBox crond swallows pipe output)
  • Timestamped job execution — Start/end messages include ISO timestamps
  • Formatted startup table — Container startup shows a clean table of scheduled jobs with schedule, name, and onstart status

Code Fixes (entrypoint.sh)

  • Shared-settings merge order inverted$shared was overriding per-job values instead of acting as defaults
  • Broken shebang in generated scriptsecho "#\!/usr/bin/env bash" wrote a literal backslash
  • parse_schedule failure silently produced broken crontab entries@every now properly rejected (related: security: cron schedule strings are written to crontab without format validation #18)
  • Missing null command guard in make_image_cmd
  • Empty crontab crash — Container aborted if all jobs were invalid
  • Unquoted container name in docker args — Mapping config keys with spaces produced broken --name args
  • Missing closing quote in schedule-missing error message
  • Temp file cleanup — Added trap for mktemp cleanup on error
  • Dead code removal — Removed unused skip_next variable

Infrastructure Improvements

  • update-project.yml now uses update-project.sh — Eliminated duplicate update logic between CI workflow and local script
  • Fixed update-project.sh Docker Hub API — Added &name=dind-alpine filter so dind-alpine tags are found within page limits
  • Fixed update-project.yml/.sh for single-stage Dockerfile — Removed stale builder image references after rq removal
  • Added owner field to cleanup-images workflow

Documentation Fixes

  • Updated README badges (centered div, Build, License, pre-commit, Docker, Shell, Alpine, Claude Code)
  • Fixed grammar errors throughout README
  • Documented undocumented config fields: environment, expose, networks, ports, volumes
  • Documented all supported schedule shortcuts (sorted most→least frequent)
  • Replaced @every examples with valid cron syntax
  • Fixed stale GitLab registry path → ghcr.io
  • Fixed --it-it in README
  • Updated CLAUDE.md: single-stage build, yq references, all 4 platform architectures
  • Updated Alpine references from 3.21 to 3.23 across all samples

Config Fixes

  • Renamed "null" key to "logrotate" in mapping config samples
  • Added depends_on to docker-compose.yml

Issues Addressed

Test plan

  • Build Docker image locally and verify entrypoint generates correct crontab
  • Verify generated job scripts have correct #!/usr/bin/env bash shebang
  • Test with mapping config containing ~~shared-settings to confirm per-job overrides work
  • Test with @every schedule to confirm it's properly skipped with error message
  • Test with mapping config keys containing spaces to verify --name quoting
  • Test with all-invalid config to verify container starts gracefully with empty crontab
  • Test YAML config parsing with yq
  • Test TOML config parsing with yq
  • Verify docker logs shows timestamped job output and startup table
  • Run docker-compose up and confirm crontab starts after myapp
  • Verify multi-arch build works (yq native Alpine package)

🤖 Generated with Claude Code

SimplicityGuy and others added 13 commits April 4, 2026 10:50
- Fix shared-settings merge order so per-job values override shared defaults
- Fix parse_schedule failure silently producing broken crontab entries
- Fix broken shebang (#\!) in generated job scripts
- Add null command guard in make_image_cmd (parity with make_container_cmd)
- Add temp file cleanup trap on error during script generation
- Clean up intermediate crontab file after copying to crontabs directory
- Downgrade actions/checkout@v6 to @v4 (v6 does not exist)
- Downgrade docker/metadata-action@v6 to @v5 (v6 does not exist)
- Remove -d flag from sample dockerargs (defeats error propagation)
- Rename "null" key to "logrotate" in mapping config samples
- Replace @every examples with valid cron syntax in README
- Fix stale GitLab registry path in README Dockerfile example
- Remove invalid --it flag from README dockerargs example
- Add depends_on to docker-compose.yml to prevent race condition

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
The previous commit incorrectly downgraded actions/checkout@v6 and
docker/metadata-action@v6 — these versions exist and were correct.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
These are valid Docker flags (-d for detached, --it for interactive
terminal) that were incorrectly removed.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…elds

- Update README badges to centered div style with Build, License,
  pre-commit, Docker, Shell, Alpine, and Claude Code badges
- Fix grammar: "to all" → "to allow", "probably has" → "probably have",
  "run on in" → "run in", "images name" → "image name"
- Document undocumented config fields: environment, expose, networks,
  ports, volumes
- Document all supported schedule shortcuts: @yearly/@annually,
  @monthly, @Weekly, @daily/@midnight, @hourly, @random
- Remove stale @every reference from CLAUDE.md
- Add owner field to cleanup-images workflow (matches discogsography)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Add touch before cat to prevent crash when no valid jobs exist
  (all jobs skipped due to missing schedule/command/unsupported syntax)
- Fix missing closing quote in 'schedule missing' error message

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Mapping config keys like 'map a volume' are injected as the job name
by normalize_config. Without quoting, --name map a volume produces a
broken docker command. Now generates --name "map a volume".

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Add name=dind-alpine filter to Docker Hub API query in
  update-project.sh so dind-alpine tags appear in results
  (previously, page_size=100 without filtering missed them)
- Remove unused skip_next variable and associated dead code
  from start_app in entrypoint.sh

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Update all sample configs, docker-compose.yml, and README to reference
alpine:3.23 which matches the Dockerfile base image.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Add per-platform SHA256 checksums for rq v1.0.2 binaries and verify
the download integrity with sha256sum before extraction. This prevents
supply chain attacks via compromised releases or MITM.

Also add SHELL pipefail directive to builder stage to satisfy hadolint.

Closes #17

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
rq (last release: 2019) has been replaced with yq (mikefarah/yq),
an actively maintained tool available from Alpine repos.

Changes:
- Remove entire Dockerfile builder stage (rq download, upx, checksums)
- Remove gcompat from release stage (only needed for rq glibc binaries)
- Add yq-go to Alpine packages
- Update entrypoint.sh to use yq for YAML and TOML conversion
- Remove rq version update logic from update-project.sh
- Update CLAUDE.md references

This also fixes the arm64/arm glibc-on-musl issue since yq is a
native Alpine package built for all supported architectures.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
SimplicityGuy and others added 4 commits April 4, 2026 11:47
BusyBox crond swallows pipe output (tries to mail it), so the
previous 2>&1 | cat approach silently lost all job output.

Now redirects to /proc/1/fd/1 and /proc/1/fd/2 (PID 1's stdout/stderr)
which is what docker logs reads. Also adds timestamps to job start/end
log messages for observability.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Replace raw crontab dump with a clean table showing schedule, job name,
and onstart flag. Also route onstart job output to /proc/1/fd/1 for
docker logs visibility, and clean up status messages.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Fix update-project.yml: remove builder image grep (builder stage no
  longer exists), only check docker dind base image
- Fix update-project.sh: remove Alpine FROM grep and stale Alpine
  tag lookup (no standalone Alpine stage anymore)
- Fix CLAUDE.md: "multi-stage" → "single-stage", add all platforms

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Eliminates duplicate logic between the CI workflow and local script.
The workflow now runs the script with --no-backup --skip-tests, checks
for git changes, then handles PR creation and Discord notification.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@SimplicityGuy SimplicityGuy merged commit 034e82d into main Apr 4, 2026
2 checks passed
@SimplicityGuy SimplicityGuy deleted the fix/comprehensive-bug-fixes branch April 4, 2026 18:59
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

security: rq binary downloaded without checksum verification

1 participant