Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

chore(server): add UploadAssetFromURL on gcs file implementation #1379

Merged
merged 6 commits into from
Jan 28, 2025

Conversation

soneda-yuya
Copy link
Contributor

@soneda-yuya soneda-yuya commented Jan 27, 2025

Overview

we need to save url as asset on each storage service

What I've done

  • implement add UploadAssetFromURL method on gcs storage infrastructure.

What I haven't done

  • implement add UploadAssetFromURL method on local storage infrastructure.
  • implement add UploadAssetFromURL method on storage s3 infrastructure.

How I tested

  • path test on gcs emulator

Which point I want you to review particularly

Memo

Summary by CodeRabbit

  • New Features

    • Added support for uploading assets from URLs
    • Enhanced development environment configuration for file repositories
  • Infrastructure

    • Updated Fake GCS Server Docker configuration
    • Updated Docker Compose file with specific GCS server version
  • Testing

    • Added new test cases for URL-based asset uploads
    • Introduced test data and utility functions for GCS testing

Copy link

coderabbitai bot commented Jan 27, 2025

Warning

Rate limit exceeded

@soneda-yuya has exceeded the limit for the number of commits or files that can be reviewed per hour. Please wait 3 minutes and 5 seconds before requesting another review.

⌛ How to resolve this issue?

After the wait time has elapsed, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout.

Please see our FAQ for further information.

📥 Commits

Reviewing files that changed from the base of the PR and between d512050 and b5ba8f8.

📒 Files selected for processing (4)
  • server/internal/app/repo.go (1 hunks)
  • server/internal/infrastructure/fs/file.go (1 hunks)
  • server/internal/infrastructure/gcs/file.go (6 hunks)
  • server/internal/infrastructure/s3/s3.go (1 hunks)

Walkthrough

This pull request introduces enhancements to the file upload and storage infrastructure, primarily focusing on Google Cloud Storage (GCS) functionality. The changes include adding a development mode for GCS interactions, implementing a new method for uploading assets from URLs, and updating the testing infrastructure. A new Fake GCS Server is integrated into the CI workflow and Docker Compose configuration, providing a more robust local development and testing environment.

Changes

File Change Summary
.github/workflows/ci_server.yml Added a step to start Fake GCS Server using Docker in the ci-server-test job
docker-compose.yml Updated GCS service image to specific version fsouza/fake-gcs-server:1.52.1
server/internal/app/repo.go Modified gcs.NewFile function call to include conf.Dev parameter
server/internal/infrastructure/fs/file.go Added placeholder UploadAssetFromURL method
server/internal/infrastructure/gcs/file.go Added isDev flag, updated NewFile constructor, implemented UploadAssetFromURL method
server/internal/infrastructure/gcs/file_test.go Added new test utilities and TestUploadAssetFromURL test
server/internal/infrastructure/gcs/testdata/geojson.json New test GeoJSON file added
server/internal/infrastructure/s3/s3.go Added placeholder UploadAssetFromURL method
server/internal/usecase/gateway/file.go Added UploadAssetFromURL method to File interface

Sequence Diagram

sequenceDiagram
    participant Client
    participant FileGateway
    participant GCSRepo
    participant GCSClient
    
    Client->>FileGateway: UploadAssetFromURL(context, url)
    FileGateway->>GCSRepo: UploadAssetFromURL(context, url)
    GCSRepo->>GCSRepo: Validate URL
    GCSRepo->>GCSClient: Fetch URL content
    GCSRepo->>GCSClient: Upload to Storage
    GCSClient-->>GCSRepo: Upload result
    GCSRepo-->>FileGateway: Return uploaded asset URL
    FileGateway-->>Client: Return uploaded asset details
Loading

Possibly related PRs

Suggested reviewers

  • pyshx

Poem

🐰 Hop, hop, through the cloud we go,
With URLs in paw and data to stow,
Fake GCS server, our testing delight,
Uploads dancing with bits of might!
A rabbit's code, precise and neat, 🚀


Thank you for using CodeRabbit. We offer it for free to the OSS community and would appreciate your support in helping us grow. If you find it useful, would you consider giving us a shout-out on your favorite social media?

❤️ Share
🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Generate unit testing code for this file.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai generate unit testing code for this file.
    • @coderabbitai modularize this function.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read src/utils.ts and generate unit testing code.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.
    • @coderabbitai help me debug CodeRabbit configuration file.

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

