Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,7 @@ To add and configure the "BrowserStack App Automate - Espresso" step in Bitrise,
| --- | --- |
| `$BROWSERSTACK_BUILD_URL` |BrowserStack Dashboard url for the executed build|
| `$BROWSERSTACK_BUILD_STATUS`| Status of the executed build. Check out the [test results guide](https://www.browserstack.com/docs/app-automate/espresso/view-test-results) to learn about available status |
| `$BROWSERSTACK_COVERAGE_REPORTS`| Path to the coverage report downloaded from Browserstack when coverage is enabled |

</details>

Expand Down
2 changes: 2 additions & 0 deletions constants.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@ const (
APP_AUTOMATE_BUILD_ENDPOINT = "/app-automate/espresso/v2/build"
APP_AUTOMATE_BUILD_STATUS_ENDPOINT = "/app-automate/espresso/v2/builds/"
APP_AUTOMATE_BUILD_DASHBOARD_URL = "https://app-automate.browserstack.com/dashboard/v2/builds/"
APP_AUTOMATE_SESSIONS_PATH = "/sessions/"
COVERAGE_FOLDER = "browserstack_coverage"

SAMPLE_APP = "bs://b91841adbf33515fef7a1cca869a9526a86f9a0e"
SAMPLE_TEST_SUITE = "bs://535a0932c8a785384b8470ec6166e093cd3b2c5f"
Expand Down
13 changes: 13 additions & 0 deletions main.go
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,19 @@ func main() {
failf(err.Error())
}

use_coverage, _ := strconv.ParseBool(os.Getenv("use_coverage"))
if use_coverage {
err = getCoverageReports(build_id, username, access_key)
if err != nil {
fmt.Printf("Failed to get coverage reports, error: %#v", err)
}
cmd_log_coverage_report, err_coverage_report := exec.Command("bitrise", "envman", "add", "--key", "BROWSERSTACK_COVERAGE_REPORTS", "--value", COVERAGE_FOLDER).CombinedOutput()

if err_coverage_report != nil {
fmt.Printf("Failed to expose coverage report with envman, error: %#v | output: %s", err, cmd_log_coverage_report)
}
}

cmd_log_build_id, err_build_id := exec.Command("bitrise", "envman", "add", "--key", "BROWSERSTACK_BUILD_URL", "--value", APP_AUTOMATE_BUILD_DASHBOARD_URL+build_parsed_response["build_id"].(string)).CombinedOutput()
cmd_log_build_status, err_build_status := exec.Command("bitrise", "envman", "add", "--key", "BROWSERSTACK_BUILD_STATUS", "--value", build_status).CombinedOutput()

Expand Down
93 changes: 93 additions & 0 deletions services.go
Original file line number Diff line number Diff line change
Expand Up @@ -212,3 +212,96 @@ func checkBuildStatus(build_id string, username string, access_key string, waitF
}
}
}

func getCoverageReports(build_id string, username string, access_key string) error {

var sessionIds, err = getSessionIds(build_id, username, access_key)
if err != nil {
return err
}
if err := os.Mkdir(COVERAGE_FOLDER, os.ModePerm); err != nil {
return err
}
for _, session := range sessionIds {
err = getCoverageReport(build_id, session, username, access_key)
if err != nil {
return err
}
}
return nil
}

func getCoverageReport(build_id string, sessionId string, username string, access_key string) error {
client := &http.Client{}
req, _ := http.NewRequest("GET", BROWSERSTACK_DOMAIN+APP_AUTOMATE_BUILD_STATUS_ENDPOINT+build_id+APP_AUTOMATE_SESSIONS_PATH+sessionId+"/coverage", nil)

req.SetBasicAuth(username, access_key)

req.Header.Set("Content-Type", "application/json")

res, err := client.Do(req)

if err != nil {
return fmt.Errorf(HTTP_ERROR, err)
}

defer res.Body.Close()

// Create the file
var filePath = COVERAGE_FOLDER + "/" + sessionId + "-coverage.ec"
out, err := os.Create(filePath)
if err != nil {
return fmt.Errorf(HTTP_ERROR, err)
}
defer out.Close()

_, err = io.Copy(out, res.Body)

if err != nil {
return fmt.Errorf(HTTP_ERROR, err)
}
// Download all coverage files (may not be android), document the output variable
log.Println("Coverage file saved : ", filePath)
return nil
}

