diff --git a/.gitignore b/.gitignore index 05b4672..41685e2 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,2 @@ -id_rsa +id node_modules/ \ No newline at end of file diff --git a/README.md b/README.md index 7abc703..846e3ed 100644 --- a/README.md +++ b/README.md @@ -21,6 +21,7 @@ this is a github action script for upload files to server via SFTP protocol. dryRun: true # Optional. Default to true. exclude: 'node_modules/,**/*.spec.ts' # Optional. exclude patterns (glob), use ',' to split, Default to ''. forceUpload: false # Optional, Force uploading all files, Default to false(upload only newer files). + removeExtraFilesOnServer: false # Optional, Remove extra files on server. Default to false. ``` ## Example usage diff --git a/action.yml b/action.yml index d4e6ce3..a355ed3 100644 --- a/action.yml +++ b/action.yml @@ -37,6 +37,9 @@ inputs: forceUpload: required: false default: false + removeExtraFilesOnServer: + required: false + default: false runs: using: 'node16' main: 'dist/index.js' diff --git a/lib/deployer.js b/lib/deployer.js index 3f2cb86..8bcac90 100644 --- a/lib/deployer.js +++ b/lib/deployer.js @@ -1,4 +1,4 @@ -const { lstat, opendir } = require('fs/promises'); +const { access, lstat, opendir } = require('fs/promises'); const Client = require('ssh2-sftp-client'); const path = require('path'); const M = require('minimatch'); @@ -17,7 +17,7 @@ class Deployer { removeRedundant: false, ...options }; - if(this.options.dryRun) console.warn('dryRun option is enabled! no files will be changed.'); + if (this.options.dryRun) console.warn('dryRun option is enabled! no files will be changed.'); this.sftp = new Client(); this.promises = []; } @@ -36,7 +36,7 @@ class Deployer { if (remoteStats === '-' || remoteStats === 'l') { if (this.options.forceUpload) { console.log(`${this.options.dryRun ? 'Dry-run: ' : ''}removing directory: ${remotePath} on remote.`); - if (!this.options.dryRun) await this.sftp.rmdir(remoteFile, true); + if (!this.options.dryRun) await this.sftp.rmdir(remotePath, true); } else { throw new Error(`remote has same name file as the directory: ${path.basename(remotePath)}`); } @@ -48,6 +48,20 @@ class Deployer { if (localStats.isDirectory()) { console.log(`checking dir: ${localPath}`); const dir = await opendir(localPath); + if (this.options.removeExtraFilesOnServer) { + const filesOnServer = await this.sftp.list(remotePath); + for (const file of filesOnServer) { + const localFile = path.join(localPath, file.name); + try { + await access(localFile); + } catch { + const isDirectory = file.type === 'd'; + console.log(`${this.options.dryRun ? 'Dry-run: ' : ''}removing extra ${isDirectory ? 'folder' : 'file'} '${file.name}' on remote.`); + const remoteFile = path.posix.join(remotePath, file.name); + if (!this.options.dryRun) isDirectory ? await this.sftp.rmdir(remoteFile, true) : await this.sftp.delete(remoteFile); + } + } + } for await (const dirent of dir) { const localFile = path.join(localPath, dirent.name); const remoteFile = path.posix.join(remotePath, dirent.name); @@ -72,7 +86,6 @@ class Deployer { } else { await this.uploadFile(localFile, remoteFile); } - } } else { const remoteFile = path.posix.join(remotePath, path.basename(localPath)); diff --git a/package.json b/package.json index 4e19687..9f56f17 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "sftp-upload-action", - "version": "1.4.5", + "version": "1.4.6", "description": "sftp upload using sftp-sync-deploy", "private": true, "scripts": { diff --git a/sftp.cjs b/sftp.cjs index a71f63e..405a734 100644 --- a/sftp.cjs +++ b/sftp.cjs @@ -16,7 +16,8 @@ const config = { const options = { dryRun: JSON.parse(core.getInput('dryRun')), // Enable dry-run mode. Default to true exclude: core.getInput('exclude').split(','), // exclude patterns (glob) - forceUpload: JSON.parse(core.getInput('forceUpload')) // Force uploading all files, Default to false(upload only newer files). + forceUpload: JSON.parse(core.getInput('forceUpload')), // Force uploading all files, Default to false(upload only newer files). + removeExtraFilesOnServer: JSON.parse(core.getInput('dryRun')) // Remove extra files on server, default to false. }; new Deployer(config, options) diff --git a/test.js b/test.js index 37cba6e..8ecfd11 100644 --- a/test.js +++ b/test.js @@ -3,8 +3,11 @@ const fs = require('fs'); new Deployer({ host: '192.168.0.99', - privateKey: fs.readFileSync('./id_rsa'), + privateKey: fs.readFileSync('./id'), localDir: './test', remoteDir: '/root/test/' -}, { exclude: ['node_modules'], dryRun: false }) - .sync(); \ No newline at end of file +}, { + exclude: ['node_modules'], + dryRun: false, + removeExtraFilesOnServer: true, +}).sync(); \ No newline at end of file