Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Globalize #54

Open
wants to merge 4 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 11 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -3,3 +3,14 @@
*.tgz
node_modules
test/.test_artifacts
intl/MSG.json
intl/de
intl/es
intl/fr
intl/it
intl/ja
intl/ko
intl/pt
intl/ru
intl/zh-Hans
intl/zh-Hant
33 changes: 18 additions & 15 deletions bin/sl-deploy.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,21 +5,23 @@
var Parser = require('posix-getopt').BasicParser;
var debug = require('debug')('strong-deploy');
var defaults = require('strong-url-defaults');
var getPackageInfo = require('../lib/package').getPackageInfo;
var defaultPackagePath = require('../lib/package').getPackagePath;
var deploy = require('../');
var fs = require('fs');
var getPackageInfo = require('../lib/package').getPackageInfo;
var g = require('strong-globalize');
var maybeTunnel = require('strong-tunnel');
var path = require('path');

function printHelp($0, prn) {
var USAGE = fs.readFileSync(require.resolve('./sl-deploy.txt'), 'utf-8')
.replace(/%MAIN%/g, $0)
.trim();

var USAGE = g.t('sl-deploy.txt')
.replace(/%MAIN%/g, $0).
trim();
prn(USAGE);
}

g.setRootDir(path.resolve(__dirname, '..'));