CodeRabbit Commands (Invoked using PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai generate docstrings to generate docstrings for this PR. (Beta)
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

@soneda-yuya soneda-yuya force-pushed the chore/new-method-on-gcs branch 9 times, most recently from 2796ac3 to b43f1a0 Compare January 27, 2025 09:06
@soneda-yuya soneda-yuya force-pushed the chore/new-method-on-gcs branch from b43f1a0 to 364daa4 Compare January 27, 2025 09:08
@soneda-yuya soneda-yuya marked this pull request as ready for review January 27, 2025 09:14
@soneda-yuya soneda-yuya requested a review from pyshx as a code owner January 27, 2025 09:14
Base automatically changed from chore/gcs_emulator to main January 27, 2025 09:16
@soneda-yuya soneda-yuya force-pushed the chore/new-method-on-gcs branch from 2582d68 to d512050 Compare January 27, 2025 09:19
Copy link

netlify bot commented Jan 27, 2025

Deploy Preview for reearth-web canceled.

Name Link
🔨 Latest commit b5ba8f8
🔍 Latest deploy log https://app.netlify.com/sites/reearth-web/deploys/6797548d6b0d740008f58ef8

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 2

🧹 Nitpick comments (8)
server/internal/infrastructure/gcs/file.go (2)

35-35: Development mode flag detection
Adding the isDev bool field is an effective approach to differentiate between production and development environments.

If you anticipate future expansion (multiple dev endpoints, different environment flags), consider grouping such env-specific settings into a dedicated struct. This ensures the code remains extensible.


41-43: Hardcoded local dev endpoint
Defining devBaseURL = "http://localhost:4443/storage/v1/b" works for local testing, but it might be more flexible to read from configuration or environment variables.

-const (
-	devBaseURL = "http://localhost:4443/storage/v1/b"
-)
+const devBaseURLDefault = "http://localhost:4443/storage/v1/b"

+func DevBaseURL() string {
+	if env := os.Getenv("GCS_DEV_ENDPOINT"); env != "" {
+		return env
+	}
+	return devBaseURLDefault
+}
server/internal/infrastructure/gcs/file_test.go (4)

14-15: Cloud/Hyperscaler-related imports
The new imports for "cloud.google.com/go/storage", "github.com/google/uuid", and "google.golang.org/api/iterator" are all required to manage GCS buckets, unique IDs, and object iteration.

Keep a watchful eye on version updates to maintain compatibility and avoid known issues.

Also applies to: 16-16, 18-18


22-50: Helper function uploadTestData
This function is an effective convenience method for populating test data in a GCS bucket. A few considerations:

  1. File path: Hardcoded "testdata/geojson.json" is fine for now, but dynamic path resolution may help if the file moves.
  2. Error messages: Consider returning the error instead of panic for better test control.

52-84: Bucket creation and teardown helpers
createBucket and deleteBucketWithObjects abstract away GCS complexities well. Using panic is okay for test setup, but returning errors could give more granular test control.


102-134: Test TestUploadAssetFromURL
This test thoroughly checks the end-to-end logic of uploading an asset from one bucket (source) to another (destination). The usage of a separate dev-based URL, ephemeral bucket names, and a random test file name is solid.

Consider adding assertions for file size or verifying the final content in the destination bucket if feasible.

server/internal/infrastructure/s3/s3.go (1)

106-109: Enhance error message for better context.

The error message could be more descriptive to help with debugging and maintenance.

Apply this diff to improve the error message:

func (f *fileRepo) UploadAssetFromURL(ctx context.Context, u *url.URL) (*url.URL, int64, error) {
-    // Note: not implemented
-    return nil, 0, errors.New("not implemented")
+    return nil, 0, errors.New("UploadAssetFromURL: not implemented for S3 storage")
}
.github/workflows/ci_server.yml (1)

33-39: Add container health check and cleanup.

The Fake GCS Server setup could be improved with health checking and proper cleanup.

Apply this diff to enhance the setup:

      - name: Start Fake GCS Server
        run: |
          docker run -d --name fake-gcs-server \
            -p 4443:4443 \
            -v /tmp/gcs:/storage \
            fsouza/fake-gcs-server:1.52.1 \
-            -scheme http
+            -scheme http && \
+          timeout 30s bash -c 'until curl -s http://localhost:4443 > /dev/null; do sleep 1; done'

+      - name: Cleanup Fake GCS Server
+        if: always()
+        run: docker rm -f fake-gcs-server
📜 Review details

Configuration used: .coderabbit.yaml
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 267cfbd and d512050.

📒 Files selected for processing (9)
  • .github/workflows/ci_server.yml (1 hunks)
  • docker-compose.yml (1 hunks)
  • server/internal/app/repo.go (1 hunks)
  • server/internal/infrastructure/fs/file.go (1 hunks)
  • server/internal/infrastructure/gcs/file.go (6 hunks)
  • server/internal/infrastructure/gcs/file_test.go (2 hunks)
  • server/internal/infrastructure/gcs/testdata/geojson.json (1 hunks)
  • server/internal/infrastructure/s3/s3.go (1 hunks)
  • server/internal/usecase/gateway/file.go (1 hunks)
✅ Files skipped from review due to trivial changes (2)
  • server/internal/infrastructure/gcs/testdata/geojson.json
  • docker-compose.yml
🔇 Additional comments (9)
server/internal/infrastructure/gcs/file.go (4)

8-8: Additional HTTP dependency looks good
The newly added import "net/http" is appropriate for the new remote URL fetching logic. No issues detected.


22-22: Required Google API options import
The introduction of the "google.golang.org/api/option" import aligns with the new client options. This is necessary to handle authentication and endpoint overrides. Looks fine.


289-292: Dev-specific client configuration
Conditionally constructing the storage.NewClient with WithoutAuthentication() and custom endpoint is a clean approach, ensuring production credentials remain separate. This looks good.


Line range hint 45-62: Constructor signature change
The updated signature NewFile(isDev bool, bucketName, base string, cacheControl string) makes sense to support a development endpoint. However, it might break existing call sites.

Please run a quick search to confirm that all invocations of NewFile are updated accordingly:

✅ Verification successful

All call sites are properly updated to use the new signature
The constructor change only affects the GCS implementation, and both the production usage in server/internal/app/repo.go and test usage in server/internal/infrastructure/gcs/file_test.go are using the correct signature with all required parameters.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Searching for all references to NewFile across the repo
rg -A 5 $'NewFile('

Length of output: 87


Script:

#!/bin/bash
# Search using ripgrep with escaped parentheses
echo "=== Searching with ripgrep ==="
rg -A 5 "NewFile\("

# Search using ast-grep for function calls
echo -e "\n=== Searching with ast-grep ==="
ast-grep --pattern 'NewFile($$$)'

Length of output: 18280

server/internal/usecase/gateway/file.go (1)

24-24: Interface extension
Adding UploadAssetFromURL to the File interface correctly abstracts the asset-fetching logic. Ensure other storage backends implement this method (even as a no-op or future placeholder) to maintain interface consistency.

✅ Verification successful

Interface consistency verified across all storage backends
All three File interface implementers (GCS, S3, and filesystem) have defined the UploadAssetFromURL method, with GCS having a full implementation while S3 and filesystem have placeholder implementations for future work.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Confirm that all other File interface implementers define UploadAssetFromURL
ast-grep --pattern $'type $_ struct { $$$ }\n\nfunc ($_ *$_) UploadAssetFromURL($_,$_)' 

Length of output: 86


Script:

#!/bin/bash
# Find the File interface definition
echo "=== File Interface Definition ==="
ast-grep --pattern 'type File interface {
  $$$
}'

