Skip to content

Commit

Permalink
Merge pull request #12077 from danidoni/improvements-for-the-workflow…
Browse files Browse the repository at this point in the history
…-runs-index-ui

Show meaningful data for each workflow run
  • Loading branch information
vpereira committed Jan 18, 2022
2 parents a3adcfe + c1e0e9c commit 550f59c
Show file tree
Hide file tree
Showing 7 changed files with 408 additions and 38 deletions.
26 changes: 26 additions & 0 deletions src/api/app/components/workflow_run_detail_component.html.haml
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
%ul.nav.nav-tabs#workflow-run-tabs{ role: 'tablist' }
%li.nav-item{ role: 'presentation' }
%a.nav-link.active{ id: "request-tab#{id}", data: { toggle: 'tab' }, href: "#request-tab-content#{id}",
role: 'tab', aria: { controls: "request-tab-content#{id}", selected: 'true' } }
Request
%li.nav-item{ role: 'presentation' }
%a.nav-link{ id: "response-tab#{id}", data: { toggle: 'tab' }, href: "#response-tab-content#{id}",
role: 'tab', aria: { controls: "response-tab-content#{id}", selected: 'false' } }
Response
.tab-content.p-3#workflow-run-tabs-content
.tab-pane.fade.show.active{ id: "request-tab-content#{id}", role: 'tabpanel',
aria: { labelledby: "request-tab#{id}" } }
%h5 Request Headers
%pre.border.p-2#request-headers
= request_headers
%h5 Request Payload
%pre.border.p-2#request-payload
= pretty_request_payload
.tab-pane.fade{ id: "response-tab-content#{id}", role: 'tabpanel',
aria: { labelledby: "response-tab#{id}" } }
%h5 Response URL
%pre.border.p-2#response-url
= response_url
%h5 Response Body
%pre.border.p-2#response-body
= response_body
21 changes: 21 additions & 0 deletions src/api/app/components/workflow_run_detail_component.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
class WorkflowRunDetailComponent < ApplicationComponent
attr_reader :id, :request_headers, :pretty_request_payload,
:response_url, :response_body

def initialize(workflow_run:)
super
@id = workflow_run.id
@request_headers = workflow_run.request_headers
@pretty_request_payload = parse_payload(workflow_run)
@response_url = workflow_run.response_url
@response_body = workflow_run.response_body
end

private

def parse_payload(workflow_run)
JSON.pretty_generate(JSON.parse(workflow_run.request_payload))
rescue JSON::ParserError
workflow_run.request_payload
end
end
14 changes: 14 additions & 0 deletions src/api/app/components/workflow_run_row_component.html.haml
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
.col-1.text-left
%i{ title: status_title, class: status_icon }
.col.text-left
#{hook_event.humanize} event
- if hook_action
%span.badge.badge-primary= hook_action.humanize
.col.text-left
= link_to_if repository_url, repository_name, repository_url
- if hook_source_name
= link_to formatted_hook_source_name, hook_source_url, { class: 'link-secondary' }
- else
Unknown source
.col.text-right
= workflow_run.created_at
98 changes: 98 additions & 0 deletions src/api/app/components/workflow_run_row_component.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
class WorkflowRunRowComponent < ApplicationComponent
attr_reader :workflow_run, :status

def initialize(workflow_run:)
super

@workflow_run = workflow_run
@status = workflow_run.status
end

def hook_action
return payload['action'] if
hook_event == 'pull_request' && ScmWebhookEventValidator::ALLOWED_PULL_REQUEST_ACTIONS.include?(payload['action'])

'Unsupported'
end

def hook_event
parsed_request_headers['HTTP_X_GITHUB_EVENT']
end

def repository_name
payload.dig('repository', 'full_name')
end

def repository_url
payload.dig('repository', 'html_url')
end

def hook_source_name
case hook_event
when 'pull_request'
payload.dig('pull_request', 'number')
when 'push'
payload.dig('head_commit', 'id')
else
payload.dig('repository', 'full_name')
end
end

def formatted_hook_source_name
case hook_event
when 'pull_request'
"##{hook_source_name}"
else
hook_source_name
end
end

def hook_source_url
case hook_event
when 'pull_request'
payload.dig('pull_request', 'url')
when 'push'
payload.dig('head_commit', 'url')
else
payload.dig('repository', 'html_url')
end
end

def status_title
case status
when 'running'
'Status: running'
when 'success'
'Status: success'
else
'Status: failed'
end
end

