
Security News
The Nightmare Before Deployment
Season’s greetings from Socket, and here’s to a calm end of year: clean dependencies, boring pipelines, no surprises.
grunt-ssh-deploy-release
Advanced tools
Create an archive of "localPath" (except excluded folders).
Copy this archive to the remote server using SCP.
Decompress the release on remote server.
Create "shared" folders symlink.
Create release symlink.
Clean temporary files and old releases.
/deployPath
|
├── www --> symlink to ./releases/<currentRelease>
|
├── releases
| ├── 2017-02-08-17-14-21-867-UTC
| ├── ...
| └── 2017-02-09-18-01-10-765-UTC
| ├── ...
| └── logs --> symlink to shared/logs
|
└── shared
└── logs
npm install grunt-ssh-deploy-release
grunt.config.set('ssh-deploy-release', {
// Global options
// ==============
options: {
// Local folder to deploy
localPath: 'www',
// Excluded local folders
exclude: [
'tmp/**',
'images/**',
],
// Shared folders (use symlink)
// Example : 'sharedFolder' : 'linkName'
share: {
'images': 'assets/images',
'upload': {
symlink: 'app/upload',
mode: '777',
},
},
// Create folder + make writable
create: [
'tmp',
'logs'
],
// Make writable folders
makeWritable: [
'test',
'foo'
]
},
// Environments
// ============
// Preproduction
preproduction: {
options: {
host: 'hostname',
username: 'username',
password: 'password',
deployPath: '/opt/path/to'
}
},
// Production
production: {
options: {
host: 'hostname',
username: 'username',
password: 'password',
deployPath: '/opt/path/to'
}
}
});
grunt ssh-deploy-release:environmentName
grunt ssh-deploy-release:environmentName --remove
See allowRemove option.
Use --debug option :
grunt ssh-deploy-release:environmentName --debug
ssh-deploy-release uses ssh2 to handle SSH connections.
The options object is forwarded to ssh2 methods,
which means you can set all ssh2 options:
Port used to connect to the remote server.
Default : 22
Remote server hostname.
Username used to connect to the remote server.
Password used to connect to the remote server.
For an encrypted private key, this is the passphrase used to decrypt it.
Default: (null)
Default: null
'archive' : Deploy an archive and decompress it on the remote server.
'synchronize' : Use rsync. Files are synchronized in the synchronized folder on the remote server.
Default : 'archive'
'zip' : Use zip compression (unzip command on remote)
'tar' : Use tar gz compression (tar command on remote)
Default : 'tar'
Name of the archive.
Default : 'release.tar.gz'
Delete the local archive after the deployment.
Default : true
SCP connection timeout duration.
Default : 20000
Name of the current release symbolic link. Relative to deployPath.
Defaut : 'www'
Name of the folder containing shared folders. Relative to deployPath.
Default : 'shared'
Name of the folder containing releases. Relative to deployPath.
Default : 'releases'
Name of the local folder to deploy.
Default : 'www'
Absolute path on the remote server where releases will be deployed. Do not specify currentReleaseLink (or www folder) in this path.
Name of the remote folder where rsync synchronize release.
Used when mode is 'synchronize'.
Default : 'www'
Additional options for rsync process.
Default : ''
rsyncOptions : '--exclude-from="exclude.txt" --delete-excluded'
Number of releases to keep on the remote server.
Default : 3
Name of the release. Must be different for each release.
Default : Use current timestamp.
List of paths (glob format) to not deploy. Paths must be relative to localPath.
Not working with mode: 'synchronize', use rsyncOptions instead.
Default : []
List of folders to "share" between releases. A symlink will be created for each item.
Item can be either a string or an object (to specify the mode to set to the symlink target).
share: {
'images': 'assets/images',
'upload': {
symlink: 'app/upload',
mode: '777' // Will chmod 777 shared/upload
}
}
Keys = Folder to share (relative to sharedFolder)
Values = Symlink path (relative to release folder)
List of folders to create on the remote server.
List of files to make writable on the remote server. (chmod ugo+w)
List of files to make executable on the remote server. (chmod ugo+x)
If true, the remote release folder can be deleted with --remove cli parameter.
Default: false
The following object is passed to onXXXDeploy functions :
{
// Current configuration
options: { ... },
// Current release name
releaseTag: '2017-01-25-08-40-15-138-UTC',
// Current release path on the remote server
releasePath: '/opt/.../releases/2017-01-25-08-40-15-138-UTC',
// Use this function to execute some commands on the remote server
execRemote: [Function: execRemote]
}
onBeforeDeploy, onBeforeLink, onAfterDeploy options.
You have to call callback function to continue deployment process.
onAfterDeploy: (deployer, callback) => {
const command = 'pwd';
const showLog = false;
deployer.execRemote(command, showLog, callback);
}
onBeforeDeployExecute, onBeforeLinkExecute, onAfterDeployExecute options.
onAfterDeployExecute: [
'do something on the remote server',
'and another thing'
]
Or with a function :
onAfterDeployExecute: (deployer) => {
grunt.log.subhead('Doing something');
return [
'do something on the remote server',
'and another thing'
];
}
Function called before deployment. Call callback to continue;
Type: function(deployer, callback)
Array (or function returning array) of commands to execute on the remote server.
Type: function(deployer) | []
Function called before symlink creation. Call callback to continue;
Type: function(deployer, callback)
Array (or function returning array) of commands to execute on the remote server.
Type: function(deployer) | []
Function called after deployment. Call callback to continue;
Type: function(deployer, callback)
Array (or function returning array) of commands to execute on the remote server.
Type: function(deployer) | []
grunt.config.set('ssh-deploy-release', {
options: {
localPath: 'public',
},
production: {
options: {
host: 'hostname',
username: 'username',
password: 'password',
deployPath: '/opt/path/to'
}
},
onAfterDeployExecute: (deployer) => {
grunt.log.subhead('Restart php-fpm and apache');
return [
'sudo /opt/bitnami/ctlscript.sh restart apache'
];
}
});
For example, create one environement by git branch.
grunt.config.set('ssh-deploy-release', {
options: {
localPath: 'public',
},
review: {
options: {
host: 'hostname',
username: 'username',
password: 'password',
deployPath: '/opt/path/to/' + grunt.option('branch'),
allowRemove: true
}
},
});
grunt ssh-deploy-release:review --branch="BRANCH_NAME"
grunt ssh-deploy-release:review --branch="BRANCH_NAME" --remove
In order to avoid mistakes (remove production..),
allowRemovemust be true to remove release on the remote server
Example of .gitlab-ci.yml :
Deploy review:
stage: deploy
except:
- preproduction
- production
environment:
name: review/$CI_BUILD_REF_SLUG
url: http://host/$CI_BUILD_REF_SLUG/www/
on_stop: stop_review
script:
- yarn
- grunt ssh-deploy-release:review --branch="$CI_BUILD_REF_SLUG"
stop_review:
stage: deploy
script:
- yarn
- grunt ssh-deploy-release:review --branch="$CI_BUILD_REF_SLUG" --remove
when: manual
variables:
GIT_STRATEGY: none
except:
- preproduction
- production
environment:
name: review/$CI_BUILD_REF_SLUG
action: stop
A command on a callback method is not executed or not found.
Try to add set -i && source ~/.bashrc && before your commmand :
onAfterDeployExecute:[
'set -i && source ~/.bashrc && my command'
]
See this issue : https://github.com/mscdex/ssh2/issues/77
FAQs
Grunt plugin for deploying release on remote server over ssh.
The npm package grunt-ssh-deploy-release receives a total of 6 weekly downloads. As such, grunt-ssh-deploy-release popularity was classified as not popular.
We found that grunt-ssh-deploy-release demonstrated a not healthy version release cadence and project activity because the last version was released a year ago. It has 1 open source maintainer collaborating on the project.
Did you know?

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Security News
Season’s greetings from Socket, and here’s to a calm end of year: clean dependencies, boring pipelines, no surprises.

Research
/Security News
Impostor NuGet package Tracer.Fody.NLog typosquats Tracer.Fody and its author, using homoglyph tricks, and exfiltrates Stratis wallet JSON/passwords to a Russian IP address.

Security News
Deno 2.6 introduces deno audit with a new --socket flag that plugs directly into Socket to bring supply chain security checks into the Deno CLI.