diff --git a/.github/workflows/deploy-data.yml b/.github/workflows/deploy-data.yml index 74d9e7547c..0c9828932c 100644 --- a/.github/workflows/deploy-data.yml +++ b/.github/workflows/deploy-data.yml @@ -23,8 +23,13 @@ env: MISE_RUBY_COMPILE: 'false' jobs: + docs: + name: Build the documentation + uses: $/.github/workflows/docs.yml + build: name: Validate and bundle the data + needs: docs runs-on: ubuntu-latest steps: - name: Check out the code @@ -48,6 +53,16 @@ jobs: - name: Bundle the data run: mise run bundle-data + # Pages replaces the whole site on each deploy, so the documentation + # rides along every time. docs.yml cached it, on a Mac if it had changed. + - name: Restore the documentation + uses: actions/cache/restore@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6.1.0 + with: + path: docs/documentation + key: ${{ needs.docs.outputs.cache-key }} + fail-on-cache-miss: true + enableCrossOsArchive: true + # Uploads docs/ as the Pages artifact. The bundle is the whole site -- # sixteen JSON files, a stylesheet and the images, no index -- so it needs no base # path and no configure-pages step ahead of it. diff --git a/.github/workflows/docs.yml b/.github/workflows/docs.yml new file mode 100644 index 0000000000..b8266c0c19 --- /dev/null +++ b/.github/workflows/docs.yml @@ -0,0 +1,75 @@ +name: Docs + +# Builds the DocC site in documentation/. docc ships with Xcode, so the build +# runs on a Mac; the site is cached so a deploy that left documentation/ alone +# never starts a Mac. +on: + pull_request: + paths: + - 'documentation/**' + - 'scripts/build-docs.sh' + - '.github/workflows/docs.yml' + workflow_call: + outputs: + cache-key: + description: The key the built site is cached under + value: ${{ jobs.cache-lookup.outputs.cache-key }} + +permissions: + contents: read + +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: ${{ github.event_name == 'pull_request' }} + +env: + xcode_version: 'Xcode_27.0' + +jobs: + cache-lookup: + name: Look for the built site + runs-on: ubuntu-slim + outputs: + hit: ${{ steps.lookup.outputs.cache-hit }} + cache-key: ${{ steps.key.outputs.value }} + steps: + - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 + with: + persist-credentials: false + + - name: Name the cache key + id: key + run: echo "value=docs-site/e=1/hash=${{ hashFiles('documentation/**', 'scripts/build-docs.sh') }}" >>"$GITHUB_OUTPUT" + + # The Mac saves the site and the Linux deploy job restores it, so the + # archive must cross operating systems. + - name: Look for the cached site + id: lookup + uses: actions/cache/restore@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6.1.0 + with: + path: docs/documentation + key: ${{ steps.key.outputs.value }} + lookup-only: true + enableCrossOsArchive: true + + build: + name: Build the site + needs: cache-lookup + if: needs.cache-lookup.outputs.hit != 'true' + runs-on: xcode-27 + steps: + - run: sudo xcode-select -s /Applications/${{ env.xcode_version }}.app + + - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 + with: + persist-credentials: false + + - name: Build the site + run: scripts/build-docs.sh + + - name: Save the site + uses: actions/cache/save@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6.1.0 + with: + path: docs/documentation + key: ${{ needs.cache-lookup.outputs.cache-key }} + enableCrossOsArchive: true diff --git a/documentation/AllAboutAnything.docc/AllAboutAnything.md b/documentation/AllAboutAnything.docc/AllAboutAnything.md new file mode 100644 index 0000000000..bd903a5570 --- /dev/null +++ b/documentation/AllAboutAnything.docc/AllAboutAnything.md @@ -0,0 +1,30 @@ +# All About Anything + +@Metadata { + @TechnologyRoot +} + +How the app is built, tested, and shipped. The code builds two apps, All About Olaf and CARLS. + +## Overview + +This is the **landing page** (a root page). Everything else hangs off its Topics. + +## Topics + +### Start here + +- + +### Testing + +- +- + +### The apps + +See the All About Olaf and CARLS catalogs. + +### Tutorials + +- diff --git a/documentation/AllAboutAnything.docc/GettingStarted.md b/documentation/AllAboutAnything.docc/GettingStarted.md new file mode 100644 index 0000000000..7b10487fe7 --- /dev/null +++ b/documentation/AllAboutAnything.docc/GettingStarted.md @@ -0,0 +1,24 @@ +# Getting started + +Set up the repo and run the app on a simulator. + +## Overview + +This is a plain **article**: prose, headings, code blocks, asides, and lists. + +```bash +mise run agent:setup +APP_VARIANT=aao-dev mise run aao:ios +``` + +> Note: An aside like this renders as a callout. Also supported: `Important`, +> `Warning`, `Tip`, and `Experiment`. + +### Variants + +| `APP_VARIANT` | Home screen | +| --- | --- | +| `aao` | All About Olaf | +| `carls` | CARLS | + +See for the next step. diff --git a/documentation/AllAboutAnything.docc/Resources/chapter.svg b/documentation/AllAboutAnything.docc/Resources/chapter.svg new file mode 100644 index 0000000000..0e45a82d73 --- /dev/null +++ b/documentation/AllAboutAnything.docc/Resources/chapter.svg @@ -0,0 +1 @@ + diff --git a/documentation/AllAboutAnything.docc/Resources/example-1.tsx b/documentation/AllAboutAnything.docc/Resources/example-1.tsx new file mode 100644 index 0000000000..13aa7e9df9 --- /dev/null +++ b/documentation/AllAboutAnything.docc/Resources/example-1.tsx @@ -0,0 +1,3 @@ +export default function Example() { + return null +} diff --git a/documentation/AllAboutAnything.docc/Resources/example-2.tsx b/documentation/AllAboutAnything.docc/Resources/example-2.tsx new file mode 100644 index 0000000000..2872cbb822 --- /dev/null +++ b/documentation/AllAboutAnything.docc/Resources/example-2.tsx @@ -0,0 +1,5 @@ +export default function Example() { + return null +} + +export const options = {title: 'Example'} diff --git a/documentation/AllAboutAnything.docc/SampleCodeExample.md b/documentation/AllAboutAnything.docc/SampleCodeExample.md new file mode 100644 index 0000000000..7416e8b091 --- /dev/null +++ b/documentation/AllAboutAnything.docc/SampleCodeExample.md @@ -0,0 +1,23 @@ +# Chaos run example + +Drive the app at random and read what it finds. + +@Metadata { + @PageKind(sampleCode) +} + +## Overview + +This is a **sample code** page: an article with a call-to-action button that +links to the code. + +@Row { + @Column { + Run `mise run chaos:bundled --seed 1234`. + } + @Column { + Evidence lands in `logs/chaos/1234/`. + } +} + +@CallToAction(url: "https://github.com/StoDevX/aao-react-native/tree/master/uitests/Chaos", purpose: link, label: "View the code") diff --git a/documentation/AllAboutAnything.docc/TestingGuides.md b/documentation/AllAboutAnything.docc/TestingGuides.md new file mode 100644 index 0000000000..c6b95307bb --- /dev/null +++ b/documentation/AllAboutAnything.docc/TestingGuides.md @@ -0,0 +1,18 @@ +# Testing guides + +Everything about checking a change. + +## Overview + +This is an **API collection**: a page that is only a list of links, with no +prose beyond a short abstract. + +## Topics + +### Jest + +- + +### UI tests + +- diff --git a/documentation/AllAboutAnything.docc/Tutorials/AddAScreen.tutorial b/documentation/AllAboutAnything.docc/Tutorials/AddAScreen.tutorial new file mode 100644 index 0000000000..18b011f0e5 --- /dev/null +++ b/documentation/AllAboutAnything.docc/Tutorials/AddAScreen.tutorial @@ -0,0 +1,25 @@ +@Tutorial(time: 10) { + @Intro(title: "Add a screen") { + This is a **tutorial**: numbered steps, each pairing text with code. + } + + @Section(title: "Create the route") { + @ContentAndMedia { + Routes live in `app/`. + } + + @Steps { + @Step { + Make a file for the route. + + @Code(name: "example.tsx", file: example-1.tsx) + } + + @Step { + Give it a title. + + @Code(name: "example.tsx", file: example-2.tsx) + } + } + } +} diff --git a/documentation/AllAboutAnything.docc/Tutorials/ContributorTutorials.tutorial b/documentation/AllAboutAnything.docc/Tutorials/ContributorTutorials.tutorial new file mode 100644 index 0000000000..db9c2e5271 --- /dev/null +++ b/documentation/AllAboutAnything.docc/Tutorials/ContributorTutorials.tutorial @@ -0,0 +1,13 @@ +@Tutorials(name: "Contributor tutorials") { + @Intro(title: "Contribute to All About Olaf") { + Step-by-step lessons with a code pane beside the text. + } + + @Chapter(name: "Your first change") { + This is a **tutorial table of contents** with chapters. + + @Image(source: chapter.svg, alt: "Placeholder") + + @TutorialReference(tutorial: "doc:AddAScreen") + } +} diff --git a/documentation/AllAboutOlaf.docc/AllAboutOlaf.md b/documentation/AllAboutOlaf.docc/AllAboutOlaf.md new file mode 100644 index 0000000000..218dab956f --- /dev/null +++ b/documentation/AllAboutOlaf.docc/AllAboutOlaf.md @@ -0,0 +1,18 @@ +# All About Olaf + +@Metadata { + @TechnologyRoot +} + +The St. Olaf College app. + +## Overview + +All About Olaf gives students, faculty and staff campus info, dining menus, +course catalogs and maps. It is the `aao` build variant. + +## Topics + +### Builds + +- diff --git a/documentation/AllAboutOlaf.docc/Builds.md b/documentation/AllAboutOlaf.docc/Builds.md new file mode 100644 index 0000000000..5284a35fcd --- /dev/null +++ b/documentation/AllAboutOlaf.docc/Builds.md @@ -0,0 +1,20 @@ +# Builds + +Which variant to build, and what it installs. + +## Overview + +`APP_VARIANT` names the app a build is. It has no default, so a forgotten +variant fails at once. + +| `APP_VARIANT` | Bundle identifier | Home screen | +| --- | --- | --- | +| `aao` | `NFMTHAZVS9.com.drewvolz.stolaf` | All About Olaf | +| `aao-dev` | `…stolaf.dev` | AAO Dev | + +Both use the windmill icon and the `all-about-olaf` Sentry project, so tell +them apart by name. TestFlight and App Store builds ship `aao`. + +```bash +mise run aao:ios [device] +``` diff --git a/documentation/CARLS.docc/Builds.md b/documentation/CARLS.docc/Builds.md new file mode 100644 index 0000000000..6c85877303 --- /dev/null +++ b/documentation/CARLS.docc/Builds.md @@ -0,0 +1,18 @@ +# Builds + +Which variant to build, and what it installs. + +## Overview + +| `APP_VARIANT` | Bundle identifier | Home screen | +| --- | --- | --- | +| `carls` | `com.rives.carls` | CARLS | +| `carls-dev` | `com.rives.carls.dev` | CARLS Dev | + +The penguin is the primary icon and no St. Olaf icon is bundled. Both use the +`carls` Sentry project. `com.rives.carls` is the CARLS app's own identifier, so +a release build updates CARLS on the App Store. + +```bash +mise run carls:ios [device] +``` diff --git a/documentation/CARLS.docc/CARLS.md b/documentation/CARLS.docc/CARLS.md new file mode 100644 index 0000000000..70c276b417 --- /dev/null +++ b/documentation/CARLS.docc/CARLS.md @@ -0,0 +1,18 @@ +# CARLS + +@Metadata { + @TechnologyRoot +} + +The Carleton College app. + +## Overview + +CARLS builds the same code as All About Olaf, with the campus fixed to +Carleton. It is the `carls` build variant. + +## Topics + +### Builds + +- diff --git a/mise.toml b/mise.toml index fa14234f93..ad24a42d65 100644 --- a/mise.toml +++ b/mise.toml @@ -384,6 +384,10 @@ description = "Bundle data files" wait_for = ["pnpm:install:*"] run = "node scripts/bundle-data.mjs data/ docs/" +[tasks.docs] +description = "Build the DocC site from documentation/ into docs/documentation/" +run = "scripts/build-docs.sh" + [tasks.images] description = "Convert images//source/ originals to the WebP files the app fetches" run = "node scripts/make-images.mjs" diff --git a/scripts/build-docs.sh b/scripts/build-docs.sh new file mode 100755 index 0000000000..219ab77b5d --- /dev/null +++ b/scripts/build-docs.sh @@ -0,0 +1,48 @@ +#!/usr/bin/env bash +# Builds each DocC catalog in documentation/, merges them into one site and +# writes it to docs/documentation/, which Pages serves under the data bundle. +# docc ships with Xcode on a Mac and with the Swift toolchain on Linux. +set -euo pipefail + +# The site is served from https://stolaf.dev/AAO-React-Native/, and DocC bakes +# its base path into every link. +base_path='AAO-React-Native/documentation' +out='docs/documentation' +work="$(mktemp -d)" +trap 'rm -rf "$work"' EXIT + +docc() { + if command -v xcrun >/dev/null; then + xcrun docc "$@" + else + command docc "$@" + fi +} + +for catalog in documentation/*.docc; do + name="$(basename "$catalog" .docc)" + docc convert "$catalog" \ + --fallback-display-name "$name" \ + --fallback-bundle-identifier "com.rives.aao.docs.$name" \ + --output-path "$work/$name.doccarchive" +done + +docc merge "$work"/*.doccarchive \ + --synthesized-landing-page-name 'All About Anything' \ + --synthesized-landing-page-kind Technology \ + --output-path "$work/merged.doccarchive" + +rm -rf "$out" +mkdir -p "$(dirname "$out")" +docc process-archive transform-for-static-hosting "$work/merged.doccarchive" \ + --hosting-base-path "$base_path" \ + --output-path "$out" + +# The archive's own index.html has no page at its root route, so it renders +# blank. Send the root to the merged landing page. +cat >"$out/index.html" <<'HTML' + + + +Documentation +HTML