Skip to content

Commit

Permalink
Add simple scripting to build specification releases
Browse files Browse the repository at this point in the history
Add some make driven automation to build releases of the specification and
maintain an HTML index of releases. To be driven by a GitHub actions
workflow calling make release with, i.e.
  mkdir build && cd build && make -f ../Makefile release

Adds some helper scripts:
* get_version.py: is a simple Python script which uses a regex to fetch
  the version number from a tuf-spec.md -- the script helps avoid dealing
  with different options between GNU grep (Linux) and BSD grep (macOS
  and other BSDs)
* build_index.py: includes a string which replicates enough of the style
  of the bikeshed formatted specification to build an appropriately
  themed HTML page linking to latest, draft, and versioned releases

Signed-off-by: Joshua Lock <[email protected]>
  • Loading branch information
joshuagl committed Feb 18, 2021
1 parent d508ee4 commit 8280e43
Show file tree
Hide file tree
Showing 3 changed files with 264 additions and 3 deletions.
20 changes: 17 additions & 3 deletions Makefile
Original file line number Diff line number Diff line change
@@ -1,5 +1,19 @@
SHELL=/bin/bash -o pipefail
.PHONY: local
SPEC_DIR:=$(shell dirname $(realpath $(firstword $(MAKEFILE_LIST))))
.PHONY: spec

local: tuf-spec.md
bikeshed spec tuf-spec.md tuf-spec.html
spec: $(SPEC_DIR)/tuf-spec.md
bikeshed spec $(SPEC_DIR)/tuf-spec.md tuf-spec.html

latest: spec
mkdir -p latest
cp tuf-spec.html latest/index.html

versioned: spec
mkdir -p $(shell python3 $(SPEC_DIR)/get_version.py $(SPEC_DIR)/tuf-spec.md)
cp tuf-spec.html $(shell python3 $(SPEC_DIR)/get_version.py $(SPEC_DIR)/tuf-spec.md)/index.html

index:
python3 $(SPEC_DIR)/build_index.py

release: spec latest versioned
203 changes: 203 additions & 0 deletions build_index.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,203 @@
#!/usr/bin/env python3

"""
<Program Name>
build_index.py
<Author>
Joshua Lock <[email protected]>
<Started>
Feb 1, 2021
<Copyright>
See LICENSE-MIT for licensing information.
<Purpose>
Quick and dirty script to generate an index of published specification
versions.
Style cribbed from the bikeshed W3C theme we are using in our bikeshed
generated specification documents.
"""

import os
import sys

from subprocess import run

html_header = """<!DOCTYPE html>
<html lang="en">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<title>The Update Framework Specification</title>
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<style data-fill-with="stylesheet">
body {
counter-reset: example figure issue;
/* Layout */
max-width: 50em; /* limit line length to 50em for readability */
margin: 0 auto; /* center text within page */
padding: 1.6em 1.5em 2em 50px; /* assume 16px font size for downlevel clients */
padding: 1.6em 1.5em 2em calc(26px + 1.5em); /* leave space for status flag */
/* Typography */
line-height: 1.5;
font-family: sans-serif;
widows: 2;
orphans: 2;
word-wrap: break-word;
overflow-wrap: break-word;
hyphens: auto;
color: black;
color: var(--text);
background: white top left fixed no-repeat;
background: var(--bg) top left fixed no-repeat;
background-size: 25px auto;
}
div.head { margin-bottom: 1em; }
div.head h1 {
font-weight: bold;
margin: 0 0 .1em;
font-size: 220%;
}
p {
margin: 1em 0;
}
dd > p:first-child,
li > p:first-child {
margin-top: 0;
}
ul, ol {
margin-left: 0;
padding-left: 2em;
}
li {
margin: 0.25em 0 0.5em;
padding: 0;
}
a {
color: #034575;
color: var(--a-normal-text);
text-decoration: none;
border-bottom: 1px solid #707070;
border-bottom: 1px solid var(--a-normal-underline);
/* Need a bit of extending for it to look okay */
padding: 0 1px 0;
margin: 0 -1px 0;
}
a:visited {
color: #034575;
color: var(--a-visited-text);
border-bottom-color: #bbb;
border-bottom-color: var(--a-visited-underline);
}
a:focus,
a:hover {
background: #f8f8f8;
background: rgba(75%, 75%, 75%, .25);
background: var(--a-hover-bg);
border-bottom-width: 3px;
margin-bottom: -2px;
}
a:active {
color: #c00;
color: var(--a-active-text);
border-color: #c00;
border-color: var(--a-active-underline);
}
h1, h2, h3, h4, h5, h6, dt {
page-break-after: avoid;
page-break-inside: avoid;
font: 100% sans-serif; /* Reset all font styling to clear out UA styles */
font-family: inherit; /* Inherit the font family. */
line-height: 1.2; /* Keep wrapped headings compact */
hyphens: manual; /* Hyphenated headings look weird */
}
h2, h3, h4, h5, h6 {
margin-top: 3rem;
}
h1, h2, h3 {
color: #005A9C;
color: var(--heading-text);
}
h1 { font-size: 170%; }
h2 { font-size: 140%; }
:root {
color-scheme: light dark;
--text: black;
--bg: white;
--heading-text: #005a9c;
--a-normal-text: #034575;
--a-normal-underline: #707070;
--a-visited-text: var(--a-normal-text);
--a-visited-underline: #bbb;
--a-hover-bg: rgba(75%, 75%, 75%, .25);
--a-active-text: #c00;
--a-active-underline: #c00;
}
</style>
</head>
<body class="h-entry">
<div class="head">
<h1 id="title" class="p-name no-ref">The Update Framework Specification</h1>
</div>
<div>
<ul>
"""

html_footer = """</ul>
</body>
</html>
"""

def sanity_check():
branch = None

try:
branch = run("git branch --show-current".split(), capture_output=True).stdout
except Exception:
pass

if branch != b"gh-pages\n":
print(f"build_index.py must be run from the 'gh-pages' branch (on '{branch}'")
sys.exit()

def build_index():
# sanity_check()

html = html_header

html_locations = ['latest', 'draft']
dir_contents = sorted(os.listdir('.'), reverse=True)
for path in dir_contents:
if path.startswith('v'):
if not os.path.exists(f'{path}/index.html'):
continue
html_locations.append(path)

for loc in html_locations:
link = f" <li><a href='{loc}/index.html'>{loc}</a></li>\n"
html = html + link

html = html + html_footer

return html

if __name__ == "__main__":
html = build_index()
with open('index.html', 'w') as index:
index.write(html)
44 changes: 44 additions & 0 deletions get_version.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
#!/usr/bin/env python3

"""
<Program Name>
get_version.py
<Author>
Joshua Lock <[email protected]>
<Started>
Feb 2, 2021
<Copyright>
See LICENSE-MIT for licensing information.
<Purpose>
Quick and dirty script to get the version number from tuf-spec.md
Unfortunately GNU grep and BSD grep take different options...
"""

import re
import sys

pattern = re.compile("VERSION (\d+\.\d+\.\d+)")

def get_version():
out = ''
spec = 'tuf-spec.md'

if (len(sys.argv) > 1):
spec = sys.argv[1]

with open(spec, 'r') as spec:
for line in spec:
for match in re.finditer(pattern, line):
if match.group():
break
out = match.groups()[0]

return f'v{out}'

if __name__ == "__main__":
print(get_version())

0 comments on commit 8280e43

Please sign in to comment.