heroku 11.0.0-alpha.1 → 11.0.0-alpha.10

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (76) hide show
  1. package/README.md +3 -0
  2. package/lib/commands/local/index.d.ts +19 -0
  3. package/lib/commands/local/index.js +77 -0
  4. package/lib/commands/local/run.d.ts +11 -0
  5. package/lib/commands/local/run.js +37 -0
  6. package/lib/commands/local/version.d.ts +5 -0
  7. package/lib/commands/local/version.js +10 -0
  8. package/lib/commands/members/add.d.ts +13 -0
  9. package/lib/commands/members/add.js +32 -0
  10. package/lib/commands/members/index.d.ts +12 -0
  11. package/lib/commands/members/index.js +80 -0
  12. package/lib/commands/members/remove.d.ts +10 -0
  13. package/lib/commands/members/remove.js +43 -0
  14. package/lib/commands/members/set.d.ts +11 -0
  15. package/lib/commands/members/set.js +24 -0
  16. package/lib/commands/pipelines/add.d.ts +14 -0
  17. package/lib/commands/pipelines/add.js +58 -0
  18. package/lib/commands/pipelines/connect.d.ts +12 -0
  19. package/lib/commands/pipelines/connect.js +49 -0
  20. package/lib/commands/pipelines/create.d.ts +15 -0
  21. package/lib/commands/pipelines/create.js +89 -0
  22. package/lib/commands/pipelines/destroy.d.ts +9 -0
  23. package/lib/commands/pipelines/destroy.js +24 -0
  24. package/lib/commands/pipelines/diff.d.ts +20 -0
  25. package/lib/commands/pipelines/diff.js +156 -0
  26. package/lib/commands/pipelines/index.d.ts +9 -0
  27. package/lib/commands/pipelines/index.js +25 -0
  28. package/lib/commands/pipelines/info.d.ts +13 -0
  29. package/lib/commands/pipelines/info.js +41 -0
  30. package/lib/lib/local/env-file-validator.d.ts +1 -0
  31. package/lib/lib/local/env-file-validator.js +10 -0
  32. package/lib/lib/local/fork-foreman.js +7 -0
  33. package/lib/lib/local/load-foreman-procfile.d.ts +1 -2
  34. package/lib/lib/local/load-foreman-procfile.js +5 -1
  35. package/lib/lib/local/{run-foreman.js → run-foreman.cjs} +2 -1
  36. package/lib/lib/members/team-invite-utils.d.ts +14 -0
  37. package/lib/lib/members/team-invite-utils.js +26 -0
  38. package/lib/lib/pipelines/disambiguate.js +2 -2
  39. package/lib/lib/pipelines/ownership.d.ts +5 -1
  40. package/lib/lib/pipelines/ownership.js +33 -44
  41. package/lib/lib/pipelines/render-pipeline.d.ts +7 -1
  42. package/lib/lib/pipelines/render-pipeline.js +62 -68
  43. package/npm-shrinkwrap.json +31675 -0
  44. package/oclif.manifest.json +7573 -0
  45. package/package.json +10 -8
  46. package/lib/lib/members/utils.d.ts +0 -2
  47. package/lib/lib/members/utils.js +0 -10
  48. package/lib/oldCommands/local/index.d.ts +0 -1
  49. package/lib/oldCommands/local/index.js +0 -91
  50. package/lib/oldCommands/local/run.d.ts +0 -1
  51. package/lib/oldCommands/local/run.js +0 -54
  52. package/lib/oldCommands/local/version.d.ts +0 -1
  53. package/lib/oldCommands/local/version.js +0 -17
  54. package/lib/oldCommands/members/add.d.ts +0 -1
  55. package/lib/oldCommands/members/add.js +0 -36
  56. package/lib/oldCommands/members/index.d.ts +0 -1
  57. package/lib/oldCommands/members/index.js +0 -92
  58. package/lib/oldCommands/members/remove.d.ts +0 -1
  59. package/lib/oldCommands/members/remove.js +0 -70
  60. package/lib/oldCommands/members/set.d.ts +0 -1
  61. package/lib/oldCommands/members/set.js +0 -24
  62. package/lib/oldCommands/pipelines/add.d.ts +0 -1
  63. package/lib/oldCommands/pipelines/add.js +0 -70
  64. package/lib/oldCommands/pipelines/connect.d.ts +0 -1
  65. package/lib/oldCommands/pipelines/connect.js +0 -69
  66. package/lib/oldCommands/pipelines/create.d.ts +0 -1
  67. package/lib/oldCommands/pipelines/create.js +0 -105
  68. package/lib/oldCommands/pipelines/destroy.d.ts +0 -1
  69. package/lib/oldCommands/pipelines/destroy.js +0 -34
  70. package/lib/oldCommands/pipelines/diff.d.ts +0 -1
  71. package/lib/oldCommands/pipelines/diff.js +0 -202
  72. package/lib/oldCommands/pipelines/index.d.ts +0 -1
  73. package/lib/oldCommands/pipelines/index.js +0 -34
  74. package/lib/oldCommands/pipelines/info.d.ts +0 -1
  75. package/lib/oldCommands/pipelines/info.js +0 -51
  76. /package/lib/lib/local/{run-foreman.d.ts → run-foreman.d.cts} +0 -0
