Skip to content
Open
Show file tree
Hide file tree
Changes from all 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
8 changes: 7 additions & 1 deletion src/commands/buildpacks/add.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import {Command, flags as Flags} from '@heroku-cli/command'
import {hux} from '@heroku/heroku-cli-util'
import {Args} from '@oclif/core'

import {BuildpackCommand} from '../../lib/buildpacks/buildpacks.js'
Expand All @@ -17,6 +18,7 @@ export default class Add extends Command {
char: 'i',
description: 'the 1-based index of the URL in the list of URLs',
}),
json: Flags.boolean({char: 'j', description: 'output in json format'}),
remote: Flags.remote(),
}

Expand All @@ -41,6 +43,10 @@ export default class Add extends Command {
}

const buildpackUpdates = await buildpackCommand.mutate(flags.app, buildpacks, spliceIndex, args.buildpack, 'add')
buildpackCommand.displayUpdate(flags.app, flags.remote || '', buildpackUpdates, 'added')
if (flags.json) {
hux.styledJSON(buildpackUpdates)
} else {
buildpackCommand.displayUpdate(flags.app, flags.remote || '', buildpackUpdates, 'added')
}
}
}
4 changes: 3 additions & 1 deletion src/commands/buildpacks/clear.ts
Original file line number Diff line number Diff line change
@@ -1,17 +1,19 @@
import {Command, flags as Flags} from '@heroku-cli/command'
import {hux} from '@heroku/heroku-cli-util'

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

delete-unused-code (Code style · minor · 60% confidence): The diff adds import {hux} from '@heroku/heroku-cli-util' but hux is never referenced anywhere in this file — run() only delegates to buildpackCommand.clear(...). An unused import is dead code that should be removed rather than left in place.


import {BuildpackCommand} from '../../lib/buildpacks/buildpacks.js'

export default class Clear extends Command {
static description = 'clear all buildpacks set on the app'
static flags = {
app: Flags.app({required: true}),
json: Flags.boolean({char: 'j', description: 'output in json format'}),
remote: Flags.remote(),
}

async run() {
const {flags} = await this.parse(Clear)
const buildpackCommand = new BuildpackCommand(this.heroku)
await buildpackCommand.clear(flags.app, 'clear', 'cleared')
await buildpackCommand.clear(flags.app, 'clear', 'cleared', flags.json)
}
}
5 changes: 4 additions & 1 deletion src/commands/buildpacks/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ export default class Index extends Command {
static description = 'list the buildpacks on an app'
static flags = {
app: Flags.app({required: true}),
json: Flags.boolean({char: 'j', description: 'output in json format'}),
remote: Flags.remote(),
}

Expand All @@ -22,7 +23,9 @@ export default class Index extends Command {
})
const isFirApp = getGeneration(app) === 'fir'
const buildpacks = await buildpacksCommand.fetch(flags.app, isFirApp)
if (buildpacks.length === 0) {
if (flags.json) {
hux.styledJSON(buildpacks)
} else if (buildpacks.length === 0) {
this.log(`${color.app(flags.app)} has no Buildpacks.`)
} else {
const pluralizedBuildpacks = buildpacks.length > 1 ? 'Buildpacks' : 'Buildpack'
Expand Down
15 changes: 11 additions & 4 deletions src/commands/buildpacks/info.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import {Command} from '@heroku-cli/command'
import {Command, flags as Flags} from '@heroku-cli/command'
import {BuildpackRegistry} from '@heroku/buildpack-registry'
import {hux} from '@heroku/heroku-cli-util'
import {Args, ux} from '@oclif/core'
Expand All @@ -12,9 +12,12 @@ export default class Info extends Command {
}),
}
static description = 'fetch info about a buildpack'
static flags = {
json: Flags.boolean({char: 'j', description: 'output in json format'}),
}

async run() {
const {args} = await this.parse(Info)
const {args, flags} = await this.parse(Info)
const registry = new BuildpackRegistry()

const validationResult = BuildpackRegistry.isValidBuildpackSlug(args.buildpack)
Expand All @@ -32,8 +35,12 @@ export default class Info extends Command {
}
},
Ok(buildpack: unknown) {
hux.styledHeader(args.buildpack)
hux.styledObject(buildpack, ['description', 'category', 'license', 'support', 'source', 'readme'])
if (flags.json) {
hux.styledJSON(buildpack)
} else {
hux.styledHeader(args.buildpack)
hux.styledObject(buildpack, ['description', 'category', 'license', 'support', 'source', 'readme'])
}
},
}, result as any)
}
Expand Down
10 changes: 8 additions & 2 deletions src/commands/buildpacks/remove.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import {Command, flags as Flags} from '@heroku-cli/command'
import {hux} from '@heroku/heroku-cli-util'
import * as color from '@heroku/heroku-cli-util/color'
import {Args, ux} from '@oclif/core'