def status_icon
classes = case status
when 'running'
['fas', 'fa-running']
when 'success'
['fas', 'fa-check', 'text-primary']
else
['fas', 'fa-exclamation-triangle', 'text-danger']
end
classes.join(' ')
end

private

def parsed_request_headers
workflow_run.request_headers.split("\n").each_with_object({}) do |h, headers|
k, v = h.split(':')
headers[k] = v.strip
end
end

def payload
@payload ||= JSON.parse(workflow_run.request_payload)
rescue JSON::ParserError
{}
end
end
40 changes: 2 additions & 38 deletions src/api/app/views/webui/workflow_runs/index.html.haml
Original file line number Diff line number Diff line change
Expand Up @@ -16,45 +16,9 @@
%button.btn.btn-block{ type: 'button', data: { toggle: 'collapse', target: "#workflow-run#{workflow_run.id}" },
aria: { expanded: 'false', controls: "workflow-run#{workflow_run.id}" } }
.row
.col-1.text-left
- case workflow_run.status
- when 'running'
%i.fas.fa-running{ title: 'Status: running' }
- when 'success'
%i.fas.fa-check.text-primary{ title: 'Status: success' }
- else
%i.fas.fa-exclamation-triangle.text-danger{ title: 'Status: failed' }
.col.text-left
Workflow Run #{workflow_run.id}
.col.text-right
= workflow_run.created_at
= render(WorkflowRunRowComponent.new(workflow_run: workflow_run))
.collapse{ id: "workflow-run#{workflow_run.id}", aria: { labelledby: "#workflow-run-heading#{workflow_run.id}" },
data: { parent: '#workflow-runs-accordion' } }
.card-body
%ul.nav.nav-tabs#workflow-run-tabs{ role: 'tablist' }
%li.nav-item{ role: 'presentation' }
%a.nav-link.active{ id: "request-tab#{workflow_run.id}", data: { toggle: 'tab' }, href: "#request-tab-content#{workflow_run.id}",
role: 'tab', aria: { controls: "request-tab-content#{workflow_run.id}", selected: 'true' } }
Request
%li.nav-item{ role: 'presentation' }
%a.nav-link{ id: "response-tab#{workflow_run.id}", data: { toggle: 'tab' }, href: "#response-tab-content#{workflow_run.id}",
role: 'tab', aria: { controls: "response-tab-content#{workflow_run.id}", selected: 'false' } }
Response
.tab-content.p-3#workflow-run-tabs-content
.tab-pane.fade.show.active{ id: "request-tab-content#{workflow_run.id}", role: 'tabpanel',
aria: { labelledby: "request-tab#{workflow_run.id}" } }
%h5 Request Headers
%pre.border.p-2#request-headers
= workflow_run.request_headers
%h5 Request Payload
%pre.border.p-2#request-payload
= JSON.pretty_generate(JSON.parse(workflow_run.request_payload))
.tab-pane.fade{ id: "response-tab-content#{workflow_run.id}", role: 'tabpanel',
aria: { labelledby: "response-tab#{workflow_run.id}" } }
%h5 Response URL
%pre.border.p-2#response-url
= workflow_run.response_url
%h5 Response Body
%pre.border.p-2#response-body
= workflow_run.response_body
= render(WorkflowRunDetailComponent.new(workflow_run: workflow_run))
= paginate @workflow_runs, views_prefix: 'webui'
42 changes: 42 additions & 0 deletions src/api/spec/components/workflow_run_detail_component_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
require 'rails_helper'

RSpec.describe WorkflowRunDetailComponent, type: :component do
let(:workflow_token) { create(:workflow_token) }
let(:request_headers) do
<<~END_OF_HEADERS
HTTP_X_GITHUB_EVENT: pull_request
END_OF_HEADERS
end
let(:request_payload) do
<<-END_OF_PAYLOAD
{
"foo": "bar"
}
END_OF_PAYLOAD
end
let(:workflow_run) do
create(:workflow_run,
token: workflow_token,
request_headers: request_headers,
request_payload: request_payload)
end

before do
render_inline(described_class.new(workflow_run: workflow_run))
end

context 'every single workflow run' do
it { expect(rendered_component).to have_text('Request') }
it { expect(rendered_component).to have_text('Response') }
it { expect(rendered_component).to have_text('pull_request') }
it { expect(rendered_component).to have_text('foo') }
end

context 'when the payload cannot be parsed' do
let(:request_payload) { 'Unparseable payload' }

it 'shows nothing on the payload tab' do
expect(rendered_component).to have_text('Unparseable payload')
end
end
end
Loading

0 comments on commit 550f59c

Please sign in to comment.