Skip to content

Commit ea75b20

Browse files
Harden docs CI and workflow governance
1 parent 0c7c6c7 commit ea75b20

13 files changed

Lines changed: 362 additions & 36 deletions

.github/workflows/deploy.yml

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,19 @@ on:
44
push:
55
branches:
66
- main
7+
paths-ignore:
8+
- "**/*.md"
9+
- "docs/**"
10+
- "Documentation/**"
11+
- ".github/workflows/docs-*.yml"
712
pull_request:
813
branches:
914
- main
15+
paths-ignore:
16+
- "**/*.md"
17+
- "docs/**"
18+
- "Documentation/**"
19+
- ".github/workflows/docs-*.yml"
1020
workflow_dispatch:
1121

1222
env:

.github/workflows/docs-markdownlint.yml

Lines changed: 14 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -6,12 +6,18 @@ on:
66
- "README.md"
77
- "docs/**"
88
- ".github/workflows/docs-markdownlint.yml"
9+
- "CONTRIBUTING.md"
10+
- "Documentation/**"
11+
- ".markdownlint-docs.json"
912
push:
1013
branches: [main]
1114
paths:
1215
- "README.md"
1316
- "docs/**"
1417
- ".github/workflows/docs-markdownlint.yml"
18+
- "CONTRIBUTING.md"
19+
- "Documentation/**"
20+
- ".markdownlint-docs.json"
1521

1622
jobs:
1723
markdownlint:
@@ -27,15 +33,13 @@ jobs:
2733

2834
- name: Run markdownlint (targeted docs)
2935
run: |
30-
cat > /tmp/markdownlint-docs.json <<'EOF'
31-
{
32-
"default": true,
33-
"MD013": false,
34-
"MD007": false,
35-
"MD033": false
36-
}
37-
EOF
3836
npx --yes markdownlint-cli2 \
39-
--config /tmp/markdownlint-docs.json \
37+
--config .markdownlint-docs.json \
4038
README.md \
41-
docs/ALERT_RUNBOOKS.md
39+
CONTRIBUTING.md \
40+
docs/ALERT_RUNBOOKS.md \
41+
docs/index.md \
42+
docs/README.md \
43+
Documentation/README.md \
44+
docs/DOCUMENTATION_MAINTENANCE.md \
45+
Documentation/Project/REPO_SETTINGS_ADMIN_RUNBOOK.md

.github/workflows/docs-pages.yml

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ on:
66
paths:
77
- "README.md"
88
- "docs/**"
9+
- "scripts/check_markdown_assets.py"
910
- ".github/workflows/docs-pages.yml"
1011
workflow_dispatch:
1112

@@ -39,6 +40,11 @@ jobs:
3940
- name: Install markdown renderer
4041
run: python -m pip install --upgrade pip markdown
4142

43+
- name: Validate docs image assets
44+
run: |
45+
mapfile -t markdown_files < <(find docs -type f -name '*.md' | sort)
46+
python scripts/check_markdown_assets.py README.md "${markdown_files[@]}"
47+
4248
- name: Build docs site
4349
run: |
4450
python - <<'PY'
@@ -116,6 +122,12 @@ jobs:
116122
(root / '.nojekyll').write_text('', encoding='utf-8')
117123
PY
118124
125+
- name: Pages build smoke test
126+
run: |
127+
test -f .pages-site/index.html
128+
test -s .pages-site/index.html
129+
echo "Pages build smoke test passed"
130+
119131
- name: Upload Pages artifact
120132
uses: actions/upload-pages-artifact@fc324d3547104276b827a68afc52ff2a11cc49c9 # v5.0.0
121133
with:

.github/workflows/docs-quality.yml

Lines changed: 17 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -4,18 +4,20 @@ on:
44
pull_request:
55
paths:
66
- "README.md"
7-
- "docs/README.md"
8-
- "Documentation/README.md"
9-
- "docs/DOCUMENTATION_MAINTENANCE.md"
7+
- "CONTRIBUTING.md"
8+
- "docs/**"
9+
- "Documentation/**"
10+
- ".markdownlint-docs.json"
1011
- "scripts/check_markdown_links_subset.py"
1112
- ".github/workflows/docs-quality.yml"
1213
push:
1314
branches: [main]
1415
paths:
1516
- "README.md"
16-
- "docs/README.md"
17-
- "Documentation/README.md"
18-
- "docs/DOCUMENTATION_MAINTENANCE.md"
17+
- "CONTRIBUTING.md"
18+
- "docs/**"
19+
- "Documentation/**"
20+
- ".markdownlint-docs.json"
1921
- "scripts/check_markdown_links_subset.py"
2022
- ".github/workflows/docs-quality.yml"
2123
workflow_dispatch:
@@ -43,25 +45,23 @@ jobs:
4345

