summary refs log tree commit diff stats
path: root/testament/azure.nim
blob: 7299af48008430dfdd6d41195b08ed2a0874711a (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
#
#
#              The Nim Tester
#        (c) Copyright 2019 Leorize
#
#    Look at license.txt for more info.
#    All rights reserved.

import base64, json, httpclient, os, strutils
import specs

const
  ApiRuns = "/_apis/test/runs"
  ApiVersion = "?api-version=5.0"
  ApiResults = ApiRuns & "/$1/results"

var runId* = -1

proc getAzureEnv(env: string): string =
  # Conversion rule at:
  # https://docs.microsoft.com/en-us/azure/devops/pipelines/process/variables#set-variables-in-pipeline
  env.toUpperAscii().replace('.', '_').getEnv

proc invokeRest(httpMethod: HttpMethod; api: string; body = ""): Response =
  let http = newHttpClient()
  defer: close http
  result = http.request(getAzureEnv("System.TeamFoundationCollectionUri") &
                        getAzureEnv("System.TeamProjectId") & api & ApiVersion,
                        httpMethod,
                        $body,
                        newHttpHeaders {
                          "Accept": "application/json",
                          "Authorization": "Basic " & encode(':' & getAzureEnv("System.AccessToken")),
                          "Content-Type": "application/json"
                        })
  if not result.code.is2xx:
    raise newException(HttpRequestError, "Server returned: " & result.body)

proc finish*() {.noconv.} =
  if not isAzure or runId < 0:
    return

  try:
    discard invokeRest(HttpPatch,
                       ApiRuns & "/" & $runId,
                       $ %* { "state": "Completed" })
  except:
    stderr.writeLine "##vso[task.logissue type=warning;]Unable to finalize Azure backend"
    stderr.writeLine getCurrentExceptionMsg()

  runId = -1

# TODO: Only obtain a run id if tests are run
# NOTE: We can't delete test runs with Azure's access token
proc start*() =
  if not isAzure:
    return
  try:
    if runId < 0:
      runId = invokeRest(HttpPost,
                         ApiRuns,
                         $ %* {
                           "automated": true,
                           "build": { "id": getAzureEnv("Build.BuildId") },
                           "buildPlatform": hostCPU,
                           "controller": "nim-testament",
                           "name": getAzureEnv("Agent.JobName")
                         }).body.parseJson["id"].getInt(-1)
  except:
    stderr.writeLine "##vso[task.logissue type=warning;]Unable to initialize Azure backend"
    stderr.writeLine getCurrentExceptionMsg()

proc addTestResult*(name, category: string; durationInMs: int; errorMsg: string;
                    outcome: TResultEnum) =
  if not isAzure or runId < 0:
    return
  let outcome = case outcome
                of reSuccess: "Passed"
                of reDisabled, reJoined: "NotExecuted"
                else: "Failed"
  try:
    discard invokeRest(HttpPost,
                       ApiResults % [$runId],
                       $ %* [{
                         "automatedTestName": name,
                         "automatedTestStorage": category,
                         "durationInMs": durationInMs,
                         "errorMessage": errorMsg,
                         "outcome": outcome,
                         "testCaseTitle": name
                       }])
  except:
    stderr.writeLine "##vso[task.logissue type=warning;]Unable to log test case: ",
                     name, ", outcome: ", outcome
    stderr.writeLine getCurrentExceptionMsg()