@@ -1,105 +0,0 @@
1
- export {};
2
- /*
3
- import color from '@heroku-cli/color'
4
- import {Command, flags} from '@heroku-cli/command'
5
- import {StageCompletion} from '@heroku-cli/command/lib/completions'
6
- import {Args, ux} from '@oclif/core'
7
- import {prompt, type Answers, type InputQuestion, type ListQuestion} from 'inquirer'
8
-
9
- import {createCoupling, createPipeline, getAccountInfo, getTeam, Owner} from '../../lib/api'
10
- import infer from '../../lib/pipelines/infer'
11
- import {inferrableStageNames as stages} from '../../lib/pipelines/stages'
12
- import {getGenerationByAppId} from '../../lib/apps/generation'
13
-
14
- export default class Create extends Command {
15
- static description = `create a new pipeline
16
- An existing app must be specified as the first app in the pipeline.
17
- The pipeline name will be inferred from the app name if not specified.
18
- The stage of the app will be guessed based on its name if not specified.
19
- The pipeline owner will be the user creating the pipeline if not specified with -t for teams or -o for orgs.`
20
-
21
- static examples = [
22
- '$ heroku pipelines:create -a my-app-staging',
23
- '$ heroku pipelines:create my-pipeline -a my-app-staging',
24
- ]
25
-
26
- static flags = {
27
- app: flags.app({required: true}),
28
- remote: flags.remote(),
29
- stage: flags.string({
30
- name: 'stage',
31
- char: 's',
32
- description: 'stage of first app in pipeline',
33
- completion: StageCompletion,
34
- }),
35
- team: flags.team({
36
- description: 'the team which will own the apps',
37
- }),
38
- }
39
-
40
- static args = {
41
- name: Args.string({
42
- description: 'name of pipeline (defaults to basename of the app)',
43
- required: false,
44
- }),
45
- }
46
-
47
- async run() {
48
- const {args, flags} = await this.parse(Create)
49
-
50
- let name
51
- let stage
52
- let owner: Owner
53
- const guesses = infer(flags.app)
54
- const questions: (InputQuestion | ListQuestion)[] = []
55
-
56
- const app = flags.app
57
-
58
- if (args.name) {
59
- name = args.name
60
- } else {
61
- questions.push({
62
- type: 'input',
63
- name: 'name',
64
- message: 'Pipeline name',
65
- default: guesses[0],
66
- })
67
- }
68
-
69
- if (flags.stage) {
70
- stage = flags.stage
71
- } else {
72
- questions.push({
73
- type: 'list',
74
- name: 'stage',
75
- message: `Stage of ${app}`,
76
- choices: stages,
77
- default: guesses[1],
78
- })
79
- }
80
-
81
- const teamName = flags.team
82
- const ownerType = teamName ? 'team' : 'user'
83
-
84
- // If team or org is not specified, we assign ownership to the user creating
85
- const response = teamName ? await getTeam(this.heroku, teamName) : await getAccountInfo(this.heroku)
86
- owner = response.body
87
- const ownerID = owner.id
88
-
89
- owner = {id: ownerID, type: ownerType}
90
-
91
- const answers: Answers = await prompt(questions)
92
- if (answers.name) name = answers.name
93
- if (answers.stage) stage = answers.stage
94
-
95
- ux.action.start(`Creating ${name} pipeline`)
96
- const generation = await getGenerationByAppId(app, this.heroku)
97
- const {body: pipeline} = await createPipeline(this.heroku, name, owner, generation)
98
- ux.action.stop()
99
-
100
- ux.action.start(`Adding ${color.app(app)} to ${color.pipeline(pipeline.name)} pipeline as ${stage}`)
101
- await createCoupling(this.heroku, pipeline, app, stage)
102
- ux.action.stop()
103
- }
104
- }
105
- */
@@ -1 +0,0 @@
1
- export {};
@@ -1,34 +0,0 @@
1
- export {};
2
- /*
3
- import color from '@heroku-cli/color'
4
- import {Command} from '@heroku-cli/command'
5
- import * as Heroku from '@heroku-cli/schema'
6
- import {Args, ux} from '@oclif/core'
7
-
8
- import {destroyPipeline} from '../../lib/api'
9
- import disambiguate from '../../lib/pipelines/disambiguate'
10
-
11
- export default class PipelinesDestroy extends Command {
12
- static description = 'destroy a pipeline'
13
-
14
- static examples = [
15
- '$ heroku pipelines:destroy my-pipeline',
16
- ]
17
-
18
- static args = {
19
- pipeline: Args.string({
20
- description: 'name of pipeline',
21
- required: true,
22
- }),
23
- }
24
-
25
- async run() {
26
- const {args} = await this.parse(PipelinesDestroy)
27
- const pipeline: Heroku.Pipeline = await disambiguate(this.heroku, args.pipeline)
28
-
29
- ux.action.start(`Destroying ${color.pipeline(pipeline.name!)} pipeline`)
30
- await destroyPipeline(this.heroku, pipeline.name, pipeline.id)
31
- ux.action.stop()
32
- }
33
- }
34
- */
@@ -1 +0,0 @@
1
- export {};
@@ -1,202 +0,0 @@
1
- export {};
2
- /*
3
- import color from '@heroku-cli/color'
4
- import {Command, flags} from '@heroku-cli/command'
5
- import {ux} from '@oclif/core'
6
- import {hux} from '@heroku/heroku-cli-util'
7
- import HTTP from '@heroku/http-call'
8
-
9
- import {getCoupling, getPipeline, getReleases, listPipelineApps, SDK_HEADER} from '../../lib/api'
10
- import KolkrabbiAPI from '../../lib/pipelines/kolkrabbi-api'
11
- import type {OciImage, Slug, PipelineCoupling} from '../../lib/types/fir'
12
- import type {Commit, GitHubDiff} from '../../lib/types/github'
13
- import {GenerationKind, getGeneration} from '../../lib/apps/generation'
14
-
15
- interface AppInfo {
16
- name: string;
17
- repo?: string;
18
- hash?: string;
19
- }
20
-
21
- const PROMOTION_ORDER = ['development', 'staging', 'production']
22
-
23
- async function diff(targetApp: AppInfo, downstreamApp: AppInfo, githubToken: string, herokuUserAgent: string) {
24
- if (!downstreamApp.repo) {
25
- return ux.log(`\n${color.app(targetApp.name)} was not compared to ${color.app(downstreamApp.name)} as ${color.app(downstreamApp.name)} is not connected to GitHub`)
26
- }
27
-
28
- if (downstreamApp.repo !== targetApp.repo) {
29
- return ux.log(`\n${color.app(targetApp.name)} was not compared to ${color.app(downstreamApp.name)} as ${color.app(downstreamApp.name)} is not connected to the same GitHub repo as ${color.app(targetApp.name)}`)
30
- }
31
-
32
- if (!downstreamApp.hash) {
33
- return ux.log(`\n${color.app(targetApp.name)} was not compared to ${color.app(downstreamApp.name)} as ${color.app(downstreamApp.name)} does not have any releases`)
34
- }
35
-
36
- if (downstreamApp.hash === targetApp.hash) {
37
- return ux.log(`\n${color.app(targetApp.name)} is up to date with ${color.app(downstreamApp.name)}`)
38
- }
39
-
40
- // Do the actual GitHub diff
41
- try {
42
- const path = `${targetApp.repo}/compare/${downstreamApp.hash}...${targetApp.hash}`
43
- const headers = {
44
- authorization: 'token ' + githubToken,
45
- 'Content-Type': 'application/vnd.github+json',
46
- 'X-GitHub-Api-Version': '2022-11-28',
47
- }
48
-
49
- if (herokuUserAgent) {
50
- Reflect.set(headers, 'user-agent', herokuUserAgent)
51
- }
52
-
53
- const {body: githubDiff} = await HTTP.get<GitHubDiff>(`https://api.github.com/repos/${path}`, {headers})
54
-
55
- ux.log('')
56
- hux.styledHeader(`${color.app(targetApp.name)} is ahead of ${color.app(downstreamApp.name)} by ${githubDiff.ahead_by} commit${githubDiff.ahead_by === 1 ? '' : 's'}`)
57
- const mapped = githubDiff.commits.map((commit: Commit) => {
58
- return {
59
- sha: commit.sha.slice(0, 7),
60
- date: commit.commit.author.date,
61
- author: commit.commit.author.name,
62
- message: commit.commit.message.split('\n')[0],
63
- }
64
- }).reverse()
65
- hux.table(mapped, {
66
- sha: {
67
- header: 'SHA',
68
- },
69
- date: {},
70
- author: {},
71
- message: {},
72
- })
73
- ux.log(`\nhttps://github.com/${path}`)
74
- } catch {
75
- ux.log(`\n${color.app(targetApp.name)} was not compared to ${color.app(downstreamApp.name)} because we were unable to perform a diff`)
76
- ux.log('are you sure you have pushed your latest commits to GitHub?')
77
- }
78
- }
79
-
80
- export default class PipelinesDiff extends Command {
81
- static description = 'compares the latest release of this app to its downstream app(s)'
82
-
83
- static examples = [
84
- '$ heroku pipelines:diff -a my-app-staging',
85
- ]
86
-
87
- static flags = {
88
- app: flags.app({required: true}),
89
- remote: flags.remote(),
90
- }
91
-
92
- kolkrabbi: KolkrabbiAPI = new KolkrabbiAPI(this.config.userAgent, () => this.heroku.auth)
93
-
94
- getAppInfo = async (appName: string, appId: string, generation: GenerationKind): Promise<AppInfo> => {
95
- // Find GitHub connection for the app
96
- const githubApp = await this.kolkrabbi.getAppLink(appId)
97
- .catch(() => {
98
- return {name: appName, repo: null, hash: null}
99
- })
100
-
101
- // Find the commit hash of the latest release for this app
102
- let slug: Slug
103
- let ociImages: Array<OciImage>
104
- let commit: string | undefined
105
-
106
- try {
107
- const {body: releases} = await getReleases(this.heroku, appId)
108
- const release = releases.find(r => r.status === 'succeeded')
109
- if (!release || !(release.slug || release.oci_image)) {
110
- throw new Error(`no release found for ${appName}`)
111
- }
112
-
113
- if (generation === 'cedar' && release.slug) {
114
- slug = await this.heroku.get<Slug>(`/apps/${appId}/slugs/${release.slug.id}`, {
115
- headers: {Accept: SDK_HEADER},
116
- }).then(res => res.body)
117
- commit = slug.commit!
118
- } else if (generation === 'fir' && release.oci_image) {
119
- ociImages = await this.heroku.get<Array<OciImage>>(`/apps/${appId}/oci-images/${release.oci_image.id}`, {
120
- headers: {Accept: SDK_HEADER},
121
- }).then(res => res.body)
122
- commit = ociImages[0]?.commit
123
- }
124
- } catch {
125
- return {name: appName, repo: githubApp.repo, hash: undefined}
126
- }
127
-
128
- return {name: appName, repo: githubApp.repo, hash: commit}
129
- }
130
-
131
- async run() {
132
- const {flags} = await this.parse(PipelinesDiff)
133
- const targetAppName = flags.app
134
-
135
- let coupling: PipelineCoupling | undefined
136
- try {
137
- ({body: coupling} = await getCoupling(this.heroku, targetAppName))
138
- } catch {
139
- ux.error(`This app (${targetAppName}) does not seem to be a part of any pipeline`)
140
- return
141
- }
142
-
143
- const {body: pipeline} = await getPipeline(this.heroku, coupling.pipeline!.id!)
144
-
145
- const targetAppId = coupling!.app!.id!
146
- const generation = getGeneration(pipeline)!
147
-
148
- ux.action.start('Fetching apps from pipeline')
149
- const allApps = await listPipelineApps(this.heroku, coupling!.pipeline!.id!)
150
- ux.action.stop()
151
-
152
- const sourceStage = coupling.stage
153
-
154
- if (!sourceStage) {
155
- return ux.error(`Unable to diff ${targetAppName}`)
156
- }
157
-
158
- const downstreamStage = PROMOTION_ORDER[PROMOTION_ORDER.indexOf(sourceStage) + 1]
159
- if (!downstreamStage || !PROMOTION_ORDER.includes(sourceStage)) {
160
- return ux.error(`Unable to diff ${targetAppName}`)
161
- }
162
-
163
- const downstreamApps = allApps.filter(app => app.pipelineCoupling.stage === downstreamStage)
164
-
165
- if (downstreamApps.length === 0) {
166
- return ux.error(`Cannot diff ${targetAppName} as there are no downstream apps configured`)
167
- }
168
-
169
- // Fetch GitHub repo/latest release hash for [target, downstream[0], .., downstream[n]] apps
170
- const appInfoPromises = [this.getAppInfo(targetAppName, targetAppId, generation)]
171
- downstreamApps.forEach(app => {
172
- if (app.name && app.id) {
173
- appInfoPromises.push(this.getAppInfo(app.name, app.id, generation))
174
- }
175
- })
176
- ux.action.start('Fetching release info for all apps')
177
- const appInfo = await Promise.all(appInfoPromises)
178
- ux.action.stop()
179
-
180
- // Verify the target app
181
- const targetAppInfo = appInfo[0]
182
- if (!targetAppInfo.repo) {
183
- const command = `heroku pipelines:open ${coupling.pipeline!.name}`
184
- return ux.error(`${targetAppName} does not seem to be connected to GitHub!\nRun ${color.cyan(command)} and "Connect to GitHub".`)
185
- }
186
-
187
- if (!targetAppInfo.hash) {
188
- return ux.error(`No release was found for ${targetAppName}, unable to diff`)
189
- }
190
-
191
- // Fetch GitHub token for the user
192
- const githubAccount = await this.kolkrabbi.getAccount()
193
- // Diff [{target, downstream[0]}, {target, downstream[1]}, .., {target, downstream[n]}]
194
- const downstreamAppsInfo = appInfo.slice(1)
195
- for (const downstreamAppInfo of downstreamAppsInfo) {
196
- await diff(
197
- targetAppInfo, downstreamAppInfo, githubAccount.github.token, this.config.userAgent,
198
- )
199
- }
200
- }
201
- }
202
- */
@@ -1 +0,0 @@
1
- export {};
@@ -1,34 +0,0 @@
1
- export {};
2
- /*
3
- import {Command, flags} from '@heroku-cli/command'
4
- import * as Heroku from '@heroku-cli/schema'
5
- import {ux} from '@oclif/core'
6
- import {hux} from '@heroku/heroku-cli-util'
7
-
8
- export default class Pipelines extends Command {
9
- static description = 'list pipelines you have access to'
10
-
11
- static examples = [
12
- '$ heroku pipelines',
13
- ]
14
-
15
- static flags = {
16
- json: flags.boolean({description: 'output in json format'}),
17
- }
18
-
19
- async run() {
20
- const {flags} = await this.parse(Pipelines)
21
-
22
- const {body: pipelines} = await this.heroku.get<Heroku.Pipeline[]>('/pipelines')
23
-
24
- if (flags.json) {
25
- hux.styledJSON(pipelines)
26
- } else {
27
- hux.styledHeader('My Pipelines')
28
- for (const pipeline of pipelines) {
29
- ux.log(pipeline.name)
30
- }
31
- }
32
- }
33
- }
34
- */
@@ -1 +0,0 @@
1
- export {};
@@ -1,51 +0,0 @@
1
- export {};
2
- /*
3
- import {Command, flags} from '@heroku-cli/command'
4
- import * as Heroku from '@heroku-cli/schema'
5
- import {Args} from '@oclif/core'
6
- import {hux} from '@heroku/heroku-cli-util'
7
-
8
- import {listPipelineApps} from '../../lib/api'
9
- import disambiguate from '../../lib/pipelines/disambiguate'
10
- import renderPipeline from '../../lib/pipelines/render-pipeline'
11
-
12
- export default class PipelinesInfo extends Command {
13
- static description = 'show list of apps in a pipeline'
14
-
15
- static examples = [
16
- '$ heroku pipelines:info my-pipeline',
17
- ]
18
-
19
- static flags = {
20
- json: flags.boolean({
21
- description: 'output in json format',
22
- }),
23
- 'with-owners': flags.boolean({
24
- description: 'shows owner of every app',
25
- hidden: true,
26
- }),
27
- }
28
-
29
- static args = {
30
- pipeline: Args.string({
31
- description: 'pipeline to show list of apps for',
32
- required: true,
33
- }),
34
- }
35
-
36
- async run() {
37
- const {args, flags} = await this.parse(PipelinesInfo)
38
- const pipeline: Heroku.Pipeline = await disambiguate(this.heroku, args.pipeline)
39
- const pipelineApps = await listPipelineApps(this.heroku, pipeline.id!)
40
-
41
- if (flags.json) {
42
- hux.styledJSON({pipeline, apps: pipelineApps})
43
- } else {
44
- await renderPipeline(this.heroku, pipeline, pipelineApps, {
45
- withOwners: flags['with-owners'],
46
- showOwnerWarning: true,
47
- })
48
- }
49
- }
50
- }
51
- */