github.com/web-platform-tests/wpt.fyi@v0.0.0-20240530210107-70cf978996f1/api/test_run.go (about)

     1  // Copyright 2017 The WPT Dashboard Project. All rights reserved.
     2  // Use of this source code is governed by a BSD-style license that can be
     3  // found in the LICENSE file.
     4  
     5  package api
     6  
     7  import (
     8  	"encoding/json"
     9  	"errors"
    10  	"fmt"
    11  	"net/http"
    12  	"strconv"
    13  
    14  	"github.com/gorilla/mux"
    15  
    16  	"github.com/web-platform-tests/wpt.fyi/shared"
    17  )
    18  
    19  // apiTestRunHandler is responsible for emitting the test-run JSON for a specific run.
    20  func apiTestRunHandler(w http.ResponseWriter, r *http.Request) {
    21  	if r.Method != http.MethodGet {
    22  		http.Error(w, "Only GET is supported.", http.StatusMethodNotAllowed)
    23  
    24  		return
    25  	}
    26  
    27  	vars := mux.Vars(r)
    28  	idParam := vars["id"]
    29  	ctx := r.Context()
    30  	store := shared.NewAppEngineDatastore(ctx, true)
    31  	var testRun shared.TestRun
    32  	// nolint:nestif // TODO: Fix nestif lint error
    33  	if idParam != "" {
    34  		id, err := strconv.ParseInt(idParam, 10, 0)
    35  		if err != nil {
    36  			http.Error(w, fmt.Sprintf("Invalid id '%s'", idParam), http.StatusBadRequest)
    37  
    38  			return
    39  		}
    40  		run := new(shared.TestRun)
    41  		err = store.Get(store.NewIDKey("TestRun", id), run)
    42  		if err != nil {
    43  			if errors.Is(err, shared.ErrNoSuchEntity) {
    44  				http.NotFound(w, r)
    45  
    46  				return
    47  			}
    48  			http.Error(w, err.Error(), http.StatusInternalServerError)
    49  
    50  			return
    51  		}
    52  		testRun = *run
    53  	} else {
    54  		filters, err := shared.ParseTestRunFilterParams(r.URL.Query())
    55  		if err != nil {
    56  			http.Error(w, err.Error(), http.StatusBadRequest)
    57  
    58  			return
    59  		} else if len(filters.Products) == 0 {
    60  			http.Error(w, "Missing required 'product' param", http.StatusBadRequest)
    61  
    62  			return
    63  		} else if len(filters.Products) > 1 {
    64  			http.Error(w, "Only one 'product' param value is allowed", http.StatusBadRequest)
    65  
    66  			return
    67  		}
    68  		one := 1
    69  		testRuns, err := store.TestRunQuery().LoadTestRuns(
    70  			filters.Products,
    71  			filters.Labels,
    72  			filters.SHAs,
    73  			nil,
    74  			nil,
    75  			&one,
    76  			nil,
    77  		)
    78  		if err != nil {
    79  			http.Error(w, err.Error(), http.StatusInternalServerError)
    80  
    81  			return
    82  		}
    83  
    84  		allRuns := testRuns.AllRuns()
    85  		if len(allRuns) == 0 {
    86  			http.NotFound(w, r)
    87  
    88  			return
    89  		}
    90  		testRun = allRuns[0]
    91  	}
    92  
    93  	testRunsBytes, err := json.Marshal(testRun)
    94  	if err != nil {
    95  		http.Error(w, err.Error(), http.StatusInternalServerError)
    96  
    97  		return
    98  	}
    99  
   100  	_, err = w.Write(testRunsBytes)
   101  	if err != nil {
   102  		logger := shared.GetLogger(r.Context())
   103  		logger.Warningf("Failed to write data in api/run handler: %s", err.Error())
   104  	}
   105  }