Expand All @@ -17,6 +18,7 @@ export default class Remove extends Command {
char: 'i',
description: 'the 1-based index of the URL to remove from the list of URLs',
}),
json: Flags.boolean({char: 'j', description: 'output in json format'}),
remote: Flags.remote(),
}

Expand Down Expand Up @@ -51,10 +53,14 @@ export default class Remove extends Command {
}

if (buildpacks.length === 1) {
await buildpackCommand.clear(flags.app, 'remove', 'removed')
await buildpackCommand.clear(flags.app, 'remove', 'removed', flags.json)
} else {
const buildpackUpdates = await buildpackCommand.mutate(flags.app, buildpacks, spliceIndex, args.buildpack as string, 'remove')
buildpackCommand.displayUpdate(flags.app, flags.remote || '', buildpackUpdates, 'removed')
if (flags.json) {
hux.styledJSON(buildpackUpdates)
} else {
buildpackCommand.displayUpdate(flags.app, flags.remote || '', buildpackUpdates, 'removed')
}
}
}
}
8 changes: 7 additions & 1 deletion src/commands/buildpacks/set.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import {Command, flags as Flags} from '@heroku-cli/command'
import {hux} from '@heroku/heroku-cli-util'
import {Args} from '@oclif/core'

import {BuildpackCommand} from '../../lib/buildpacks/buildpacks.js'
Expand All @@ -17,6 +18,7 @@ export default class Set extends Command {
char: 'i',
description: 'the 1-based index of the URL in the list of URLs',
}),
json: Flags.boolean({char: 'j', description: 'output in json format'}),
remote: Flags.remote(),
}

Expand All @@ -42,6 +44,10 @@ export default class Set extends Command {
}

const buildpackUpdates = await buildpackCommand.mutate(flags.app, buildpacks, spliceIndex, args.buildpack, 'set')
buildpackCommand.displayUpdate(flags.app, flags.remote || '', buildpackUpdates, 'set')
if (flags.json) {
hux.styledJSON(buildpackUpdates)
} else {
buildpackCommand.displayUpdate(flags.app, flags.remote || '', buildpackUpdates, 'set')
}
}
}
8 changes: 7 additions & 1 deletion src/lib/buildpacks/buildpacks.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import {APIClient} from '@heroku-cli/command'
import * as Heroku from '@heroku-cli/schema'
import {BuildpackRegistry} from '@heroku/buildpack-registry'
import {hux} from '@heroku/heroku-cli-util'
import * as color from '@heroku/heroku-cli-util/color'
import {ux} from '@oclif/core/ux'
import _ from 'lodash'
Expand All @@ -25,9 +26,14 @@ export class BuildpackCommand {
this.registry = new BuildpackRegistry()
}

async clear(app: string, command: 'clear' | 'remove', action: 'cleared' | 'removed') {
async clear(app: string, command: 'clear' | 'remove', action: 'cleared' | 'removed', json = false) {
await this.put(app, [])

if (json) {
hux.styledJSON([])
return
}

const configVars: any = await this.heroku.get(`/apps/${app}/config-vars`)
const message = `Buildpack${command === 'clear' ? 's' : ''} ${action}.`
if (configVars.body.BUILDPACK_URL) {
Expand Down
15 changes: 15 additions & 0 deletions test/unit/commands/buildpacks/add.unit.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -209,4 +209,19 @@ Run git push heroku main to create a new release using these buildpacks.
expect(error?.message).to.include('Invalid index. Must be greater than 0.')
})
})

describe('--json', function () {
it('# outputs added buildpacks as JSON', async function () {
Stubber.get(api)
Stubber.put(api, ['https://github.com/heroku/heroku-buildpack-ruby'])

const {stderr, stdout} = await runCommand(BuildpacksAdd, ['https://github.com/heroku/heroku-buildpack-ruby', '-a', 'example', '--json'])

expect(stderr).to.equal('')
const parsed = JSON.parse(stdout)
expect(parsed).to.be.an('array')
expect(parsed).to.have.lengthOf(1)
expect(parsed[0].buildpack.url).to.equal('https://github.com/heroku/heroku-buildpack-ruby')
})
})
})
10 changes: 10 additions & 0 deletions test/unit/commands/buildpacks/clear.unit.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -52,4 +52,14 @@ describe('buildpacks:clear', function () {
expect(stdout).to.equal('Buildpacks cleared.\n')
expect(unwrap(stderr)).to.equal('Warning: The LANGUAGE_PACK_URL config var is still set and will be used for the next release\n')
})

it('# outputs empty array as JSON when --json flag is set', async function () {
Stubber.put(api)

const {stdout} = await runCommand(Clear, ['-a', 'example', '--json'])

const parsed = JSON.parse(stdout)
expect(parsed).to.be.an('array')
expect(parsed).to.have.lengthOf(0)
})
})
25 changes: 25 additions & 0 deletions test/unit/commands/buildpacks/index.unit.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -298,4 +298,29 @@ describe('buildpacks', function () {
expect(stderr).to.equal('')
expect(stdout).to.equal(`⬢ ${firApp.name} has no Buildpacks.\n`)
})