var argv = process.argv;
var $0 = process.env.CMD ? process.env.CMD : path.basename(argv[1]);
var parser = new Parser([
Expand Down Expand Up @@ -56,7 +58,7 @@ while ((option = parser.getopt()) !== undefined) {
local = true;
break;
default:
console.error('Invalid usage (near option \'%s\'), try `%s --help`.',
g.error('Invalid usage (near option \'%s\'), try {{`%s --help`}}.',
option.optopt,
$0);
process.exit(1);
Expand All @@ -65,7 +67,7 @@ while ((option = parser.getopt()) !== undefined) {

var numArgs = argv.length - parser.optind();
if (numArgs > 2) {
console.error('Invalid usage, try `%s --help`.', $0);
g.error('Invalid usage, try {{`%s --help`}}.', $0);
process.exit(1);
}

Expand All @@ -78,11 +80,12 @@ var packageInfo = getPackageInfo(workingDir);
serviceName = serviceName || (packageInfo ? packageInfo.name : null);

if (!serviceName) {
console.error(
'Unable to detect service name, package.json has no "name" property.\n' +
'Please update your package.json or specify a service name.\n' +
'See `%s --help` for more details.', $0
);
g.error(
'Unable to detect service name, {{package.json}} ' +
'has no "name" property.\n' +
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

name has to be protected

'Please update your package.json or specify a service name.\n' +
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

package.json needs protection

'See {{`%s --help`}} for more details.', $0
);
process.exit(1);
}

Expand Down Expand Up @@ -118,7 +121,7 @@ if (!local) {
maybeTunnel(baseURL, sshOpts, function(err, url) {
exit.url = url;
if (err) {
console.error('Error setting up tunnel:', err);
g.error('Error setting up tunnel: %s', err);
return exit(err);
}
debug('Connecting to %s via %s', baseURL, url);
Expand All @@ -144,11 +147,11 @@ if (!local) {
function exit(err, service) {
var svc = service ? (service.name || service.id) : serviceName;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I am trying to find the globalize docs for this { key}, {key: value} syntax, where are they?

Some tools do:

glb.error('this {$1} is a {$2}, 'statue', 'dog')... basically keys prefixed with a$` are positional args. its more concise for some uses. Does globalize support this? If not, maybe we can suggest it.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

strong-globalize supports both glb.error('this {0} is a {1}, ['statue', 'dog']) and glb.error('this {statue} is a {dog}, {statue: 'statue', dog: 'dog'}). i don't think we want to advertise the former notation, do we?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why not? Its way more concise, and its concision makes it less error prone to use, particularly when converting from code that already uses positional args. Note the error you made at #54 (comment). Its easy to do that kind of thing, and its particularly bad because there are _three_ identical strings that must be identical, or the code is broken, and made worse because unit tests to cover this kind of thing are hard to build. The above is an error case, and we often don't test the exact message output from CLIs, particularly for errors, the tests are hard to build and fragile, but the effect is bugs like the above are easy to miss, and easy to create during what is a rote, bulk translation exercise.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

opened the gate in strong=globalize/lint for {0}, {1}, .. placeholder names.

var dt = glb.d(new Date());
"{dateTime} Hello World"
glb.t('{dateTime} Hello World', {dateTime: dt});

"{0} Hello World"
glb.t('{0} Hello World', {0: dt});

"{0} Hello World"
glb.t('{0} Hello World', [dt]);

They are all supported. I think the former gives more context to the human translator. No difference for machines.

if (err) {
console.error('Failed to deploy `%s` as `%s` to `%s` via `%s`',
g.error('Failed to deploy `%s` as `%s` to `%s` via `%s`',
branchOrPack, svc, baseURL, exit.url);
process.exit(1);
} else {
console.log('Deployed `%s` as `%s` to `%s`', branchOrPack, svc, baseURL);
g.log('Deployed `%s` as `%s` to `%s`', branchOrPack, svc, baseURL);
process.exit(0);
}
}
64 changes: 0 additions & 64 deletions bin/sl-deploy.txt

This file was deleted.

27 changes: 27 additions & 0 deletions intl/en/messages.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
{
"a92646afd9c4b22bb4e2aa68259c2273": "Invalid usage (near option '{0}'), try {{`{1} --help`}}.",
"3c9e808f506d30fa603f262b8b2d952f": "Invalid usage, try {{`{0} --help`}}.",
"32494893ae5067ca7944c5d50a699445": "Unable to detect service name, {{package.json}} has no \"name\" property.\nPlease update your package.json or specify a service name.\nSee {{`{0} --help`}} for more details.",
"7e23e9511e64cbc6e4e5a801b5fd3e14": "Error setting up tunnel: {0}",
"0a402996683b8af6001a51d13edae1e2": "Failed to deploy `{0}` as `{1}` to `{2}` via `{3}`",
"0099b15ad24474f028c0a35a53f52fd9": "Deployed `{0}` as `{1}` to `{2}`",
"14946b39b8b24c3bf42f87461d71e61a": "Failed to connect to {0}: {1}",
"0c5caf9bcef355ca74967f6d820a94ea": "Cannot access remote. If authentication is required, credentials should be given in the URL.",
"7daa7e1103db022989b15f9911a008b2": "Error connecting to server: {0}",
"1b96db9d6574f771b8a481d6692b19d1": "Directory {0} does not exist",
"dcd9e9c0430b4ae8667b3aeddd87a0e5": "This directory does not contain a valid {{git}} repository",
"63e17bd19141679739ef73ea050d5d07": "Branch `{0}` is not available in this repository",
"70e3014d13daf4aa92c75300671854b6": "invalid branch",
"aa9c1df2cd67ed86e10427cda41a7f34": "URL `{0}` is not valid",
"699165228b0c9f2ceba22cb3c009c3c5": "invalid url",
"b4a6153b6150d282c79cf75d0705785e": "{{git push}} failed",
"7505a317caea95d045fe62de0b6e5819": "Invalid URL `{0}`. Only http:// URLs are supported.",
"f9c7939a8397ee022fefee2bdb3407af": "Invalid URL",
"ad48139ecdc33ed94bb5166e62b573b1": "Invalid URL `{0}`. Only {{localhost}} URLs are supported.",
"0dee2a33280f6051b6e3f06a0d537c31": "Cannot deploy `{0}`: not an {{npm}} package directory",
"428d89a07f67cc0fb564cb71afc7c63b": "Invalid path, not a directory",
"d870f51884c0ce8fd49309c7c865a046": "HTTP error {0}",
"528f2bc3a794ad63da2e1bfd5fc79fe0": "Deploy `{0}` to `{1}` failed: {2}",
"5979ce669741c05125c9cd188b25490f": "Error while reading file: {0}",
"8b11479607ff0842f800cf914692bb45": "Valid credentials must be given in the URL."
}
64 changes: 64 additions & 0 deletions intl/en/sl-deploy.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
usage: {{%MAIN% [options] [URL [PACK|BRANCH]]}}

Deploy a node application to a StrongLoop process manager

Options:
{{-h,--help}} Print this message and exit.
{{-v,--version}} Print version and exit.
{{-s,--service SVC}} Deploy to service {{SVC}}.
{{-z,--size SIZE}} Set size of cluster to {{SIZE}} before deploy.

Arguments:
{{SIZE}}: A number, n, or the string '{{cpus}}', meaning run a worker per CPU.

{{SVC}}: The name or ID of the service on the process manager.

Defaults to the name of the application specified in the {{package.json}} file.

If a service with that name is not available on the process manager,
a new service will be created and the application will be deployed.

{{URL}}: The URL of the StrongLoop process manager.

Defaults to `{{http://localhost:8701}}`. If a URL is provided, both the host
and port is optional, they default to `{{localhost}}` and 8701, respectively.
If the server requires authentication, the credentials must be part of the
URL, see examples.

URL may also use the `{{http+ssh://}}` protocol which will connect using ssh
and then tunnel the http requests over that connection. The ssh username
will default to your current user and authentication defaults to using your
current ssh-agent. The {{username}} can be overridden by setting an `{{SSH_USER}}`
environment variable. The authentication can be overridden to use an
existing private key instead of an agent by setting the `SSH_KEY`
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

SSH_KEY

environment variable to the path of the private key to be used. The port
used for ssh can be overridden by setting an `{{SSH_PORT}}` environment
variable.

{{PACK}}: Deploy an {{NPM package/tarball}}.

{{BRANCH}}: Deploy a {{git}} branch.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

git did, so npm does need protection

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

sure


Default behaviour is to deploy to `{{http://localhost:8701}}`. An {{npm}} package from
the parent directory is deployed, if one is found for the current application
version, otherwise the {{git}} branch `{{deploy}}` is deployed.

Note that if {{PACK}} or {{BRANCH}} is specified, URL *must* be specified as well.

Examples:

Deploy the default {{npm}} package or {{git}} branch to {{localhost}}:

{{%MAIN%}}

Deploy the default {{npm}} package or {{git}} branch to a remote host:

{{%MAIN% http://prod1.example.com}}

Deploy to a remote host, on a non-standard port, using authentication:

{{%MAIN% http://user:[email protected]:8765}}

Deploy '{{production}}' branch to {{localhost}}:

{{%MAIN% http://localhost production}}
7 changes: 4 additions & 3 deletions lib/deploy-endpoint.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,15 @@

var MeshClient = require('strong-mesh-models').Client;
var debug = require('debug')('strong-deploy');
var g = require('strong-globalize');

exports.get = getDeployEndpoint;

function getDeployEndpoint(url, serviceName, clusterSize, callback) {
var client = new MeshClient(url);
client.checkRemoteApiSemver(function(err) {
if (err) {
console.error('Failed to connect to %s: %s',
g.error('Failed to connect to %s: %s',
url, err.message || err);
return callback(err);
}
Expand All @@ -22,11 +23,11 @@ function serviceFindOrCreate(client, serviceName, clusterSize, callback) {
if (err) {
debug('client.serviceFindOrCreate(%s, 1): %s', serviceName, err);
if (err.statusCode === 401) {
console.error(
g.error(
'Cannot access remote. If authentication is required,' +
' credentials should be given in the URL.');
} else {
console.error('Error connecting to server:', err);
g.error('Error connecting to server: %s', err);
}
return callback(err);
}
Expand Down
16 changes: 9 additions & 7 deletions lib/git.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,19 +2,21 @@ var async = require('async');
var childProcess = require('child_process');
var debug = require('debug')('strong-deploy:git');
var getDeployEndpoint = require('./deploy-endpoint').get;
var g = require('strong-globalize');
var shell = require('shelljs');
var util = require('util');
var urlParse = require('url').parse;
var urlFormat = require('url').format;

function getCurrentBranch(workingDir) {
if (!shell.pushd(workingDir)) {
return Error(util.format('Directory %s does not exist', workingDir));
return g.Error('Directory %s does not exist', workingDir);
}
var output = shell.exec('git symbolic-ref --short HEAD', {silent: true});
shell.popd();
if (output.code !== 0) {
return Error('This directory does not contain a valid git repository');
return g.Error(
'This directory does not contain a valid {{git}} repository');
}
return output.output.trim();
}
Expand All @@ -28,9 +30,9 @@ function isValidBranch(workingDir, branchName, callback) {
debug('stderr: ' + stderr);
if (err) {
debug(err);
console.error('Branch `%s` is not available in this repository',
g.error('Branch `%s` is not available in this repository',
branchName);
err = Error('invalid branch');
err = g.Error('invalid branch');
}
callback(err);
});
Expand All @@ -46,9 +48,9 @@ function isValidGitURL(workingDir, url, callback) {
if (err) {
debug(err);
if (urlFormat(urlParse(url)) !== url) {
console.error('URL `%s` is not valid', url);
g.error('URL `%s` is not valid', url);
}
err = Error('invalid url');
err = g.Error('invalid url');
}
callback(err);
});
Expand All @@ -73,7 +75,7 @@ function doGitPush(workingDir, gitURL, branch, callback) {
child.once('exit', function(code) {
if (!callback) return;

if (code !== 0) return callback(Error('git push failed'));
if (code !== 0) return callback(g.Error('{{git push}} failed'));
callback();
callback = null;
});
Expand Down
Loading