Skip to content

chore: Root Directory Cleanup - Remove 1,100 Lines Outdated Docs #462

chore: Root Directory Cleanup - Remove 1,100 Lines Outdated Docs

chore: Root Directory Cleanup - Remove 1,100 Lines Outdated Docs #462

Workflow file for this run

name: PR Validation
on:
pull_request:
branches:
- main
- integrate/mvp
concurrency:
group: ${{ github.ref }}
cancel-in-progress: true
permissions:
contents: read
jobs:
scope-classifier:
name: Scope Classifier
runs-on: ubuntu-latest
outputs:
full_gate: ${{ steps.classify.outputs.full_gate }}
docs_ci_only: ${{ steps.classify.outputs.docs_ci_only }}
changed_count: ${{ steps.classify.outputs.changed_count }}
steps:
- name: Checkout
uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Classify PR change scope
id: classify
run: |
git diff --name-only "${{ github.event.pull_request.base.sha }}" "${{ github.event.pull_request.head.sha }}" > changed_files.txt
python3 - <<'PY'
import fnmatch
import os
from pathlib import Path
files = [line.strip() for line in Path("changed_files.txt").read_text(encoding="utf-8").splitlines() if line.strip()]
fast_patterns = [
"docs/**",
".github/workflows/**",
"ci/**",
"README.md",
"SECURITY.md",
"CONTRIBUTING.md",
"CODE_OF_CONDUCT.md",
"CHANGELOG.md",
"QUICKSTART.md",
"scripts/README.md",
"scripts/validate-root-allowlist.sh",
]
docs_ci_only = bool(files) and all(any(fnmatch.fnmatch(f, p) for p in fast_patterns) for f in files)
full_gate = not docs_ci_only
with open(os.environ["GITHUB_OUTPUT"], "a", encoding="utf-8") as out:
out.write(f"changed_count={len(files)}\n")
out.write(f"docs_ci_only={'true' if docs_ci_only else 'false'}\n")
out.write(f"full_gate={'true' if full_gate else 'false'}\n")
print(f"changed_count={len(files)}")
print(f"docs_ci_only={docs_ci_only}")
print(f"full_gate={full_gate}")
PY
build-validation:
needs: [scope-classifier]
if: needs.scope-classifier.outputs.full_gate == 'true'
uses: ./.github/workflows/_go-ci-job.yml
with:
job-name: Build Validation
timeout-minutes: 10
run-command: make -f Makefile.ci ci-ultra-fast
config-tests:
needs: [scope-classifier]
if: needs.scope-classifier.outputs.full_gate == 'true'
uses: ./.github/workflows/_go-ci-job.yml
with:
job-name: Config Tests
timeout-minutes: 10
run-command: |
NPROC="$(nproc)"
go test -short -timeout=2m -p "$NPROC" ./pkg/config/...
auth-core-tests:
needs: [scope-classifier]
if: needs.scope-classifier.outputs.full_gate == 'true'
uses: ./.github/workflows/_go-ci-job.yml
with:
job-name: Auth Core Tests
timeout-minutes: 12
run-command: |
NPROC="$(nproc)"
go test -short -timeout=2m -p "$NPROC" ./pkg/auth
auth-provider-tests:
needs: [scope-classifier]
if: needs.scope-classifier.outputs.full_gate == 'true'
uses: ./.github/workflows/_go-ci-job.yml
with:
job-name: Auth Provider Tests
timeout-minutes: 10
run-command: |
NPROC="$(nproc)"
go test -short -timeout=2m -p "$NPROC" ./pkg/auth/providers ./pkg/auth/docker
security-tests:
needs: [scope-classifier]
if: needs.scope-classifier.outputs.full_gate == 'true'
uses: ./.github/workflows/_go-ci-job.yml
with:
job-name: Security Tests
timeout-minutes: 10
run-command: |
NPROC="$(nproc)"
go test -short -timeout=2m -p "$NPROC" ./internal/security/...
docs-link-integrity:
name: Docs Link Integrity
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Scan markdown relative links
run: |
python3 - <<'PY'
from pathlib import Path
import re
from collections import Counter
files = sorted(set(list(Path("docs").rglob("*.md")) + [Path("README.md"), Path("SECURITY.md")]))
pattern = re.compile(r'\[[^\]]+\]\(([^)]+)\)')
ignored_prefixes = ("http://", "https://", "mailto:", "tel:", "javascript:", "#")
missing = []
for f in files:
text = f.read_text(encoding="utf-8", errors="ignore")
for raw in pattern.findall(text):
u = raw.strip().strip("<>").split()[0]
if not u or u.startswith(ignored_prefixes) or u.startswith("`") or u.startswith("$" + "{{"):
continue
u = u.split("#", 1)[0].split("?", 1)[0]
if not u:
continue
p = (f.parent / u).resolve() if not u.startswith("/") else Path(u)
if p.exists():
continue
if u.endswith("/") and p.is_dir() and ((p / "index.md").exists() or (p / "README.md").exists()):
continue
missing.append((str(f), u))
if not missing:
print("No missing relative markdown links found.")
else:
print(f"::error::Found {len(missing)} missing relative markdown links.")
counts = Counter(src for src, _ in missing)
for src, n in counts.most_common(15):
print(f"{n:3d} {src}")
raise SystemExit(1)
PY
root-allowlist:
name: Root Allowlist
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Validate root allowlist
run: ./scripts/validate-root-allowlist.sh
basic-validation:
name: Basic Validation
runs-on: ubuntu-latest
needs: [scope-classifier, build-validation, config-tests, auth-core-tests, auth-provider-tests, security-tests, docs-link-integrity, root-allowlist]
if: always()
steps:
- name: Enforce required status outcome
run: |
echo "Scope: docs_ci_only=${{ needs.scope-classifier.outputs.docs_ci_only }}, full_gate=${{ needs.scope-classifier.outputs.full_gate }}, changed_count=${{ needs.scope-classifier.outputs.changed_count }}"
if [ "${{ needs.docs-link-integrity.result }}" != "success" ] || \
[ "${{ needs.root-allowlist.result }}" != "success" ]; then
echo "Basic Validation: FAIL"
exit 1
fi
if [ "${{ needs.scope-classifier.outputs.full_gate }}" = "true" ]; then
if [ "${{ needs.build-validation.result }}" != "success" ] || \
[ "${{ needs.config-tests.result }}" != "success" ] || \
[ "${{ needs.auth-core-tests.result }}" != "success" ] || \
[ "${{ needs.auth-provider-tests.result }}" != "success" ] || \
[ "${{ needs.security-tests.result }}" != "success" ]; then
echo "Basic Validation: FAIL"
exit 1
fi
fi
echo "Basic Validation: PASS"