add a hook_url to conduct a git pull

This commit is contained in:
Hannes Mehnert 2022-09-04 14:51:41 +02:00
parent 3d1bb6c153
commit ef2ec2e946
2 changed files with 58 additions and 14 deletions

View file

@ -28,6 +28,13 @@ let remote =
in in
Key.(create "remote" Arg.(opt string "https://github.com/ocaml/opam-repository.git#master" doc)) Key.(create "remote" Arg.(opt string "https://github.com/ocaml/opam-repository.git#master" doc))
let hook_url =
let doc =
Key.Arg.info
~doc:"URL to conduct an update of the git repository" ["hook-url"]
in
Key.(create "hook-url" Arg.(opt string "update" doc))
let port = let port =
let doc = Key.Arg.info ~doc:"HTTP listen port." ["port"] in let doc = Key.Arg.info ~doc:"HTTP listen port." ["port"] in
Key.(create "port" Arg.(opt int 80 doc)) Key.(create "port" Arg.(opt int 80 doc))
@ -41,7 +48,7 @@ let tls_authenticator =
let mirror = let mirror =
foreign "Unikernel.Make" foreign "Unikernel.Make"
~keys:[ Key.v key_hex ; Key.v check ; Key.v remote ; Key.v tls_authenticator ; Key.v port ] ~keys:[ Key.v key_hex ; Key.v check ; Key.v remote ; Key.v hook_url ; Key.v tls_authenticator ; Key.v port ]
~packages:[ ~packages:[
package ~min:"0.1.0" ~sublibs:[ "mirage" ] "paf" ; package ~min:"0.1.0" ~sublibs:[ "mirage" ] "paf" ;
package "h2" ; package "h2" ;

View file

@ -451,9 +451,7 @@ module Make
Fmt.to_to_string (Irmin.Type.pp Store.Hash.t) (Store.Commit.hash commit) Fmt.to_to_string (Irmin.Type.pp Store.Hash.t) (Store.Commit.hash commit)
let repo commit = let repo commit =
let upstream = List.hd (String.split_on_char '#' (Key_gen.remote ())) let upstream = List.hd (String.split_on_char '#' (Key_gen.remote ())) in
and commit = commit_id commit
in
Fmt.str Fmt.str
{|opam-version: "2.0" {|opam-version: "2.0"
upstream: "%s#%s" upstream: "%s#%s"
@ -470,18 +468,42 @@ stamp: %S
ptime_to_http_date ptime ptime_to_http_date ptime
type t = { type t = {
commit_id : string ; mutable commit_id : string ;
modified : string ; mutable modified : string ;
repo : string ; mutable repo : string ;
index : string ; mutable index : string ;
} }
let create commit repo index = let create commit store =
let commit_id = commit_id commit let commit_id = commit_id commit
and modified = modified commit and modified = modified commit
in in
let repo = repo commit_id in
Tarball.of_git repo store >|= fun index ->
{ commit_id ; modified ; repo ; index } { commit_id ; modified ; repo ; index }
let update_lock = Lwt_mutex.create ()
let update_git t git_ctx =
Lwt_mutex.with_lock update_lock (fun () ->
Git.connect git_ctx >>= fun (store, upstream) ->
Git.pull store upstream >>= function
| Error `Msg msg ->
Logs.err (fun m -> m "error %s while updating git" msg);
Lwt.return None
| Ok (commit, msg) ->
Logs.info (fun m -> m "git: %s" msg);
let commit_id = commit_id commit
and modified = modified commit
in
let repo = repo commit_id in
Tarball.of_git repo store >|= fun index ->
t.commit_id <- commit_id ;
t.modified <- modified ;
t.repo <- repo ;
t.index <- index;
Some store)
let not_modified request (modified, etag) = let not_modified request (modified, etag) =
match Httpaf.Headers.get request.Httpaf.Request.headers "if-modified-since" with match Httpaf.Headers.get request.Httpaf.Request.headers "if-modified-since" with
| Some ts -> String.equal ts modified | Some ts -> String.equal ts modified
@ -517,10 +539,26 @@ stamp: %S
let resp = Httpaf.Response.create `Not_modified in let resp = Httpaf.Response.create `Not_modified in
respond_with_empty reqd resp respond_with_empty reqd resp
else *) else *)
let dispatch t store _flow _conn reqd = let dispatch t store hook_url git_ctx update _flow _conn reqd =
let request = Httpaf.Reqd.request reqd in let request = Httpaf.Reqd.request reqd in
Logs.info (fun f -> f "requested %s" request.Httpaf.Request.target); Logs.info (fun f -> f "requested %s" request.Httpaf.Request.target);
match String.split_on_char '/' request.Httpaf.Request.target with match String.split_on_char '/' request.Httpaf.Request.target with
| [ ""; x ] when String.equal x hook_url ->
Lwt.async (fun () ->
update_git t git_ctx >>= function
| None -> Lwt.return_unit
| Some store -> update store);
let data = "Update in progress" in
let mime_type = "text/plain" in
let headers = [
"content-type", mime_type ;
"etag", t.commit_id ;
"last-modified", t.modified ;
"content-length", string_of_int (String.length data) ;
] in
let headers = Httpaf.Headers.of_list headers in
let resp = Httpaf.Response.create ~headers `OK in
Httpaf.Reqd.respond_with_string reqd resp data
| [ ""; "repo" ] -> | [ ""; "repo" ] ->
if not_modified request (t.modified, t.commit_id) then if not_modified request (t.modified, t.commit_id) then
let resp = Httpaf.Response.create `Not_modified in let resp = Httpaf.Response.create `Not_modified in
@ -640,14 +678,13 @@ stamp: %S
| Error `Msg msg -> Lwt.fail_with msg | Error `Msg msg -> Lwt.fail_with msg
| Ok (commit, msg) -> | Ok (commit, msg) ->
Logs.info (fun m -> m "git: %s" msg); Logs.info (fun m -> m "git: %s" msg);
let repo = Serve.repo commit in Serve.create commit store >>= fun serve ->
Tarball.of_git repo store >>= fun index ->
let serve = Serve.create commit repo index in
Paf.init ~port:(Key_gen.port ()) (Stack.tcp stack) >>= fun t -> Paf.init ~port:(Key_gen.port ()) (Stack.tcp stack) >>= fun t ->
let update store = download_archives disk http_ctx store in
let service = let service =
Paf.http_service Paf.http_service
~error_handler:(fun _ ?request:_ _ _ -> ()) ~error_handler:(fun _ ?request:_ _ _ -> ())
(Serve.dispatch serve disk) (Serve.dispatch serve disk (Key_gen.hook_url ()) git_ctx update)
in in
let `Initialized th = Paf.serve service t in let `Initialized th = Paf.serve service t in
Logs.info (fun f -> f "listening on %d/HTTP" (Key_gen.port ())); Logs.info (fun f -> f "listening on %d/HTTP" (Key_gen.port ()));