diff --git a/.github/workflows/pages.yml b/.github/workflows/pages.yml new file mode 100644 index 0000000..e1cb940 --- /dev/null +++ b/.github/workflows/pages.yml @@ -0,0 +1,321 @@ +name: Deploy to GitHub Pages + +on: + push: + branches: ["main"] + workflow_dispatch: + +permissions: + contents: read + pages: write + id-token: write + +concurrency: + group: "pages" + cancel-in-progress: false + +jobs: + build: + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: Generate Jekyll site + shell: bash + env: + REPO_NAME: ${{ github.event.repository.name }} + REPO_FULL: ${{ github.repository }} + REPO_DESC: ${{ github.event.repository.description }} + run: | + set -e + + OWNER="${REPO_FULL%%/*}" + REPO="${REPO_NAME}" + DESC="${REPO_DESC:-$REPO}" + BASE_URL="/${REPO}" + STAGE="_site_source" + + echo "::group::Staging allowed files" + + # ── Stage ONLY allowed files into a clean directory ─────────── + # Whitelist: *.md files + LICENSE + LICENSE.txt + # Everything else is excluded from the site. + mkdir -p "${STAGE}" + + # Copy all .md files preserving directory structure + find . -name '*.md' \ + -not -path './.git/*' \ + -not -path "./${STAGE}/*" \ + | while read -r f; do + dest="${STAGE}/${f#./}" + mkdir -p "$(dirname "$dest")" + cp "$f" "$dest" + done + + # Copy LICENSE files (plain text) + for lf in LICENSE LICENSE.txt; do + [ -f "$lf" ] && cp "$lf" "${STAGE}/" + done + + # Remove any .gitkeep files that got copied + find "${STAGE}" -name '.gitkeep' -delete + + echo "Staged files:" + find "${STAGE}" -type f | sort + echo "::endgroup::" + + # ── Everything below operates inside the staging dir ────────── + cd "${STAGE}" + + echo "::group::Generating Jekyll config and layout" + + # ── _config.yml ─────────────────────────────────────────────── + cat > _config.yml << CONFIGEOF + title: "${REPO}" + description: "${DESC}" + permalink: pretty + baseurl: "${BASE_URL}" + + defaults: + - scope: + path: "docs" + values: + layout: default + nav_section: docs + CONFIGEOF + + # ── _layouts/default.html ───────────────────────────────────── + mkdir -p _layouts + cat > _layouts/default.html << 'LAYOUTEOF' + + + + + + {{ page.title | default: site.title }} + + + + + + +
+
{{ content }}
+
+ + + LAYOUTEOF + echo "::endgroup::" + + echo "::group::Processing content files" + + # ── README.md → homepage ────────────────────────────────────── + if [ -f "README.md" ] && ! head -1 README.md | grep -q '^\-\-\-'; then + TEMP=$(mktemp) + printf -- '---\nlayout: default\ntitle: Home\npermalink: /\n---\n\n' > "$TEMP" + cat README.md >> "$TEMP" + mv "$TEMP" README.md + echo "Processed README.md → homepage" + fi + + # ── Docs: add front matter + create index ───────────────────── + if [ -d "docs" ]; then + for f in docs/*.md; do + [ -f "$f" ] || continue + [ "$(basename "$f")" = "index.md" ] && continue + + if ! head -1 "$f" | grep -q '^\-\-\-'; then + BASENAME=$(basename "$f" .md) + SYNOPSIS=$(grep -m1 -A1 '## Synopsis' "$f" 2>/dev/null | tail -1 | sed 's/^[[:space:]]*//') + [ -z "$SYNOPSIS" ] && SYNOPSIS="$BASENAME" + TEMP=$(mktemp) + printf -- '---\nlayout: default\ntitle: %s\ndescription: "%s"\n---\n\n' "$BASENAME" "$SYNOPSIS" > "$TEMP" + cat "$f" >> "$TEMP" + mv "$TEMP" "$f" + echo "Processed $f" + fi + done + + if [ ! -f "docs/index.md" ]; then + cat > docs/index.md << 'DOCSEOF' + --- + layout: default + title: Docs + permalink: /docs/ + --- + # Function reference + {% assign doc_pages = site.pages | where_exp: "p", "p.path contains 'docs/'" | where_exp: "p", "p.name != 'index.md'" | sort: "title" %} + {% if doc_pages.size > 0 %} + + {% else %} +

