npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

dopy

v0.1.5

Published

Deploy tool for nodejs applications

Downloads

4

Readme

Dopy

Yep, we deploy a lot.

Keys fetures

  • remote tasks by system's OpenSSH SSH client
  • extensive bash completion support using yargs
  • environment inheritance
  • environment templating by mustache
  • multi server and multitarget environments support
  • yaml environment templates

Installation using dopy-cli

  1. Install dopy globally: npm -g install dopy. You could run dp anywhere after that.

  2. Create directory structure:

deploy/
|
├─ envs/
|   ├─ default.yml
|   ├─ dev.yml
|   └─ prod.yml
|   └─ ...
|
└─ tasks/
    ├─ my-task1.js
    └─ my-task2.js
    └─ ...

You should have both /envs and /tasks directories.

  1. Add environment files to /envs dir:
default.yml:

```yaml
---
web-app:
  # root for `web-app` environment

  general:
    # this will be merged to the remote and local section
    repo: [email protected]:user/git.git

  remote:
    # settings for the commands that will be run remotely
    log:
      nginx: /var/log/nginx/nginx.log
      app: '{{{ applog }}}/app.log'

  local:
    # settings for the commands that will be run localy
    path: /home/user/repo
```

dev.yml:

```yaml
---
parent: web-app # inherit all props from web-app
template:
  applog: /home/app
development:
  remote:
    servers: alpha.domain.com
test:
  remote:
    servers: beta.domain.com
```

prod.yml:

```yaml
---
parent: web-app # inherit all props from web-app
template:
  applog: /var/log
production:
  remote:
    servers:
      - [email protected]
      - [email protected]
```
  1. Add your tasks to /tasks dir. For example simple log task:
log.js

```js
exports.command = 'log [type]';

exports.desc = 'Show logs at remote server';

exports.task = (env, argv) => {
  let logs = env.config.remote.log;

  if (!logs) return taskCb('no logs configured for ' + env.name);

  let path = (typeof logs === 'object') ? logs[argv.type || 'app'] : logs;

  return env.remote(`tail -n100 -f ${path}`, { verbose:true });
};
```
Where:
  - `env` is the object containing main `dopy` worker methods such as `.remote` and `.local`.
  - `argv` parsed arguments
  1. Run dp from the root directory: dp development log dp production log nginx
You could also specify root path with `--cwd` option and run:
`dp --cwd ~/deploy test log`

You could even make an alias in your `.bashrc` file:
`alias dp="dp --cwd ~/deploy"` and run `dp` with your tasks anywhere

Installation using dopy api

  1. Run npm install dopy

  2. Create a .js file:

const dopy = require('dopy');

let envs = {
  webApp: {
    remote: {
      repo: '[email protected]:user/git.git',
      log: {
        nginx: '/var/log/nginx/nginx.log',
        app: '{{{ applog }}}/app.log'
      },
    }
  },
  dev: {
    parent: 'webApp',
    template: {
      applog: '/home/app'
    },
    remote: {
      servers: '192.168.10.113'
    }
  },
  prod: {
    parent: 'webApp',
    template: {
      applog: '/var/log/app'
    },
    remote: {
      servers: [
        '[email protected]',
        '[email protected]'
      ]
    }
  }
};

function task(env) {
  let repo = env.config.remote.repo;
  return env.local('pwd; ls -a').then(() => env.remote(`git clone ${repo}`));
}

dopy.run(task, dopy.config.initEnv('dev', envs));

Install bash completions

See dp completions output and run dp completions >> ~/.bashrc or dp completions >> ~/.bash_profile. Open new terminal session. After that you will be able to use bash completions in your tasks.

Debug

Run DEBUG=* dp to see verbose output from all running commands.

Multitarget usage

If you have multiple applications (deployable parts) installed on the same servers, you could use targets:

/envs/production.yml:

---
production:
  remote:
    servers:
      - [email protected]
      - [email protected]
  targets:
    framework:
      remote:
        path: /var/www/app
    api:
      remote:
        path: /var/www/app/api
    frontend:
      remote:
        path: /var/www/app/public

Than add targets as command argument at your task file:

exports.command = 'taskname [targets]';

Or init it manually:

dopy.config.initTargets(argv.targets);

Then run it as:

dp <env> <your-task> target1[,target2][...,targetN]

You could select all targets with ALL argument:

dp <env> <your-task> ALL

After that env instance will have targets property with array of selected targets. Each target will have the .remote and .local methods for runnning commands. You are free to control how command will be executed for each target. And you are also may use env.local, env.remote to run nontargeted commands.

For example:

task.js

exports.task = (env, argv, taskCb) => {
  if (!env.targets) env.targets = [env];

  function runInSeries(targetsCb) {
    let tasks = [];

    env.targets.forEach(t => tasks.push(cb => t.remote('npm install', cb)));

    async.series(tasks, targetsCb);
  }

  function runInParallel(targetsCb) {
    let tasks = [];

    env.targets.forEach(t => tasks.push(cb => t.remote('git reset --hard', cb)));

    async.parallel(tasks, targetsCb);
  }

  runInParallel(runInSeries(taskCb));
}

Methods of the env object

.local(command, options, [callback])

Execute local command through the system shell using execa. It takes a callback or returns a promise. Returns error or result object which contains stdout, stderr and exit code and some other useful information. See exaca for details. If mute is set to false (by default) it will pipe stdout and stderr to the console.

Additional options are:

prefix

Type: object Default:

{
  cmd: '> ',
  stdout: '  ',
  stderr: '@err '
}

verbose

Default: false If set to true it will print the running command before execution

mute

Default: false If set to true no output will be redirected to the console. You will get error and the result object when command is finished.

.remote(command, options, [callback])

Execute command on the remote servers in parallel through system's OpenSSH client. So you should install and setup ssh client first. It takes a callback or returns a promise. Returns error or array of results matching the order of servers set in configuration. If you want to use remote commands in your deploy task you should set servers in your configuration:

web:
  remote:
    servers:
      - [email protected]
      - [email protected]
      - [email protected]
      ...

NB: You could use some advanced bash scripting like this: env.reomte('git describe --tags $(git rev-parse origin/master)'

NB: If you want to run the commands in serial (command will be run at the next server only when it will finish at the previous server) you could use: env.ssh.execSeries.

All ssh-specific options are grouped in options.ssh object.

Additional options are:

ssh.user

This user will be used to login to servers.

ssh.interactive

Default: false Ssh session will be spawn with -tt option for the interactive input. NB: Any command containing sudo will be set as interactive.

ssh.port

Ssh session will be spawn with -p option to specify port to connect to on the remote host.

ssh.key

Selects a file from which the identity (private key) for public key authentication is read.

ssh.cwd

Specify current working dir for the remote command to run.


.log(message, color)

Fancy print log messages to the console. Servers and targets will be properly prefixed using various colors for easy reading.

To be continued...

For more information you could check this deploy tasks: deploy