aboutsummaryrefslogtreecommitdiff
path: root/sourcehut-builds/poller.luau
blob: 39cfa5b2fa800112f54678950d8dbc98493302bd (plain)
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
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
--!nonstrict
-- Poller for sourcehut, checks the actual poll

local K = require("./constants.luau")
local ErrorUtils = require("./error_utils.luau")
local DateUtils = require("./date_utils.luau")
local TableUtils = require("./table_utils.luau")

--------------------------------------------------------------------------------
-- Internal Functions
--------------------------------------------------------------------------------

--------------------------------------------------------------- State Management

local function notifyStateChange(state: PollerStatus)
  noctalia.state.set(K.events.poller_state_updated, state)
end

local function notifyError(error: string)
  notifyStateChange({type = "error", error = error})
end

local function notifyBuildsChange(state: SourcehutBuildsState)
  noctalia.state.set(K.events.builds_state_updated, state)
end

------------------------------------------------------------------------ Parsing

local function parseBuilds(builds: SourcehutBuildResponse)
  local successful = 0
  local failed = 0
  local inProgress = 0
  local cutoff = noctalia.getConfig(K.poller.cutoff_configuration_key)
  local build_count = noctalia.getConfig(K.poller.build_count_configuration_key)
  local now = os.time()
  local eligible_builds = TableUtils.trim(builds.data.me.jobs.results, build_count)
  for _, job in ipairs(eligible_builds) do
    local jobDate = DateUtils.parseDate(job.created)
    if now - jobDate > cutoff then
      continue
    end
    if job.status == "SUCCESS" then
      successful += 1
    end
    if job.status == "FAILED" then
      failed += 1
    end
    if job.status == "RUNNING" then
      inProgress += 1
    end
  end
  local state = {
    successful = successful,
    failed = failed,
    inProgress = inProgress,
    user = builds.data.me.canonicalName,
    builds = eligible_builds
  }
  notifyStateChange(K.poller.state.ok)
  notifyBuildsChange(state)
end

------------------------------------------------------------------------ Network

local function onBuildsFetched(response: HttpResponse)
  if not response.ok then
    notifyError(K.poller.errors.request_failed)
    return
  end
  local builds, error = noctalia.json.decode(response.body)
  if error or builds == nil then
    notifyError(K.poller.errors.bad_response)
    return
  end
  if response.status == 400 then
    if type(builds.errors) == "table" then
      for _, error_response in ipairs(builds.errors) do
        if ErrorUtils.isUnauthorized(error_response) then
          notifyError(K.poller.errors.unauthorized)
          return
        end
      end
    end
    notifyError(K.poller.errors.bad_response)
    return
  end
  parseBuilds(builds)
end

local function fetchBuilds()
  local request: HttpRequest = {
    url = K.sourcehut.builds_url,
    method = "GET",
    body = K.sourcehut.query,
    headers = {
      "Content-Type: application/json",
      "Authorization: Bearer " .. noctalia.getConfig(K.sourcehut.token_configuration_key)
    },
  }
  noctalia.http(request, onBuildsFetched)
end

---------------------------------------------------------------------- Lifecycle

local function run()
  noctalia.setUpdateInterval(K.poller.update_interval)
  update()
end

--------------------------------------------------------------------------------
-- Public API
--------------------------------------------------------------------------------
function update()
  fetchBuilds()
end

function onConfigChanged()
  fetchBuilds()
end

run()