From c569d5d5b464571b592994e1322304c9ac85433f Mon Sep 17 00:00:00 2001 From: Priveetee Date: Thu, 6 Aug 2026 10:58:29 +0200 Subject: [PATCH 1/6] chore: prepare downloader 1.4.0 --- VERSION | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/VERSION b/VERSION index 3a3cd8c..88c5fb8 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -1.3.1 +1.4.0 From b730fb51e86c4834ee6f5305baa665f8459d80f0 Mon Sep 17 00:00:00 2001 From: Priveetee Date: Sat, 8 Aug 2026 12:50:04 +0200 Subject: [PATCH 2/6] chore: update downloader dependencies --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index e965e7d..a7ab7c4 100644 --- a/go.mod +++ b/go.mod @@ -5,7 +5,7 @@ go 1.26 require ( github.com/jackc/pgx/v5 v5.10.0 github.com/minio/minio-go/v7 v7.2.1 - github.com/redis/go-redis/v9 v9.21.0 + github.com/redis/go-redis/v9 v9.22.0 golang.org/x/sys v0.47.0 ) diff --git a/go.sum b/go.sum index 0b47c05..efc89d7 100644 --- a/go.sum +++ b/go.sum @@ -41,8 +41,8 @@ github.com/philhofer/fwd v1.2.0 h1:e6DnBTl7vGY+Gz322/ASL4Gyp1FspeMvx1RNDoToZuM= github.com/philhofer/fwd v1.2.0/go.mod h1:RqIHx9QI14HlwKwm98g9Re5prTQ6LdeRQn+gXJFxsJM= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= -github.com/redis/go-redis/v9 v9.21.0 h1:FPBE4hhbAke+TLmcY3WkpbDffJEomdqPn3HYiqAtL9E= -github.com/redis/go-redis/v9 v9.21.0/go.mod h1:v/M13XI1PVCDcm01VtPFOADfZtHf8YW3baQf57KlIkA= +github.com/redis/go-redis/v9 v9.22.0 h1:laDvpYXTJtZLloinw1fA5Kqd6HAEH2XKxOkG/PDq2F0= +github.com/redis/go-redis/v9 v9.22.0/go.mod h1:y2g0Wj8rQvuK0ELM+oxSudcLtC09JScs98I/X9gRWY4= github.com/rogpeppe/go-internal v1.14.1 h1:UQB4HGPB6osV0SQTLymcB4TgvyWu6ZyliaW0tI/otEQ= github.com/rogpeppe/go-internal v1.14.1/go.mod h1:MaRKkUm5W0goXpeCfT7UZI6fk/L7L7so1lCWt35ZSgc= github.com/rs/xid v1.6.0 h1:fV591PaemRlL6JfRxGDEPl69wICngIQ3shQtzfy2gxU= From 9234f0067c5579bd082b975fd6bddf5323775460 Mon Sep 17 00:00:00 2001 From: Priveetee Date: Tue, 11 Aug 2026 12:03:14 +0200 Subject: [PATCH 3/6] chore: align development version with 1.5.0 --- Dockerfile | 2 +- Dockerfile.wolfi | 2 +- VERSION | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Dockerfile b/Dockerfile index 154d938..f6065cc 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,6 +1,6 @@ FROM golang:1.26-alpine3.23 AS build -ARG BUILD_VERSION=1.2.4-dev +ARG BUILD_VERSION=1.5.0-dev ARG BUILD_REVISION=development ARG BUILD_TIME=unknown WORKDIR /src diff --git a/Dockerfile.wolfi b/Dockerfile.wolfi index bd3540b..932dc08 100644 --- a/Dockerfile.wolfi +++ b/Dockerfile.wolfi @@ -1,6 +1,6 @@ FROM cgr.dev/chainguard/go:latest-dev AS build -ARG BUILD_VERSION=1.2.4-dev +ARG BUILD_VERSION=1.5.0-dev ARG BUILD_REVISION=development ARG BUILD_TIME=unknown USER root diff --git a/VERSION b/VERSION index 88c5fb8..bc80560 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -1.4.0 +1.5.0 From 10ffbd1b064bc4377cbaf2b946808b2c01c96c66 Mon Sep 17 00:00:00 2001 From: Priveetee Date: Wed, 12 Aug 2026 16:42:22 +0200 Subject: [PATCH 4/6] fix: mark internal artifact redirects --- internal/artifact/s3.go | 16 ++++++++--- internal/artifact/s3_test.go | 55 ++++++++++++++++++++++++++++++++++++ 2 files changed, 67 insertions(+), 4 deletions(-) create mode 100644 internal/artifact/s3_test.go diff --git a/internal/artifact/s3.go b/internal/artifact/s3.go index 68d42d3..9bc4040 100644 --- a/internal/artifact/s3.go +++ b/internal/artifact/s3.go @@ -13,6 +13,8 @@ import ( "github.com/minio/minio-go/v7/pkg/credentials" ) +const internalRedirectHeader = "X-TypeType-Artifact-Proxy" + type S3Config struct { Endpoint string PublicEndpoint string @@ -27,9 +29,10 @@ type S3Config struct { } type S3Store struct { - client *minio.Client - presign *minio.Client - cfg S3Config + client *minio.Client + presign *minio.Client + proxyRedirect bool + cfg S3Config } func (s *S3Store) Name() string { return "s3" } @@ -67,7 +70,9 @@ func NewS3Store(cfg S3Config) (*S3Store, error) { if cfg.URLTTL <= 0 { cfg.URLTTL = 15 * time.Minute } - return &S3Store{client: client, presign: presign, cfg: cfg}, nil + proxyRedirect := cfg.PublicEndpoint == "" || + (cfg.PublicEndpoint == cfg.Endpoint && cfg.PublicUseSSL == cfg.UseSSL) + return &S3Store{client: client, presign: presign, proxyRedirect: proxyRedirect, cfg: cfg}, nil } func (s *S3Store) Save(ctx context.Context, localPath string, objectKey string) (Saved, error) { @@ -100,6 +105,9 @@ func (s *S3Store) ServeHTTP(w http.ResponseWriter, r *http.Request, saved Saved, if err != nil { return err } + if s.proxyRedirect { + w.Header().Set(internalRedirectHeader, "1") + } http.Redirect(w, r, url.String(), http.StatusFound) return nil } diff --git a/internal/artifact/s3_test.go b/internal/artifact/s3_test.go new file mode 100644 index 0000000..5575a74 --- /dev/null +++ b/internal/artifact/s3_test.go @@ -0,0 +1,55 @@ +package artifact + +import ( + "net/http" + "net/http/httptest" + "testing" +) + +func TestS3StoreMarksInternalRedirect(t *testing.T) { + store := newTestS3Store(t, "typetype-garage:3900") + response := httptest.NewRecorder() + request := httptest.NewRequest(http.MethodGet, "/artifact", nil) + + if err := store.ServeHTTP(response, request, Saved{Location: "artifact.mp4"}, "video.mp4"); err != nil { + t.Fatal(err) + } + + if response.Code != http.StatusFound { + t.Fatalf("status = %d", response.Code) + } + if response.Header().Get(internalRedirectHeader) != "1" { + t.Fatalf("internal redirect header = %q", response.Header().Get(internalRedirectHeader)) + } +} + +func TestS3StoreLeavesPublicRedirectUnmarked(t *testing.T) { + store := newTestS3Store(t, "downloads.example.com") + response := httptest.NewRecorder() + request := httptest.NewRequest(http.MethodGet, "/artifact", nil) + + if err := store.ServeHTTP(response, request, Saved{Location: "artifact.mp4"}, "video.mp4"); err != nil { + t.Fatal(err) + } + + if response.Header().Get(internalRedirectHeader) != "" { + t.Fatalf("public redirect was marked internal") + } +} + +func newTestS3Store(t *testing.T, publicEndpoint string) *S3Store { + t.Helper() + store, err := NewS3Store(S3Config{ + Endpoint: "typetype-garage:3900", + PublicEndpoint: publicEndpoint, + Region: "garage", + Bucket: "downloads", + AccessKey: "key", + SecretKey: "secret", + PathStyle: true, + }) + if err != nil { + t.Fatal(err) + } + return store +} From 3e8a138084d6b2cb09275e2edc75459e52498fb8 Mon Sep 17 00:00:00 2001 From: Priveetee Date: Sat, 22 Aug 2026 11:16:09 +0200 Subject: [PATCH 5/6] chore: prepare downloader 1.6.0 --- Dockerfile | 2 +- Dockerfile.wolfi | 2 +- VERSION | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Dockerfile b/Dockerfile index f6065cc..59c3131 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,6 +1,6 @@ FROM golang:1.26-alpine3.23 AS build -ARG BUILD_VERSION=1.5.0-dev +ARG BUILD_VERSION=1.6.0-dev ARG BUILD_REVISION=development ARG BUILD_TIME=unknown WORKDIR /src diff --git a/Dockerfile.wolfi b/Dockerfile.wolfi index 932dc08..88a0ce4 100644 --- a/Dockerfile.wolfi +++ b/Dockerfile.wolfi @@ -1,6 +1,6 @@ FROM cgr.dev/chainguard/go:latest-dev AS build -ARG BUILD_VERSION=1.5.0-dev +ARG BUILD_VERSION=1.6.0-dev ARG BUILD_REVISION=development ARG BUILD_TIME=unknown USER root diff --git a/VERSION b/VERSION index bc80560..dc1e644 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -1.5.0 +1.6.0 From 52c2e93e23c1d1e5f44497ed5d021016f8d0624e Mon Sep 17 00:00:00 2001 From: Priveetee Date: Sat, 22 Aug 2026 11:34:06 +0200 Subject: [PATCH 6/6] test: make storage reservation check deterministic --- internal/storage/monitor_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/internal/storage/monitor_test.go b/internal/storage/monitor_test.go index cd4c8df..dbdc7d6 100644 --- a/internal/storage/monitor_test.go +++ b/internal/storage/monitor_test.go @@ -61,7 +61,7 @@ func TestMonitorTracksAndReleasesReservations(t *testing.T) { if capacity.ReservedBytes != reserved || !capacity.Available { t.Fatalf("capacity = %#v", capacity) } - if _, err := monitor.Reserve("second", 1); !errors.Is(err, ErrInsufficientStorage) { + if _, err := monitor.Reserve("second", capacity.TotalBytes); !errors.Is(err, ErrInsufficientStorage) { t.Fatalf("reserve error = %v", err) } release()