Skip to content

Commit 9f7b1b8

Browse files
committed
feat(T11,T12,A8): Phase 2 CI gates: add release readiness + outbound safety checks, plus plugin migration tooling
1 parent 47dec1c commit 9f7b1b8

20 files changed

+2568
-10
lines changed
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
name: Outbound Safety Check
2+
3+
on:
4+
push:
5+
branches:
6+
- main
7+
- dev
8+
paths:
9+
- '**/*.py'
10+
- 'scripts/check_outbound_safety.py'
11+
- '.github/workflows/outbound-safety.yml'
12+
pull_request:
13+
paths:
14+
- '**/*.py'
15+
- 'scripts/check_outbound_safety.py'
16+
workflow_dispatch:
17+
18+
jobs:
19+
outbound-safety:
20+
runs-on: ubuntu-latest
21+
timeout-minutes: 5
22+
23+
steps:
24+
- name: Checkout code
25+
uses: actions/checkout@v4
26+
27+
- name: Set up Python
28+
uses: actions/setup-python@v5
29+
with:
30+
python-version: '3.10'
31+
32+
- name: Run outbound safety check
33+
run: |
34+
python scripts/check_outbound_safety.py
35+
36+
- name: Summary
37+
if: success()
38+
run: |
39+
echo "✅ Outbound safety check passed!"
40+
echo "- No raw context fields in outbound payloads"
41+
echo "- All POST requests use sanitize_outbound_payload()"
42+
echo "- No dangerous fallback patterns detected"
Lines changed: 182 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,182 @@
1+
name: Phase 2 Release Gate
2+
3+
on:
4+
push:
5+
branches:
6+
- main
7+
- dev
8+
- 'release/**'
9+
paths:
10+
# Trigger on Phase 2 critical files
11+
- 'pipeline/**/*.py'
12+
- 'sanitizer.py'
13+
- 'outbound.py'
14+
- 'config.py'
15+
- '__init__.py'
16+
- 'tests/test_plugins_security.py'
17+
- 'tests/test_metadata_contract.py'
18+
- 'tests/test_pipeline_dependency_policy.py'
19+
- 'tests/test_outbound_payload_safety.py'
20+
- 'web/**/*.js'
21+
- 'tests/e2e/**/*.js'
22+
- '.github/workflows/phase2-release-gate.yml'
23+
pull_request:
24+
branches:
25+
- main
26+
- dev
27+
paths:
28+
- 'pipeline/**/*.py'
29+
- 'sanitizer.py'
30+
- 'outbound.py'
31+
- 'config.py'
32+
- '__init__.py'
33+
- 'tests/test_plugins_security.py'
34+
- 'tests/test_metadata_contract.py'
35+
- 'tests/test_pipeline_dependency_policy.py'
36+
- 'tests/test_outbound_payload_safety.py'
37+
- 'web/**/*.js'
38+
- 'tests/e2e/**/*.js'
39+
- '.github/workflows/phase2-release-gate.yml'
40+
workflow_dispatch:
41+
42+
jobs:
43+
phase2-python-gate:
44+
name: Phase 2 Python Security & Contract Tests
45+
runs-on: ubuntu-latest
46+
timeout-minutes: 5
47+
48+
steps:
49+
- name: Checkout code
50+
uses: actions/checkout@v4
51+
52+
- name: Set up Python 3.10
53+
uses: actions/setup-python@v5
54+
with:
55+
python-version: '3.10'
56+
cache: 'pip'
57+
cache-dependency-path: |
58+
pyproject.toml
59+
pytest.ini
60+
61+
- name: Install dependencies
62+
run: |
63+
pip install pytest jsonschema
64+
65+
- name: Run Plugin Security Suite
66+
run: |
67+
pytest -q tests/test_plugins_security.py --tb=short
68+
timeout-minutes: 2
69+
70+
- name: Run Metadata Contract Suite
71+
run: |
72+
pytest -q tests/test_metadata_contract.py --tb=short
73+
timeout-minutes: 1
74+
75+
- name: Run Dependency Policy Suite
76+
run: |
77+
pytest -q tests/test_pipeline_dependency_policy.py --tb=short
78+
timeout-minutes: 1
79+
80+
- name: Run Outbound Payload Safety Suite
81+
run: |
82+
pytest -q tests/test_outbound_payload_safety.py --tb=short
83+
timeout-minutes: 1
84+
85+
- name: Summary
86+
if: success()
87+
run: |
88+
echo "✅ Phase 2 Python Gate Passed"
89+
echo "- Plugin security: PASS"
90+
echo "- Metadata contract: PASS"
91+
echo "- Dependency policy: PASS"
92+
echo "- Outbound payload safety: PASS"
93+
94+
phase2-e2e-gate:
95+
name: Phase 2 E2E Regression Tests
96+
runs-on: ubuntu-latest
97+
timeout-minutes: 10
98+
99+
steps:
100+
- name: Checkout code
101+
uses: actions/checkout@v4
102+
103+
- name: Set up Node.js 18
104+
uses: actions/setup-node@v4
105+
with:
106+
node-version: '18'
107+
cache: 'npm'
108+
109+
- name: Set up Python 3.10 (for HTTP server)
110+
uses: actions/setup-python@v5
111+
with:
112+
python-version: '3.10'
113+
114+
- name: Install npm dependencies
115+
run: npm ci
116+
117+
- name: Install Playwright browsers
118+
run: npx playwright install chromium --with-deps
119+
120+
- name: Run E2E tests
121+
run: npm test
122+
env:
123+
CI: true
124+
timeout-minutes: 8
125+
126+
- name: Upload test results
127+
if: failure()
128+
uses: actions/upload-artifact@v4
129+
with:
130+
name: playwright-report
131+
path: playwright-report/
132+
retention-days: 7
133+
134+
- name: Upload screenshots on failure
135+
if: failure()
136+
uses: actions/upload-artifact@v4
137+
with:
138+
name: playwright-screenshots
139+
path: test-results/
140+
retention-days: 7
141+
142+
- name: Summary
143+
if: success()
144+
run: |
145+
echo "✅ Phase 2 E2E Gate Passed"
146+
echo "- Preact loader: PASS"
147+
echo "- Settings UI: PASS"
148+
echo "- Statistics UI: PASS"
149+
echo "- Sidebar UI: PASS"
150+
151+
phase2-gate-complete:
152+
name: Phase 2 Gate Complete
153+
runs-on: ubuntu-latest
154+
needs: [phase2-python-gate, phase2-e2e-gate]
155+
if: always()
156+
157+
steps:
158+
- name: Check gate status
159+
run: |
160+
if [[ "${{ needs.phase2-python-gate.result }}" == "success" ]] && [[ "${{ needs.phase2-e2e-gate.result }}" == "success" ]]; then
161+
echo "✅ Phase 2 Release Gate: ALL CHECKS PASSED"
162+
echo ""
163+
echo "Security & Governance:"
164+
echo " ✅ Plugin security (10 tests)"
165+
echo " ✅ Metadata contract (1 test)"
166+
echo " ✅ Dependency policy (2 tests)"
167+
echo " ✅ Outbound payload safety (4 tests)"
168+
echo ""
169+
echo "Frontend Regression:"
170+
echo " ✅ E2E tests (61 tests)"
171+
echo ""
172+
echo "This change is safe to merge."
173+
exit 0
174+
else
175+
echo "❌ Phase 2 Release Gate: FAILED"
176+
echo ""
177+
echo "Python Gate: ${{ needs.phase2-python-gate.result }}"
178+
echo "E2E Gate: ${{ needs.phase2-e2e-gate.result }}"
179+
echo ""
180+
echo "Please fix the failing checks before merging."
181+
exit 1
182+
fi

