diff --git a/lib/gitlab/ci/trace/stream.rb b/lib/gitlab/ci/trace/stream.rb
index 72a0d669de01b130684ed3673053aea6ae8c0d76..546f6788a78cd88d03c056c821043ab576f9a334 100644
--- a/lib/gitlab/ci/trace/stream.rb
+++ b/lib/gitlab/ci/trace/stream.rb
@@ -119,16 +119,31 @@ module Gitlab
         def reverse_line
           pos = BUFFER_SIZE
           max = stream.size
+          debris = ''
 
           while pos < max
             stream.seek(-pos, IO::SEEK_END)
-            yield(stream.read(BUFFER_SIZE))
+            stream.read(BUFFER_SIZE).tap do |buf|
+              buf = buf + debris
+              lines = buf.split("\n")
+              lines.reverse.each do |line|
+                yield(line)
+              end
+              debris = lines.count > 0 ? lines[0] : ''
+            end
             pos += BUFFER_SIZE
           end
 
           # Reached the head, read only left
           stream.seek(0)
-          yield(stream.read(BUFFER_SIZE - (pos - max)))
+          last = (max > BUFFER_SIZE) ? (max % BUFFER_SIZE) : max
+          stream.read(last).tap do |buf|
+            buf = buf + debris
+            lines = buf.split("\n")
+            lines.reverse.each do |line|
+              yield(line)
+            end
+          end
         end
       end
     end
diff --git a/spec/lib/gitlab/ci/trace/stream_spec.rb b/spec/lib/gitlab/ci/trace/stream_spec.rb
index a607f000431a0d5396d5df4211e7535b5ff4e694..d90ccf4f799f7f85bd752f15506a7ad77eacdc9b 100644
--- a/spec/lib/gitlab/ci/trace/stream_spec.rb
+++ b/spec/lib/gitlab/ci/trace/stream_spec.rb
@@ -254,6 +254,28 @@ describe Gitlab::Ci::Trace::Stream do
       end
     end
 
+    context 'when BUFFER_SIZE is smaller than stream.size' do
+      let(:data) { 'Coverage 1033 / 1051 LOC (98.29%) covered\n' }
+      let(:regex) { '\(\d+.\d+\%\) covered' }
+
+      before do
+        stub_const('Gitlab::Ci::Trace::Stream::BUFFER_SIZE', 5)
+      end
+
+      it { is_expected.to eq("98.29") }
+    end
+
+    context 'when BUFFER_SIZE is equal to stream.size' do
+      let(:data) { 'Coverage 1033 / 1051 LOC (98.29%) covered\n' }
+      let(:regex) { '\(\d+.\d+\%\) covered' }
+
+      before do
+        stub_const('Gitlab::Ci::Trace::Stream::BUFFER_SIZE', data.length)
+      end
+
+      it { is_expected.to eq("98.29") }
+    end
+
     context 'using a regex capture' do
       let(:data) { 'TOTAL      9926   3489    65%' }
       let(:regex) { 'TOTAL\s+\d+\s+\d+\s+(\d{1,3}\%)' }