name: documentation
on:
push:
branches: ["main"]
pull_request:
branches: ["main"]
jobs:
documentation:
name: documentation
runs-on: ubuntu-latest
outputs:
percent: ${{ steps.coverage.outputs.documented }}
steps:
- name: checkout
uses: actions/checkout@v2
- name: installation
uses: actions-rs/toolchain@v1
with:
toolchain: nightly
- name: calculation
id: coverage
run: |
set -euo pipefail
# Build docs and produce target/doc/spf.json
cargo +nightly rustdoc -- -Z unstable-options --show-coverage --output-format json
JSON_FILE="target/doc/spf.json"
if [ ! -f "$JSON_FILE" ]; then
echo "No coverage JSON found at $JSON_FILE" >&2
# Fallback outputs
echo "documented=0%" >> $GITHUB_OUTPUT
echo "table<<EOF" >> $GITHUB_OUTPUT
echo "No coverage JSON found." >> $GITHUB_OUTPUT
echo "EOF" >> $GITHUB_OUTPUT
echo "json<<EOF" >> $GITHUB_OUTPUT
echo "{}" >> $GITHUB_OUTPUT
echo "EOF" >> $GITHUB_OUTPUT
exit 0
fi
# Node script: parse spf.json and produce a markdown table + documented percent
cat > coverage-report.js <<'NODE'
const fs = require('fs');
const raw = fs.readFileSync('target/doc/spf.json', 'utf8');
const parsed = JSON.parse(raw);
// rustdoc json layout: coverage may be top-level or under `coverage`
const cov = parsed.coverage || parsed;
const rows = [['File', 'Documented', 'Percentage', 'Examples', 'Percentage']];
let total = 0, with_docs = 0, total_examples = 0, with_examples = 0;
const files = Object.keys(cov).sort();
for (const file of files) {
const e = cov[file] || {};
const t = Number(e.total || 0);
const wd = Number(e.with_docs || 0);
const te = Number(e.total_examples || 0);
const we = Number(e.with_examples || 0);
total += t; with_docs += wd; total_examples += te; with_examples += we;
const pctDocs = t ? Math.round(100 * wd / t) : 0;
const pctEx = te ? Math.round(100 * we / te) : 0;
rows.push([file, String(wd), `${pctDocs}%`, String(we), `${pctEx}%`]);
}
const pctTotal = total ? Math.round(100 * with_docs / total) : 0;
const pctExTotal = total_examples ? Math.round(100 * with_examples / total_examples) : 0;
rows.push(['**Total**', String(with_docs), `${pctTotal}%`, String(with_examples), `${pctExTotal}%`]);
// Render a simple aligned markdown table
const colWidths = [];
rows.forEach(r => r.forEach((c, i) => colWidths[i] = Math.max(colWidths[i] || 0, String(c).length)));
const pad = (s, w) => s + ' '.repeat(w - String(s).length);
const line = r => '| ' + r.map((c, i) => pad(c, colWidths[i])).join(' | ') + ' |';
const sep = '| ' + colWidths.map(w => '-'.repeat(w)).join(' | ') + ' |';
const table = [line(rows[0]), sep].concat(rows.slice(1).map(line)).join('\n');
const out = { documented: `${pctTotal}%`, table, json: cov };
fs.writeFileSync('coverage-result.json', JSON.stringify(out, null, 2), 'utf8');
NODE
# Run parser
node coverage-report.js
# Set GitHub Actions outputs
documented=$(node -e "console.log(JSON.parse(require('fs').readFileSync('coverage-result.json','utf8')).documented)")
echo "documented=$documented" >> $GITHUB_OUTPUT
echo "table<<EOF" >> $GITHUB_OUTPUT
node -e "console.log(JSON.parse(require('fs').readFileSync('coverage-result.json','utf8')).table)" >> $GITHUB_OUTPUT
echo "EOF" >> $GITHUB_OUTPUT
echo "json<<EOF" >> $GITHUB_OUTPUT
node -e "console.log(JSON.stringify(JSON.parse(require('fs').readFileSync('coverage-result.json','utf8')).json))" >> $GITHUB_OUTPUT
echo "EOF" >> $GITHUB_OUTPUT
- name: write
run: |
# Preserve newlines; write the table output to documentation.md for the gist deploy step
printf '%s\n' "${{ steps.coverage.outputs.table }}" > documentation.md
- name: update
uses: exuanbo/actions-deploy-gist@v1
with:
token: ${{ secrets.GIST_SECRET }}
gist_id: cfebb0fe555ac7e77ada109c469cdeb4
gist_file_name: documentation.md
file_type: text
file_path: documentation.md
badge:
runs-on: ubuntu-latest
needs: documentation
if: always() && github.event_name == 'push'
steps:
- name: checkout
uses: actions/checkout@v2
- uses: julia-actions/setup-julia@v2
with:
version: "1"
- run: julia .ci/interpolate_colors.jl '#d94a69' '#00bfa3' ${{ needs.documentation.outputs.percent }}
- name: Update badge
uses: SimplePixelFont/badge-spf-action@main
with:
filename: documentation.png
label: Documentation
message: "${{ needs.documentation.outputs.percent }}"
labelColor: "#2d3136"
color: "${{ env.COLOR }}"
logo: "https://raw.githubusercontent.com/The-Nice-One/GalleryArt/refs/heads/main/emojis_flattened/document.png"
font: "https://raw.githubusercontent.com/SimplePixelFont/web-spf/refs/heads/main/Monogram5x8-light.spf"
- name: deploy badge
uses: exuanbo/actions-deploy-gist@v1
with:
token: ${{ secrets.GIST_SECRET }}
gist_id: cfebb0fe555ac7e77ada109c469cdeb4
file_path: documentation.png
file_type: binary