Repository: fsouza/fake-gcs-server
Pull request #1538 (2024-03-14 18:10:32)

build(deps): bump docker/build-push-action from 5.2.0 to 5.3.0
Bumps [docker/build-push-action](https://github.com/docker/build-push-action) from 5.2.0 to 5.3.0.
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a href="https://github.com/docker/build-push-action/releases">docker/build-push-action's releases</a>.</em></p>
<blockquote>
<h2>v5.3.0</h2>
<ul>
<li>Bump <code>@​docker/actions-toolkit</code> from 0.18.0 to 0.19.0 in <a href="https://redirect.github.com/docker/build-push-action/pull/1080">docker/build-push-action#1080</a></li>
</ul>
<p><strong>Full Changelog</strong>: <a href="https://github.com/docker/build-push-action/compare/v5.2.0...v5.3.0">https://github.com/docker/build-push-action/compare/v5.2.0...v5.3.0</a></p>
</blockquote>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a href="https://github.com/docker/build-push-action/commit/2cdde995de11925a030ce8070c3d77a52ffcf1c0"><code>2cdde99</code></a> Merge pull request <a href="https://redirect.github.com/docker/build-push-action/issues/1080">#1080</a> from docker/dependabot/npm_and_yarn/docker/actions-t...</li>
<li><a href="https://github.com/docker/build-push-action/commit/008747aa03417139ec2995efe44e7f080b8323c3"><code>008747a</code></a> chore: update generated content</li>
<li><a href="https://github.com/docker/build-push-action/commit/15807531260fa0e39af66835230d13071751862e"><code>1580753</code></a> chore(deps): Bump <code>@​docker/actions-toolkit</code> from 0.18.0 to 0.19.0</li>
<li><a href="https://github.com/docker/build-push-action/commit/2a7db1d68aab1a514ba647f39bcde60888a1753f"><code>2a7db1d</code></a> Merge pull request <a href="https://redirect.github.com/docker/build-push-action/issues/1075">#1075</a> from crazy-max/ci-multi-output</li>
<li><a href="https://github.com/docker/build-push-action/commit/35e7dd592106dcd929ef8706706f6d54678d1f67"><code>35e7dd5</code></a> ci: test multi output</li>
<li>See full diff in <a href="https://github.com/docker/build-push-action/compare/v5.2.0...v5.3.0">compare view</a></li>
</ul>
</details>
<br />


[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=docker/build-push-action&package-manager=github_actions&previous-version=5.2.0&new-version=5.3.0)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores)

Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`.

[//]: # (dependabot-automerge-start)
[//]: # (dependabot-automerge-end)

---

<details>
<summary>Dependabot commands and options</summary>
<br />

You can trigger Dependabot actions by commenting on this PR:
- `@dependabot rebase` will rebase this PR
- `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it
- `@dependabot merge` will merge this PR after your CI passes on it
- `@dependabot squash and merge` will squash and merge this PR after your CI passes on it
- `@dependabot cancel merge` will cancel a previously requested merge and block automerging
- `@dependabot reopen` will reopen this PR if it is closed
- `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually
- `@dependabot show <dependency name> ignore conditions` will show all of the ignore conditions of the specified dependency
- `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself)
- `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself)
- `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)


</details>


Patch:
diff --git a/.github/workflows/docker-push.yml b/.github/workflows/docker-push.yml
index a5fee7f..31f842d 100644
--- a/.github/workflows/docker-push.yml
+++ b/.github/workflows/docker-push.yml
@@ -29,7 +29,7 @@ jobs:
 
       - name: setup buildx
         id: buildx
-        uses: docker/setup-buildx-action@v3.1.0
+        uses: docker/setup-buildx-action@v3.2.0
 
       - name: login to docker hub
         uses: docker/login-action@v3.1.0
@@ -38,7 +38,7 @@ jobs:
           password: ${{ secrets.DOCKER_PASSWORD }}
 
       - name: build and push
-        uses: docker/build-push-action@v5.2.0
+        uses: docker/build-push-action@v5.3.0
         with:
           cache-from: fsouzaci/gha-cache:fake-gcs-server
           cache-to: fsouzaci/gha-cache:fake-gcs-server
