Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
27 changes: 27 additions & 0 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
FROM golang:1.24-alpine AS builder
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

🧩 Analysis chain

🌐 Web query:

Go 1.24 release date golang Docker image tags 2024 2025

💡 Result:

  • Go 1.24 release date: February 11, 2025. [1][2]

  • Official golang Docker image tags (examples for the 1.24 series you can pull): 1.24, 1.24.12 (point releases), 1.24-alpine / 1.24-alpine3.22 / 1.24-alpine3.23, 1.24-bookworm, 1.24-trixie, and Windows variants like 1.24-windowsservercore-ltsc2022, 1.24-nanoserver-ltsc2025, etc. (official Docker Hub tag listing). [3]

Sources:

  1. Go 1.24 release notes (golang.org).
  2. Secondary release listings confirming Feb 11, 2025 (version/chocolatey summaries).
  3. Official golang image tags on Docker Hub.

🌐 Web query:

Alpine Linux 3.19 support status end of life

💡 Result:

Alpine Linux 3.19 reached end-of-life (EOL) on November 1, 2025 — it is no longer receiving security updates. [1][2]

Sources:
[1] endoflife.date — Alpine Linux (EOL listing for 3.19).
[2] Alpine Linux release announcements (3.19.x series; latest updates prior to EOL).


Consider upgrading Alpine Linux to a supported version.

Alpine Linux 3.19 reached end-of-life on November 1, 2025 and no longer receives security updates. Upgrade the base image on line 18 to Alpine 3.20 or later. The golang:1.24-alpine tag is valid and officially supported.

🤖 Prompt for AI Agents
In `@Dockerfile` at line 1, The Dockerfile uses an unsupported Alpine base tag;
update the FROM image tag (currently "golang:1.24-alpine") to an Alpine 3.20+
variant (for example "golang:1.24-alpine3.20" or another official golang:1.24
image that embeds Alpine 3.20 or newer) by replacing the FROM line so the build
uses a supported Alpine release; ensure any alpine-specific package commands
still work after the change and adjust package names if needed.


RUN apk add --no-cache git ca-certificates

WORKDIR /src

# Cache dependencies
COPY go.mod go.sum ./
RUN go mod download

# Copy source
COPY . .

# Build
RUN CGO_ENABLED=0 GOOS=linux go build -o /wallets .

# Final image
FROM alpine:3.19

RUN apk add --no-cache ca-certificates curl

COPY --from=builder /wallets /usr/bin/wallets

ENV OTEL_SERVICE_NAME=wallets

ENTRYPOINT ["/usr/bin/wallets"]
CMD ["serve"]
39 changes: 39 additions & 0 deletions deployments/docker-compose/Caddyfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
{
admin off
auto_https off
}

