Skip to content

Rebuild for s3proxy 4.1.0 on Hono#101

Open
gmoon wants to merge 2 commits into
mainfrom
s3proxy-4.1.0-hono
Open

Rebuild for s3proxy 4.1.0 on Hono#101
gmoon wants to merge 2 commits into
mainfrom
s3proxy-4.1.0-hono

Conversation

@gmoon

@gmoon gmoon commented Jul 13, 2026

Copy link
Copy Markdown
Contributor

Rebuilds the image around s3proxy 4.1.0 on Hono, replacing the unfinished Fastify/v3 adaptation on main (which used the v3 get()/head() API that no longer exists in v4) and restoring the repo's lean conventions.

App

  • server.js — Hono on @hono/node-server using the v4 proxy.fetch() API, per the library's documented Hono pattern. /health, /version, //index.html, GET|HEAD /* streaming, XML error bodies via a single app.onError, graceful shutdown, and the dev credentials.json path.
  • package.jsons3proxy ^4.1.0; Fastify deps swapped for hono + @hono/node-server; restored the Docker Hub publish/credentials scripts the old CD workflow depended on.

Dockerfile

  • Lean multi-stage base → test → production (non-root node user, tini as PID 1, WORKDIR /src).
  • BuildKit npm cache mount on both dep installs; dropped the curl package in favour of BusyBox wget for the healthcheck.
  • Healthcheck hits 127.0.0.1, not localhost — Alpine resolves localhost to IPv6 ::1 first but the server binds IPv4 0.0.0.0, so localhost never went healthy. (Caught during a real container build.)

CI/CD

  • Replaced the Mega-Linter / Node 16 / docker scan workflow with:
    • ci.yml — Biome lint, app tests, and a real container smoke test (build once with GHA cache, wait for healthy, assert a 200 object + 404). AWS jobs skip on Dependabot. The docker job runs the container tests against the image it already built (S3PROXY_IMAGE) rather than triggering a second uncached build.
    • publish.yml — multi-arch (amd64+arm64) build & push to forkzero/s3proxy on release, semver tags, non-blocking Trivy scan.
  • Dropped the now-unused Mega-Linter configs; Dependabot → weekly.

Cleanup

  • Removed docker-compose.yml and the AI planning docs (PROGRESS.md, TODO.md, S3PROXY_DOCKER_ADAPTATION_GUIDE.md).
  • Rewrote the container tests for the new image (/src, node user, missing-BUCKET guard); updated app tests for Hono.
  • Wrote a real README (was a two-line stub).

Includes a follow-up /simplify pass (dead instanceof, hoisted S3Proxy.version(), simplified getCredentials(), dropped a /version placeholder, CI env hoisting + the double-build fix).

Verification

  • npm run lint — clean (10 files).
  • npm test7/7 (app + container suites) against the public s3proxy-public bucket.
  • docker build (181 MB) → container goes healthy in ~4s, streams /index.html (200), returns 404 XML, and stops cleanly on SIGTERM.

Requires (repo secrets)

AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY, AWS_REGION (test/smoke jobs) and DOCKERHUB_USER, DOCKERHUB_ACCESS_TOKEN (publish).

Follow-up

Library issue gmoon/s3proxy#142 proposes fetchWeb(), a Web-standard Request → Response adapter. Once it ships, server.js's GET/HEAD handler collapses to (c) => proxy.fetchWeb(c.req.raw) (keeping the XML onError) and we bump the dep here.

Not addressed

Base image is the floating node:22-alpine tag; pinning by digest (Dependabot-maintained) is recommended but deferred.

🤖 Generated with Claude Code

gmoon and others added 2 commits July 12, 2026 22:15
Replace the unfinished Fastify/v3 adaptation with a lean image that
follows this repo's original conventions.

App:
- server.js: Hono on @hono/node-server using the s3proxy v4 fetch() API
  (the v3 get()/head()/healthCheckStream() calls no longer exist).
- package.json: s3proxy ^4.1.0; swap Fastify deps for hono +
  @hono/node-server; restore the dockerhub publish/credentials scripts
  the CD workflow depends on.

Dockerfile:
- Lean multi-stage base -> test -> production (non-root node user, tini
  as PID 1), back to WORKDIR /src.
- BuildKit npm cache mount; drop the curl package in favour of BusyBox
  wget for the healthcheck.
- Healthcheck hits 127.0.0.1, not localhost: Alpine resolves localhost
  to IPv6 ::1 first but the server binds IPv4 0.0.0.0, so localhost
  never went healthy.

CI/CD:
- Replace the Mega-Linter/Node 16 workflow with ci.yml (Biome lint,
  unit tests, real container smoke test) and publish.yml (multi-arch
  build + push to forkzero/s3proxy on release, Trivy scan). Drop the
  now-unused Mega-Linter configs; Dependabot -> weekly.

Cleanup:
- Remove docker-compose.yml and the AI planning docs (PROGRESS.md,
  TODO.md, S3PROXY_DOCKER_ADAPTATION_GUIDE.md).
- Rewrite the container tests for the new image (/src, node user) and
  the missing-BUCKET guard.
- Write a real README.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
server.js:
- Drop the no-op `instanceof S3ProxyError` in onError (both branches read
  .statusCode); collapse to `error.statusCode || 500` and drop the now
  unused import.
- Hoist S3Proxy.version() to a module const (was recomputed per /version
  request) and reuse it in the startup log.
- Remove the misleading `hono: 'hono'` placeholder from /version (Hono
  blocks its package.json subpath, so there's no clean real version).
- Simplify getCredentials(): check prod first, then read the CWD-relative
  ./credentials.json (WORKDIR is /src, so the explicit /src path was
  redundant); drop the ternary in the S3Proxy constructor.

Dockerfile:
- Add the BuildKit npm cache mount to the test stage too.

CI:
- Hoist BUCKET/IMAGE to workflow-level env.
- Split app tests (test:app) from container tests (test:container); the
  docker job now runs the container tests against the image it already
  built (via S3PROXY_IMAGE) instead of triggering a second, uncached
  image build in the test job.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
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.

1 participant