Skip to content

Commit 5cc320c

Browse files
debug db: adapt to use with the buildkite webhook (#190)
1 parent e695a48 commit 5cc320c

27 files changed

Lines changed: 319 additions & 269 deletions

db/sql/failed_builds_webhook.sql

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
-- @ensure_failed_builds_webhook_table
2+
CREATE TABLE IF NOT EXISTS failed_builds_webhook (
3+
id TEXT PRIMARY KEY,
4+
sha VARCHAR(40) NOT NULL,
5+
build_payload TEXT NOT NULL,
6+
pipeline_payload TEXT NOT NULL,
7+
jobs TEXT NOT NULL,
8+
commit_author VARCHAR(255) NOT NULL,
9+
commit_url VARCHAR(255) NOT NULL,
10+
build_state VARCHAR(10) NOT NULL,
11+
build_url VARCHAR(255) NOT NULL,
12+
build_number INTEGER NOT NULL,
13+
is_canceled BOOLEAN NOT NULL,
14+
pipeline VARCHAR(255) NOT NULL,
15+
repository VARCHAR(255) NOT NULL,
16+
branch VARCHAR(255) NOT NULL,
17+
state_before_notification TEXT NOT NULL,
18+
state_after_notification TEXT NOT NULL,
19+
last_handled_in TEXT NOT NULL,
20+
has_state_update BOOLEAN NOT NULL,
21+
notification_created_at TIMESTAMP NOT NULL,
22+
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP NOT NULL
23+
);
24+
25+
-- @create
26+
INSERT INTO failed_builds_webhook VALUES;
27+
28+
-- @update_state_after_notification
29+
UPDATE failed_builds_webhook
30+
SET has_state_update = @has_state_update, state_after_notification = @state_after_notification, last_handled_in = @last_handled_in
31+
WHERE id = @id;
32+
33+
-- @get_by_sha
34+
SELECT id, sha, build_state, build_number, is_canceled, has_state_update, last_handled_in, state_before_notification, state_after_notification
35+
FROM failed_builds_webhook WHERE sha = ? and pipeline = @pipeline and branch = @branch ORDER BY id DESC;
36+
37+
-- @get_by_build_number
38+
SELECT id, sha, build_state, build_number, is_canceled, has_state_update, last_handled_in, state_before_notification, state_after_notification
39+
FROM failed_builds_webhook WHERE build_number = ? and pipeline = @pipeline and branch = @branch ORDER BY id DESC;
40+
41+
-- @get_after
42+
SELECT id, sha, build_state, build_number, is_canceled, has_state_update, last_handled_in, state_before_notification, state_after_notification
43+
FROM failed_builds_webhook WHERE build_number >= ? and pipeline = @pipeline and branch = @branch ORDER BY build_number desc, id desc;
44+
45+
-- @get_from_to
46+
SELECT id, sha, build_state, build_number, is_canceled, has_state_update, last_handled_in, state_before_notification, state_after_notification
47+
FROM failed_builds_webhook WHERE build_number >= ? and build_number <= @to_ and pipeline = @pipeline and branch = @branch ORDER BY build_number desc, id desc;

db/sql/status_notifications.sql

Lines changed: 0 additions & 56 deletions
This file was deleted.

lib/action.ml

Lines changed: 29 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -238,7 +238,7 @@ module Action (Github_api : Api.Github) (Slack_api : Api.Slack) (Buildkite_api :
238238
| None -> n.branches
239239
| Some build_url ->
240240
let status_switched (_ : branch) =
241-
match Util.Build.get_org_pipeline_build' build_url with
241+
match Util.Build.get_org_pipeline_build n with
242242
| Error e ->
243243
log#error "failed to get org/pipeline/build_nr from build url %s: %s" build_url e;
244244
false
@@ -592,20 +592,21 @@ module Action (Github_api : Api.Github) (Slack_api : Api.Slack) (Buildkite_api :
592592
let process_buildkite_webhook (ctx : Context.t) headers body =
593593
let open Util.Webhook in
594594
try_process_notification body
595-
(let n = Buildkite_webhook_j.webhook_build_payload_of_string body in
595+
(let n = Buildkite_j.webhook_build_payload_of_string body in
596596
log#info "[buildkite_webhook] [%s] event %s: state=%s, branch=%s, commit=%s, pipeline=%s, build_url=%s"
597597
n.pipeline.provider.settings.repository
598-
(Buildkite_webhook_j.string_of_webhook_event n.event)
598+
(Buildkite_j.string_of_webhook_event n.event)
599599
(Buildkite_j.string_of_build_state n.build.state)
600600
n.build.branch (String.sub n.build.sha 0 8) (pipeline_name n) n.build.web_url;
601601
let secrets = Context.get_secrets_exn ctx in
602602
match validate_signature ?signing_key:secrets.buildkite_signing_secret ~headers body with
603603
| Error e -> action_error e
604604
| Ok () ->
605+
let%lwt (_ : int64 Database.db_use_result) = Database.Failed_builds.create ~ctx n in
605606
let repo_url = validate_repo_url secrets n in
606607
let%lwt cfg =
607608
match Context.find_repo_config ctx repo_url with
608-
| Some config -> Lwt.return config
609+
| Some cfg -> Lwt.return cfg
609610
| None ->
610611
(* Fetch the config from github.
611612
Emulate a repository record with the necessary fields to fetch the config *)
@@ -626,27 +627,48 @@ module Action (Github_api : Api.Github) (Slack_api : Api.Slack) (Buildkite_api :
626627
| Error e -> action_error @@ Printf.sprintf "failed to fetch config for %s: %s" repo_url e)
627628
in
628629
let repo_state = State.find_or_add_repo ctx.state repo_url in
629-
let org, pipeline, _build_nr = Result.get_ok @@ Util.Build.get_org_pipeline_build' n.build.web_url in
630+
let org, pipeline, _build_nr = Util.Build.get_org_pipeline_build' n.build.web_url in
630631
let repo_key = repo_key org pipeline in
631632
let is_main_branch = cfg.main_branch_name |> Option.map_default (String.equal n.build.branch) false in
632633
let should_notify = is_main_branch && (notify_fail cfg n || notify_success repo_state repo_key n) in
633634
(match should_notify with
634-
| false -> Lwt.return_unit
635+
| false ->
636+
let%lwt (_ : int64 Database.db_use_result) =
637+
Database.Failed_builds.update_state_after_notification ~repo_state ~has_state_update:false n
638+
"should notify > false"
639+
in
640+
Lwt.return_unit
635641
| true ->
636642
let channel = Common.Status_notification.inject_channel (failed_builds_channel_exn cfg n) in
637643
let%lwt notifications =
638644
match n.build.state with
639645
| Passed ->
646+
(* If the build is successful, we can remove the failed steps from the repo state. *)
640647
Stringtbl.replace repo_state.failed_steps repo_key
641648
{ steps = Common.FailedStepSet.empty; last_build = n.build.number };
649+
650+
let%lwt (_ : int64 Database.db_use_result) =
651+
Database.Failed_builds.update_state_after_notification ~repo_state ~has_state_update:true n
652+
"should notify > true > build state = passed"
653+
in
642654
Lwt.return
643655
[
644656
Slack.generate_failed_build_notification ~is_fix_build_notification:true
645657
~failed_steps:Common.FailedStepSet.empty n channel;
646658
]
647659
| Failed ->
648660
(* repo state is updated upon fetching new failed steps *)
649-
(match%lwt new_failed_steps ~repo_state ~get_build:(Buildkite_api.get_build ~cache:`Refresh ~ctx) n with
661+
(match%lwt
662+
new_failed_steps ~repo_state
663+
~get_build:(Buildkite_api.get_build ~cache:`Refresh ~ctx)
664+
~db_update:(fun ~repo_state ~has_state_update n msg ->
665+
let%lwt (_ : int64 Database.db_use_result) =
666+
Database.Failed_builds.update_state_after_notification ~repo_state ~has_state_update n
667+
(Printf.sprintf "should notify > true > build state = failed > %s" msg)
668+
in
669+
Lwt.return_unit)
670+
n
671+
with
650672
| Error e -> action_error e
651673
| Ok failed_steps ->
652674
match FailedStepSet.is_empty failed_steps with

lib/api_local.ml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -238,7 +238,7 @@ module Buildkite : Api.Buildkite = struct
238238

239239
[@@@warning "-27"]
240240
let get_build ?(cache : [ `Use | `Refresh ] option) ~ctx build_url =
241-
let* org, pipeline, build_nr = Lwt.return @@ Util.Build.get_org_pipeline_build' build_url in
241+
let org, pipeline, build_nr = Util.Build.get_org_pipeline_build' build_url in
242242
let file = clean_forward_slashes (sprintf "organizations/%s/pipelines/%s/builds/%s" org pipeline build_nr) in
243243
let url = Filename.concat buildkite_cache_dir file in
244244
with_cache_file url Buildkite_j.get_build_res_of_string

lib/api_remote.ml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -331,7 +331,7 @@ module Buildkite : Api.Buildkite = struct
331331
let cache_key org pipeline build_nr = sprintf "%s/%s/%s" org pipeline build_nr
332332

333333
let get_build ?(cache : [ `Use | `Refresh ] = `Use) ~(ctx : Context.t) build_url =
334-
let* org, pipeline, build_nr = Lwt.return @@ Util.Build.get_org_pipeline_build' build_url in
334+
let org, pipeline, build_nr = Util.Build.get_org_pipeline_build' build_url in
335335
let path = sprintf "organizations/%s/pipelines/%s/builds/%s" org pipeline build_nr in
336336
let build_key = cache_key org pipeline build_nr in
337337
let get () =

lib/buildkite.atd

Lines changed: 58 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -74,12 +74,12 @@ type job_type = [
7474
| Waiter <json name="waiter"> of non_job
7575
] <json adapter.ocaml="Atdgen_runtime.Json_adapter.Type_field"> <ocaml repr="classic">
7676

77+
type jobs = job_type list
78+
7779
type get_build_res = {
78-
state: build_state;
80+
inherit build_base;
7981
created_at: string;
80-
finished_at: string nullable;
81-
jobs: job_type list;
82-
branch: string;
82+
jobs: jobs;
8383
}
8484

8585
(* Custom type for the steps state and not a Buildkite type. We have them here
@@ -88,3 +88,57 @@ type failed_step = {
8888
name: string;
8989
build_url: string;
9090
}
91+
92+
(* for now we only subscribe to build.finished *)
93+
type webhook_event = [
94+
| Build_finished <json name="build.finished">
95+
| Other of string
96+
] <json open_enum> <ocaml repr="classic">
97+
98+
type build_creator = {
99+
email: string;
100+
}
101+
type build_metadata = {
102+
?commit <json name="buildkite:git:commit"> : string nullable;
103+
}
104+
105+
type build_base = {
106+
id: string;
107+
api_url <json name="url"> : string;
108+
web_url: string;
109+
number: int;
110+
state: build_state;
111+
created_at: string;
112+
cancel_reason: string nullable;
113+
blocked: bool;
114+
blocked_state: string nullable;
115+
message: string;
116+
sha <json name="commit"> : string;
117+
branch: string;
118+
?meta_data: build_metadata nullable;
119+
creator: build_creator;
120+
}
121+
122+
type pipeline_provider_settings = {
123+
repository: string;
124+
}
125+
126+
type pipeline_provider = {
127+
settings: pipeline_provider_settings;
128+
}
129+
130+
type pipeline = {
131+
id: string;
132+
web_url: string;
133+
name: string;
134+
description: string;
135+
repository: string;
136+
slug: string nullable;
137+
provider: pipeline_provider;
138+
}
139+
140+
type webhook_build_payload = {
141+
event: webhook_event;
142+
build: build_base;
143+
pipeline: pipeline;
144+
}

lib/buildkite_webhook.atd

Lines changed: 0 additions & 56 deletions
This file was deleted.

0 commit comments

Comments
 (0)