diff --git a/.github/scripts/build_index.py b/.github/scripts/build_index.py
index 83569e7..6d35f76 100644
--- a/.github/scripts/build_index.py
+++ b/.github/scripts/build_index.py
@@ -20,6 +20,84 @@
PDF_LIST_MARKER = ""
GENERATED_MARKER = ""
+# The documents are listed in waterfall order, which is not the order in which
+# the course creates them: the V&V plan is written before the design, but is
+# read after it. Listing them this way reinforces the rational design process
+# the course asks students to fake, and makes the documentation easier to
+# follow for a reader from outside the course.
+#
+# Taken from the Final Documentation (Revision 1) list in the course outline.
+# A directory not named here is listed after these, alphabetically, so adding
+# a document folder cannot make it disappear from the page.
+SECTION_ORDER = [
+ ("ProblemStatementAndGoals", "Problem Statement and Goals"),
+ ("DevelopmentPlan", "Development Plan"),
+ ("SRS", "Requirements (SRS)"),
+ ("SRS-Volere", "Requirements, Volere template"),
+ ("SRS-Meyer", "Requirements, Meyer template"),
+ ("HazardAnalysis", "Hazard Analysis"),
+ ("Design", "Design"),
+ ("VnVPlan", "Verification and Validation Plan"),
+ ("VnVReport", "Verification and Validation Report"),
+ ("UserGuide", "User Guide"),
+ ("CDs", "Custom Documents"),
+ ("ReflectAndTrace", "Reflection and Traceability"),
+ ("projMngmnt", "Project Management"),
+ ("Checklists", "Checklists"),
+]
+
+# Within a section, documents that should not be alphabetical. The checklists
+# mirror the deliverables, so they follow the same order as the sections above;
+# the design documents go architecture first, then detailed design.
+FILE_ORDER = {
+ "Checklists": [
+ "GettingStarted-Checklist.pdf",
+ "ProbState-Checklist.pdf",
+ "DevPlan-Checklist.pdf",
+ "SRS-Checklist.pdf",
+ "SRS-SciComp-Checklist.pdf",
+ "HA-Checklist.pdf",
+ "MG-Checklist.pdf",
+ "MIS-Checklist.pdf",
+ "VnV-Checklist.pdf",
+ "POC-Checklist.pdf",
+ "Code-Checklist.pdf",
+ "Writing-Checklist.pdf",
+ "FinalDoc-Checklist.pdf",
+ ],
+ "Design": ["MG.pdf", "MIS.pdf"],
+ # The requirements document first, then the questions about it.
+ "SRS": ["SRS.pdf", "SRS-FAQ.pdf"],
+ # Chronological: proof of concept, then revision 0, then final.
+ "projMngmnt": [
+ "POC_Productivity_Rep.pdf",
+ "Rev0_Productivity_Rep.pdf",
+ "Final_Productivity_Rep.pdf",
+ ],
+}
+
+
+def section_rank(directory):
+ """Position of a section, with unlisted ones sorted after the known ones."""
+ for index, (name, _title) in enumerate(SECTION_ORDER):
+ if name == directory:
+ return (0, index, "")
+ return (1, 0, directory.lower())
+
+
+def section_title(directory):
+ for name, title in SECTION_ORDER:
+ if name == directory:
+ return title
+ return directory
+
+
+def file_rank(directory, filename):
+ order = FILE_ORDER.get(directory)
+ if order and filename in order:
+ return (0, order.index(filename), "")
+ return (1, 0, filename.lower())
+
def git_last_updated(repo_relative_path):
"""Commit time of a path, or None when git knows nothing about it."""
@@ -86,10 +164,12 @@ def collect(public_dir, tracked_dir):
def render(sections):
lines = []
- for section in sorted(sections):
- lines.append("
%s
" % escape(section))
+ for section in sorted(sections, key=section_rank):
+ lines.append("%s
" % escape(section_title(section)))
lines.append("")
- for href, name, moment in sections[section]:
+ entries = sorted(sections[section],
+ key=lambda e: file_rank(section, e[1]))
+ for href, name, moment in entries:
lines.append(
' - %s%s
'
% (escape(href), escape(name),
diff --git a/.github/scripts/select_docs.py b/.github/scripts/select_docs.py
index aa663ec..81cb521 100755
--- a/.github/scripts/select_docs.py
+++ b/.github/scripts/select_docs.py
@@ -24,7 +24,10 @@
# Instructor-owned prose and things this pipeline never builds from. Changes
# to these must not trigger the full-rebuild fallback.
IGNORED_BASENAMES = {"README.md", "README.txt", ".gitignore"}
-IGNORED_PREFIXES = ("pdfs/", "docs/SRS-Meyer/", ".github/")
+# site/ is the index page template. It changes what the published page
+# looks like, never the content of a PDF, so it must not trigger a
+# rebuild even though it does need to trigger the workflow.
+IGNORED_PREFIXES = ("pdfs/", "docs/SRS-Meyer/", ".github/", "site/")
# Changing how documents are built can change every document, even though no
# document source changed: the package list decides which LaTeX packages are
diff --git a/.github/scripts/update_pages_link.py b/.github/scripts/update_pages_link.py
new file mode 100644
index 0000000..8fabc81
--- /dev/null
+++ b/.github/scripts/update_pages_link.py
@@ -0,0 +1,77 @@
+#!/usr/bin/env python3
+"""Point the README's GitHub Pages link at this repository's own page.
+
+The template ships with a link to the template's own page and a comment
+asking teams to update it, which is easy to miss. Since the build already
+commits to the repository, it can correct the link itself: every team's
+README then links to their documentation rather than to the template's.
+
+Any Markdown link in the README whose target is a github.io address is
+treated as the project's Pages link. Nothing is reported as an error if no
+such link exists, because a team is free to reword or remove it.
+
+Usage: update_pages_link.py [README.md]
+"""
+
+import os
+import re
+import sys
+
+MARKDOWN_LINK = re.compile(r"(\]\()\s*(https?://[^)\s]*github\.io[^)\s]*)\s*(\))")
+
+
+def pages_url(slug):
+ """The Pages URL for owner/repo, as GitHub serves it."""
+ if "/" not in slug:
+ raise ValueError("expected owner/repo, got %r" % slug)
+ owner, repo = slug.split("/", 1)
+ # GitHub serves Pages from a lowercased owner name.
+ owner_host = owner.lower() + ".github.io"
+ if repo.lower() == owner_host:
+ # The owner's user/organisation site is served from the host root.
+ return "https://%s/" % owner_host
+ return "https://%s/%s/" % (owner_host, repo)
+
+
+def main():
+ if len(sys.argv) < 2:
+ sys.exit("usage: update_pages_link.py [README.md]")
+
+ slug = sys.argv[1]
+ readme = sys.argv[2] if len(sys.argv) > 2 else "README.md"
+ url = pages_url(slug)
+
+ if not os.path.exists(readme):
+ print("update_pages_link: no %s, nothing to do" % readme)
+ return
+
+ with open(readme) as handle:
+ original = handle.read()
+
+ replaced = []
+
+ def swap(match):
+ was = match.group(2)
+ if was == url:
+ return match.group(0)
+ replaced.append(was)
+ return match.group(1) + url + match.group(3)
+
+ updated = MARKDOWN_LINK.sub(swap, original)
+
+ if not replaced:
+ if url in original:
+ print("update_pages_link: %s already points at %s" % (readme, url))
+ else:
+ print("update_pages_link: no github.io link found in %s" % readme)
+ return
+
+ with open(readme, "w") as handle:
+ handle.write(updated)
+
+ for was in replaced:
+ print("update_pages_link: %s -> %s" % (was, url))
+
+
+if __name__ == "__main__":
+ main()
diff --git a/.github/workflows/latex-pages.yml b/.github/workflows/latex-pages.yml
index 3f38e09..f258ad1 100644
--- a/.github/workflows/latex-pages.yml
+++ b/.github/workflows/latex-pages.yml
@@ -3,10 +3,10 @@ name: Build LaTeX and Deploy PDFs
on:
push:
branches: main
- paths: [docs/**, refs/**, Makefile, .github/scripts/**, .github/workflows/latex-pages.yml]
+ paths: [docs/**, refs/**, site/**, Makefile, .github/scripts/**, .github/workflows/latex-pages.yml]
pull_request:
branches: main
- paths: [docs/**, refs/**, Makefile, .github/scripts/**, .github/workflows/latex-pages.yml]
+ paths: [docs/**, refs/**, site/**, Makefile, .github/scripts/**, .github/workflows/latex-pages.yml]
workflow_dispatch:
permissions:
@@ -163,12 +163,17 @@ jobs:
rm -rf pdfs
mkdir -p pdfs
rsync -av --delete build-pdf/ pdfs/
+ - name: Point the README at this repository's Pages site
+ run: |
+ # The template ships with a link to the template's own page. Every
+ # repository made from it would otherwise keep pointing there.
+ python3 .github/scripts/update_pages_link.py "${{ github.repository }}"
- name: Commit PDFs to repo
if: github.event_name == 'push' && github.ref == 'refs/heads/main'
run: |
git config user.name "github-actions[bot]"
git config user.email "github-actions[bot]@users.noreply.github.com"
- git add pdfs .pdf-deps.json
+ git add pdfs .pdf-deps.json README.md
if git diff --cached --quiet; then
echo "No PDF changes to commit"
else
diff --git a/README.md b/README.md
index b22fbc9..6fb4dac 100644
--- a/README.md
+++ b/README.md
@@ -14,4 +14,4 @@ src - Source code
test - Test cases
etc.
-The documentation for this project is updated on the project's [GitHub page](https://smiths.github.io/capTemplate/).
\ No newline at end of file
+The documentation for this project is updated on the project's [GitHub page](https://smiths.github.io/capTemplate/).
\ No newline at end of file
diff --git a/site/index.html b/site/index.html
index e373b73..5691ddb 100644
--- a/site/index.html
+++ b/site/index.html
@@ -7,6 +7,10 @@
Available PDFs
+ The documents are listed in the order they are meant to be
+ read, which is not the order in which they are written. Reading them in this
+ order follows the rational design process the project documentation
+ presents.
Site generated
diff --git a/site/style.css b/site/style.css
index bf70d97..e8cea0d 100644
--- a/site/style.css
+++ b/site/style.css
@@ -38,3 +38,9 @@ li {
font-size: .85rem;
white-space: nowrap;
}
+
+.intro {
+ color: #333;
+ max-width: 60ch;
+ line-height: 1.5;
+}