domain/architecture/system/plan/ops.bend
near-v-framework@0.3.0.1 · 100 lines · 0 definitions
1import Base
2import near-v-framework@0.3.0.1/domain/architecture/system/release/type.bend as Rl
3import near-v-framework@0.3.0.1/domain/architecture/system/release/ops.bend as RlO
4import near-v-framework@0.3.0.1/domain/architecture/system/plan/type.bend as P
5
6def visibility(p: Bool) -> String:
7 match p:
8 case True{}:
9 "public"
10 case False{}:
11 "private"
12
13# ---- the repository: Bend only and no dead code come first, then GitHub ----
14def repo_steps(+fs: List<&2, String>, +reached: List<&2, String>) -> List<&2, P.Step>:
15 List.append(&2, P.Step,
16 Bool.pick(List<&2, P.Step>, String.is_empty(RlO.not_bend(fs)), [],
17 [P.Blocked{"repository", RlO.not_bend(fs) ++ " is not Bend"}]),
18 List.append(&2, P.Step,
19 Bool.pick(List<&2, P.Step>, String.is_empty(RlO.dead(fs, reached)), [],
20 [P.Blocked{"repository", RlO.dead(fs, reached) ++ " is dead code: no entry reaches it"}]),
21 Bool.pick(List<&2, P.Step>, String.is_empty(RlO.hub_refused(reached)), [],
22 [P.Blocked{"repository", RlO.hub_refused(reached) ++ ": the Bend hub refuses this path (segments of letters, digits and _)"}])))
23
24def remote_step(+repo: Rl.Repository, rm: P.Remote) -> P.Step:
25 match repo rm:
26 case Rl.Repository{+name, +public} P.Remote{+origin, +vis, clean, pushed}:
27 Bool.pick(P.Step, String.contains(origin, name),
28 Bool.pick(P.Step, String.eq(vis, visibility(public)),
29 Bool.pick(P.Step, clean,
30 Bool.pick(P.Step, pushed, P.Current{"github " ++ name}, P.Push{name}),
31 P.Blocked{"github " ++ name, "uncommitted changes"}),
32 P.Blocked{"github " ++ name, "GitHub says " ++ Bool.pick(String, String.is_empty(vis), "nothing (unreachable)", vis) ++ ", declared " ++ visibility(public)}),
33 P.Blocked{"github " ++ name, "origin is " ++ origin})
34
35# ---- each package: already published as it is, new, or changed without a new version ----
36def package_step(p: Rl.Package, h: P.Hub) -> P.Step:
37 match p:
38 case Rl.Package{+n, +v, e, _}:
39 match h:
40 case P.Same{}:
41 P.Current{"package " ++ n ++ "@" ++ v}
42 case P.Unpublished{}:
43 P.Publish{n, v, e}
44 case P.Differs{f}:
45 P.Blocked{"package " ++ n ++ "@" ++ v, f ++ " changed since it was published; give it a new version"}
46
47def package_steps(ps: List<&2, Rl.Package>, hs: List<&2, P.Hub>) -> List<&2, P.Step>:
48 match ps:
49 case []:
50 []
51 case p <> prest:
52 match hs:
53 case []:
54 []
55 case h <> hrest:
56 package_step(p, h) <> package_steps(prest, hrest)
57
58# The plan: what a deploy would do, from the release and what was observed.
59def plan(r: Rl.Release, o: P.Observed) -> List<&2, P.Step>:
60 match r o:
61 case Rl.Release{repo, ps} P.Observed{+fs, +reached, hs, rm}:
62 List.append(&2, P.Step, repo_steps(fs, reached), List.append(&2, P.Step, package_steps(ps, hs), [remote_step(repo, rm)]))
63
64def blocked(s: P.Step) -> Bool:
65 match s:
66 case P.Blocked{_, _}:
67 True{}
68 case _:
69 False{}
70
71def any_blocked(ss: List<&2, P.Step>) -> Bool:
72 match ss:
73 case []:
74 False{}
75 case s <> rest:
76 blocked(s) || any_blocked(rest)
77
78def show(s: P.Step) -> String:
79 match s:
80 case P.Current{w}:
81 "current " ++ w
82 case P.Publish{n, v, _}:
83 "publish " ++ n ++ "@" ++ v
84 case P.Push{r}:
85 "push github " ++ r
86 case P.Rebuild{h, _, _}:
87 "rebuild nix-darwin " ++ h
88 case P.ServePort{p, t, _}:
89 "serve :" ++ U32.show(p) ++ " -> " ++ t
90 case P.Change{w, now, want}:
91 "change " ++ w ++ ": " ++ now ++ " -> " ++ want
92 case P.Blocked{w, why}:
93 "blocked " ++ w ++ ": " ++ why
94
95def show_all(ss: List<&2, P.Step>) -> String:
96 match ss:
97 case []:
98 ""
99 case s <> rest:
100 show(s) ++ "\n" ++ show_all(rest)