diff --git a/app/graphql/resolvers/ci/all_jobs_resolver.rb b/app/graphql/resolvers/ci/all_jobs_resolver.rb
index 8e9a1deb5419fd2a9f7f994cb0adde7bdfa3579d..54dd435d617d8f82c0f10140103fd95bb387c870 100644
--- a/app/graphql/resolvers/ci/all_jobs_resolver.rb
+++ b/app/graphql/resolvers/ci/all_jobs_resolver.rb
@@ -39,9 +39,18 @@ def preloads
browse_artifacts_path: [{ project: { namespace: [:route] } }],
play_path: [{ project: { namespace: [:route] } }],
web_path: [{ project: { namespace: [:route] } }],
- tags: [:tags]
+ tags: [:tags],
+ trace: [{ project: [:namespace] }, :job_artifacts_trace]
}
end
+
+ def nested_preloads
+ super.merge({
+ trace: {
+ html_summary: [:trace_chunks]
+ }
+ })
+ end
end
end
end
diff --git a/app/graphql/resolvers/ci/runner_jobs_resolver.rb b/app/graphql/resolvers/ci/runner_jobs_resolver.rb
index 39908d8fd11332bb6c07a6585e71a281da3d689a..c0a5057cddd070627fc726eb2000267c6066b647 100644
--- a/app/graphql/resolvers/ci/runner_jobs_resolver.rb
+++ b/app/graphql/resolvers/ci/runner_jobs_resolver.rb
@@ -44,9 +44,18 @@ def preloads
play_path: [{ project: { namespace: [:route] } }],
web_path: [{ project: { namespace: [:route] } }],
short_sha: [:pipeline],
- tags: [:tags]
+ tags: [:tags],
+ trace: [{ project: [:namespace] }, :job_artifacts_trace]
}
end
+
+ def nested_preloads
+ super.merge({
+ trace: {
+ html_summary: [:trace_chunks]
+ }
+ })
+ end
end
end
end
diff --git a/app/graphql/types/ci/job_trace_type.rb b/app/graphql/types/ci/job_trace_type.rb
index a68e26106b8687938ac247b1f1a707a1236e7797..b959d37f3272949ff14d7d61709f4cc01e199513 100644
--- a/app/graphql/types/ci/job_trace_type.rb
+++ b/app/graphql/types/ci/job_trace_type.rb
@@ -7,11 +7,15 @@ class JobTraceType < BaseObject
graphql_name 'CiJobTrace'
field :html_summary, GraphQL::Types::String, null: false,
- alpha: { milestone: '15.11' }, # As we want the option to change from 10 if needed
- description: "HTML summary containing the last 10 lines of the trace."
+ alpha: { milestone: '15.11' },
+ description: 'HTML summary that contains the tail lines of the trace.' do
+ argument :last_lines, Integer,
+ required: false, default_value: 10,
+ description: 'Number of tail lines to return, up to a maximum of 100 lines.'
+ end
- def html_summary
- object.html(last_lines: 10).html_safe
+ def html_summary(last_lines:)
+ object.html(last_lines: last_lines.clamp(1, 100)).html_safe
end
end
end
diff --git a/doc/api/graphql/reference/index.md b/doc/api/graphql/reference/index.md
index 49bb9fdbefd021e4ddb9ce434271edcc133c0b59..a1fc29747439afe215891912941421fe4b35be4a 100644
--- a/doc/api/graphql/reference/index.md
+++ b/doc/api/graphql/reference/index.md
@@ -13866,11 +13866,23 @@ CI/CD variables for a GitLab instance.
### `CiJobTrace`
-#### Fields
+#### Fields with arguments
+
+##### `CiJobTrace.htmlSummary`
+
+HTML summary that contains the tail lines of the trace.
+
+WARNING:
+**Introduced** in 15.11.
+This feature is an Experiment. It can be changed or removed at any time.
+
+Returns [`String!`](#string).
+
+###### Arguments
| Name | Type | Description |
| ---- | ---- | ----------- |
-| `htmlSummary` **{warning-solid}** | [`String!`](#string) | **Introduced** in 15.11. This feature is an Experiment. It can be changed or removed at any time. HTML summary containing the last 10 lines of the trace. |
+| `lastLines` | [`Int`](#int) | Number of tail lines to return, up to a maximum of 100 lines. |
### `CiJobsDurationStatistics`
diff --git a/spec/graphql/types/ci/job_trace_type_spec.rb b/spec/graphql/types/ci/job_trace_type_spec.rb
index 71803aa9ece3f96ada5ff9cabaec2c834abba641..5f4f3097ace7920377359af59b3da540d04c3110 100644
--- a/spec/graphql/types/ci/job_trace_type_spec.rb
+++ b/spec/graphql/types/ci/job_trace_type_spec.rb
@@ -13,15 +13,83 @@
expect(described_class).to have_graphql_fields(*expected_fields)
end
- it 'shows the correct trace contents' do
- job.trace.set('BUILD TRACE')
+ describe 'htmlSummary' do
+ subject(:resolved_field) { resolve_field(:html_summary, job.trace, args: args) }
- expect_next_instance_of(Gitlab::Ci::Trace) do |trace|
- expect(trace).to receive(:html).with(last_lines: 10).and_call_original
+ context 'when trace contains few lines' do
+ before do
+ job.trace.set('BUILD TRACE')
+ end
+
+ context 'when last_lines is set to 10' do
+ let(:args) { { last_lines: 10 } }
+
+ it 'shows the correct trace contents' do
+ expect_next_instance_of(Gitlab::Ci::Trace) do |trace|
+ expect(trace).to receive(:html).with(last_lines: 10).and_call_original
+ end
+
+ is_expected.to eq('BUILD TRACE')
+ end
+ end
end
- resolved_field = resolve_field(:html_summary, job.trace)
+ context 'when trace contains many lines' do
+ before do
+ job.trace.set((1..200).map { |i| "Line #{i}" }.join("\n"))
+ end
+
+ def expected_html_trace_contents(line_count)
+ "#{((200 - (line_count - 1))..200).map { |i| "Line #{i}" }.join('
')}"
+ end
+
+ context 'when last_lines is not set' do
+ let(:args) { {} }
+
+ it 'shows the last 10 lines of trace contents' do
+ expect_next_instance_of(Gitlab::Ci::Trace) do |trace|
+ expect(trace).to receive(:html).with(last_lines: 10).and_call_original
+ end
+
+ is_expected.to eq expected_html_trace_contents(10)
+ end
+ end
+
+ context 'when last_lines is set to a negative number' do
+ let(:args) { { last_lines: -10 } }
- expect(resolved_field).to eq("BUILD TRACE")
+ it 'shows the last line of trace contents' do
+ expect_next_instance_of(Gitlab::Ci::Trace) do |trace|
+ expect(trace).to receive(:html).with(last_lines: 1).and_call_original
+ end
+
+ is_expected.to eq expected_html_trace_contents(1)
+ end
+ end
+
+ context 'when last_lines is set to 10' do
+ let(:args) { { last_lines: 10 } }
+
+ it 'shows the correct trace contents' do
+ expect_next_instance_of(Gitlab::Ci::Trace) do |trace|
+ expect(trace).to receive(:html).with(last_lines: 10).and_call_original
+ end
+
+ is_expected.to eq expected_html_trace_contents(10)
+ end
+ end
+
+ context 'when last_lines is set to 150' do
+ let(:args) { { last_lines: 150 } }
+
+ it 'shows the last 100 lines of trace contents' do
+ expect_next_instance_of(Gitlab::Ci::Trace) do |trace|
+ expect(trace).to receive(:html).with(last_lines: 100).and_call_original
+ end
+
+ is_expected.to eq expected_html_trace_contents(100)
+ end
+ end
+ end
end
end