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

Prepare beta v1 #5

Merged
merged 15 commits into from
Feb 13, 2023
Merged
47 changes: 14 additions & 33 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,63 +1,44 @@
# @humanmade/cli
# @humanmade/altis-cli

CLI for running Human Made utilities and commands.
CLI for running Altis utilities and commands.


## Installing

You need Node v5 or later.
You need Node v18 or later.

```sh
# Install globally:
npm install -g @humanmade/cli
npm install -g @humanmade/altis-cli

# Run it:
hm
```

You may also want to install the autocompletions (Bash only):

```sh
hm completion >> ~/.bashrc
altis-cli
```

## Available Commands

Always use `hm help` for the most up-to-date list of commands.

* `cs` - Coding standards helpers.
* `add` - Add coding standards to an existing repo.
* `run` - Run coding standards on the current repo.
* `completion` - Bash auto-completion script.
* `config` - CLI configuration.
* `reset` - Reset all configuration.
* `setup` - Set or change various configuration.
* `status` - Check what you've configured.
* `issues` - Repo issue helpers.
* `list` - List open issues on the project's repo.
* `open` - Open an issue in your browser.
* `prs` - Pull request helpers.
* `list` - List open pull requests on the project's repo.
* `repo` - Repo helpers.
* `open` - Open the repo in your browser.
* `stack` - HM Stack/hosting helpers.
Always use `altis-cli help` for the most up-to-date list of commands.
* `cli` - Meta CLI commands
* `clear-cache` - Clear the cache file
* `config` - Configuration commands
* `reset` - Reset configuration
* `setup` - Set up configuration
* `status` - Show stored configuration
* `stack` - Stack commands
* `list` - List stacks available in our hosting.
* `backup [stack]` - Create a new backup for the stack.
* `backups [stack]` - List backups for the stack.
* `deploy [stack]` - Deploy a given stack.
* `info [stack]` - Get information for a stack.
* `sequel [stack]` - Connect to stack database via Sequel Pro.
* `scp <src> <dest>` - Copy a file to/from a stack.
* `ssh [stack]` - SSH into a stack.
* `php-logs [stack]` - Show PHP logs for a stack.
* `tests` - Unit testing helpers.
* `add` - Add unit tests to your repo.

## Credits

Created by Ryan McCue to make your day better.

Licensed under the MIT license. Copyright 2017 Human Made.
Licensed under the MIT license. Copyright 2017-2023 Human Made.