# Find struct types and their UploadAssetFromURL implementations
echo -e "\n=== Struct Implementations ==="
rg "type.*struct" -A 20 server/internal/usecase/gateway/

Length of output: 3437


Script:

#!/bin/bash
# Find all implementations of UploadAssetFromURL
echo "=== UploadAssetFromURL Implementations ==="
rg "func.*UploadAssetFromURL" -A 2

# Find implementations of other File interface methods to identify implementers
echo -e "\n=== File Interface Implementers ==="
rg "func.*UploadAsset.*\(context\.Context, \*file\.File\)" -B 5

Length of output: 1356

server/internal/infrastructure/gcs/file_test.go (3)

4-7: Added imports for URL-based tests
Imports for "context", "errors", "fmt", and "io" are consistent with the newly introduced tests. This is standard for extended coverage.


9-10: Additional path and OS usage
Imports "os" and "path" seem necessary for handling file-based test data and path manipulations.


101-101: Empty line
No comment needed.

server/internal/app/repo.go (1)

112-112: LGTM: Development mode parameter added correctly.

The addition of conf.Dev parameter enables proper configuration for development environments, which is essential for testing with the Fake GCS Server.

server/internal/infrastructure/gcs/file.go Outdated Show resolved Hide resolved
server/internal/infrastructure/fs/file.go Outdated Show resolved Hide resolved
@pyshx pyshx changed the title chore(server): add UploadAssetFromURL on gsc file implementation chore(server): add UploadAssetFromURL on gcs file implementation Jan 28, 2025
@soneda-yuya soneda-yuya merged commit 75dbc0f into main Jan 28, 2025
21 checks passed
@soneda-yuya soneda-yuya deleted the chore/new-method-on-gcs branch January 28, 2025 15:11
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants