-
Notifications
You must be signed in to change notification settings - Fork 0
Commands: workflowRuns info and event creation
#69
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
Merged
+551
−8
Merged
Changes from all commits
Commits
Show all changes
24 commits
Select commit
Hold shift + click to select a range
52a1164
WIP: define command for triggering workflow run
andrewjensen 7e0a907
Merge branch 'main' of github.com:get-dx/cli into adj/cmd/workflowRun…
andrewjensen e91f64e
Add web link, color some items
andrewjensen 71e312d
WIP: Collect parameter data
andrewjensen 03e7962
Implement more param prompts, show clearer error on unimplemented use…
andrewjensen b617b0f
Extract module for parameters, improve output
andrewjensen 6ffcdb2
Define info command, move things into its module
andrewjensen 686d14f
Start handling events
andrewjensen 7c1b016
Define commands for posting events
andrewjensen 7ce35f9
Simplify polling
andrewjensen d879c66
Make some args into required options
andrewjensen 07c7e03
Extract new module for rendering events
andrewjensen 458e179
Render different types of events
andrewjensen cbc1995
Render duration, links
andrewjensen dfa6047
Show events for info command too
andrewjensen 4cbeb6a
Confirm before running
andrewjensen 78f6a41
stdout must also be a TTY to consider the run interactive
andrewjensen 6e8a6fd
Remove unused arg
andrewjensen 3e62945
Update tests to match new behavior
andrewjensen 10a3397
Merge branch 'main' of github.com:get-dx/cli into adj/cmd/workflowRun…
andrewjensen bc5a6cc
Add examples to event commands
andrewjensen 8cdb624
Cleanup items
andrewjensen e2618d5
Handle approvals and notifying approvers
andrewjensen e555b9c
Delete trigger command and related helpers
andrewjensen File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,19 @@ | ||
| import { Command } from "commander"; | ||
|
|
||
| import { addLinkCommand } from "./workflowRuns/addLink.js"; | ||
| import { changeStatusCommand } from "./workflowRuns/changeStatus.js"; | ||
| import { infoCommand } from "./workflowRuns/info.js"; | ||
| import { postMessageCommand } from "./workflowRuns/postMessage.js"; | ||
|
|
||
| export function workflowRunsCommand(): Command { | ||
| const workflowRuns = new Command() | ||
| .name("workflowRuns") | ||
| .description("Trigger and monitor Self-service workflow runs"); | ||
|
|
||
| workflowRuns.addCommand(addLinkCommand()); | ||
| workflowRuns.addCommand(changeStatusCommand()); | ||
| workflowRuns.addCommand(infoCommand()); | ||
| workflowRuns.addCommand(postMessageCommand()); | ||
|
|
||
| return workflowRuns; | ||
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,79 @@ | ||
| import { Command } from "commander"; | ||
|
|
||
| import { | ||
| createExampleText, | ||
| getContext, | ||
| wrapAction, | ||
| } from "../../commandHelpers.js"; | ||
| import { buildRuntime } from "../../runtime.js"; | ||
| import { renderJson, renderRichText } from "../../renderers.js"; | ||
| import * as ui from "../../ui.js"; | ||
| import { request } from "../../http.js"; | ||
| import { Runtime } from "../../types.js"; | ||
|
|
||
| export function addLinkCommand() { | ||
| return new Command() | ||
| .name("addLink") | ||
| .description("Add a link to a workflow run") | ||
| .argument("<workflow-run-id>", "The ID of the workflow run") | ||
| .requiredOption("--url <url>", "The URL of the link") | ||
| .requiredOption("--label <label>", "The label of the link") | ||
| .addHelpText( | ||
| "afterAll", | ||
| createExampleText([ | ||
| { | ||
| label: "Add a link to a workflow run", | ||
| command: | ||
| 'dx workflowRuns addLink hvserjgz5lo7 --url https://www.example.com --label "Example Website"', | ||
| }, | ||
| ]), | ||
| ) | ||
| .action( | ||
| wrapAction(async (workflowRunId: string, options, command) => { | ||
| const context = getContext(command); | ||
| const runtime = buildRuntime(context); | ||
|
|
||
| const response = await addLink( | ||
| runtime, | ||
| workflowRunId, | ||
| options.url, | ||
| options.label, | ||
| ); | ||
|
|
||
| if (runtime.context.json) { | ||
| renderJson(response); | ||
| } else { | ||
| renderRichText([ | ||
| ui.p( | ||
| `${ui.success(ui.GLYPHS.CHECK)} Added link to workflow run ${ui.code(workflowRunId)}.`, | ||
| ), | ||
| ui.p( | ||
| `Web link: ${ui.link(ui.webLink(`/self-service/workflow-runs/${workflowRunId}`, runtime))}`, | ||
| ), | ||
| ]); | ||
| } | ||
| }), | ||
| ); | ||
| } | ||
|
|
||
| type AddLinkResponse = { | ||
| ok: true; | ||
| }; | ||
|
|
||
| async function addLink( | ||
| runtime: Runtime, | ||
| workflowRunId: string, | ||
| url: string, | ||
| label: string, | ||
| ): Promise<{ body: AddLinkResponse }> { | ||
| return request<AddLinkResponse>(runtime, "/workflowRuns.addLink", { | ||
| method: "POST", | ||
| body: { | ||
| workflow_run_id: workflowRunId, | ||
| link: { | ||
| url, | ||
| label, | ||
| }, | ||
| }, | ||
| }); | ||
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,93 @@ | ||
| import { Command } from "commander"; | ||
|
|
||
| import { | ||
| createExampleText, | ||
| getContext, | ||
| wrapAction, | ||
| } from "../../commandHelpers.js"; | ||
| import { buildRuntime } from "../../runtime.js"; | ||
| import { renderJson, renderRichText } from "../../renderers.js"; | ||
| import * as ui from "../../ui.js"; | ||
| import { request } from "../../http.js"; | ||
| import { Runtime } from "../../types.js"; | ||
| import { CliError, EXIT_CODES } from "../../errors.js"; | ||
|
|
||
| export function changeStatusCommand() { | ||
| return new Command() | ||
| .name("changeStatus") | ||
| .description("Change the status of a workflow run") | ||
| .argument("<workflow-run-id>", "The ID of the workflow run") | ||
| .requiredOption("--status <updated-status>", "The status to change to") | ||
| .addHelpText( | ||
| "afterAll", | ||
| createExampleText([ | ||
| { | ||
| label: "Mark a workflow run as succeeded", | ||
| command: | ||
| "dx workflowRuns changeStatus hvserjgz5lo7 --status SUCCEEDED", | ||
| }, | ||
| { | ||
| label: "Mark a workflow run as failed", | ||
| command: "dx workflowRuns changeStatus hvserjgz5lo7 --status FAILED", | ||
| }, | ||
| ]), | ||
| ) | ||
| .action( | ||
| wrapAction(async (workflowRunId: string, options, command) => { | ||
| const context = getContext(command); | ||
| const runtime = buildRuntime(context); | ||
|
|
||
| if (!isValidStatus(options.status)) { | ||
| throw new CliError( | ||
| `Invalid status: ${options.status}. Must be one of: SUCCEEDED, FAILED.`, | ||
| EXIT_CODES.ARGUMENT_ERROR, | ||
| ); | ||
| } | ||
|
|
||
| const response = await changeStatus( | ||
| runtime, | ||
| workflowRunId, | ||
| options.status, | ||
| ); | ||
|
|
||
| if (runtime.context.json) { | ||
| renderJson(response); | ||
| } else { | ||
| renderRichText([ | ||
| ui.p( | ||
| `${ui.success(ui.GLYPHS.CHECK)} Changed status of workflow run ${ui.code(workflowRunId)} to ${ui.code(options.status)}.`, | ||
| ), | ||
| ui.p( | ||
| `Web link: ${ui.link(ui.webLink(`/self-service/workflow-runs/${workflowRunId}`, runtime))}`, | ||
| ), | ||
| ]); | ||
| } | ||
| }), | ||
| ); | ||
| } | ||
|
|
||
| function isValidStatus( | ||
| updatedStatus: string, | ||
| ): updatedStatus is WorkflowRunStatus { | ||
| return updatedStatus === "SUCCEEDED" || updatedStatus === "FAILED"; | ||
| } | ||
|
|
||
| type WorkflowRunStatus = "SUCCEEDED" | "FAILED"; | ||
|
|
||
| type ChangeStatusResponse = { | ||
| ok: true; | ||
| }; | ||
|
|
||
| async function changeStatus( | ||
| runtime: Runtime, | ||
| workflowRunId: string, | ||
| status: WorkflowRunStatus, | ||
| ): Promise<{ body: ChangeStatusResponse }> { | ||
| return request<ChangeStatusResponse>(runtime, "/workflowRuns.changeStatus", { | ||
| method: "POST", | ||
| body: { | ||
| workflow_run_id: workflowRunId, | ||
| status, | ||
| }, | ||
| }); | ||
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,75 @@ | ||
| import { WorkflowRunEvent } from "./info.js"; | ||
| import * as ui from "../../ui.js"; | ||
|
|
||
| export function workflowRunEventContent(event: WorkflowRunEvent): ui.Block { | ||
| const ts = ui.dim(event.occurred_at); | ||
| const message = formatEventMessage(event); | ||
| return ui.p(`${ts} ${message}`, false); | ||
| } | ||
|
|
||
| function formatEventMessage(event: WorkflowRunEvent): string { | ||
| const userName = event.user?.name ?? event.user?.email ?? "API"; | ||
|
|
||
| switch (event.type) { | ||
| case "WORKFLOW_TRIGGERED": | ||
| return `Workflow run triggered by ${ui.bold(userName)}`; | ||
|
|
||
| case "WORKFLOW_RUN_REQUESTED": | ||
| return `Workflow run requested by ${ui.bold(userName)}`; | ||
|
|
||
| case "APPROVERS_NOTIFIED": | ||
| return "Approvers notified"; | ||
|
|
||
| case "APPROVAL_PERFORMED": | ||
| return `Approved by ${ui.bold(userName)}`; | ||
|
|
||
| case "REJECTION_PERFORMED": | ||
| return `Rejected by ${ui.bold(userName)}`; | ||
|
|
||
| case "HTTP_REQUEST_COMPLETED": { | ||
| const method = event.data?.request?.method?.toUpperCase(); | ||
| const url = event.data?.request?.url; | ||
| const status = event.data?.response?.status; | ||
| const reqSummary = method && url ? ` ${ui.code(`${method} ${url}`)}` : ""; | ||
| const statusSummary = status ? ` → ${ui.code(String(status))}` : ""; | ||
| return `Sent HTTP request${reqSummary}${statusSummary}`; | ||
| } | ||
|
|
||
| case "POST_MESSAGE": { | ||
| const text = event.message ?? ""; | ||
| const truncated = text.length > 120 ? text.slice(0, 120) + "…" : text; | ||
| return truncated; | ||
| } | ||
|
|
||
| case "ADD_LINK": { | ||
| const link = event.data?.link; | ||
| if (link) { | ||
| const label = link.label ? `${link.label}: ` : ""; | ||
| return `Added link ${label}${ui.link(link.url)}`; | ||
| } | ||
| return "Added a link"; | ||
| } | ||
|
|
||
| case "CHANGE_STATUS": { | ||
| const status = event.data?.status; | ||
| return status | ||
| ? `Status changed to ${ui.bold(status.toLowerCase())}` | ||
| : "Status changed"; | ||
| } | ||
|
|
||
| case "WORKFLOW_SUCCEEDED": | ||
| return `${ui.success(ui.GLYPHS.CHECK)} Workflow run succeeded`; | ||
|
|
||
| case "WORKFLOW_FAILED": | ||
| return `${ui.error(ui.GLYPHS.ERROR)} Workflow run failed`; | ||
|
|
||
| case "WORKFLOW_TIMEOUT": | ||
| return `${ui.error(ui.GLYPHS.ERROR)} Workflow run timed out`; | ||
|
|
||
| case "WORKFLOW_CANCELLED": | ||
| return `${ui.warning(ui.GLYPHS.WARNING)} Workflow run cancelled by ${ui.bold(userName)}`; | ||
|
|
||
| default: | ||
| return `Event: ${(event as WorkflowRunEvent).type}`; | ||
| } | ||
| } |
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is this needed?