```
:+oo/ .hmNh oyy. /dMMm: /syo.
Expand Down
File renamed without changes.
90 changes: 65 additions & 25 deletions lib/commands/stack/deploy.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,17 +2,22 @@ const chalk = require( 'chalk' );
const inquirer = require( 'inquirer' );
const ora = require( 'ora' );

const { getStackRegion, streamLog } = require( './util' );
const { getStack, streamLog } = require( './util' );
const Vantage = require( '../../vantage' );

function deploy( vantage, stack, force ) {
function deploy( vantage, stack, force, buildId ) {

console.log( `Deploying ${stack}...` );

let url = `stack/applications/${stack}/deploys?stream=true`;
if ( force ) {
url += '&force=true';
}

if ( buildId ) {
url += `&build=${ buildId }`;
}

const opts = { method: 'POST' };
return vantage.fetch( url, opts ).then( resp => {
if ( ! resp.ok ) {
Expand All @@ -34,36 +39,71 @@ function deploy( vantage, stack, force ) {
});
}

const handler = function ( argv ) {
const handler = argv => {
const { config, debug, force } = argv;

getStackRegion( argv ).then( ( { region, stack } ) => {
const v = new Vantage( config, region );
if ( argv.resume ) {
streamLog( v, stack, argv.resume, debug );
return;
}
getStack( argv ).then( ( stack ) => {
const v = new Vantage( config );

deploy( v, stack, force )
.then( id => {
console.log( chalk.yellow( `Deploy started, resume later with...` ) );
console.log( chalk.yellow( ` hm stack deploy ${ stack } --resume ${ id }\n` ) );
const status = new ora( `Loading builds for ${ stack }…` );
status.start();

streamLog( v, stack, id, debug );
} )
.catch( err => {
if ( err.code && err.code === 'already-upto-date' ) {
console.log();
ora( `${ chalk.bold( stack ) } is already up to date.` ).fail();
v.fetch( `stack/applications/${ stack }/builds` )
.then( resp => resp.json() )
.then( builds => {
status.succeed();

console.log( chalk.yellow( 'You can force deployment with...' ) );
console.log( chalk.yellow( ` hm stack deploy ${ stack } --force` ) );
const latest = builds.slice();
latest.sort( ( a, b ) => {
const aTime = new Date( a.date );
const bTime = new Date( b.date );

process.exit( 1 );
} else {
throw err;
}
return bTime - aTime;
});

const rows = latest.map( row => {
return {
name: `${ row.source_version.slice(0,8) } ${ chalk.grey( `(${ ( row.date ) })` ) }`,
value: row,
short: row.id,
};
} );

return inquirer.prompt({
type: 'list',
name: 'build',
message: 'Select build to use:',
choices: rows,
});
})
.then( choices => choices.build )
.then( row => {
if ( argv.resume ) {
streamLog( v, stack, argv.resume, debug );
return;
}

deploy( v, stack, force, row.id )
.then( id => {
console.log( chalk.yellow( `Deploy started, resume later with...` ) );
console.log( chalk.yellow( ` altis-cli stack deploy ${ stack } --resume ${ id }\n` ) );

streamLog( v, stack, id, debug );
} )
.catch( err => {
if ( err.code && err.code === 'already-upto-date' ) {
console.log();
ora( `${ chalk.bold( stack ) } is already up to date.` ).fail();

console.log( chalk.yellow( 'You can force deployment with...' ) );
console.log( chalk.yellow( ` altis-cli stack deploy ${ stack } --force` ) );

process.exit( 1 );
} else {
throw err;
}
} )
} );
} );
};
module.exports = {
Expand Down
67 changes: 67 additions & 0 deletions lib/commands/stack/local-setup.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
const bytes = require( 'bytes' );
const chalk = require( 'chalk' );
const clipboardy = require( 'clipboardy' );
const fs = require( 'fs' );
const inquirer = require( 'inquirer' );
const fetch = require( 'node-fetch' );
const logUpdate = require( 'log-update' );
const ora = require( 'ora' );
const path = require( 'path' );
jerico marked this conversation as resolved.
Show resolved Hide resolved
const progressStream = require( 'progress-stream' );
const unusedFilename = require( 'unused-filename' );
const process = require( 'process' );
const cmd = require( 'node-cmd' );

const Vantage = require( '../../vantage' );
const { getStack, streamLog } = require( './util' );

const getProgress = progress => {
jerico marked this conversation as resolved.
Show resolved Hide resolved
const { percentage, speed } = progress;
let bar = Array( Math.floor( 45 * percentage / 100 ) ).join( '=' ) + '>'
while ( bar.length < 45 ) {
bar += ' ';
}

return `[${ bar }] ${ percentage.toFixed( 1 ) }% (${ bytes( speed ) }/s)`;
};

const handler = argv => {
getStack( argv ).then( stack => {
const v = new Vantage(argv.config);

const status = new ora(`Loading repository for ${ stack }…`);
status.start();

v.fetch(`stack/applications/${ stack }`)
.then( resp => resp.json() )
.then( repo => {
status.succeed();

const url = repo['git-deployment']['url'];
const branch = repo['git-deployment']['ref'];
const dir = `./${stack}`;

if ( !fs.existsSync( dir ) ){
console.log( chalk.yellow( `Creating directory: ${ chalk.underline( dir ) }` ) );
fs.mkdirSync(dir);
}

process.chdir(dir);

console.log( chalk.yellow( `Cloning: ${ chalk.underline( url ) }` ) );
cmd.runSync(`git clone --branch ${branch} ${url} ./`);

console.log( chalk.yellow( `Installing dependencies…` ) );
cmd.runSync('composer install');

console.log( chalk.yellow( `${ chalk.underline( stack ) } is now available at ${ chalk.underline( dir ) }` ) );
console.log( chalk.yellow( `Run \`composer server start\` to get started` ) );
} );
})
};

module.exports = {
command: 'local-setup [stack]',
description: 'Setup an existing Altis stack locally.',
handler,
};
4 changes: 2 additions & 2 deletions lib/commands/stack/scp.js
Original file line number Diff line number Diff line change
Expand Up @@ -367,7 +367,7 @@ const handler = function ( argv ) {
if ( parsedSrc.type === 'local' && ! fs.existsSync( parsedSrc.path ) ) {
console.log( `${ parsedSrc.path }: No such file or directory` );
process.exit( 1 );
} else if ( parsedDest.type === 'remote' && ! fs.existsSync( parsedDest.path ) ) {
} else if ( parsedDest.type === 'remote' && ! fs.existsSync( parsedSrc.path ) ) {
console.log( `${ parsedSrc.path }: No such file or directory` );
process.exit( 1 );
}
Expand Down Expand Up @@ -425,7 +425,7 @@ const handler = function ( argv ) {

module.exports = {
command: 'scp <src> <dest>',
description: 'Copy a file to/from a stack.',
description: 'Copy a file to/from a stack. Remote src/dest are determined by a colon in the input, e.g. stack:/usr/src/app.',
builder: subcommand => {
subcommand.option( 'verbose', {
alias: 'v',
Expand Down
45 changes: 0 additions & 45 deletions lib/commands/stack/sequel.js

This file was deleted.

2 changes: 1 addition & 1 deletion lib/vantage.js
Original file line number Diff line number Diff line change
Expand Up @@ -114,7 +114,7 @@ class VantageAPI {
}

getLogStream( args ) {
const urlObj = parse( resolve( this.baseUrl, '/stream-log' ), true );
const urlObj = parse( resolve( BASE_URL, '/stream-log' ), true );
urlObj.query = args;
const absUrl = format( urlObj );
return this.authenticate().then( ( { token } ) => {
Expand Down
Loading