From 549a2fa7873366b52e9ba3caa849073b7b958b73 Mon Sep 17 00:00:00 2001
From: Tomasz Maczukin <tomasz@maczukin.pl>
Date: Fri, 8 Jan 2016 14:01:31 +0100
Subject: [PATCH] Modify builds scope filtering in builds API

---
 app/models/ci/build.rb           |  4 ++++
 doc/api/builds.md                |  5 ++---
 lib/api/builds.rb                | 31 +++++++++++++++++++------------
 spec/requests/api/builds_spec.rb | 15 ++++++++++++++-
 4 files changed, 39 insertions(+), 16 deletions(-)

diff --git a/app/models/ci/build.rb b/app/models/ci/build.rb
index 3e67b2771c1..8fb68743a9b 100644
--- a/app/models/ci/build.rb
+++ b/app/models/ci/build.rb
@@ -94,6 +94,10 @@ module Ci
         new_build.save
         new_build
       end
+
+      def available_statuses
+        state_machines[:status].states.map &:value
+      end
     end
 
     state_machine :status, initial: :pending do
diff --git a/doc/api/builds.md b/doc/api/builds.md
index b716499dd36..c52266714d0 100644
--- a/doc/api/builds.md
+++ b/doc/api/builds.md
@@ -11,7 +11,7 @@ GET /projects/:id/builds
 Parameters:
 
 - `id` (required) - The ID of a project
-- `scope` (optional) - The scope of builds to show (one of: `all`, `finished`, `running`; default: `all`)
+- `scope` (optional) - The scope of builds to show (one or array of: pending, running, failed, success, canceled; if none provided showing all builds)
 
 ```json
 [
@@ -64,8 +64,7 @@ Parameters:
 
 - `id` (required) - The ID of a project
 - `sha` (required) - The SHA id of a commit
-- `scope` (optional) - The scope of builds to show (one of: `all`, `finished`, `running`; default: `all`)
-
+- `scope` (optional) - The scope of builds to show (one or array of: pending, running, failed, success, canceled; if none provided showing all builds)
 
 ```json
 [
diff --git a/lib/api/builds.rb b/lib/api/builds.rb
index 6b0edcff820..6aae1856953 100644
--- a/lib/api/builds.rb
+++ b/lib/api/builds.rb
@@ -8,9 +8,8 @@ module API
       #
       # Parameters:
       #   id (required) - The ID of a project
-      #   scope (optional) - The scope of builds to show (one of: all, finished, running; default: all)
-      #   page (optional) - The page number for pagination
-      #   per_page (ooptional) - The value of items per page to show
+      #   scope (optional) - The scope of builds to show (one or array of: pending, running, failed, success, canceled;
+      #                      if none provided showing all builds)
       # Example Request:
       #   GET /projects/:id/builds
       get ':id/builds' do
@@ -24,7 +23,8 @@ module API
       # Parameters:
       #   id (required) - The ID of a project
       #   sha (required) - The SHA id of a commit
-      #   scope (optional) - The scope of builds to show (one of: all, finished, running; default: all)
+      #   scope (optional) - The scope of builds to show (one or array of: pending, running, failed, success, canceled;
+      #                      if none provided showing all builds)
       # Example Request:
       #   GET /projects/:id/builds/commit/:sha
       get ':id/builds/commit/:sha' do
@@ -112,14 +112,21 @@ module API
       end
 
       def filter_builds(builds, scope)
-        case scope
-        when 'finished'
-          builds.finished
-        when 'running'
-          builds.running
-        else
-          builds
-        end
+        available_scopes = Ci::Build.available_statuses
+        scope =
+          if scope.is_a?(String) || scope.is_a?(Symbol)
+            available_scopes & [scope.to_s]
+          elsif scope.is_a?(Array)
+            available_scopes & scope
+          elsif scope.respond_to?(:to_h)
+            available_scopes & scope.to_h.values
+          else
+            []
+          end
+
+        return builds if scope.empty?
+
+        builds.where(status: scope)
       end
 
       def authorize_manage_builds!
diff --git a/spec/requests/api/builds_spec.rb b/spec/requests/api/builds_spec.rb
index d4af7639d4b..a953eb2fac2 100644
--- a/spec/requests/api/builds_spec.rb
+++ b/spec/requests/api/builds_spec.rb
@@ -18,7 +18,20 @@ describe API::API, api: true  do
       it 'should return project builds' do
         get api("/projects/#{project.id}/builds", user)
 
-        puts json_response
+        expect(response.status).to eq(200)
+        expect(json_response).to be_an Array
+      end
+
+      it 'should filter project with one scope element' do
+        get api("/projects/#{project.id}/builds?scope=pending", user)
+
+        expect(response.status).to eq(200)
+        expect(json_response).to be_an Array
+      end
+
+      it 'should filter project with array of scope elements' do
+        get api("/projects/#{project.id}/builds?scope[0]=pending&scope[1]=running", user)
+
         expect(response.status).to eq(200)
         expect(json_response).to be_an Array
       end
-- 
GitLab