forked from ChelseaKR/mrf-honest
-
Notifications
You must be signed in to change notification settings - Fork 0
155 lines (149 loc) · 7.15 KB
/
Copy pathpages.yml
File metadata and controls
155 lines (149 loc) · 7.15 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
name: publish
# The site is rebuilt only from data already committed to this repository: the newest
# data/cohorts/*.comparison.json, which `mrf-honest compare` generated from persisted,
# integrity-verified assessment rows. There is deliberately no scheduled collection here —
# broad scheduled retrieval remains blocked on the robots.txt/pacing/Retry-After work recorded
# in docs/ROADMAP.md, and a publish workflow must not quietly become a crawler.
on:
push:
branches: [master]
workflow_dispatch:
permissions: {}
concurrency:
group: pages
cancel-in-progress: false
jobs:
build:
runs-on: ubuntu-latest
permissions:
contents: read
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
persist-credentials: false # this job only reads; it never pushes
- uses: actions/setup-python@5fda3b95a4ea91299a34e894583c3862153e4b97 # v7.0.0
with:
python-version: "3.12"
- name: Install
run: python -m pip install -e .
# The published artifact is checked against the code that claims to generate it, before
# anything is rendered from it. `make verify` runs the same derivation
# (tests/test_published_cohort.py), but `verify` is a separate workflow and a red run
# there does not stop this one from deploying. A publish job that renders a comparison
# nobody re-derived can ship numbers the code no longer produces, so the check lives on
# the deploy path too.
- name: Re-derive every committed comparison and require a byte-for-byte match
shell: bash
run: |
set -euo pipefail
for comparison in data/cohorts/*.comparison.json; do
prefix="${comparison%.comparison.json}"
for input in "${prefix}.assessments.jsonl" "${prefix}.json"; do
if [ ! -e "${input}" ]; then
echo "::error title=Cohort input missing::${comparison} cannot be re-derived: ${input} is not committed."
exit 1
fi
done
# Warehouse ingest evidence exists only for cohorts whose profile the warehouse
# implements. A cohort re-derived without evidence it was published with cannot
# pass the byte comparison below, so a missing directory is not a separate error.
args=()
if [ -d "${prefix}.ingest" ]; then
for evidence in "${prefix}.ingest"/*.json; do
[ -e "${evidence}" ] || continue
args+=(--ingest-result "${evidence}")
done
fi
generated_at="$(python -c "import json,sys;print(json.load(open(sys.argv[1]))['generated_at'])" "${comparison}")"
python -m mrf_honest.cli compare \
--assessments "${prefix}.assessments.jsonl" \
--manifest "${prefix}.json" \
${args[@]+"${args[@]}"} \
--generated-at "${generated_at}" \
--format json > /tmp/rederived.json
if ! cmp -s "${comparison}" /tmp/rederived.json; then
echo "::error title=Comparison is stale::${comparison} is not what mrf-honest compare derives from its committed inputs. The site would publish numbers the code no longer produces. Regenerate the comparison and commit it."
exit 1
fi
echo "re-derived ${comparison} byte-for-byte"
done
- name: Render the site from the newest committed comparison of each profile
shell: bash
run: |
set -euo pipefail
# One section per assessment profile, each from its newest committed cohort, JSON
# profile first. Selection reads each document's own comparison scope rather than
# trusting a filename convention.
python - > /tmp/render-list.txt <<'PY'
import glob, json
newest: dict[str, tuple[str, str]] = {}
for path in sorted(glob.glob("data/cohorts/*.comparison.json")):
document = json.load(open(path))
cohort = document["cohort"]
profile = str(cohort["comparison_scope"]["profile"])
key = (str(cohort["as_of"]), path)
if profile not in newest or key > newest[profile]:
newest[profile] = key
order = ["cms-hospital-json-v3", "cms-hospital-csv-v3"]
ordered = [p for p in order if p in newest] + sorted(set(newest) - set(order))
for profile in ordered:
print(newest[profile][1])
PY
args=()
while read -r comparison; do
echo "rendering from ${comparison}"
args+=(--comparison "${comparison}")
done < /tmp/render-list.txt
python -m mrf_honest.cli site \
"${args[@]}" \
--out site \
--origin "https://chelseakr.github.io/mrf-honest"
- name: Check the rendered site says what the data says
shell: bash
run: |
set -euo pipefail
test -f site/index.html
test -f site/how-we-grade/index.html
test -f site/sitemap.xml
test -f site/404.html
grep -Fq 'Sitemap: https://chelseakr.github.io/mrf-honest/sitemap.xml' site/robots.txt
total_rendered=0
total_targeted=0
while read -r comparison; do
targeted="$(python -c "import json,sys;print(json.load(open(sys.argv[1]))['summary']['targeted'])" "${comparison}")"
grep -Fq "<strong>${targeted}</strong> machine-readable files" site/index.html
total_targeted=$((total_targeted + targeted))
# Every graded file gets its own page, or the index links somewhere that 404s. The
# count check above passes on a render that emitted no file pages at all.
python -c "import json,sys;print('\n'.join(row['slug'] for row in json.load(open(sys.argv[1]))['files']))" \
"${comparison}" > /tmp/slugs.txt
while read -r slug; do
[ -n "${slug}" ] || continue
if [ ! -f "site/hospital/${slug}/index.html" ]; then
echo "::error title=Missing file page::${slug} is a row in ${comparison} but site/hospital/${slug}/index.html was not rendered."
exit 1
fi
grep -Fq "hospital/${slug}/" site/index.html
total_rendered=$((total_rendered + 1))
done < /tmp/slugs.txt
done < /tmp/render-list.txt
if [ "${total_rendered}" -ne "${total_targeted}" ]; then
echo "::error title=Page count disagrees with the data::${total_rendered} file pages checked against ${total_targeted} targeted rows."
exit 1
fi
- uses: actions/configure-pages@45bfe0192ca1faeb007ade9deae92b16b8254a0d # v6.0.0
- uses: actions/upload-pages-artifact@fc324d3547104276b827a68afc52ff2a11cc49c9 # v5.0.0
with:
path: site
deploy:
needs: build
runs-on: ubuntu-latest
permissions:
pages: write
id-token: write
environment:
name: github-pages
url: ${{ steps.deployment.outputs.page_url }}
steps:
- id: deployment
uses: actions/deploy-pages@cd2ce8fcbc39b97be8ca5fce6e763baed58fa128 # v5.0.0