README.md

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -767,6 +767,32 @@ And more...
767767

768768
---
769769

770+
## Phase 2 Release Gate
771+
772+
Before merging Phase 2 changes (pipeline, security, plugin hardening), all code must pass the **Phase 2 Release Gate**.
773+
774+
### Required Checks
775+
776+
- **Plugin security suite** (10 tests) - Allowlist, trust states, DoS limits
777+
- **Metadata contract suite** (1 test) - Schema validation
778+
- **Dependency policy suite** (2 tests) - Requires/provides enforcement
779+
- **Outbound payload safety suite** (4 tests) - Sanitization funnel
780+
- **E2E regression suite** (61 tests) - UI stability
781+
782+
### Run Locally
783+
784+
```bash
785+
# Full gate (Python + E2E)
786+
python scripts/phase2_gate.py
787+
788+
# Fast mode (Python only, < 2 minutes)
789+
python scripts/phase2_gate.py --fast
790+
```
791+
792+
**CI Status**: The gate runs automatically on push/PR to `main` and `dev` branches.
793+
794+
---
795+
770796
## Tips
771797

772798
1. **Pair with ComfyUI Manager**: Install missing custom nodes automatically

ROADMAP.md

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -419,11 +419,12 @@ graph TD
419419
- **Foundation for**: v2.0 advanced chat features, v3.0 multi-workspace features
420420
- **Design Reference**: See `.planning/ComfyUI-Doctor Architecture In-Depth Analysis and Optimization Blueprint.md`
421421
- [ ] **A5**: Create `LLMProvider` Protocol for unified LLM interface - 🟡 Medium ⚠️ *Use dev branch*
422-
- [ ] **A8**: Plugin Migration Tooling (Plan 6.3) - 🟡 Medium
422+
- [x] **A8**: Plugin Migration Tooling (Plan 6.3) - 🟡 Medium*Completed (2026-01-09)*
423423
- **Goal**: Reduce configuration friction for safe-by-default plugin policy (manifest + allowlist helpers; optional HMAC signer).
424-
- **Deliverables**: `scripts/plugin_manifest.py`, `scripts/plugin_allowlist.py`, optional `scripts/plugin_hmac_sign.py`
424+
- **Deliverables**: `scripts/plugin_manifest.py`, `scripts/plugin_allowlist.py`, `scripts/plugin_validator.py`, optional `scripts/plugin_hmac_sign.py`
425425
- **Acceptance**: Generate valid manifests + allowlist snippet in one command; safe defaults (`--dry-run`); never prints/writes secret keys.
426426
- **Plan Update Record**: `.planning/260109-PHASE2_CI_GATE_AND_MIGRATION_TOOLING_PLAN_UPDATE_RECORD.md`
427+
- **Implementation Record**: `.planning/260109-T11_T12_A8_IMPLEMENTATION_RECORD.md`
427428
- [ ] **A4**: Convert `NodeContext` to `@dataclass(frozen=True)` + validation - 🟡 Medium ⚠️ *Use dev branch*
428429
- [x] **A1**: Add `py.typed` marker + mypy config in pyproject.toml - 🟢 Low ✅ *Completed (Phase 3A)*
429430
- [x] **A2**: Integrate ruff linter (replace flake8/isort) - 🟢 Low ✅ *Completed (Phase 3A)*
@@ -433,17 +434,19 @@ graph TD
433434

