megahertz / electron-simple-publisher

Simple way to publish releases for electron-simple-updater
MIT License
66 stars 25 forks source link

Permission denied when using SSH as transport to publish updates #14

Closed yuanfang-dev closed 7 years ago

yuanfang-dev commented 7 years ago

I was using the configuration in example folder (changed the credentials to use my server) to test SSH uploading. I found that when using npm run release, there is always an error says 'Permission denied'. After a bit of investigation, I found the reason is that it always publishes assets in a new folder, which doesn't exist on the remote server. Am I missing something or should there be a mkdir if the path doesn't exist?

megahertz commented 7 years ago

Only the path which is configured through remotePath option should exist on a server. Could you provide more information? Like config (just replace your host and credentials), command output with --debug flag

yuanfang-dev commented 7 years ago

Hi, thanks for the quick reply! Here is the config file.

{
  "transport": {
    "module": "ssh",
    "host": "HOST",
    "username": "USER",
    "password": "PASS",
    "remotePath": "/download/",
    "remoteUrl": "http://HOST/static/download",
    "updatesJsonUrl": "http://HOST/static/download/updates.json"
  },
  "fields": {
    "readme": "The first version"
  }
}

What I was mentioning is not related to configurations. I was trying to publish a release file called Simple-Updater-Example-Setup-0.0.4.exe to /download folder. Instead of uploading the file to /download/Simple-Updater-Example-Setup-0.0.4.exe it always adds a folder path before the file so it becomes something like /download/win32-x64-prod-v0.0.4/Simple-Updater-Example-Setup-0.0.4.exe. However, there's no mkdir command prior to the upload command. So it's always got a permission denied error. If I create the dir manually before uploading, it works ok.

yuanfang-dev commented 7 years ago

I've also tried to add a mkdir before uploading. However, mkdir in node-ssh is buggy, when the local machine uses a different system (between windows and *nux) it changes the path from like /download to c:\download, which is pretty annoying. I've created an issue in their repo though.

megahertz commented 7 years ago

It seems that your remotePath is relative to home dir, but it should be absolute, I'll add this tip to documentation. Also, the updatesJsonUrl option should be in the root of publisher.json (or in package.json:updater.url)

yuanfang-dev commented 7 years ago

@megahertz Thanks, but It's actually nothing to do with my configuration. I've configured chroot on the sFTP server to prevent FTP users from accessing system paths, so it looks like a relative path.

In lib/transport/ssh.js line 184:

  getRemoteFilePath(localFilePath, build) {
    localFilePath = path.basename(localFilePath);
    return path.posix.join(
      this.options.remotePath,
      this.getBuildId(build),
      this.normalizeFileName(localFilePath)
    );
  }

A remote path consists of 3 parts:

  1. remotePath in configuration.
  2. A buildId which is something like ${platform}-${arch}-${channel}-v${version}.
  3. File name.

What I mean is that the second part (buildId) is a directory path, but before uploading, it's not been created, so it's always got a permission rejected error.

However it cannot be easily fixed by simply adding a mkdir using node-ssh, since node-ssh got a bug as well, when I use windows and the remote server is linux, the remote path will be converted to something like c:\absolute\path which is definately wrong.

yuanfang-dev commented 7 years ago

I'm writing a patch for node-ssh now, hopefully it will be merged soon and I think we can add a mkdir in this module. What do you think?

megahertz commented 7 years ago

I haven't used this module with chroot before, I'll try later. As another solution it's possible to add beforeUploadCommand to SshTransport for dir creating.

yuanfang-dev commented 7 years ago

@megahertz It's actually nothing to do with chroot either. Without chroot this issue still occurs. Even if we use beforeUploadCommand, node-ssh is still buggy with mkdir, it tries to reuse mkdirp module (for local files but with an api to provide an adapter). The code quality isn't really good. Is it possible to switch to ssh2-sftp-client? It seems to be better. The API is rather neat:

let Client = require('ssh2-sftp-client');
let sftp = new Client();
sftp.connect({
    host: '127.0.0.1',
    port: '8080',
    username: 'username'
    password: '******'
}).then(() => {
    return sftp.list('/pathname');
}).then((data) => {
    console.log(data, 'the data info');
}).catch((err) => {
    console.log(err, 'catch error');
});
megahertz commented 7 years ago

@wangtao2012 Thank you for the investigation. I think that ssh2-sftp-client is a pretty good and I'll try to use it later. But I'll be very busy on the next week, so I can't promise you that I can do it quickly.

yuanfang-dev commented 7 years ago

Hi, @megahertz I opened a ticket there and I've got the answer from the author, 'node-ssh' actually does support this with an extra parameter. I'll try to create a pull request later

megahertz commented 7 years ago

Thank you @wangtao2012