4446
- name: Markdown lint (targeted files)
4547
run: |
46-
cat > /tmp/markdownlint-docs-quality.json <<'EOF'
47-
{
48-
"default": true,
49-
"MD013": false,
50-
"MD007": false,
51-
"MD033": false
52-
}
53-
EOF
5448
npx --yes markdownlint-cli2 \
55-
--config /tmp/markdownlint-docs-quality.json \
49+
--config .markdownlint-docs.json \
5650
README.md \
51+
CONTRIBUTING.md \
5752
docs/README.md \
5853
Documentation/README.md \
59-
docs/DOCUMENTATION_MAINTENANCE.md
54+
docs/DOCUMENTATION_MAINTENANCE.md \
55+
docs/index.md \
56+
Documentation/Project/REPO_SETTINGS_ADMIN_RUNBOOK.md
6057
6158
- name: Local markdown link check (targeted files)
6259
run: |
6360
python scripts/check_markdown_links_subset.py \
6461
README.md \
62+
CONTRIBUTING.md \
6563
docs/README.md \
6664
Documentation/README.md \
67-
docs/DOCUMENTATION_MAINTENANCE.md
65+
docs/DOCUMENTATION_MAINTENANCE.md \
66+
docs/index.md \
67+
Documentation/Project/REPO_SETTINGS_ADMIN_RUNBOOK.md

.github/workflows/lint.yml

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,18 @@ on:
44
workflow_dispatch:
55
push:
66
branches: [ main ]
7+
paths-ignore:
8+
- "**/*.md"
9+
- "docs/**"
10+
- "Documentation/**"
11+
- ".github/workflows/docs-*.yml"
712
pull_request:
813
branches: [ main ]
14+
paths-ignore:
15+
- "**/*.md"
16+
- "docs/**"
17+
- "Documentation/**"
18+
- ".github/workflows/docs-*.yml"
919

1020
permissions:
1121
contents: read

.github/workflows/workflow-action-pin-check.yml

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,3 +41,68 @@ jobs:
4141
fi
4242
4343
echo "All workflow action references are SHA-pinned."
44+
45+
- name: Verify pinned SHAs resolve
46+
env:
47+
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
48+
run: |
49+
python - <<'PY'
50+
import os
51+
import re
52+
import sys
53+
import urllib.error
54+
import urllib.request
55+
from pathlib import Path
56+
57+
token = os.environ.get('GITHUB_TOKEN', '')
58+
uses_re = re.compile(r"^\s*uses:\s*([^\s#]+)")
59+
sha_re = re.compile(r"^[0-9a-fA-F]{40}$")
60+
refs = set()
61+
62+
for workflow in sorted(Path('.github/workflows').glob('*.yml')):
63+
for line in workflow.read_text(encoding='utf-8', errors='ignore').splitlines():
64+
m = uses_re.match(line)
65+
if not m:
66+
continue
67+
ref = m.group(1)
68+
if ref.startswith('./') or ref.startswith('docker://'):
69+
continue
70+
if '@' not in ref:
71+
continue
72+
action, rev = ref.rsplit('@', 1)
73+
if not sha_re.fullmatch(rev):
74+
continue
75+
refs.add((action, rev, workflow.as_posix()))
76+
77+
if not refs:
78+
print('No pinned action SHAs found to resolve.')
79+
sys.exit(0)
80+
81+
headers = {
82+
'Accept': 'application/vnd.github+json',
83+
'User-Agent': 'workflow-action-pin-check',
84+
}
85+
if token:
86+
headers['Authorization'] = f'Bearer {token}'
87+
88+
failures = []
89+
for action, rev, workflow in sorted(refs):
90+
url = f'https://api.github.com/repos/{action}/commits/{rev}'
91+
req = urllib.request.Request(url, headers=headers)
92+
try:
93+
with urllib.request.urlopen(req, timeout=20) as resp:
94+
if resp.status != 200:
95+
failures.append((workflow, action, rev, f'HTTP {resp.status}'))
96+
except urllib.error.HTTPError as exc:
97+
failures.append((workflow, action, rev, f'HTTP {exc.code}'))
98+
except Exception as exc:
99+
failures.append((workflow, action, rev, str(exc)))
100+
101+
if failures:
102+
print('Found unresolved pinned action SHAs:')
103+
for workflow, action, rev, reason in failures:
104+
print(f'- {workflow}: {action}@{rev} -> {reason}')
105+
sys.exit(1)
106+
107+
print(f'All pinned action SHAs resolved successfully ({len(refs)} refs).')
108+
PY

.markdownlint-docs.json

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
{
2+
"default": true,
3+
"MD013": false
4+
}

