-
Notifications
You must be signed in to change notification settings - Fork 19
/
Copy pathbuild.ml
125 lines (113 loc) · 4.37 KB
/
build.ml
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
122
123
124
125
open Current.Syntax
module Github = Current_github
let timeout = Duration.of_min 50
let password_path = "/run/secrets/ocurrent-hub"
let push_repo = "ocurrentbuilder/staging"
let auth : (string * string) option option ref = ref None
let get_auth () =
match !auth with
| Some a -> a
| None ->
if Sys.file_exists password_path then (
let ch = open_in_bin password_path in
let len = in_channel_length ch in
let password = really_input_string ch len |> String.trim in
close_in ch;
auth := Some (Some ("ocurrent", password))
) else (
Logs.warn (fun f -> f "Password file %S not found; images will not be pushed to hub@." password_path);
auth := Some (None)
);
Option.join !auth
type org = string * Current_github.Api.t option
let account = fst
let api = snd
let org ?app ~account id =
let api =
app |> Option.map @@ fun app ->
Current_github.App.installation app ~account id
|> Current_github.Installation.api
in
account, api
let head_of ?github repo name =
let gref = `Ref ("refs/heads/" ^ name) in
match github with
| None ->
None, Github.Api.Anonymous.head_of repo gref
| Some github ->
let commit = Github.Api.head_of github repo gref in
Some commit, Current.map Github.Api.Commit.id commit
(* Push a Slack notification to [channel] to say that [x] is updating [service] to [commit].
[repo] is used for the URL in the message. *)
let notify ?channel ~web_ui ~service ~commit ~repo x =
match channel with
| None -> x
| Some channel ->
let s =
let+ state = Current.state x
and+ commit in
let uri = Github.Api.Commit.uri commit in
Fmt.str "@[<h>Deploy <%a|%a> as %s: <%s|%a>@]"
Uri.pp uri Github.Api.Commit.pp_short commit
service
(Uri.to_string (web_ui repo)) (Current_term.Output.pp Current.Unit.pp) state
in
Current.all [
Current_slack.post channel ~key:("deploy-" ^ service) s;
x (* If [x] fails, the whole pipeline should fail too. *)
]
let label l x =
Current.component "%s" l |>
let> x in
Current.Primitive.const x
module Make(T : S.T) = struct
(* TODO Summarise build results. *)
let status_of_build ~url build =
let+ state = Current.state build in
match state with
| Ok _ -> Github.Api.CheckRunStatus.v ~url (`Completed `Success) ~summary:"Passed"
| Error (`Active _) -> Github.Api.CheckRunStatus.v ~url `Queued
| Error (`Msg m) -> Github.Api.CheckRunStatus.v ~url (`Completed (`Failure m)) ~summary:m
let repo ?channel ~web_ui ~org:(org, github) ?additional_build_args ~name build_specs =
let repo_name = Printf.sprintf "%s/%s" org name in
let repo = { Github.Repo_id.owner = org; name } in
let root = Current.return ~label:repo_name () in (* Group by repo in the diagram *)
Current.with_context root @@ fun () ->
let builds = github |> Option.map @@ fun github ->
let refs = Github.Api.ci_refs github repo in
let collapse_value = repo_name ^ "-builds" in
let url = web_ui collapse_value in
let pipeline =
refs
|> Current.list_iter (module Github.Api.Commit) @@ fun commit ->
let src = Current.map Github.Api.Commit.id commit in
Current.all (
List.map (fun (build_info, _) ->
T.build ?additional_build_args build_info repo src
) build_specs
)
|> status_of_build ~url
|> Github.Api.CheckRun.set_status commit "deployability"
in
Current.collapse ~key:"repo" ~value:collapse_value ~input:refs pipeline
and deployment =
let root = label "deployments" root in
Current.with_context root @@ fun () ->
Current.all (
build_specs |> List.map (fun (build_info, deploys) ->
Current.all (
deploys |> List.map (fun (branch, deploy_info) ->
let service = T.name deploy_info in
let commit, src = head_of ?github repo branch in
let deploy = T.deploy build_info deploy_info ?additional_build_args src in
match channel, commit with
| Some channel, Some commit -> notify ~channel ~web_ui ~service ~commit ~repo:repo_name deploy
| _ -> deploy
)
)
)
)
|> Current.collapse ~key:"repo" ~value:repo_name ~input:root
in
Current.all (deployment :: Option.to_list builds)
end