From 78f63e640f94d2f091f9322933cc9ef45e7d613d Mon Sep 17 00:00:00 2001 From: Leon Mika Date: Sat, 2 May 2026 13:54:57 +1000 Subject: [PATCH] Print public HTTPS URL of uploaded artefact MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit After a successful S3 upload, log the HTTPS URL so the workflow run output shows where the artefact was published. Uses the regional virtual-hosted form for AWS S3 and path-style for custom endpoints, matching how NewClient configures the client. The URL is what the object would be served at if the bucket allows public reads — the orchestrator does not assert anything about the bucket's access policy. Co-Authored-By: Claude Opus 4.7 (1M context) --- cmd/wails-release/main.go | 1 + internal/upload/upload.go | 13 ++++++++++ internal/upload/upload_test.go | 43 ++++++++++++++++++++++++++++++++++ 3 files changed, 57 insertions(+) diff --git a/cmd/wails-release/main.go b/cmd/wails-release/main.go index 4e76341..073cff3 100644 --- a/cmd/wails-release/main.go +++ b/cmd/wails-release/main.go @@ -174,6 +174,7 @@ func run(ctx context.Context) error { if err != nil { return err } + fmt.Println("Uploaded to:", upload.HTTPSURL(cfg.S3Bucket, key, cfg.S3Region, cfg.S3EndpointURL)) } // 8. Outputs (fixed order so partial-write failures are reproducible) diff --git a/internal/upload/upload.go b/internal/upload/upload.go index 1c1bac6..a880f33 100644 --- a/internal/upload/upload.go +++ b/internal/upload/upload.go @@ -47,6 +47,19 @@ func Upload(ctx context.Context, c PutObjectAPI, o Opts) (string, error) { return fmt.Sprintf("s3://%s/%s", o.Bucket, o.Key), nil } +// HTTPSURL returns the HTTPS form of an upload location. For AWS S3 it uses +// the regional virtual-hosted form; for a custom endpoint it appends the +// bucket and key path-style, matching how NewClient configures the client. +// +// The bucket may still be private — this is purely the URL where the object +// would be served if it (or its bucket) were publicly readable. +func HTTPSURL(bucket, key, region, endpointURL string) string { + if endpointURL != "" { + return strings.TrimRight(endpointURL, "/") + "/" + bucket + "/" + key + } + return fmt.Sprintf("https://%s.s3.%s.amazonaws.com/%s", bucket, region, key) +} + // WriteFileForTest is exposed for use from this package's tests. func WriteFileForTest(path string, b []byte) error { return os.WriteFile(path, b, 0o600) diff --git a/internal/upload/upload_test.go b/internal/upload/upload_test.go index 61fc80b..4a25304 100644 --- a/internal/upload/upload_test.go +++ b/internal/upload/upload_test.go @@ -29,6 +29,49 @@ func TestRenderKey(t *testing.T) { } } +func TestHTTPSURL(t *testing.T) { + cases := []struct { + name string + bucket, key string + region string + endpoint string + want string + }{ + { + name: "aws regional virtual-hosted", + bucket: "my-bucket", key: "releases/1.2.3/App.app.zip", + region: "ap-southeast-2", + want: "https://my-bucket.s3.ap-southeast-2.amazonaws.com/releases/1.2.3/App.app.zip", + }, + { + name: "aws us-east-1 still uses regional form", + bucket: "my-bucket", key: "k", + region: "us-east-1", + want: "https://my-bucket.s3.us-east-1.amazonaws.com/k", + }, + { + name: "custom endpoint path-style", + bucket: "releases", key: "myapp/1.0.0/App.app.zip", + region: "auto", endpoint: "https://my-minio.example.com", + want: "https://my-minio.example.com/releases/myapp/1.0.0/App.app.zip", + }, + { + name: "custom endpoint with trailing slash is normalised", + bucket: "b", key: "k", + region: "auto", endpoint: "https://example.com/", + want: "https://example.com/b/k", + }, + } + for _, c := range cases { + t.Run(c.name, func(t *testing.T) { + got := upload.HTTPSURL(c.bucket, c.key, c.region, c.endpoint) + if got != c.want { + t.Fatalf("got %q\nwant %q", got, c.want) + } + }) + } +} + type fakePut struct { calls []*s3.PutObjectInput }