Version 0.2.
[goaljobs.git] / goaljobs-reference.pod
index 7912568..da98946 100644 (file)
@@ -180,6 +180,85 @@ program:
      cc %s -o %s
    " object program
 
+=head1 SPECIAL VALUES INSIDE GOALS
+
+=head2 goalname
+
+Inside goals, you can use C<goalname> to get the name of the goal, ie:
+
+ let goal foo () =
+   printf "my name is %s\n" goalname
+
+would print:
+
+ my name is foo
+
+=head2 goalloc
+
+Inside goals, you can use C<goalloc> to get a printable source
+location of the goal, ie:
+
+ let goal foo () =
+   printf "%s\n" goalloc
+
+would print:
+
+ File "source.ml", line 2, characters 13-71 (end at line 3, character 23)
+
+Note that the actual string format depends on the internal OCaml
+function C<Loc.to_string> so it might change in future.
+
+=head2 onfail, onsuccess, onrun
+
+Inside goals you can register function(s) which run if the goal
+completes successfully (C<onsuccess>), if the goal completes
+successfully after running to the end (C<onrun>), or if the goal fails
+(C<onfail>).
+
+For example:
+
+ let goal built () =
+   onfail (fun _ -> eprintf "goal '%s' failed\n" goalname);
+   sh "
+     cc -o program main.o
+   "
+
+If the shell command (or another part of the goal) fails, then this
+would print out:
+
+ goal 'built' failed
+
+The single parameter passed to C<onfail> is the exception that was
+thrown.
+
+Note that the helper function C<Goaljobs.mailto> is a useful function
+to call from an C<onfail> handler:
+
+ let from = "me@example.com"
+ let to_ = "you@example.com"
+ let logfile = log_program_output ()
+ let goal built () =
+   onfail (fun _ ->
+             let subject = sprintf "goal: %s: BUILD FAILED" goalname in
+             mailto ~from ~subject ~attach:[logfile] to_);
+   sh "
+     cc -o program main.o
+   "
+
+C<onsuccess> and C<onrun> are slightly different from C<onfail> and
+from each other:
+
+C<onsuccess> functions can be called if a C<target> condition is met
+and the rest of the goal is short-circuited.  C<onrun> will only be
+called if all the instructions in the goal actually run and succeed.
+
+The single unit C<()> parameter is passed to the C<onsuccess> and
+C<onrun> functions.
+
+You can register as many functions as you want for each handler.  The
+order in which the functions are called is not defined.
+
 =head1 PERIODIC JOBS
 
 If you want to have a goal that runs when some outside event happens
@@ -200,6 +279,7 @@ sees one it will ensure it passes the tests:
  let goal git_commit_tested commit =
    let key = sprintf "repo-tested-%s" commit in
    target (memory_exists key);
+   onrun (fun () -> memory_set key "1");
  
    sh "
      git clone %s test
@@ -207,10 +287,7 @@ sees one it will ensure it passes the tests:
      ./configure
      make
      make check
-   " repo_url;
-
-   (* Record that this commit was tested successfully. *)
-   memory_set key "1"
+   " repo_url
  
  every 30 minutes (fun () ->
    let commit = shout "cd %s && git rev-parse HEAD" repo in
@@ -291,10 +368,9 @@ A common pattern is:
 let goal tested version =
   let key = "myapp-tested-" ^ version in
   target (memory_exists key);
+  onrun (fun () -> memory_set key "1");
  
   (* some code to test this version *)
-  memory_set key "1"
 
 Note in that example the value C<1> is arbitrary.  You just want to
 store I<any> value so that a later call to C<memory_exists> will