:80 {
# Route ledger API requests
handle /api/ledger/* {
uri strip_prefix /api/ledger
reverse_proxy ledger:3068
}

# Route wallets API requests
handle /api/wallets/* {
uri strip_prefix /api/wallets
reverse_proxy wallets:8081
}
Comment on lines +8 to +17
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Match base paths without trailing slash (avoid 502 on /api/ledger and /api/wallets).
With the current /* matchers, /api/ledger and /api/wallets fall through to the /api/* handler and return 502. Consider matching both the base path and subpaths.

🐛 One way to cover both base and subpaths
-	handle /api/ledger/* {
-		uri strip_prefix /api/ledger
-		reverse_proxy ledger:3068
-	}
+	handle_path /api/ledger* {
+		reverse_proxy ledger:3068
+	}
 
-	handle /api/wallets/* {
-		uri strip_prefix /api/wallets
-		reverse_proxy wallets:8081
-	}
+	handle_path /api/wallets* {
+		reverse_proxy wallets:8081
+	}

Also applies to: 31-33

🤖 Prompt for AI Agents
In `@deployments/docker-compose/Caddyfile` around lines 8 - 17, The Caddy handle
blocks for "/api/ledger/*" and "/api/wallets/*" only match subpaths and miss the
base paths "/api/ledger" and "/api/wallets", causing those requests to fall
through; update the two handle directives (the blocks currently starting with
handle /api/ledger/* and handle /api/wallets/*) to match both the base path and
subpaths (e.g., include both "/api/ledger" and "/api/ledger/*" in the handle
matcher, and likewise for wallets) and keep the existing uri strip_prefix and
reverse_proxy settings so requests to both the base path and any subpaths are
proxied correctly.


# Health check endpoint
handle /_healthcheck {
respond "OK" 200
}

# Service info endpoint
handle /_info {
header Content-Type application/json
respond `{"services":{"ledger":"/api/ledger","wallets":"/api/wallets"},"version":"standalone"}` 200
}

# Catch-all for unknown /api/* routes
handle /api/* {
respond "Bad Gateway" 502
}

# Default handler
handle {
respond "Not Found" 404
}
}
75 changes: 75 additions & 0 deletions docker-compose.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
volumes:
postgres:

services:
# API Gateway - routes to ledger and wallets
gateway:
image: caddy:2-alpine
healthcheck:
test: ["CMD", "wget", "-q", "--spider", "http://127.0.0.1:80/_healthcheck"]
interval: 5s
timeout: 3s
retries: 10
depends_on:
ledger:
condition: service_healthy
ports:
- "${GATEWAY_PORT:-8080}:80"
volumes:
- ./deployments/docker-compose/Caddyfile:/etc/caddy/Caddyfile

# PostgreSQL database for Ledger
postgres:
image: postgres:16-alpine
healthcheck:
test: ["CMD-SHELL", "pg_isready -U ledger"]
interval: 10s
timeout: 5s
retries: 5
environment:
POSTGRES_USER: ledger
POSTGRES_PASSWORD: ledger
POSTGRES_DB: ledger
command: -c max_connections=200
# Uncomment for persistent data:
# volumes:
# - postgres:/var/lib/postgresql/data

# Ledger service - the backing store for wallets
ledger:
image: ghcr.io/formancehq/ledger:latest
healthcheck:
test: ["CMD", "curl", "-f", "http://127.0.0.1:3068/_healthcheck"]
interval: 10s
timeout: 5s
retries: 10
depends_on:
postgres:
condition: service_healthy
ports:
- "${LEDGER_PORT:-3068}:3068"
environment:
DEBUG: ${DEBUG:-true}
POSTGRES_URI: postgres://ledger:ledger@postgres:5432/ledger?sslmode=disable
EXPERIMENTAL_FEATURES: "true"
AUTO_UPGRADE: "true"

# Wallets service (runs from local source)
wallets:
image: golang:1.24-alpine
healthcheck:
test: ["CMD", "wget", "-q", "--spider", "http://127.0.0.1:8081/_healthcheck"]
interval: 10s
timeout: 5s
retries: 10
depends_on:
gateway:
condition: service_healthy
ports:
- "${WALLETS_PORT:-8082}:8081"
volumes:
- .:/src
working_dir: /src
environment:
DEBUG: ${DEBUG:-true}
command: ["go", "run", ".", "serve", "--stack-url", "http://gateway", "--ledger", "wallets-001", "--listen", ":8081"]
40 changes: 9 additions & 31 deletions flake.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion flake.nix
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@

outputs = { self, nixpkgs, nur }:
let
goVersion = 23;
goVersion = 24;

supportedSystems = [
"x86_64-linux"
Expand Down
4 changes: 2 additions & 2 deletions pkg/testserver/testserver.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,10 @@ import (
"github.com/formancehq/go-libs/v3/httpserver"
"github.com/formancehq/go-libs/v3/testing/deferred"
"github.com/formancehq/go-libs/v3/testing/testservice"
. "github.com/formancehq/go-libs/v3/testing/testservice/ginkgo"
. "github.com/formancehq/go-libs/v3/testing/testservice/ginkgo" //nolint:staticcheck
"github.com/formancehq/wallets/cmd"
walletsclient "github.com/formancehq/wallets/pkg/client"
. "github.com/onsi/ginkgo/v2/dsl/core"
. "github.com/onsi/ginkgo/v2/dsl/core" //nolint:staticcheck
)

func StackURLInstrumentation(stackURL *deferred.Deferred[string]) testservice.Instrumentation {
Expand Down