From 0f52326c087f470e41000d25a25b126294df866a Mon Sep 17 00:00:00 2001 From: Zane Whitfield Date: Tue, 29 Nov 2022 09:09:07 -0800 Subject: [PATCH] feat(cli): remove references to free (#2145) * chore(apps-v5): remove free dyno quota exhaustion error & update apps readme (#2142) * chore(addons-v5): update addons copy to reflect new plans (#2141) * chore(addons-v5): update addons copy to support new plans * Address feedback & update tests * chore(ps): remove free and add basic for dynos (#2137) * chore(ps): remove free and add basic for dynos * Address feedback & update tests * chore(cli): update size flags for free (#2146) * chore(cli): update size flags for free * Update indentation * Add back free metadata and process tier check * Remove free check for size. API will handle invalid params. --- docs/ps.md | 4 +-- packages/addons-v5/index.js | 28 ++++++++--------- .../addons-v5/test/commands/addons.--all.js | 10 +++--- .../addons-v5/test/commands/addons.--app.js | 16 +++++----- .../addons-v5/test/commands/addons/docs.js | 2 +- .../addons-v5/test/commands/addons/info.js | 12 +++---- packages/addons-v5/test/fixtures.js | 18 +++++------ packages/apps-v5/README.md | 6 ++-- packages/apps-v5/src/commands/ps/index.js | 6 ++-- packages/apps-v5/src/commands/ps/type.js | 31 +++++++++---------- packages/apps-v5/src/error_info.js | 2 +- packages/apps-v5/test/commands/ps/index.js | 16 +++++----- packages/apps-v5/test/commands/ps/type.js | 14 ++++----- packages/run/src/commands/console.ts | 1 - packages/run/src/commands/run/index.ts | 1 + 15 files changed, 82 insertions(+), 85 deletions(-) diff --git a/docs/ps.md b/docs/ps.md index c942b8f352..768f694cbf 100644 --- a/docs/ps.md +++ b/docs/ps.md @@ -182,7 +182,7 @@ DESCRIPTION Called with no arguments shows the current dyno size. Called with one argument sets the size. - Where SIZE is one of free|eco|hobby|standard-1x|standard-2x|performance + Where SIZE is one of eco|basic|standard-1x|standard-2x|performance Called with 1..n TYPE=SIZE arguments sets the quantity per type. ``` @@ -300,7 +300,7 @@ DESCRIPTION Called with no arguments shows the current dyno size. Called with one argument sets the size. - Where SIZE is one of free|eco|hobby|standard-1x|standard-2x|performance + Where SIZE is one of eco|basic|standard-1x|standard-2x|performance Called with 1..n TYPE=SIZE arguments sets the quantity per type. ``` diff --git a/packages/addons-v5/index.js b/packages/addons-v5/index.js index cd7db48717..1d7ea33472 100644 --- a/packages/addons-v5/index.js +++ b/packages/addons-v5/index.js @@ -9,7 +9,7 @@ exports.topic = { Add-ons are created with the \`addons:create\` command, providing a reference to an add-on service (such as \`heroku-postgresql\`) or a service and plan - (such as \`heroku-postgresql:hobby-dev\`). + (such as \`heroku-postgresql:mini\`). At creation, each add-on is given a globally unique name. In addition, each add-on has at least one attachment alias to each application which uses the @@ -21,15 +21,15 @@ exports.topic = { is \`postgresql-deep-6913\` with a default attachment alias of \`DATABASE\`: $ heroku addons:create heroku-postgresql --app my-app - Creating postgresql-deep-6913... done, (free) + Creating postgresql-deep-6913... done, (mini) Adding postgresql-deep-6913 to my-app... done Setting DATABASE_URL and restarting my-app... done, v5 Database has been created and is available $ heroku addons --app my-app - Add-on Plan Price - ───────────────────────────────────────── ───────── ───── - heroku-postgresql (postgresql-deep-6913) hobby-dev free + Add-on Plan Price + ───────────────────────────────────────── ──── ──────── + heroku-postgresql (postgresql-deep-6913) mini $5/month └─ as DATABASE The add-on name and, in some cases, the attachment alias can be specified by @@ -37,18 +37,18 @@ exports.topic = { both these identifiers: $ heroku addons:create heroku-postgresql --app my-app --name main-db --as PRIMARY_DB - Creating main-db... done, (free) + Creating main-db... done, ($5/month) Adding main-db to my-app... done Setting PRIMARY_DB_URL and restarting my-app... done, v6 Database has been created and is available $ heroku addons --app my-app - Add-on Plan Price - ───────────────────────────────────────── ───────── ───── - heroku-postgresql (main-db) hobby-dev free + Add-on Plan Price + ───────────────────────────────────────── ──── ──────── + heroku-postgresql (main-db) mini $5/month └─ as PRIMARY_DB - heroku-postgresql (postgresql-deep-6913) hobby-dev free + heroku-postgresql (postgresql-deep-6913) mini $5/month └─ as DATABASE Attachment aliases can also be specified when making attachments: @@ -58,13 +58,13 @@ exports.topic = { Setting ANOTHER_NAME vars and restarting my-app... done, v7 $ heroku addons --app my-app - Add-on Plan Price - ───────────────────────────────────────── ───────── ───── - heroku-postgresql (main-db) hobby-dev free + Add-on Plan Price + ───────────────────────────────────────── ──── ──────── + heroku-postgresql (main-db) mini $5/month ├─ as PRIMARY_DB └─ as ANOTHER_NAME - heroku-postgresql (postgresql-deep-6913) hobby-dev free + heroku-postgresql (postgresql-deep-6913) mini $5/month └─ as DATABASE For more information, read https://devcenter.heroku.com/articles/add-ons` diff --git a/packages/addons-v5/test/commands/addons.--all.js b/packages/addons-v5/test/commands/addons.--all.js index 44895c68d5..d04f886b74 100644 --- a/packages/addons-v5/test/commands/addons.--all.js +++ b/packages/addons-v5/test/commands/addons.--all.js @@ -27,11 +27,11 @@ describe('addons --all', function () { it('prints add-ons in a table', function () { return cmd.run({ flags: {} }).then(function () { util.expectOutput(cli.stdout, - `Owning App Add-on Plan Price State -──────────── ───────── ─────────────────────────── ───────── ──────── -acme-inc-api api-redis heroku-redis:premium-2 $60/month created -acme-inc-www www-db heroku-postgresql:hobby-dev free created -acme-inc-www www-redis heroku-redis:premium-2 $60/month creating`) + `Owning App Add-on Plan Price State +──────────── ───────── ────────────────────── ───────── ──────── +acme-inc-api api-redis heroku-redis:premium-2 $60/month created +acme-inc-www www-db heroku-postgresql:mini $5/month created +acme-inc-www www-redis heroku-redis:premium-2 $60/month creating`) }) }) diff --git a/packages/addons-v5/test/commands/addons.--app.js b/packages/addons-v5/test/commands/addons.--app.js index 33ac42657c..4c557a7cbe 100644 --- a/packages/addons-v5/test/commands/addons.--app.js +++ b/packages/addons-v5/test/commands/addons.--app.js @@ -54,7 +54,7 @@ describe('addons --app', function () { util.expectOutput(cli.stdout, ` Add-on Plan Price State ────────────────────────── ───────── ───────── ──────── -heroku-postgresql (www-db) hobby-dev free created +heroku-postgresql (www-db) mini $5/month created └─ as DATABASE heroku-redis (www-redis) premium-2 $60/month creating @@ -72,9 +72,9 @@ The table above shows add-ons and the attachments to the current app (acme-inc-w ]) return run('acme-inc-www', function () { util.expectOutput(cli.stdout, ` -Add-on Plan Price State -───────────────────────────────── ───────── ───── ─────── -heroku-postgresql (www-db) hobby-dev free created +Add-on Plan Price State +───────────────────────────────── ──── ──────── ─────── +heroku-postgresql (www-db) mini $5/month created ├─ as DATABASE └─ as WWW_DB on acme-inc-dwh app @@ -91,9 +91,9 @@ The table above shows add-ons and the attachments to the current app (acme-inc-w return run('acme-inc-dwh', function () { util.expectOutput(cli.stdout, ` -Add-on Plan Price State -─────────────────────────────────── ───────── ──────────────────────────── ─────── -heroku-postgresql (www-db) hobby-dev (billed to acme-inc-www app) created +Add-on Plan Price State +─────────────────────────────────── ──── ──────────────────────────── ─────── +heroku-postgresql (www-db) mini (billed to acme-inc-www app) created ├─ as WWW_DB └─ as DATABASE on acme-inc-www app @@ -171,7 +171,7 @@ The table above shows add-ons and the attachments to the current app (acme-inc-d ]) return run('acme-inc-dwh', function () { - expect(cli.stdout.indexOf('hobby-dev')).to.be.lt(cli.stdout.indexOf('standard-2')) + expect(cli.stdout.indexOf('mini')).to.be.lt(cli.stdout.indexOf('standard-2')) }) }) diff --git a/packages/addons-v5/test/commands/addons/docs.js b/packages/addons-v5/test/commands/addons/docs.js index f6a3521021..5b13230bb5 100644 --- a/packages/addons-v5/test/commands/addons/docs.js +++ b/packages/addons-v5/test/commands/addons/docs.js @@ -11,7 +11,7 @@ describe('addons:docs', function () { .get('/addon-services/slowdb') .reply(200, { name: 'slowdb' }) - return cmd.run({ args: { addon: 'slowdb:free' }, flags: { 'show-url': true } }) + return cmd.run({ args: { addon: 'slowdb' }, flags: { 'show-url': true } }) .then(() => expect(cli.stdout).to.equal('https://devcenter.heroku.com/articles/slowdb\n')) .then(() => expect(cli.stderr).to.equal('')) .then(() => api.done()) diff --git a/packages/addons-v5/test/commands/addons/info.js b/packages/addons-v5/test/commands/addons/info.js index 2cbf0c1639..caf2848a8d 100644 --- a/packages/addons-v5/test/commands/addons/info.js +++ b/packages/addons-v5/test/commands/addons/info.js @@ -39,8 +39,8 @@ describe('addons:info', function () { Attachments: acme-inc-www::DATABASE Installed at: Invalid Date Owning app: acme-inc-www -Plan: heroku-postgresql:hobby-dev -Price: free +Plan: heroku-postgresql:mini +Price: $5/month State: created `) }) @@ -71,8 +71,8 @@ State: created Attachments: acme-inc-www::DATABASE Installed at: Invalid Date Owning app: acme-inc-www -Plan: heroku-postgresql:hobby-dev -Price: free +Plan: heroku-postgresql:mini +Price: $5/month State: created `) }) @@ -109,8 +109,8 @@ State: created Attachments: acme-inc-www::DATABASE Installed at: Invalid Date Owning app: acme-inc-www -Plan: heroku-postgresql:hobby-dev -Price: free +Plan: heroku-postgresql:mini +Price: $5/month State: created `) }) diff --git a/packages/addons-v5/test/fixtures.js b/packages/addons-v5/test/fixtures.js index c5cbb0a5ea..fe644447c0 100644 --- a/packages/addons-v5/test/fixtures.js +++ b/packages/addons-v5/test/fixtures.js @@ -48,15 +48,15 @@ fixtures.services = { } fixtures.plans = { - 'heroku-postgresql:hobby-dev': { + 'heroku-postgresql:mini': { 'created_at': '2013-10-24T17:21:05Z', 'default': true, - 'description': 'Heroku Postgres Hobby Dev', - 'human_name': 'Hobby Dev', + 'description': 'Heroku Postgres Mini', + 'human_name': 'Mini', 'id': '062a1cc7-f79f-404c-9f91-135f70175577', - 'name': 'heroku-postgresql:hobby-dev', + 'name': 'heroku-postgresql:mini', 'price': { - 'cents': 0, + 'cents': 500, 'unit': 'month' }, 'state': 'ga', @@ -98,10 +98,10 @@ fixtures.addons = { id: '8895ea98-4c7b-11e5-9a16-2cf0ee2c94de', name: 'www-db', addon_service: fixtures.services['heroku-postgresql'], - plan: fixtures.plans['heroku-postgresql:hobby-dev'], + plan: fixtures.plans['heroku-postgresql:mini'], state: 'provisioned', billed_price: { - cents: 0 + cents: 500 } }, 'www-redis': { @@ -131,10 +131,10 @@ fixtures.addons = { id: '87f63372-60f8-11e5-bd19-2cf0ee2c94de', name: 'dwh-test-db', addon_service: fixtures.services['heroku-postgresql'], - plan: fixtures.plans['heroku-postgresql:hobby-dev'], + plan: fixtures.plans['heroku-postgresql:mini'], state: 'provisioned', billed_price: { - cents: 0 + cents: 500 } }, 'dwh-db': { diff --git a/packages/apps-v5/README.md b/packages/apps-v5/README.md index a593a92639..fb94be9e8f 100644 --- a/packages/apps-v5/README.md +++ b/packages/apps-v5/README.md @@ -414,7 +414,7 @@ DESCRIPTION Called with no arguments shows the current dyno size. Called with one argument sets the size. - Where SIZE is one of free|eco|hobby|standard-1x|standard-2x|performance + Where SIZE is one of eco|basic|standard-1x|standard-2x|performance Called with 1..n TYPE=SIZE arguments sets the quantity per type. ``` @@ -769,7 +769,7 @@ DESCRIPTION Called with no arguments shows the current dyno size. Called with one argument sets the size. - Where SIZE is one of free|eco|hobby|standard-1x|standard-2x|performance + Where SIZE is one of eco|basic|standard-1x|standard-2x|performance Called with 1..n TYPE=SIZE arguments sets the quantity per type. ``` @@ -865,7 +865,7 @@ DESCRIPTION Called with no arguments shows the current dyno size. Called with one argument sets the size. - Where SIZE is one of free|eco|hobby|standard-1x|standard-2x|performance + Where SIZE is one of eco|basic|standard-1x|standard-2x|performance Called with 1..n TYPE=SIZE arguments sets the quantity per type. ``` diff --git a/packages/apps-v5/src/commands/ps/index.js b/packages/apps-v5/src/commands/ps/index.js index bcc67937fa..4f80789917 100644 --- a/packages/apps-v5/src/commands/ps/index.js +++ b/packages/apps-v5/src/commands/ps/index.js @@ -30,7 +30,7 @@ function printExtended (dynos) { }) } -async function printAccountQuota(context, heroku, app, account) { +async function printAccountQuota (context, heroku, app, account) { if (app.process_tier !== 'free' && app.process_tier !== 'eco') { return } @@ -83,10 +83,8 @@ async function printAccountQuota(context, heroku, app, account) { cli.log('https://devcenter.heroku.com/articles/dyno-sleeping') cli.log() } - } - function printDynos (dynos) { let dynosByCommand = reduce(dynos, function (dynosByCommand, dyno) { let since = time.ago(new Date(dyno.updated_at)) @@ -113,7 +111,7 @@ function printDynos (dynos) { }) } -async function run(context, heroku) { +async function run (context, heroku) { const { app, flags, args } = context const types = args const { json, extended } = flags diff --git a/packages/apps-v5/src/commands/ps/type.js b/packages/apps-v5/src/commands/ps/type.js index df1460a4f5..a0a43406f0 100644 --- a/packages/apps-v5/src/commands/ps/type.js +++ b/packages/apps-v5/src/commands/ps/type.js @@ -3,7 +3,7 @@ let cli = require('heroku-cli-util') const { sortBy, compact } = require('lodash') -const costs = { 'Free': 0, 'Eco': 0, 'Hobby': 7, 'Standard-1X': 25, 'Standard-2X': 50, 'Performance-M': 250, 'Performance': 500, 'Performance-L': 500, '1X': 36, '2X': 72, 'PX': 576 } +const costs = { 'Free': 0, 'Eco': 0, 'Hobby': 7, 'Basic': 7, 'Standard-1X': 25, 'Standard-2X': 50, 'Performance-M': 250, 'Performance': 500, 'Performance-L': 500, '1X': 36, '2X': 72, 'PX': 576 } let emptyFormationErr = (app) => { return new Error(`No process types on ${app}. @@ -11,7 +11,7 @@ Upload a Procfile to add process types. https://devcenter.heroku.com/articles/procfile`) } -async function run(context, heroku) { +async function run (context, heroku) { let app = context.app let parse = async function (args) { @@ -40,28 +40,28 @@ Types: ${cli.color.yellow(formation.map((f) => f.type).join(', '))}`) formation = sortBy(formation, 'type') - let dynoTotals = []; - let isShowingEcoCostMessage = false; + let dynoTotals = [] + let isShowingEcoCostMessage = false formation.forEach((d) => { - if (d.size === 'Eco' && d.quantity !== 0) { - isShowingEcoCostMessage = true; + if (d.size === 'Eco') { + isShowingEcoCostMessage = true } if (shielded) { d.size = d.size.replace('Private-', 'Shield-') } - if(d.size in dynoTotals) { - dynoTotals[d.size] += d.quantity; + if (d.size in dynoTotals) { + dynoTotals[d.size] += d.quantity } else { - dynoTotals[d.size] = d.quantity; + dynoTotals[d.size] = d.quantity } - }); + }) dynoTotals = Object.keys(dynoTotals).map((k) => ({ - type: cli.color.green(k), + type: cli.color.green(k), total: cli.color.yellow(dynoTotals[k]) - })); + })) formation = formation.map((d) => ({ type: cli.color.green(d.type), @@ -70,10 +70,9 @@ Types: ${cli.color.yellow(formation.map((f) => f.type).join(', '))}`) 'cost/mo': costs[d.size] ? '$' + (costs[d.size] * d.quantity).toString() : '' })) - if (formation.length === 0) throw emptyFormationErr() - cli.styledHeader('Dyno Types'); + cli.styledHeader('Dyno Types') cli.table(formation, { columns: [ { key: 'type' }, @@ -83,7 +82,7 @@ Types: ${cli.color.yellow(formation.map((f) => f.type).join(', '))}`) ] }) - cli.styledHeader('Dyno Totals'); + cli.styledHeader('Dyno Totals') cli.table(dynoTotals, { columns: [ @@ -111,7 +110,7 @@ let cmd = { Called with no arguments shows the current dyno size. Called with one argument sets the size. -Where SIZE is one of free|eco|hobby|standard-1x|standard-2x|performance +Where SIZE is one of eco|basic|standard-1x|standard-2x|performance Called with 1..n TYPE=SIZE arguments sets the quantity per type. `, diff --git a/packages/apps-v5/src/error_info.js b/packages/apps-v5/src/error_info.js index c50018e92d..7cce66d712 100644 --- a/packages/apps-v5/src/error_info.js +++ b/packages/apps-v5/src/error_info.js @@ -111,7 +111,7 @@ module.exports = [ }, { 'name': 'H82', - 'title': 'Free dyno quota exhausted', + 'title': "You've used up your dyno hour pool", 'level': 'info' }, { diff --git a/packages/apps-v5/test/commands/ps/index.js b/packages/apps-v5/test/commands/ps/index.js index a7109fadd4..84708560dc 100644 --- a/packages/apps-v5/test/commands/ps/index.js +++ b/packages/apps-v5/test/commands/ps/index.js @@ -41,7 +41,7 @@ function stubAppAndAccount () { reqHeaders: { 'Accept': 'application/vnd.heroku+json; version=3.process_tier' } }) .get('/apps/myapp') - .reply(200, { process_tier: 'hobby' }) + .reply(200, { process_tier: 'basic', owner: { 'id': '1234' } }) nock('https://api.heroku.com:443') .get('/account') @@ -58,17 +58,17 @@ describe('ps', function () { let api = nock('https://api.heroku.com:443') .get('/apps/myapp/dynos') .reply(200, [ - { command: 'npm start', size: 'Free', name: 'web.1', type: 'web', updated_at: hourAgo, state: 'up' }, - { command: 'bash', size: 'Free', name: 'run.1', type: 'run', updated_at: hourAgo, state: 'up' } + { command: 'npm start', size: 'Eco', name: 'web.1', type: 'web', updated_at: hourAgo, state: 'up' }, + { command: 'bash', size: 'Eco', name: 'run.1', type: 'run', updated_at: hourAgo, state: 'up' } ]) stubAppAndAccount() return cmd.run({ app: 'myapp', args: [], flags: {} }) .then(() => expect(cli.stdout).to.equal(`=== run: one-off processes (1) -run.1 (Free): up ${hourAgoStr} (~ 1h ago): bash +run.1 (Eco): up ${hourAgoStr} (~ 1h ago): bash -=== web (Free): npm start (1) +=== web (Eco): npm start (1) web.1: up ${hourAgoStr} (~ 1h ago) `)) @@ -314,14 +314,14 @@ run.1 (Eco): up ${hourAgoStr} (~ 1h ago): bash reqHeaders: { 'Accept': 'application/vnd.heroku+json; version=3.process_tier' } }) .get('/apps/myapp') - .reply(200, { process_tier: 'hobby' }) + .reply(200, { process_tier: 'eco', owner: {id: 1234} }) let dynos = nock('https://api.heroku.com:443') .get('/apps/myapp/dynos') - .reply(200, [{ command: 'bash', size: 'Free', name: 'run.1', type: 'run', updated_at: hourAgo, state: 'up' }]) + .reply(200, [{ command: 'bash', size: 'Eco', name: 'run.1', type: 'run', updated_at: hourAgo, state: 'up' }]) let ecoExpression = `=== run: one-off processes (1) -run.1 (Free): up ${hourAgoStr} (~ 1h ago): bash +run.1 (Eco): up ${hourAgoStr} (~ 1h ago): bash ` return cmd.run({ app: 'myapp', args: [], flags: {} }) diff --git a/packages/apps-v5/test/commands/ps/type.js b/packages/apps-v5/test/commands/ps/type.js index a33bf1fa4e..3d041637a4 100644 --- a/packages/apps-v5/test/commands/ps/type.js +++ b/packages/apps-v5/test/commands/ps/type.js @@ -23,21 +23,21 @@ describe('ps:type', function () { .reply(200, app()) .get('/apps/myapp/formation') .reply(200, [{ type: 'web', quantity: 1, size: 'Eco' }, { type: 'worker', quantity: 2, size: 'Eco' }]) - .patch('/apps/myapp/formation', { updates: [{ type: 'web', size: 'hobby' }, { type: 'worker', size: 'hobby' }] }) - .reply(200, [{ type: 'web', quantity: 1, size: 'Hobby' }, { type: 'worker', quantity: 2, size: 'Hobby' }]) + .patch('/apps/myapp/formation', { updates: [{ type: 'web', size: 'basic' }, { type: 'worker', size: 'basic' }] }) + .reply(200, [{ type: 'web', quantity: 1, size: 'Basic' }, { type: 'worker', quantity: 2, size: 'Basic' }]) .get('/apps/myapp/formation') - .reply(200, [{ type: 'web', quantity: 1, size: 'Hobby' }, { type: 'worker', quantity: 2, size: 'Hobby' }]) + .reply(200, [{ type: 'web', quantity: 1, size: 'Basic' }, { type: 'worker', quantity: 2, size: 'Basic' }]) - return cmd.run({ app: 'myapp', args: ['hobby'] }) + return cmd.run({ app: 'myapp', args: ['basic'] }) .then(() => expect(cli.stdout).to.eq(`=== Dyno Types type size qty cost/mo ────── ───── ─── ─────── -web Hobby 1 $7 -worker Hobby 2 $14 +web Basic 1 $7 +worker Basic 2 $14 === Dyno Totals type total ───── ───── -Hobby 3 +Basic 3 `)) .then(() => expect(cli.stderr).to.eq('Scaling dynos on myapp... done\n')) .then(() => api.done()) diff --git a/packages/run/src/commands/console.ts b/packages/run/src/commands/console.ts index 91e5b2ffe7..d76c933eeb 100644 --- a/packages/run/src/commands/console.ts +++ b/packages/run/src/commands/console.ts @@ -1,7 +1,6 @@ // tslint:disable:file-name-casing import {Command, flags} from '@heroku-cli/command' import {DynoSizeCompletion} from '@heroku-cli/command/lib/completions' - import Dyno from '../lib/dyno' import {buildCommand} from '../lib/helpers' diff --git a/packages/run/src/commands/run/index.ts b/packages/run/src/commands/run/index.ts index 0a1f815b22..c9c66bbc5d 100644 --- a/packages/run/src/commands/run/index.ts +++ b/packages/run/src/commands/run/index.ts @@ -52,6 +52,7 @@ export default class Run extends Command { if (!opts.command) { throw new Error('Usage: heroku run COMMAND\n\nExample: heroku run bash') } + await this.heroku.get('/account') const dyno = new Dyno(opts) try {