@octopusdeploy/octojs
Advanced tools
Comparing version 0.1.3 to 0.1.4
@@ -0,0 +0,0 @@ #!/usr/bin/env node |
@@ -0,5 +1,5 @@ | ||
'use strict'; | ||
var url = require('url'); | ||
var isReadableStream = require('../utils/isReadableStream'); | ||
var path = require('path'); | ||
@@ -13,94 +13,145 @@ var fs = require('fs'); | ||
function validateFile(file) { | ||
if(!file){ | ||
throw new Error("No file has been provided to be pushed"); | ||
} | ||
return true; | ||
} | ||
module.exports = function push(file, options, cb) { | ||
if(!validateFile(file) || !validateArgs(options, cb)) return; | ||
if(isReadableStream(file)) { | ||
streamToBuffer(file, function (err, buffer) { | ||
if(err){ | ||
cb(err); | ||
} else { | ||
performPost(buffer); | ||
} | ||
}); | ||
} else { | ||
performPost(file); | ||
} | ||
if (!validateFile(file) || !validateArgs(options, cb)) { | ||
return; | ||
} | ||
function performPost(fileBytes) { | ||
if (isReadableStream(file)) { | ||
streamToBuffer(file, function (err, buffer) { | ||
if (err) { | ||
cb(err); | ||
} else { | ||
performPost(buffer); | ||
} | ||
}); | ||
} else { | ||
performPost(file); | ||
} | ||
var requestOptions = { | ||
url: getUri(options), | ||
headers: { | ||
'X-Octopus-ApiKey': options.apiKey | ||
}, | ||
formData: extractFormData(fileBytes, options), | ||
json: true, | ||
timeout: (options.request | DEFAULT_TIMEOUTSECONDS) * 1000 | ||
}; | ||
function performPost(fileBytes) { | ||
getUri(options, function (err, url) { | ||
if(err){ | ||
cb(err); | ||
return; | ||
} | ||
log.info('Pushing to ' + requestOptions.url); | ||
request.post(requestOptions, function (err, resp, body) { | ||
if (err) { | ||
cb(err); | ||
} else { | ||
log.info('Push response ' + resp.statusCode +' - '+ resp.statusMessage); | ||
if (resp.statusCode === 200 || resp.statusCode === 201) { | ||
cb(null, body); | ||
} else { | ||
cb({ | ||
statusCode: resp.statusCode, | ||
statusMessage: resp.statusMessage, | ||
body: body, | ||
response: resp | ||
}); | ||
} | ||
} | ||
}); | ||
} | ||
var requestOptions = { | ||
url: url, | ||
headers: { | ||
'X-Octopus-ApiKey': options.apiKey | ||
}, | ||
formData: extractFormData(fileBytes, options), | ||
json: true, | ||
timeout: (options.request | DEFAULT_TIMEOUTSECONDS) * 1000 | ||
}; | ||
function getUri(options) { | ||
var packageUri = options.server.replace(/\/?$/, '/'); | ||
log.info('Pushing to ' + requestOptions.url); | ||
packageUri = url.resolve(packageUri, 'api/packages/raw'); | ||
if (!!options.replace) { | ||
packageUri += '?replace=true'; | ||
} | ||
return packageUri; | ||
} | ||
request.post(requestOptions, function (err, resp, body) { | ||
if (err) { | ||
log.info('Error in posting ' + err) | ||
cb(err); | ||
} else { | ||
if (resp.statusCode === 200 || resp.statusCode === 201) { | ||
log.info('Push response ' + resp.statusCode + ' - ' + resp.statusMessage); | ||
cb(null, body); | ||
} else { | ||
log.info('Push response ' + resp.statusCode + ' - ' + resp.statusMessage); | ||
cb({ | ||
statusCode: resp.statusCode, | ||
statusMessage: resp.statusMessage, | ||
body: body, | ||
response: resp | ||
}); | ||
} | ||
} | ||
}); | ||
}); | ||
function extractFormData(file, options) { | ||
} | ||
}; | ||
var fileContents; | ||
var fileName = options.name; | ||
if (typeof file === 'string') { | ||
fileContents = fs.createReadStream(file); | ||
fileName = fileName || file; | ||
} else if (Buffer.isBuffer(file) || isReadableStream(file)) { | ||
fileContents = file; | ||
} | ||
function getUri(options, cb) { | ||
var serverRoot = options.server.replace(/\/?$/, '/'); | ||
if (!fileName) { | ||
throw new Error('Filename is missing from options'); | ||
} | ||
if (options.space) { | ||
resolveSpaceId(options, function (err, spaceId) { | ||
if (err) { | ||
cb(err); | ||
} else { | ||
cb(null, buildPath(spaceId)); | ||
} | ||
}); | ||
} else { | ||
cb(null, buildPath(null)); | ||
} | ||
return { | ||
file: { | ||
value: fileContents, | ||
options: { | ||
filename: path.basename(fileName), | ||
contentType: 'application/octet-stream' | ||
} | ||
} | ||
}; | ||
} | ||
function buildPath(spaceId) { | ||
var packageUri = url.resolve(serverRoot, spaceId ? 'api/' + spaceId + '/packages/raw' : 'api/packages/raw'); | ||
if (!!options.replace) { | ||
packageUri += '?replace=true'; | ||
} | ||
return packageUri; | ||
} | ||
function resolveSpaceId(options, cb) { | ||
var requestOptions = { | ||
url: url.resolve(options.server, '/api/spaces/all'), | ||
headers: { | ||
'X-Octopus-ApiKey': options.apiKey | ||
}, | ||
json: true | ||
}; | ||
log.info('Trying to resolve space name \'' + options.space + '\''); | ||
request.get(requestOptions, function (err, resp, body) { | ||
if (resp.statusCode === 200 || resp.statusCode === 201) { | ||
var foundSpace = body.filter(function (space) { | ||
return space.Name === options.space || space.Id === options.space; | ||
})[0]; | ||
if (foundSpace) { | ||
cb(null, foundSpace.Id); | ||
return; | ||
} | ||
} | ||
cb('Unable to resolve space \'' + options.space + '\''); | ||
}); | ||
} | ||
} | ||
function validateArgs(args, cb) { | ||
function extractFormData(file, options) { | ||
var fileContents; | ||
var fileName = options.name; | ||
if (typeof file === 'string') { | ||
fileContents = fs.createReadStream(file); | ||
fileName = fileName || file; | ||
} else if (Buffer.isBuffer(file) || isReadableStream(file)) { | ||
fileContents = file; | ||
} | ||
if (!fileName) { | ||
throw new Error('Filename is missing from options'); | ||
} | ||
return { | ||
file: { | ||
value: fileContents, | ||
options: { | ||
filename: path.basename(fileName), | ||
contentType: 'application/octet-stream' | ||
} | ||
} | ||
}; | ||
} | ||
function validateFile(file) { | ||
if(!file){ | ||
throw new Error('No file has been provided to be pushed'); | ||
} | ||
return true; | ||
} | ||
function validateArgs(args) { | ||
validateApiKey(); | ||
@@ -113,3 +164,3 @@ validateServerUrl(); | ||
if(!args.apiKey) { | ||
throw new Error("You must provide an API key to access the Octopus Server.") | ||
throw new Error('You must provide an API key to access the Octopus Server.'); | ||
} | ||
@@ -120,6 +171,6 @@ } | ||
if(!args.server) { | ||
throw new Error("You must provide the server address to access the Octopus Server."); | ||
throw new Error('You must provide the server address to access the Octopus Server.'); | ||
} | ||
try{ | ||
new url.Url(args.server) | ||
new url.Url(args.server); | ||
} catch(ex){ | ||
@@ -129,2 +180,2 @@ throw new Error('Server argument `'+ args.server +'` does not appear to be a valid url'); | ||
} | ||
} | ||
} |
{ | ||
"name": "@octopusdeploy/octojs", | ||
"version": "0.1.3", | ||
"version": "0.1.4", | ||
"description": "A nodejs cli tool for packaging and pushing projects to an Octopus Deploy instance.", | ||
@@ -5,0 +5,0 @@ "main": "index.js", |
@@ -5,3 +5,3 @@ octopack | ||
**NOTE: This project is currently in a pre-release state and its api is subject to change at any time.** | ||
**NOTE: This project is currently in a pre-release state and its api is subject to change at any time.** | ||
@@ -50,3 +50,3 @@ # Installation | ||
- if executing through the cli then the `--include` argument can be provided multiple times to specify multiple glob paths. | ||
- if executing through code, then the files can individually be provided by using the `.append()` method. This method allows globs, file paths, buffers or streams. | ||
- if executing through code, then the files can individually be provided by using the `.append()` method. This method allows globs, file paths, buffers or streams. | ||
@@ -122,2 +122,3 @@ ### cli | ||
--replace If the package already exists in the repository, the default behavior is to reject the new package being pushed. You can pass this flag to overwrite the existing package. | ||
--space Name or Id of the target space. | ||
--timeout <seconds> Timeout in seconds for network operations. (default 600) | ||
@@ -142,3 +143,4 @@ -C, --config <path> Path to config file | ||
apiKey: 'API-XXX223123', | ||
server: 'http://octopus-server' | ||
server: 'http://octopus-server', | ||
space: 'My Octopus Space' // optional | ||
}, (err, result) => { | ||
@@ -145,0 +147,0 @@ if(err){ |
@@ -7,8 +7,45 @@ 'use strict'; | ||
var request = require('request'); | ||
var fs = require('fs'); | ||
// api/spaces/all | ||
var sp = JSON.stringify([ | ||
{ | ||
"Id": "Spaces-1", | ||
"Name": "Default", | ||
"Description": null, | ||
"IsDefault": true, | ||
"TaskQueueStopped": false, | ||
"SpaceManagersTeams": [ | ||
"teams-administrators", | ||
"teams-managers", | ||
"teams-spacemanagers-Spaces-1" | ||
], | ||
"SpaceManagersTeamMembers": [ | ||
"Users-1" | ||
] | ||
}, | ||
{ | ||
"Id": "Spaces-2", | ||
"Name": "Octopus", | ||
"Description": null, | ||
"IsDefault": false, | ||
"TaskQueueStopped": false, | ||
"SpaceManagersTeams": [ | ||
"teams-spacemanagers-Spaces-2", | ||
"teams-administrators" | ||
], | ||
"SpaceManagersTeamMembers": [ | ||
"Users-1" | ||
] | ||
} | ||
]); | ||
describe('push', function() { | ||
var postStub; | ||
var getStub; | ||
beforeEach(function(){ | ||
postStub = sinon.stub(request, 'post'); | ||
getStub = sinon.stub(request, 'get').yields(null, {statusCode : 200, statusMessage: "OK"}, JSON.parse(sp)); | ||
}); | ||
@@ -18,2 +55,3 @@ | ||
postStub.restore(); | ||
getStub.restore(); | ||
}); | ||
@@ -62,2 +100,24 @@ | ||
describe('resolve space id', function () { | ||
it('should call out to the spaces/all endpoint', function() { | ||
octo.push( | ||
new Buffer('hello world'), | ||
{ replace: true, server: 'http://myweb/', name: 'package.1.0.0.tar', apiKey: "KEY", space: "Octopus"}, | ||
function(e,f) {} | ||
); | ||
var req = getStub.lastCall.args[0]; | ||
expect(req.url).to.equal('http://myweb/api/spaces/all'); | ||
}); | ||
it('should resolve a spaceID from a spaceName', function () { | ||
octo.push( | ||
new Buffer('hello world'), | ||
{ replace: true, server: 'http://myweb/', name: 'package.1.0.0.tar', apiKey: "KEY", space: "Octopus"}, | ||
function(e, f) {} | ||
); | ||
var req = postStub.lastCall.args[0]; | ||
expect(req.url).to.equal('http://myweb/api/Spaces-2/packages/raw?replace=true'); | ||
}); | ||
}); | ||
it('should return response body if request successful', function(done) { | ||
@@ -80,2 +140,2 @@ var body = { prop: 12 }; | ||
}); | ||
}); | ||
}); |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
New author
Supply chain riskA new npm collaborator published a version of the package for the first time. New collaborators are usually benign additions to a project, but do indicate a change to the security surface area of a package.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
66397
888
154
5
2