func getSessionIds(build_id string, username string, access_key string) ([]string, error) {

var ids = make([]string, 0)
client := &http.Client{}
req, _ := http.NewRequest("GET", BROWSERSTACK_DOMAIN+APP_AUTOMATE_BUILD_STATUS_ENDPOINT+build_id, nil)

req.SetBasicAuth(username, access_key)

req.Header.Set("Content-Type", "application/json")

res, err := client.Do(req)

if err != nil {
return ids, fmt.Errorf(HTTP_ERROR, err)
}

defer res.Body.Close()

body, err := ioutil.ReadAll(res.Body)

if err != nil {
return ids, fmt.Errorf(HTTP_ERROR, err)
}

var buildResult Build
unmarshal_err := json.Unmarshal([]byte(body), &buildResult)

if unmarshal_err != nil {
return ids, fmt.Errorf(HTTP_ERROR, err)
}

for _, device := range buildResult.Devices {
for _, session := range device.Sessions {
ids = append(ids, session.Id)
}
}

return ids, nil

}
15 changes: 15 additions & 0 deletions step.yml
Original file line number Diff line number Diff line change
Expand Up @@ -260,6 +260,15 @@ inputs:
- "true"
- "false"
category: "Test Configuration"
- use_coverage: "false"
opts:
title: "Coverage"
description: "Generate the code coverage report"
summary: "Generate the code coverage report for projects that have jacoco and test coverage enabled"
value_options:
- "true"
- "false"
category: "Test Configuration"


outputs:
Expand All @@ -274,6 +283,12 @@ outputs:
summary: Bs build status
description: |
Status of the executed build. Check values [here:] (https://www.browserstack.com/docs/app-automate/espresso/view-test-results)
- BROWSERSTACK_COVERAGE_REPORTS:
opts:
title: "BrowserStack Coverage Report Folder"
summary: Bs coverage report folder
description: |
Path to the coverage report folder downloaded from Browserstack when coverage is enabled



13 changes: 13 additions & 0 deletions structs.go
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ type BrowserStackPayload struct {
Size []string `json:"size,omitempty"`
UseMockServer bool `json:"allowDeviceMockServer,omitempty"`
UseTestSharding interface{} `json:"shards,omitempty"`
UseCoverage bool `json:"coverage,omitempty"`

// Apart from the inputs from UI, these are some more fields which we support.
// We've mentioned the type and the json key for these field.
Expand All @@ -54,3 +55,15 @@ type BrowserStackPayload struct {
// LocalIdentifier string `json:"localIdentifier,omitempty"`
// IdleTimeout string `json:"idleTimeout,omitempty"`
}

type Build struct {
Devices []Device `json:"devices"`
}

type Device struct {
Sessions []Session `json:"sessions"`
}

type Session struct {
Id string `json:"id"`
}
2 changes: 2 additions & 0 deletions util_fns.go
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,7 @@ func createBuildPayload() BrowserStackPayload {
clear_app_data, _ := strconv.ParseBool(os.Getenv("clear_app_data"))
use_single_runner_invocation, _ := strconv.ParseBool(os.Getenv("use_single_runner_invocation"))
use_mock_server, _ := strconv.ParseBool(os.Getenv("use_mock_server"))
use_coverage, _ := strconv.ParseBool(os.Getenv("use_coverage"))

sharding_data := TestSharding{}
if os.Getenv("use_test_sharding") != "" {
Expand All @@ -136,6 +137,7 @@ func createBuildPayload() BrowserStackPayload {
UseLocal: use_local,
ClearAppData: clear_app_data,
UseMockServer: use_mock_server,
UseCoverage: use_coverage,
}

getTestFilters(&payload)
Expand Down