CONTRIBUTING.md

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -118,3 +118,17 @@ At minimum, require these checks:
118118
- `Windows Client EXE Build / Build Windows Client EXE`
119119
- `macOS Client Smoke / macOS Client Smoke`
120120
- `Observability CI / Validate Dashboard Queries`
121+
- `docs-markdownlint / markdownlint`
122+
- `Docs Quality / markdown-lint-and-links`
123+
- `Docs Pages / deploy`
124+
125+
Branch protection alignment rule:
126+
127+
- If a workflow or job name is renamed, update required checks in repository settings in the same change window. Stale required check names can block merges even when CI is healthy.
128+
129+
## Repository Settings (Admin Only)
130+
131+
Metadata updates for description, homepage, and topics require repository admin permissions. Use:
132+
133+
- Runbook: `Documentation/Project/REPO_SETTINGS_ADMIN_RUNBOOK.md`
134+
- Fallback helper: `scripts/repo_settings_fallback.sh`
Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
# Repository Settings Admin Runbook
2+
3+
Use this runbook when repository metadata updates are needed and automation cannot apply them due to permission limits.
4+
5+
## Required Permissions
6+
7+
- Repository admin rights on this repository
8+
- A GitHub CLI token with `repo` scope for private repos (or `public_repo` for public-only repos)
9+
10+
Recommended token refresh command:
11+
12+
```bash
13+
gh auth refresh -h github.com -s repo,read:org
14+
```
15+
16+
## Metadata Values to Keep Current
17+
18+
- Description
19+
- Homepage URL
20+
- Topics
21+
22+
## Admin Update Commands
23+
24+
```bash
25+
gh repo edit rwilliamspbg-ops/Sovereign_Map_Federated_Learning \
26+
--description "Formally verified federated learning runtime with hierarchical trust, TPM sovereignty, and auditable zk-style proof paths."
27+
28+
gh repo edit rwilliamspbg-ops/Sovereign_Map_Federated_Learning \
29+
--homepage "https://rwilliamspbg-ops.github.io/Sovereign_Map_Federated_Learning/"
30+
31+
gh repo edit rwilliamspbg-ops/Sovereign_Map_Federated_Learning \
32+
--add-topic federated-learning \
33+
--add-topic byzantine-fault-tolerance \
34+
--add-topic tpm \
35+
--add-topic zero-knowledge \
36+
--add-topic post-quantum-cryptography \
37+
--add-topic distributed-systems \
38+
--add-topic observability
39+
```
40+
41+
## Verification
42+
43+
```bash
44+
gh repo view rwilliamspbg-ops/Sovereign_Map_Federated_Learning \
45+
--json description,homepageUrl,repositoryTopics
46+
```
47+
48+
## Branch Protection Required Checks Alignment
49+
50+
After any workflow rename, verify required check names still match the active workflow/job names in branch protection settings.
51+
52+
At minimum, keep these docs checks aligned:
53+
54+
- `docs-markdownlint / markdownlint`
55+
- `Docs Quality / markdown-lint-and-links`
56+
- `Docs Pages / deploy`

README.md

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,8 @@ flowchart TB
6969
A --> O[Grafana + HUD]
7070
```
7171

72+
<!-- markdownlint-disable MD033 -->
73+
7274
<p align="center">
7375
<img src="docs/screenshots/hud-operations-overview.png" alt="HUD operations overview" width="400" />
7476
<img src="docs/screenshots/grafana-operations-overview.png" alt="Grafana operations overview" width="400" />
@@ -98,6 +100,8 @@ flowchart TB
98100

99101
</details>
100102

103+
<!-- markdownlint-enable MD033 -->
104+
101105
## Community and Contribution
102106

103107
The project is open to contributors who want to work on practical scale and verification problems.
@@ -108,6 +112,7 @@ The project is open to contributors who want to work on practical scale and veri
108112
- License: [LICENSE](LICENSE)
109113
- Roadmap: [Documentation/Project/ROADMAP.md](Documentation/Project/ROADMAP.md)
110114
- Research notes: [documentation/RESEARCH_FINDINGS.md](documentation/RESEARCH_FINDINGS.md)
115+
- Repo settings admin runbook: [Documentation/Project/REPO_SETTINGS_ADMIN_RUNBOOK.md](Documentation/Project/REPO_SETTINGS_ADMIN_RUNBOOK.md)
111116

112117
Looking for help with:
113118

@@ -381,10 +386,7 @@ The following environment variables are available for safe runtime tuning:
381386
- `RUNTIME_PROFILE=ultra_latency|balanced|throughput` (default `balanced`)
382387
- `MEMORY_PRESSURE_SAMPLE_SECONDS` (default `5.0`)
383388
- Runtime API endpoint: `GET/POST /runtime/profile`
384-
- `GET /metrics_summary` now includes:
385-
- `runtime_profile`
386-
- `provider_execution_policy`
387-
- `memory_pressure`
389+
- `GET /metrics_summary` includes `runtime_profile`, `provider_execution_policy`, and `memory_pressure`
388390

389391
Runtime profile quick commands:
390392

0 commit comments

Comments
 (0)