Skip to content

Commit dafebaf

Browse files
authored
Merge pull request #148 from joshuagl/joshuagl/gha-ci
GitHub Actions workflow to publish specification to GitHub Pages
2 parents d3ee698 + 948022f commit dafebaf

File tree

8 files changed

+420
-46
lines changed

8 files changed

+420
-46
lines changed

.github/workflows/draft.yml

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
name: Update draft specification
2+
on:
3+
workflow_dispatch:
4+
push:
5+
branches: draft
6+
7+
jobs:
8+
build-draft:
9+
name: Make draft spec release
10+
runs-on: ubuntu-latest
11+
steps:
12+
- name: Set up Python
13+
uses: actions/setup-python@3105fb18c05ddd93efea5f9e0bef7a03a6e9e7df
14+
with:
15+
python-version: 3.x
16+
17+
- name: Find pip cache dir
18+
id: pip-cache
19+
run: echo "::set-output name=dir::$(pip cache dir)"
20+
21+
- name: pip cache
22+
uses: actions/cache@26968a09c0ea4f3e233fdddbafd1166051a095f6
23+
with:
24+
# Use the os dependent pip cache directory found above
25+
path: ${{ steps.pip-cache.outputs.dir }}
26+
# A match with 'restore-keys' is used as fallback
27+
key: ${{ runner.os }}-pip-
28+
29+
- name: Clone
30+
uses: actions/checkout@5a4ac9002d0be2fb38bd78e4b4dbde5606d7042f
31+
32+
- name: Build specification
33+
run: |
34+
python -m pip install bikeshed
35+
mkdir build && cd build
36+
make -f ../Makefile draft
37+
38+
- name: Switch branch
39+
uses: actions/checkout@5a4ac9002d0be2fb38bd78e4b4dbde5606d7042f
40+
with:
41+
ref: gh-pages
42+
clean: false
43+
44+
- name: Push generated specification
45+
run: |
46+
git config user.name "TUF Specification Automation"
47+
git config user.email theupdateframework@googlegroups.com
48+
rm -fr draft
49+
mv build/* .
50+
rmdir build
51+
git add .
52+
git commit -m "Publish latest draft specification"
53+
git push

.github/workflows/pr.yml

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
name: CI
2+
on:
3+
pull_request:
4+
branches:
5+
- master
6+
7+
jobs:
8+
main:
9+
name: Check date and version are updated
10+
runs-on: ubuntu-20.04
11+
steps:
12+
- uses: actions/checkout@v2
13+
with:
14+
fetch-depth: 0 # we want all refs for the --is-ancestor check
15+
- name: Set up Python
16+
uses: actions/setup-python@v2
17+
with:
18+
python-version: 3.x
19+
- name: Check date and version
20+
run: python check_release.py

.github/workflows/release.yml

Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
1+
name: Release specification
2+
on:
3+
workflow_dispatch:
4+
push:
5+
branches: master
6+
7+
jobs:
8+
make-release:
9+
name: Make and publish spec release
10+
runs-on: ubuntu-latest
11+
steps:
12+
- name: Set up Python
13+
uses: actions/setup-python@3105fb18c05ddd93efea5f9e0bef7a03a6e9e7df
14+
with:
15+
python-version: 3.x
16+
17+
- name: Find pip cache dir
18+
id: pip-cache
19+
run: echo "::set-output name=dir::$(pip cache dir)"
20+
21+
- name: pip cache
22+
uses: actions/cache@26968a09c0ea4f3e233fdddbafd1166051a095f6
23+
with:
24+
# Use the os dependent pip cache directory found above
25+
path: ${{ steps.pip-cache.outputs.dir }}
26+
# A match with 'key' counts as cache hit
27+
key: ${{ runner.os }}-pip-
28+
29+
- name: Clone main
30+
uses: actions/checkout@5a4ac9002d0be2fb38bd78e4b4dbde5606d7042f
31+
with:
32+
fetch-depth: 0
33+
34+
- name: Get previous version
35+
id: prevver
36+
run: |
37+
prev_version=`git tag | sort -V -r | head -n 1 | cut -c 2-`
38+
echo "::set-output name=prev_version::$(echo -n $prev_version)"
39+
40+
- name: Get version
41+
id: getver
42+
run: |
43+
spec_version=`grep -oP 'VERSION \K(\d+\.\d+\.\d+)' tuf-spec.md`
44+
echo "::set-output name=spec_version::$(echo -n $spec_version)"
45+
46+
- name: Make release
47+
if: steps.getver.outputs.spec_version != steps.prevver.outputs.prev_version
48+
uses: actions/create-release@0cb9c9b65d5d1901c1f53e5e66eaf4afd303e70e
49+
env:
50+
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
51+
with:
52+
tag_name: v${{ steps.getver.outputs.spec_version }}
53+
release_name: v${{ steps.getver.outputs.spec_version }}
54+
body: Specification release v${{ steps.getver.outputs.spec_version }}
55+
56+
- name: Build specification
57+
if: steps.getver.outputs.spec_version != steps.prevver.outputs.prev_version
58+
run: |
59+
python -m pip install bikeshed
60+
mkdir build && cd build
61+
make -f ../Makefile release
62+
63+
- name: Switch branch
64+
if: steps.getver.outputs.spec_version != steps.prevver.outputs.prev_version
65+
uses: actions/checkout@5a4ac9002d0be2fb38bd78e4b4dbde5606d7042f
66+
with:
67+
ref: gh-pages
68+
clean: false
69+
70+
- name: Push generated specification
71+
if: steps.getver.outputs.spec_version != steps.prevver.outputs.prev_version
72+
env:
73+
SPEC_VERSION: v${{ steps.getver.outputs.spec_version }}
74+
run: |
75+
git config user.name "TUF Specification Automation"
76+
git config user.email theupdateframework@googlegroups.com
77+
rm -fr latest
78+
mv build/* .
79+
rmdir build
80+
make index
81+
git add .
82+
git commit -m "Publish latest specification $SPEC_VERSION"
83+
git push

.travis.yml

Lines changed: 0 additions & 17 deletions
This file was deleted.

Makefile

Lines changed: 21 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,23 @@
11
SHELL=/bin/bash -o pipefail
2-
.PHONY: local
2+
SPEC_DIR:=$(shell dirname $(realpath $(firstword $(MAKEFILE_LIST))))
3+
.PHONY: spec
34

4-
local: tuf-spec.md
5-
bikeshed spec tuf-spec.md tuf-spec.html
5+
spec: $(SPEC_DIR)/tuf-spec.md
6+
bikeshed spec $(SPEC_DIR)/tuf-spec.md tuf-spec.html
7+
8+
latest: spec
9+
mkdir -p latest
10+
cp tuf-spec.html latest/index.html
11+
12+
draft: spec
13+
mkdir -p draft
14+
cp tuf-spec.html draft/index.html
15+
16+
versioned: spec
17+
mkdir -p $(shell python3 $(SPEC_DIR)/get_version.py $(SPEC_DIR)/tuf-spec.md)
18+
cp tuf-spec.html $(shell python3 $(SPEC_DIR)/get_version.py $(SPEC_DIR)/tuf-spec.md)/index.html
19+
20+
index:
21+
python3 $(SPEC_DIR)/build_index.py
22+
23+
release: spec latest versioned

build_index.py

Lines changed: 189 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,189 @@
1+
#!/usr/bin/env python3
2+
3+
"""
4+
<Program Name>
5+
build_index.py
6+
7+
<Author>
8+
Joshua Lock <jlock@vmware.com>
9+
10+
<Started>
11+
Feb 1, 2021
12+
13+
<Copyright>
14+
See LICENSE-MIT for licensing information.
15+
16+
<Purpose>
17+
Quick and dirty script to generate an index of published specification
18+
versions.
19+
20+
Style cribbed from the bikeshed W3C theme we are using in our bikeshed
21+
generated specification documents.
22+
"""
23+
24+
import os
25+
import sys
26+
27+
from subprocess import run
28+
29+
html_header = """<!DOCTYPE html>
30+
<html lang="en">
31+
<head>
32+
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
33+
<title>The Update Framework Specification</title>
34+
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
35+
<style data-fill-with="stylesheet">
36+
body {
37+
counter-reset: example figure issue;
38+
39+
/* Layout */
40+
max-width: 50em; /* limit line length to 50em for readability */
41+
margin: 0 auto; /* center text within page */
42+
padding: 1.6em 1.5em 2em 50px; /* assume 16px font size for downlevel clients */
43+
padding: 1.6em 1.5em 2em calc(26px + 1.5em); /* leave space for status flag */
44+
45+
/* Typography */
46+
line-height: 1.5;
47+
font-family: sans-serif;
48+
widows: 2;
49+
orphans: 2;
50+
word-wrap: break-word;
51+
overflow-wrap: break-word;
52+
hyphens: auto;
53+
54+
color: black;
55+
color: var(--text);
56+
background: white top left fixed no-repeat;
57+
background: var(--bg) top left fixed no-repeat;
58+
background-size: 25px auto;
59+
}
60+
div.head { margin-bottom: 1em; }
61+
div.head h1 {
62+
font-weight: bold;
63+
margin: 0 0 .1em;
64+
font-size: 220%;
65+
}
66+
67+
p {
68+
margin: 1em 0;
69+
}
70+
71+
dd > p:first-child,
72+
li > p:first-child {
73+
margin-top: 0;
74+
}
75+
76+
ul, ol {
77+
margin-left: 0;
78+
padding-left: 2em;
79+
}
80+
81+
li {
82+
margin: 0.25em 0 0.5em;
83+
padding: 0;
84+
}
85+
86+
a {
87+
color: #034575;
88+
color: var(--a-normal-text);
89+
text-decoration: none;
90+
border-bottom: 1px solid #707070;
91+
border-bottom: 1px solid var(--a-normal-underline);
92+
/* Need a bit of extending for it to look okay */
93+
padding: 0 1px 0;
94+
margin: 0 -1px 0;
95+
}
96+
a:visited {
97+
color: #034575;
98+
color: var(--a-visited-text);
99+
border-bottom-color: #bbb;
100+
border-bottom-color: var(--a-visited-underline);
101+
}
102+
103+
a:focus,
104+
a:hover {
105+
background: #f8f8f8;
106+
background: rgba(75%, 75%, 75%, .25);
107+
background: var(--a-hover-bg);
108+
border-bottom-width: 3px;
109+
margin-bottom: -2px;
110+
}
111+
a:active {
112+
color: #c00;
113+
color: var(--a-active-text);
114+
border-color: #c00;
115+
border-color: var(--a-active-underline);
116+
}
117+
118+
h1, h2, h3, h4, h5, h6, dt {
119+
page-break-after: avoid;
120+
page-break-inside: avoid;
121+
font: 100% sans-serif; /* Reset all font styling to clear out UA styles */
122+
font-family: inherit; /* Inherit the font family. */
123+
line-height: 1.2; /* Keep wrapped headings compact */
124+
hyphens: manual; /* Hyphenated headings look weird */
125+
}
126+
h2, h3, h4, h5, h6 {
127+
margin-top: 3rem;
128+
}
129+
h1, h2, h3 {
130+
color: #005A9C;
131+
color: var(--heading-text);
132+
}
133+
h1 { font-size: 170%; }
134+
h2 { font-size: 140%; }
135+
136+
:root {
137+
color-scheme: light dark;
138+
139+
--text: black;
140+
--bg: white;
141+
142+
--heading-text: #005a9c;
143+
144+
--a-normal-text: #034575;
145+
--a-normal-underline: #707070;
146+
--a-visited-text: var(--a-normal-text);
147+
--a-visited-underline: #bbb;
148+
--a-hover-bg: rgba(75%, 75%, 75%, .25);
149+
--a-active-text: #c00;
150+
--a-active-underline: #c00;
151+
}
152+
</style>
153+
</head>
154+
<body class="h-entry">
155+
<div class="head">
156+
<h1 id="title" class="p-name no-ref">The Update Framework Specification</h1>
157+
</div>
158+
<div>
159+
<ul>
160+
"""
161+
162+
html_footer = """</ul>
163+
</body>
164+
</html>
165+
"""
166+
167+
def build_index():
168+
html = html_header
169+
170+
html_locations = ['latest', 'draft']
171+
dir_contents = sorted(os.listdir('.'), reverse=True)
172+
for path in dir_contents:
173+
if path.startswith('v'):
174+
if not os.path.exists(f'{path}/index.html'):
175+
continue
176+
html_locations.append(path)
177+
178+
for loc in html_locations:
179+
link = f" <li><a href='{loc}/index.html'>{loc}</a></li>\n"
180+
html = html + link
181+
182+
html = html + html_footer
183+
184+
return html
185+
186+
if __name__ == "__main__":
187+
html = build_index()
188+
with open('index.html', 'w') as index:
189+
index.write(html)

0 commit comments

Comments
 (0)