electron / forge

:electron: A complete tool for building and publishing Electron applications
https://electronforge.io
MIT License
6.42k stars 507 forks source link

Add Google Cloud Storage publisher #1751

Open mahnunchik opened 4 years ago

mahnunchik commented 4 years ago

Preflight Checklist

Problem Description

It is impossible to use @electron-forge/publisher-s3 with Google Cloud Storage. Documentation: https://cloud.google.com/storage/docs/interoperability

An unhandled error has occurred inside Forge:
Invalid argument.
InvalidArgument: Invalid argument.
{
  Code: 'InvalidArgument',
  Message: 'Invalid argument.',
  Details: 'POST object expects Content-Type multipart/form-data'
}

Proposed Solution

I think it is possible to make @electron-forge/publisher-s3 compatible with Google Cloud Storage.

Alternatives Considered

GCS publisher.

Additional Information

"publishers": [
        {
          "name": "@electron-forge/publisher-s3",
          "config": {
            "bucket": "my-backet",
            "endpoint": "https://storage.googleapis.com",
            "public": false
          }
        }
      ]
malept commented 4 years ago

I will be happy to review a pull request to add this functionality! You'd have to research whether aws-sdk's S3 client allows you to specify the Content-Type header somewhere, and make sure that the change still works with AWS S3 itself.

mahnunchik commented 4 years ago

@malept another approach is to upload files with PUT request as google recommended.

malept commented 4 years ago

@mahnunchik it already uses PUT.

mahnunchik commented 4 years ago

@malept it is really strange, google say Details: 'POST object expects Content-Type multipart/form-data'

I was able to upload file with PUT request.

mahnunchik commented 4 years ago

@malept it uses POST

Original response from error handler:

Response {
  request: Request {
    domain: null,
    service: Service {
      config: [Config],
      endpoint: [Endpoint],
      _events: [Object],
      MONITOR_EVENTS_BUBBLE: [Function: EVENTS_BUBBLE],
      CALL_EVENTS_BUBBLE: [Function: CALL_EVENTS_BUBBLE],
      _clientId: 2
    },
    operation: 'createMultipartUpload',
    params: {
      Bucket: 'my-bucket',
      Key: '1.0.1/App-darwin-x64-1.0.1.zip',
      ACL: 'private'
    },
    httpRequest: HttpRequest {
      method: 'POST',
      path: '/1.0.1/App-darwin-x64-1.0.1.zip?uploads',
      headers: [Object],
      body: '',
      endpoint: [Endpoint],
      region: 'us-east-1',
      _userAgent: 'aws-sdk-nodejs/2.692.0 darwin/v12.16.2',
      virtualHostedBucket: 'my-bucketi',
      stream: [ClientRequest]
    },
    startTime: 2020-06-09T15:24:50.048Z,
    response:...
malept commented 4 years ago

I'm going off of the AWS SDK docs:

Key — (String)

Object key for which the PUT operation was initiated.

Perhaps s3.upload decides to make it a POST because it's a multi-part upload (i.e., too large). There's no logic in the S3 Publisher to determine PUT vs POST.

At any rate, the first link is what we use to upload artifacts using the S3 API.

mahnunchik commented 4 years ago

@malept Yep, documentation of AWS SDK says it uses PUT but not in this case...

I may confirm: uploaded file was small (manifest).

malept commented 4 years ago

You might have to figure out how to change aws-sdk to emit the correct Content-Type header, then.

mahnunchik commented 4 years ago

@malept it is too weird to make aws-sdk to works with Google, so I've implemented publisher based on official Google library. Could you please have a look https://github.com/electron-userland/electron-forge/pull/1752

maccman commented 3 years ago

This would be cool to get merged.

mahnunchik commented 1 year ago

Ping https://github.com/electron/forge/pull/2100