diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 4a16d11..d71447c 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -9,50 +9,90 @@ on: permissions: contents: read +env: + PYTHONIOENCODING: utf-8 + PYTHONUTF8: "1" + jobs: validate: - name: Lint & Verify - runs-on: ubuntu-latest - timeout-minutes: 10 + name: Lint & Verify (${{ matrix.os }}, Python ${{ matrix.python-version }}) + strategy: + fail-fast: false + matrix: + os: [ubuntu-latest, windows-latest, macos-latest] + python-version: ["3.11", "3.12"] + runs-on: ${{ matrix.os }} + timeout-minutes: 20 steps: - name: Checkout repository uses: actions/checkout@v4 + env: + GIT_CONFIG_COUNT: "1" + GIT_CONFIG_KEY_0: "core.autocrlf" + GIT_CONFIG_VALUE_0: "false" with: persist-credentials: false - name: Set up Python uses: actions/setup-python@v5 with: - python-version: "3.11" + python-version: ${{ matrix.python-version }} - name: Verify accessible SVG contract - run: python3 scripts/test-lint-a11y.py + id: a11y + run: python scripts/test-lint-a11y.py - name: Verify URL SVG normalization - run: python3 scripts/test-build-icons-quoted-attributes.py + id: url_icons + run: python scripts/test-build-icons-quoted-attributes.py - name: Verify Devicon normalization - run: python3 scripts/test-build-icons-devicon.py + id: devicon + run: python scripts/test-build-icons-devicon.py - name: Verify mojibake repair utility - run: python3 scripts/test-fix-mojibake.py + id: mojibake + run: python scripts/test-fix-mojibake.py - name: Run skin linter - run: python3 scripts/lint-skin.py --all --baseline + id: skin + run: python scripts/lint-skin.py --all --baseline - name: Verify sequence OAuth specs - run: python3 scripts/verify-sequence-oauth.py + id: oauth + run: python scripts/verify-sequence-oauth.py - name: Verify draw.io import script - run: python3 scripts/verify-drawio-import.py + id: drawio + run: python scripts/verify-drawio-import.py - name: Verify Mermaid import script - run: python3 scripts/verify-mermaid-import.py + id: mermaid + run: python scripts/verify-mermaid-import.py - name: Verify generated icon assets + id: icons + shell: bash run: | - python3 scripts/build-icons.py + python scripts/build-icons.py git diff --ignore-space-at-eol --exit-code -- \ skills/diagram-design/assets/icons.html \ skills/diagram-design/references/primitive-icons.md + + - name: Generate CI execution summary table + if: always() + shell: bash + run: | + echo "### 📊 CI Verification Summary (${{ matrix.os }}, Python ${{ matrix.python-version }})" >> $GITHUB_STEP_SUMMARY + echo "| Verification Gate | Outcome |" >> $GITHUB_STEP_SUMMARY + echo "|---|---|" >> $GITHUB_STEP_SUMMARY + echo "| SVG Accessibility Contract | ${{ steps.a11y.outcome == 'success' && '✅ Passed' || (steps.a11y.outcome == 'skipped' && '⏭️ Skipped' || '❌ Failed') }} |" >> $GITHUB_STEP_SUMMARY + echo "| URL SVG Normalization | ${{ steps.url_icons.outcome == 'success' && '✅ Passed' || (steps.url_icons.outcome == 'skipped' && '⏭️ Skipped' || '❌ Failed') }} |" >> $GITHUB_STEP_SUMMARY + echo "| Devicon Normalization | ${{ steps.devicon.outcome == 'success' && '✅ Passed' || (steps.devicon.outcome == 'skipped' && '⏭️ Skipped' || '❌ Failed') }} |" >> $GITHUB_STEP_SUMMARY + echo "| Mojibake Repair Utility | ${{ steps.mojibake.outcome == 'success' && '✅ Passed' || (steps.mojibake.outcome == 'skipped' && '⏭️ Skipped' || '❌ Failed') }} |" >> $GITHUB_STEP_SUMMARY + echo "| Color Palette & Skin Linter | ${{ steps.skin.outcome == 'success' && '✅ Passed' || (steps.skin.outcome == 'skipped' && '⏭️ Skipped' || '❌ Failed') }} |" >> $GITHUB_STEP_SUMMARY + echo "| Sequence Diagram Grammar | ${{ steps.oauth.outcome == 'success' && '✅ Passed' || (steps.oauth.outcome == 'skipped' && '⏭️ Skipped' || '❌ Failed') }} |" >> $GITHUB_STEP_SUMMARY + echo "| Draw.io Import Extractor | ${{ steps.drawio.outcome == 'success' && '✅ Passed' || (steps.drawio.outcome == 'skipped' && '⏭️ Skipped' || '❌ Failed') }} |" >> $GITHUB_STEP_SUMMARY + echo "| Mermaid Import Extractor | ${{ steps.mermaid.outcome == 'success' && '✅ Passed' || (steps.mermaid.outcome == 'skipped' && '⏭️ Skipped' || '❌ Failed') }} |" >> $GITHUB_STEP_SUMMARY + echo "| Primitive Icons & Documentation | ${{ steps.icons.outcome == 'success' && '✅ Passed' || (steps.icons.outcome == 'skipped' && '⏭️ Skipped' || '❌ Failed') }} |" >> $GITHUB_STEP_SUMMARY diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index e6e6e2d..3264c57 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -19,7 +19,7 @@ See [README.md](README.md) for the full picture, including the design system and - **Create an issue first** for anything non-trivial (new type, behavior change, import grammar work). Small fixes and docs can go straight to a PR. - **Work on a branch** — never commit directly to `main`. - **Keep the scope tight.** One PR = one concern. Mixing a new diagram type with a docs rewrite makes review slow. -- **Python 3.10+ is required** for the development scripts (CI runs 3.11). +- **Python 3.10+ is required** for the development scripts (CI runs 3.11 and 3.12 across Linux, Windows, and macOS). --- @@ -133,4 +133,4 @@ A good PR: ## Questions? -Open a discussion or comment on the relevant issue. If it's about security, use the private reporting path in [SECURITY.md](SECURITY.md). \ No newline at end of file +Open a discussion or comment on the relevant issue. If it's about security, use the private reporting path in [SECURITY.md](SECURITY.md). diff --git a/README.md b/README.md index 152645a..181c55d 100644 --- a/README.md +++ b/README.md @@ -361,7 +361,7 @@ If you touch the Mermaid import path, `python3 scripts/verify-mermaid-import.py` it covers all supported grammars, multi-block Markdown, adversarial labels, trust-boundary behavior, resource caps, named failures, and reference/command wiring. -All pull requests and pushes are automatically validated via GitHub Actions CI (`.github/workflows/ci.yml`). +All pull requests and pushes are automatically validated across Linux, Windows, and macOS runners via GitHub Actions CI (`.github/workflows/ci.yml`). ### What loads when diff --git a/scripts/verify-drawio-import.py b/scripts/verify-drawio-import.py index c8e0ecc..bb27586 100644 --- a/scripts/verify-drawio-import.py +++ b/scripts/verify-drawio-import.py @@ -48,6 +48,8 @@ def run_extract(args: list[str]) -> str: [sys.executable, str(EXTRACT), *args], capture_output=True, text=True, + encoding="utf-8", + errors="replace", ) if proc.returncode != 0: fail(f"extractor exited {proc.returncode} for {args}: {proc.stderr.strip()}") diff --git a/scripts/verify-mermaid-import.py b/scripts/verify-mermaid-import.py index 78418e1..969bfa9 100644 --- a/scripts/verify-mermaid-import.py +++ b/scripts/verify-mermaid-import.py @@ -43,6 +43,8 @@ def invoke(args: list[str]) -> subprocess.CompletedProcess[str]: [sys.executable, str(EXTRACT), *args], capture_output=True, text=True, + encoding="utf-8", + errors="replace", )