#!/usr/bin/env python3
"""build.py -- the .org XWiki's three pages in the starshipos-f18.com look (the "StarshipOS.com"
design canvas: navy #0A1222, accent #F5891F, JetBrains Mono, Exo 2 headings), from one source.
site/org/build.py writes Main.WebHome.xwiki, Admin.WebHome.xwiki,
Contributors.WebHome.xwiki (each one {{html}} block)
site/org/build.py --canvas
also writes /project/Org*.dc.html, the same pages as
design-canvas artboards (status badges drawn as placeholders:
a canvas loads nothing from Gitea)
The {{html}} macro needs a page author with script rights. install.sh puts the pages on the wiki.
"""
import os
import sys
sys.path.insert(0, os.path.join(os.path.dirname(os.path.abspath(__file__)), ".."))
import colorlock # noqa: E402 the design's colours over the wiki's high-contrast theme
GITEA = "https://gitea.starshipos-f18.org/rajames/LithosAnanke"
COM = "https://starshipos-f18.com/"
ISSUES = GITEA + "/issues?state=open"
ACCENT = "#F5891F"
TEAL = "#4FD1B0"
FONTS = ('\n'
'')
H = "font-family: 'Exo 2', sans-serif"
CARD = "background: #111C30; border: 1px solid #22324D; border-radius: 6px; padding: 28px"
EYEBROW = ("margin: 0 0 12px; font-size: 13px; letter-spacing: 0.14em; text-transform: uppercase; "
"color: {accent}")
BTN = ("display: inline-block; padding: 14px 24px; background: {accent}; color: #0A1222; "
"font-weight: 700; text-decoration: none; border-radius: 4px")
BTN2 = ("display: inline-block; padding: 14px 24px; border: 1px solid #34486A; color: #EEF2F7; "
"text-decoration: none; border-radius: 4px")
WRAP = "max-width: 1120px; margin: 0 auto"
WORKFLOWS = { # file -> (branch for the badge, what it is)
"acceptance.yml": (None, "Acceptance -- the gate on every PR into master"),
"build.yml": ("StarForth-v4.0.0", "Build -- the quick check on StarForth-v4.0.0"),
"nightly.yml": ("master", "Nightly -- acceptance, images to Nexus, proofs (03:00 UTC)"),
"nightly-docs.yml": ("master", "Nightly documents (04:00 UTC)"),
"runner-image.yml": ("master", "Runner image"),
"release.yml": (None, "Release -- a v<version> tag"),
}
def badge(wf, canvas):
branch = WORKFLOWS[wf][0]
if canvas:
return ('[LIVE STATUS]')
q = "?branch=" + branch if branch else ""
return ('' % (GITEA, wf, q, wf))
def status_rows(wfs, canvas, runs=True):
rows = []
for wf in wfs:
link = (' runs' % (GITEA, wf)
if runs else "")
rows.append('
" % i for i in items))
def a(href, text):
return '%s' % (href, text)
def code(s):
return '%s' % s
def page_main(canvas, url):
links_ = [("Home", url("Main"), "Main"), ("Contributors", url("Contributors"), "Contributors")]
glance = [("v2.1.0", "LithosAnanke, the UEFI microkernel"), ("v4", "StarForth, the F18 engine"),
("3 ISAs", "amd64 · aarch64 · riscv64"), ("538", "POST checks on every boot")]
strip = ('\n
%s
\n'
% (WRAP, "".join('
%s
'
'
%s
' % (H, n, t)
for n, t in glance)))
project = section("The project", "One repository, one process, one line to master.", grid([
card("The source", "kernel, StarForth, proofs, documents",
'
Everything in one repository: LithosAnanke, '
'StarForth v3 and v4, the Isabelle/HOL proofs and the books.
Every piece of work starts as an issue with its '
'evidence, and is ruled before it is built.
' + a(GITEA + "/issues", "Open issues →")),
card("Pull requests", "the only way into master",
'
master takes nothing but a pull request that '
'passed the acceptance protocol.
' + a(GITEA + "/pulls", "Pull requests →")),
]), pad="96px 24px 48px")
accept = section("How a change is accepted", "Booted on three architectures, every time.",
'
The kernel boots in QEMU '
'on amd64, aarch64 and riscv64 to its prompt, its power-on self-test passing every check; '
'the PC stick boots loaded the way a PC loads it; the 32-bit build passes its tests. A '
'developer runs it by hand, a pull request runs it by itself, and the nightly runs it '
'again before it publishes.
\n'
% (WRAP, CARD, EYEBROW, H, url("login"), BTN, url("Contributors"), BTN2))
return "\n".join([
nav("Main", links_),
hero("ok> the working home", "Where StarshipOS is built.",
"StarshipOS is an operating system with no other operating system underneath it. LithosAnanke, a "
"UEFI microkernel, boots straight from the firmware and runs StarForth, a FORTH virtual machine, "
"as its only runtime. This wiki holds its design, its record and its dashboards; the public face "
"is " + a(COM, "starshipos-f18.com") + ".",
'Browse the sourceTry it in a browser'
% (GITEA, BTN, COM + "bin/view/TryIt/", BTN2)),
strip, project, accept, contrib, FOOTER])
def page_admin(canvas, url):
links_ = [("Home", url("Main"), "Main"), ("Contributors", url("Contributors"), "Contributors"),
("Admin", url("Admin"), "Admin")]
ci = section("CI", "Every workflow, live.", '
%s
' % (CARD, status_rows(list(WORKFLOWS), canvas)),
pad="0 24px 48px")
work = card("Work", "Gitea", links([
a(GITEA + "/pulls?state=open", "Open pull requests"),
a(ISSUES, "Open issues") + " — " + a(ISSUES + "&labels=23", "in progress") + ", "
+ a(ISSUES + "&labels=20", "blocked") + ", " + a(ISSUES + "&labels=21", "needs acceptance"),
a(GITEA + "/milestones", "Milestones") + " and " + a(GITEA + "/projects", "the project board"),
a(GITEA + "/settings/branches", "Branch protection") + " — master: no pushes, merges only after Acceptance",
a(GITEA + "/settings/actions/secrets", "Actions secrets") + " — " + code("NEXUS_CI_PASSWORD") + ", "
+ code("PACKAGES_TOKEN") + ", " + code("CAPSULE_SIGN_KEY"),
a(GITEA + "/settings/actions/runners", "Runners"),
a("https://gitea.starshipos-f18.org/user/settings/applications", "Access tokens")
+ " — revoke what a session no longer needs"]))
arts = card("Artifacts", "Nexus and packages", links([
a("https://nexus.starshipos-f18.org/#browse/browse:starshipos-snapshots:org%2Fstarship", "Snapshots")
+ " — " + code("kernelImage") + " (pc, raspi5, milkv, logs), " + code("documentation")
+ " (book, vol1–vol3, api)",
a("https://nexus.starshipos-f18.org/#browse/browse:starshipos-releases:org%2Fstarship", "Releases"),
a("https://gitea.starshipos-f18.org/rajames/-/packages", "Container images") + " — "
+ code("lithosananke-runner"), ]))
sites = card("Sites", "and the wiki itself", links([
a(COM, "starshipos-f18.com") + " and " + a(COM + "bin/view/TryIt/", "Try it"),
a(url("Contributors"), "Contributors' dashboard"),
a(url("admin"), "Wiki administration") + " — users, the group " + code("XWiki.StarshipContributors")
+ ", rights"]))
return "\n".join([
nav("Admin", links_),
hero("Administrator only", "Admin dashboard.",
"Seen by " + code("XWiki.rajames") + " alone: the Admin space allows view and edit to that "
"account and nobody else."),
ci, section("Run the project", "Work, artifacts, sites.", grid([work, arts, sites], 300), pad="0 24px 96px"),
FOOTER])
def page_contrib(canvas, url):
links_ = [("Home", url("Main"), "Main"), ("Contributors", url("Contributors"), "Contributors")]
steps = [("Found", "An issue says what is wrong or missing, with the evidence: a log, a line of code."),
("Ruled", "Captain Bob decides what is to be done. Nothing is built without a ruling, and no fix "
"nobody asked for."),
("Built", "On the working branch, " + code("StarForth-v4.0.0") + ". C99, no GNU extensions; compose "
"in FORTH before adding a C word."),
("Verified", "The acceptance protocol, below; its logs are committed under " + code("logs/") + "."),
("Merged", "A pull request into " + code("master") + ", which runs acceptance by itself. master takes "
"nothing else.")]
method = section("How we work", "The Captain Bob method.",
'
Neither agile nor waterfall: '
'one process from the developer\'s desk to master.
\n' + grid(
['
'
'%d
%s
'
'
%s
'
% (CARD, H, i + 1, H, t, d) for i, (t, d) in enumerate(steps)], 190), pad="0 24px 48px")
cmds = ("make -f kernel/Makefile ARCH=amd64 clean qemu\n"
"make -f kernel/Makefile ARCH=aarch64 clean qemu\n"
"make -f kernel/Makefile ARCH=riscv64 clean qemu\n"
"make -f kernel/Makefile ARCH=amd64 clean qemu-stick-high\n"
"make -C v4 test-32")
accept = section("The acceptance protocol", "In this order, one QEMU at a time, in the foreground.",
'
'
'%s
\n
Each boot reaches '
'%s with %s and every POST check passing, and the three architectures report the same '
'%s. %s installs everything this needs.
\n
%s
'
% (cmds, code("[zuse@Hera] ok>"), code("POST: PASSED"), code("dict_hash"),
code("make ARCH=amd64,aarch64,riscv64 init"), CARD,
status_rows(["acceptance.yml", "build.yml", "nightly.yml"], canvas)))
where = card("Where things are", "start here", links([
a(GITEA, "The repository") + " — " + code("README.md") + ", " + code("docs/README.md")
+ "; the design record is " + code("docs/fabric/FABRIC-3.md"),
a(GITEA + "/issues/new/choose", "New issue") + " — the forms: bug, work, ruling, board",
a(ISSUES + "&labels=2", "Open features") + " and " + a(ISSUES + "&labels=1", "bugs"),
a(ISSUES + "&milestone=2", "Board bring-up") + " — " + code("boards/BRINGUP.md"),
"Before touching a capsule: read " + code("experiments/bare_metal/README.md")
+ " — the block ranges are shared by every capsule"]))
rules = card("Rules that bite", "learned the hard way", links([
"No new branch, no " + code("git stash") + ", without Captain Bob's say-so.",
"Never modify a registered, tested FORTH word to fix it: the problem is in the caller.",
"ACL policy lives in " + code("ACL.4th") + ", not in C.",
"Tags are sacred: each has the logs proving its state."]))
return "\n".join([
nav("Contributors", links_),
hero("Contributors", "Contributors' dashboard.",
"For the members of " + code("XWiki.StarshipContributors") + " and the administrator. "
"Ask Captain Bob to be added."),
method, accept, section("Reference", "Where things are, and what not to do.",
grid([where, rules], 360), pad="0 24px 96px"),
FOOTER])
PAGES = { # name -> (builder, title, canvas file, canvas height)
"Main": (page_main, "StarshipOS", "OrgHome.dc.html", 2300),
"Admin": (page_admin, "Admin Dashboard", "OrgAdmin.dc.html", 1900),
"Contributors": (page_contrib, "Contributors' Dashboard", "OrgContributors.dc.html", 2500),
}
def wiki_url(key):
return {"login": "/bin/login/XWiki/XWikiLogin?xredirect=/bin/view/Contributors/",
"admin": "/bin/admin/XWiki/XWikiPreferences"}.get(key, "/bin/view/%s/" % key)
def canvas_url(key):
files = {k: v[2] for k, v in PAGES.items()}
return files.get(key, "https://starshipos-f18.org" + wiki_url(key))
def body(name, canvas):
html = PAGES[name][0](canvas, canvas_url if canvas else wiki_url)
return ('
\n\n\n\nStarshipOS.org — %s'
'\n\n\n\n\n\n%s\n\n\n%s\n'
'\n\n\n\n' % (title, FONTS, html, h))
os.makedirs(os.path.join(root, "project"), exist_ok=True)
with open(os.path.join(root, "project", file), "w") as f:
f.write(doc)
if __name__ == "__main__":
os.chdir(os.path.dirname(os.path.abspath(__file__)))
canvas_root = sys.argv[2] if len(sys.argv) > 2 and sys.argv[1] == "--canvas" else None
for n in PAGES:
write_wiki(n)
if canvas_root:
write_canvas(n, canvas_root)
print("wrote", ", ".join("%s.WebHome.xwiki" % n for n in PAGES),
"and the canvas artboards" if canvas_root else "")