diff --git a/fakestorage/object.go b/fakestorage/object.go
index c7b4095..04f86ae 100644
--- a/fakestorage/object.go
+++ b/fakestorage/object.go
@@ -556,7 +556,7 @@ func (s *Server) listObjects(r *http.Request) jsonResponse {
 	if err != nil {
 		return jsonResponse{status: http.StatusNotFound}
 	}
-	return jsonResponse{data: newListObjectsResponse(objs, prefixes)}
+	return jsonResponse{data: newListObjectsResponse(objs, prefixes, s.externalURL)}
 }
 
 func (s *Server) xmlListObjects(r *http.Request) xmlResponse {
@@ -642,7 +642,7 @@ func (s *Server) getObject(w http.ResponseWriter, r *http.Request) {
 		header.Set("Accept-Ranges", "bytes")
 		return jsonResponse{
 			header: header,
-			data:   newObjectResponse(obj.ObjectAttrs),
+			data:   newObjectResponse(obj.ObjectAttrs, s.externalURL),
 		}
 	})
 
@@ -774,9 +774,9 @@ func (s *Server) rewriteObject(r *http.Request) jsonResponse {
 	defer created.Close()
 
 	if vars["copyType"] == "copyTo" {
-		return jsonResponse{data: newObjectResponse(created.ObjectAttrs)}
+		return jsonResponse{data: newObjectResponse(created.ObjectAttrs, s.externalURL)}
 	}
-	return jsonResponse{data: newObjectRewriteResponse(created.ObjectAttrs)}
+	return jsonResponse{data: newObjectRewriteResponse(created.ObjectAttrs, s.externalURL)}
 }
 
 func (s *Server) downloadObject(w http.ResponseWriter, r *http.Request) {
@@ -1139,5 +1139,5 @@ func (s *Server) composeObject(r *http.Request) jsonResponse {
 
 	s.eventManager.Trigger(&backendObj, notification.EventFinalize, nil)
 
-	return jsonResponse{data: newObjectResponse(obj.ObjectAttrs)}
+	return jsonResponse{data: newObjectResponse(obj.ObjectAttrs, s.externalURL)}
 }
diff --git a/fakestorage/response.go b/fakestorage/response.go
index e28b84e..aff80a2 100644
--- a/fakestorage/response.go
+++ b/fakestorage/response.go
@@ -5,6 +5,8 @@
 package fakestorage
 
 import (
+	"fmt"
+	"net/url"
 	"time"
 
 	"github.com/fsouza/fake-gcs-server/internal/backend"
@@ -66,14 +68,14 @@ func newBucketResponse(bucket backend.Bucket, location string) bucketResponse {
 	}
 }
 
-func newListObjectsResponse(objs []ObjectAttrs, prefixes []string) listResponse {
+func newListObjectsResponse(objs []ObjectAttrs, prefixes []string, externalURL string) listResponse {
 	resp := listResponse{
 		Kind:     "storage#objects",
 		Items:    make([]any, len(objs)),
 		Prefixes: prefixes,
 	}
 	for i, obj := range objs {
-		resp.Items[i] = newObjectResponse(obj)
+		resp.Items[i] = newObjectResponse(obj, externalURL)
 	}
 	return resp
 }
@@ -117,9 +119,12 @@ type objectResponse struct {
 	Generation      int64                  `json:"generation,string"`
 	CustomTime      string                 `json:"customTime,omitempty"`
 	Metadata        map[string]string      `json:"metadata,omitempty"`
+	SelfLink        string                 `json:"selfLink,omitempty"`
+	MediaLink       string                 `json:"mediaLink,omitempty"`
+	Metageneration  string                 `json:"metageneration,omitempty"`
 }
 
-func newObjectResponse(obj ObjectAttrs) objectResponse {
+func newObjectResponse(obj ObjectAttrs, externalURL string) objectResponse {
 	acl := getAccessControlsListFromObject(obj)
 
 	return objectResponse{
@@ -140,6 +145,9 @@ func newObjectResponse(obj ObjectAttrs) objectResponse {
 		Updated:         formatTime(obj.Updated),
 		CustomTime:      formatTime(obj.CustomTime),
 		Generation:      obj.Generation,
+		SelfLink:        fmt.Sprintf("%s/storage/v1/b/%s/o/%s", externalURL, url.PathEscape(obj.BucketName), url.PathEscape(obj.Name)),
+		MediaLink:       fmt.Sprintf("%s/download/storage/v1/b/%s/o/%s?alt=media", externalURL, url.PathEscape(obj.BucketName), url.PathEscape(obj.Name)),
+		Metageneration:  "1",
 	}
 }
 
@@ -176,14 +184,14 @@ type rewriteResponse struct {
 	Resource            objectResponse `json:"resource"`
 }
 
-func newObjectRewriteResponse(obj ObjectAttrs) rewriteResponse {
+func newObjectRewriteResponse(obj ObjectAttrs, externalURL string) rewriteResponse {
 	return rewriteResponse{
 		Kind:                "storage#rewriteResponse",
 		TotalBytesRewritten: obj.Size,
 		ObjectSize:          obj.Size,
 		Done:                true,
 		RewriteToken:        "",
-		Resource:            newObjectResponse(obj),
+		Resource:            newObjectResponse(obj, externalURL),
 	}
 }
 
diff --git a/fakestorage/upload.go b/fakestorage/upload.go
index c85de72..7b53d2b 100644
--- a/fakestorage/upload.go
+++ b/fakestorage/upload.go
@@ -249,7 +249,7 @@ func (s *Server) simpleUpload(bucketName string, r *http.Request) jsonResponse {
 		return errToJsonResponse(err)
 	}
 	obj.Close()
-	return jsonResponse{data: newObjectResponse(obj.ObjectAttrs)}
+	return jsonResponse{data: newObjectResponse(obj.ObjectAttrs, s.externalURL)}
 }
 
 type notImplementedSeeker struct {
@@ -297,7 +297,7 @@ func (s *Server) signedUpload(bucketName string, r *http.Request) jsonResponse {
 		return errToJsonResponse(err)
 	}
 	obj.Close()
-	return jsonResponse{data: newObjectResponse(obj.ObjectAttrs)}
+	return jsonResponse{data: newObjectResponse(obj.ObjectAttrs, s.externalURL)}
 }
 
 func getObjectACL(predefinedACL string) []storage.ACLRule {
@@ -386,7 +386,7 @@ func (s *Server) multipartUpload(bucketName string, r *http.Request) jsonRespons
 		return errToJsonResponse(err)
 	}
 	defer obj.Close()
-	return jsonResponse{data: newObjectResponse(obj.ObjectAttrs)}
+	return jsonResponse{data: newObjectResponse(obj.ObjectAttrs, s.externalURL)}
 }
 
 func parseContentTypeParams(requestContentType string) (map[string]string, error) {
@@ -446,7 +446,7 @@ func (s *Server) resumableUpload(bucketName string, r *http.Request) jsonRespons
 		header.Set("X-Goog-Upload-Status", "active")
 	}
 	return jsonResponse{
-		data:   newObjectResponse(obj.ObjectAttrs),
+		data:   newObjectResponse(obj.ObjectAttrs, s.externalURL),
 		header: header,
 	}
 }
@@ -553,7 +553,7 @@ func (s *Server) uploadFileContent(r *http.Request) jsonResponse {
 	}
 	return jsonResponse{
 		status: status,
-		data:   newObjectResponse(obj.ObjectAttrs),
+		data:   newObjectResponse(obj.ObjectAttrs, s.externalURL),
 		header: responseHeader,
 	}
 }


Test patch:
diff --git a/.github/workflows/docker-tests.yml b/.github/workflows/docker-tests.yml
index 6d8818a..0f97740 100644
--- a/.github/workflows/docker-tests.yml
+++ b/.github/workflows/docker-tests.yml
@@ -16,10 +16,10 @@ jobs:
 
       - name: setup buildx
         id: buildx
-        uses: docker/setup-buildx-action@v3.1.0
+        uses: docker/setup-buildx-action@v3.2.0
 
       - name: build
-        uses: docker/build-push-action@v5.2.0
+        uses: docker/build-push-action@v5.3.0
         with:
           cache-from: fsouzaci/gha-cache:fake-gcs-server
           context: .
diff --git a/fakestorage/object_test.go b/fakestorage/object_test.go
index a943bf0..e89a664 100644
--- a/fakestorage/object_test.go
+++ b/fakestorage/object_test.go
@@ -15,6 +15,7 @@ import (
 	"hash/crc32"
 	"io"
 	"net/http"
+	"net/url"
 	"reflect"
 	"testing"
 	"time"
@@ -186,6 +187,14 @@ func checkObjectAttrs(testObj Object, attrs *storage.ObjectAttrs, t *testing.T)
 			t.Errorf("wrong MetaHeader returned\nwant %s\ngot %v", testObj.Metadata["MetaHeader"], val)
 		}
 	}
+	externalURL := "" // We don't set any `externalURL` value during tests.
+	expectedMediaLink := fmt.Sprintf("%s/download/storage/v1/b/%s/o/%s?alt=media", externalURL, url.PathEscape(testObj.BucketName), url.PathEscape(testObj.Name))
+	if attrs.MediaLink != expectedMediaLink {
+		t.Errorf("wrong MediaLink returned\nwant %s\ngot  %s", expectedMediaLink, attrs.MediaLink)
+	}
+	if attrs.Metageneration != 1 {
+		t.Errorf("wrong metageneration\nwant 1\ngot  %d", attrs.Metageneration)
+	}
 }
 
 func TestServerClientObjectAttrs(t *testing.T) {