No function documentation found yet.

+ {% endif %} + DOCSEOF + echo "Created docs/index.md" + fi + fi + + # ── Releases page ───────────────────────────────────────────── + cat > releases.md << RELEOF + --- + layout: default + title: Releases + permalink: /releases/ + --- + # Releases +
Loading releases...
+ + RELEOF + echo "Created releases.md" + + # ── License page (from LICENSE/LICENSE.txt) ──────────────────── + LICENSE_SRC="" + for lf in LICENSE LICENSE.txt; do + [ -f "$lf" ] && LICENSE_SRC="$lf" && break + done + + if [ -n "$LICENSE_SRC" ] || [ -f "LICENSE.md" ]; then + SRC="${LICENSE_SRC:-LICENSE.md}" + LICENSE_TYPE="License" + grep -qi "apache" "$SRC" 2>/dev/null && LICENSE_TYPE="Apache License 2.0" + grep -qi "mit license" "$SRC" 2>/dev/null && LICENSE_TYPE="MIT License" + grep -qi "gnu general public" "$SRC" 2>/dev/null && LICENSE_TYPE="GPL" + grep -qi "bsd" "$SRC" 2>/dev/null && LICENSE_TYPE="BSD License" + + if ! ([ -f "LICENSE.md" ] && head -1 LICENSE.md | grep -q '^\-\-\-'); then + cat > LICENSE.md << LICEOF + --- + layout: default + title: License + permalink: /license/ + --- + # License + This project is licensed under the **${LICENSE_TYPE}**. + + See the [LICENSE](https://github.com/${REPO_FULL}/blob/main/${SRC}) file for the full license text. + LICEOF + echo "Created LICENSE.md (${LICENSE_TYPE})" + fi + fi + + # ── CONTRIBUTING.md ─────────────────────────────────────────── + if [ -f "CONTRIBUTING.md" ] && ! head -1 CONTRIBUTING.md | grep -q '^\-\-\-'; then + TEMP=$(mktemp) + printf -- '---\nlayout: default\ntitle: Contributing\npermalink: /contributing/\n---\n\n' > "$TEMP" + cat CONTRIBUTING.md >> "$TEMP" + mv "$TEMP" CONTRIBUTING.md + echo "Processed CONTRIBUTING.md" + fi + + # ── CODE_OF_CONDUCT.md ──────────────────────────────────────── + if [ -f "CODE_OF_CONDUCT.md" ] && ! head -1 CODE_OF_CONDUCT.md | grep -q '^\-\-\-'; then + TEMP=$(mktemp) + printf -- '---\nlayout: default\ntitle: Code of Conduct\npermalink: /code-of-conduct/\n---\n\n' > "$TEMP" + cat CODE_OF_CONDUCT.md >> "$TEMP" + mv "$TEMP" CODE_OF_CONDUCT.md + echo "Processed CODE_OF_CONDUCT.md" + fi + + echo "::endgroup::" + + echo "Final site source contents:" + find . -type f | sort + + - name: Setup Pages + uses: actions/configure-pages@v5 + + - name: Build with Jekyll + uses: actions/jekyll-build-pages@v1 + with: + source: ./_site_source + destination: ./_site + + - name: Upload artifact + uses: actions/upload-pages-artifact@v3 + + deploy: + environment: + name: github-pages + url: ${{ steps.deployment.outputs.page_url }} + runs-on: ubuntu-latest + needs: build + steps: + - name: Deploy to GitHub Pages + id: deployment + uses: actions/deploy-pages@v5