it('# outputs buildpacks as JSON when --json flag is set', async function () {
api.get(`/apps/${cedarApp.name}`).reply(200, cedarApp)
Stubber.get(api, ['https://github.com/heroku/heroku-buildpack-ruby'])

const {stderr, stdout} = await runCommand(Buildpacks, ['-a', cedarApp.name, '--json'])

expect(stderr).to.equal('')
const parsed = JSON.parse(stdout)
expect(parsed).to.be.an('array')
expect(parsed).to.have.lengthOf(1)
expect(parsed[0].buildpack.url).to.equal('https://github.com/heroku/heroku-buildpack-ruby')
})

it('# outputs empty array as JSON when no buildpacks and --json flag is set', async function () {
api.get(`/apps/${cedarApp.name}`).reply(200, cedarApp)
Stubber.get(api)

const {stderr, stdout} = await runCommand(Buildpacks, ['-a', cedarApp.name, '--json'])

expect(stderr).to.equal('')
const parsed = JSON.parse(stdout)
expect(parsed).to.be.an('array')
expect(parsed).to.have.lengthOf(0)
})
})
23 changes: 23 additions & 0 deletions test/unit/commands/buildpacks/info.unit.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -59,4 +59,27 @@ describe('buildpacks:info', function () {

expect(error?.message).to.include('Problems finding buildpack info: some error')
})

it('outputs buildpack info as JSON when --json flag is set', async function () {
registryApi
.get('/buildpacks/heroku%2Fruby')
.reply(200, Fixture.buildpack({
name: 'ruby',
source: {
owner: 'heroku',
repo: 'heroku-buildpack-ruby',
type: 'github',
},
}))
.get('/buildpacks/heroku%2Fruby/revisions')
.reply(200, [Fixture.revision()])
.get('/buildpacks/heroku%2Fruby/readme')
.reply(200, Fixture.readme())

const {stdout} = await runCommand(BuildpacksInfo, ['heroku/ruby', '--json'])

const parsed = JSON.parse(stdout)
expect(parsed).to.be.an('object')
expect(parsed).to.have.property('description')
})
})
31 changes: 31 additions & 0 deletions test/unit/commands/buildpacks/remove.unit.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -262,4 +262,35 @@ Run git push heroku main to create a new release using these buildpacks.
expect(error?.message).to.include('Usage: heroku buildpacks:remove [BUILDPACK_URL]. Must specify a buildpack to remove, either by index or URL.')
})
})

describe('--json', function () {
it('# outputs remaining buildpacks as JSON after removal', async function () {
Stubber.get(api, [
'https://github.com/heroku/heroku-buildpack-java',
'https://github.com/heroku/heroku-buildpack-ruby',
])
Stubber.put(api, [
'https://github.com/heroku/heroku-buildpack-java',
])

const {stderr, stdout} = await runCommand(BuildpacksRemove, ['https://github.com/heroku/heroku-buildpack-ruby', '-a', 'example', '--json'])

expect(stderr).to.equal('')
const parsed = JSON.parse(stdout)
expect(parsed).to.be.an('array')
expect(parsed).to.have.lengthOf(1)
expect(parsed[0].buildpack.url).to.equal('https://github.com/heroku/heroku-buildpack-java')
})

it('# outputs empty array as JSON when last buildpack is removed', async function () {
Stubber.get(api, ['https://github.com/heroku/heroku-buildpack-ruby'])
Stubber.put(api)

const {stdout} = await runCommand(BuildpacksRemove, ['https://github.com/heroku/heroku-buildpack-ruby', '-a', 'example', '--json'])

const parsed = JSON.parse(stdout)
expect(parsed).to.be.an('array')
expect(parsed).to.have.lengthOf(0)
})
})
})
15 changes: 15 additions & 0 deletions test/unit/commands/buildpacks/set.unit.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -201,4 +201,19 @@ buildpack namespace/name of the buildpack
See more help with --help`)
})
})

describe('--json', function () {
it('# outputs set buildpacks as JSON', async function () {
Stubber.get(api)
Stubber.put(api, ['https://github.com/heroku/heroku-buildpack-ruby'])

const {stderr, stdout} = await runCommand(BuildpacksSet, ['https://github.com/heroku/heroku-buildpack-ruby', '-a', 'example', '--json'])

expect(stderr).to.equal('')
const parsed = JSON.parse(stdout)
expect(parsed).to.be.an('array')
expect(parsed).to.have.lengthOf(1)
expect(parsed[0].buildpack.url).to.equal('https://github.com/heroku/heroku-buildpack-ruby')
})
})
})
Loading