434435
*Sorted by priority (High → Low), then by item number:*
435436

436-
- [ ] **T11**: Phase 2 Release Readiness CI Gate (Plan 6.1) - 🔴 High
437+
- [x] **T11**: Phase 2 Release Readiness CI Gate (Plan 6.1) - 🔴 High*Completed (2026-01-09)*
437438
- **Goal**: Make Phase 2 hardening non-regressable (required checks before merge/release).
438439
- **Gate**: `pytest -q tests/test_plugins_security.py`, `tests/test_metadata_contract.py`, `tests/test_pipeline_dependency_policy.py`, `tests/test_outbound_payload_safety.py`, plus `npm test`.
439440
- **Acceptance**: Branch protection requires the gate; stable runtime (< ~3 minutes typical).
440441
- **Plan Update Record**: `.planning/260109-PHASE2_CI_GATE_AND_MIGRATION_TOOLING_PLAN_UPDATE_RECORD.md`
442+
- **Implementation Record**: `.planning/260109-T11_T12_A8_IMPLEMENTATION_RECORD.md`
441443

442-
- [ ] **T12**: Outbound Funnel Static CI Gate (Plan 6.2) - 🟡 Medium
444+
- [x] **T12**: Outbound Funnel Static CI Gate (Plan 6.2) - 🟡 Medium*Completed (2026-01-09)*
443445
- **Goal**: Fail CI if new outbound call paths bypass `outbound.py` / `sanitize_outbound_payload(...)`.
444-
- **Approach**: Grep guard (fast) or AST scan (precise) to detect suspicious raw-field usage outside `outbound.py`.
446+
- **Approach**: AST-based checker (`scripts/check_outbound_safety.py`) + CI workflow (`.github/workflows/outbound-safety.yml`) + tests (`tests/test_outbound_safety_gate.py`) + docs (`docs/OUTBOUND_SAFETY.md`).
445447
- **Acceptance**: CI fails on bypass attempts; low false-positive rate.
446448
- **Plan Update Record**: `.planning/260109-PHASE2_CI_GATE_AND_MIGRATION_TOOLING_PLAN_UPDATE_RECORD.md`
449+
- **Implementation Record**: `.planning/260109-T11_T12_A8_IMPLEMENTATION_RECORD.md`
447450

448451
- [x] **T8**: Pattern Validation CI - 🟡 Medium ✅ *Completed (2026-01-03)*
449452
- **Problem**: Pattern format errors and i18n gaps can break the system

0 commit comments

Comments
 (0)