diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 96e92a8..1a93f1d 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -40,3 +40,54 @@ jobs: - name: Run tests run: python -m pytest -q + + static-analysis: + name: Static analysis + needs: test + runs-on: ubuntu-latest + timeout-minutes: 10 + + steps: + - name: Check out repository + uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 + with: + persist-credentials: false + + - name: Set up Python + uses: actions/setup-python@5fda3b95a4ea91299a34e894583c3862153e4b97 # v7.0.0 + with: + python-version: "3.11" + cache: pip + cache-dependency-path: pyproject.toml + + - name: Install development dependencies + run: python -m pip install -e ".[dev]" + + - name: Analyze project tools + run: | + mkdir -p reports/ci + securecode-analyzer src --format json \ + > reports/ci/static-analysis-src.json + securecode-analyzer tools --format json \ + > reports/ci/static-analysis-tools.json + + - name: Analyze controlled demo + shell: bash + run: | + set +e + securecode-analyzer sample_app --format json \ + > reports/ci/static-analysis-sample-app.json + status=$? + set -e + + if [ "$status" -ne 1 ]; then + echo "Expected demo scan exit code 1, received $status." + exit 1 + fi + + - name: Validate controlled demo findings + run: | + cmp \ + reports/ci/static-analysis-sample-app.json \ + reports/sample-app/static-analysis.json + python -m pytest tests/test_sample_app_security_demo.py -q diff --git a/.gitignore b/.gitignore index 0deca22..3cf2156 100644 --- a/.gitignore +++ b/.gitignore @@ -13,6 +13,7 @@ __pycache__/ .coverage .coverage.* htmlcov/ +reports/ci/ # Packaging artifacts build/ diff --git a/docs/ci.md b/docs/ci.md index 773b52a..f7bc404 100644 --- a/docs/ci.md +++ b/docs/ci.md @@ -1,20 +1,20 @@ # GitHub Actions CI -Bu doküman Backlog 5.1 kapsamındaki temel test pipeline'ının gereksinimlerini, -güvenlik sınırlarını ve çalışma sırasını açıklar. +Bu doküman Backlog 5.1 ve 5.2 kapsamındaki test ve statik analiz pipeline'ının +gereksinimlerini, güvenlik sınırlarını ve çalışma sırasını açıklar. ## Mevcut Durum -Temel GitHub Actions workflow'u tamamlanmıştır: +GitHub Actions test ve statik analiz workflow'u tamamlanmıştır: ```text .github/workflows/ci.yml ``` Workflow Pull Request değişikliklerinde ve `main` branch push olaylarında -Python 3.11 test paketini çalıştırır. Sıradaki aşama static analyzer, -dependency scanner ve report artifact adımlarının ayrı CI job'ları olarak -eklenmesidir. +Python 3.11 test paketini çalıştırır. Test gate'i geçtikten sonra proje +kaynaklarını ve kontrollü demo uygulamasını ayrı bir static-analysis job'unda +tarar. Sıradaki aşama dependency scanner ve report artifact job'larıdır. ## Trigger Sözleşmesi @@ -35,12 +35,12 @@ permissions: contents: read ``` -Checkout sonrasında credential persistence kapalıdır. Test job'u -`ubuntu-latest` runner üzerinde en fazla 10 dakika çalışır. Aynı workflow ve -Git ref için yeni bir run başladığında önceki run iptal edilir. +Checkout sonrasında credential persistence kapalıdır. Test ve statik analiz +job'ları `ubuntu-latest` runner üzerinde en fazla 10 dakika çalışır. Aynı +workflow ve Git ref için yeni bir run başladığında önceki run iptal edilir. -Bu foundation job secret, write permission, deployment environment veya -external service credential kullanmaz. +Bu job'lar secret, write permission, deployment environment veya external +service credential kullanmaz. ## Action Pinleri @@ -74,6 +74,34 @@ Job sırası: Install veya test komutlarından herhangi biri non-zero exit code üretirse job ve workflow başarısız olur. +## Statik Analiz Job Akışı + +`static-analysis` job'u test job'una `needs: test` ile bağlıdır. Başarılı test +sonrasında aynı sabit action SHA değerleri ve Python 3.11 ortamıyla çalışır. + +Job aşağıdaki raporları üretir: + +```text +reports/ci/static-analysis-src.json +reports/ci/static-analysis-tools.json +reports/ci/static-analysis-sample-app.json +``` + +`src` ve `tools` taramalarında herhangi bir bulgu CLI exit code `1` ürettiği +için job başarısız olur. Bu sıfır-bulgu politikası, proje planındaki yalnızca +yüksek önem seviyelerinde durma gereksiniminden daha katıdır. Statik analiz +modeli `INFO`, `WARNING` ve `ERROR` seviyelerini kullandığından `HIGH` ve +`CRITICAL` adları bu bileşene uygulanmaz. + +`sample_app` bilerek eklenmiş beş bulgu içerir. Bu taramanın exit code `1` +üretmesi beklenir ve hata olarak değerlendirilmez. Üretilen JSON, checked-in +`reports/sample-app/static-analysis.json` baseline'ı ile byte düzeyinde +karşılaştırılır; ardından kontrollü demo entegrasyon testleri çalıştırılır. +Exit code veya baseline değişirse job başarısız olur. + +Bu aşamada `reports/ci` yalnızca job workspace'inde tutulur. Artifact upload +Backlog 5.4 kapsamında eklenecektir. + ## Yerel Eşdeğer CI test adımını yerelde doğrulamak için: @@ -84,6 +112,22 @@ python -m pip install -e ".[dev]" python -m pytest -q ``` +Statik analiz adımlarını yerelde doğrulamak için: + +```powershell +New-Item -ItemType Directory -Force reports/ci +securecode-analyzer src --format json ` + > reports/ci/static-analysis-src.json +securecode-analyzer tools --format json ` + > reports/ci/static-analysis-tools.json +securecode-analyzer sample_app --format json ` + > reports/ci/static-analysis-sample-app.json +python -m pytest tests/test_sample_app_security_demo.py -q +``` + +Demo komutunun beklenen exit code değeri `1` olmalıdır. Üretilen demo JSON'u +checked-in baseline ile birebir aynı olmalıdır. + Workflow sözleşmesi de normal test paketi içindedir: ```powershell @@ -109,6 +153,9 @@ python -m pytest tests/test_python_compatibility.py -q - Python 3.11 ve pip cache yapılandırması - Pip upgrade, dev install ve pytest komut sırası - Ubuntu runner ve 10 dakikalık timeout +- Test job'una bağlı statik analiz job'u +- `src`, `tools` ve `sample_app` JSON rapor yolları +- Kontrollü demo exit code ve baseline doğrulaması `tests/test_python_compatibility.py`, `src`, `sample_app`, `tools` ve `tests` altındaki bütün Python dosyalarını desteklenen en düşük sürüm olan Python @@ -118,23 +165,20 @@ geçen Python 3.12+ söz dizimi değişiklikleri CI'a ulaşmadan tespit edilir. Doğrulanan mevcut sonuç: ```text -CI workflow contract tests: 7 passed +CI workflow contract tests: 10 passed Python 3.11 compatibility tests: 1 passed -Complete test suite: 985 passed +Complete test suite: 988 passed Workflow YAML parse check: passed ``` ## Sonraki Güvenlik Job'ları -Bu foundation PR yalnızca Backlog 5.1'i tamamlar. Sonraki aşamalar: +Backlog 5.1 ve 5.2 tamamlanmıştır. Sonraki aşamalar: -1. `src` ve `tools` için sıfır-bulgu static self-analysis gate'i -2. `sample_app` için beklenen beş bulguyu drift testiyle doğrulama -3. Offline OSV fixture-backed dependency scan gate'i -4. Static ve dependency JSON raporlarını workflow artifact olarak yükleme +1. Offline OSV fixture-backed dependency scan gate'i +2. Static ve dependency JSON raporlarını workflow artifact olarak yükleme -Bu ayrım temel test workflow'unun ilk gerçek GitHub run sonucunu bağımsız -olarak incelemeyi sağlar. +Bu ayrım her güvenlik gate'inin davranışını bağımsız olarak incelemeyi sağlar. ## Navigation diff --git a/docs/components/sample-web-app/README.md b/docs/components/sample-web-app/README.md index 693e7ce..b6e6000 100644 --- a/docs/components/sample-web-app/README.md +++ b/docs/components/sample-web-app/README.md @@ -60,9 +60,9 @@ Mevcut özellikler: * Ayrı ve runtime dışı vulnerable dependency fixture'ı * Portable static-analysis ve dependency-scan JSON baseline'ları * Offline report generator ve drift check -* Pull Request ve `main` push için temel pytest CI workflow'u +* Pull Request ve `main` push için pytest ve statik analiz CI job'ları -Sıradaki aşama analyzer, dependency scanner ve report artifact CI job'larıdır. +Sıradaki aşama dependency scanner ve report artifact CI job'larıdır. ## Kurulum @@ -547,10 +547,10 @@ New update/delete test cases: 54 passed New frontend test cases: 18 passed New security demo test cases: 4 passed New integration report test cases: 6 passed -New CI workflow test cases: 7 passed +New CI workflow test cases: 10 passed New Python 3.11 compatibility test cases: 1 passed Sample app targeted suite: 149 passed -Complete test suite: 985 passed +Complete test suite: 988 passed Compile check: passed Sample app analysis: 5 expected findings Analyzer source self-analysis: no findings diff --git a/tests/test_ci_workflow.py b/tests/test_ci_workflow.py index 622c715..b903c10 100644 --- a/tests/test_ci_workflow.py +++ b/tests/test_ci_workflow.py @@ -123,3 +123,74 @@ def test_test_job_has_bounded_ubuntu_execution() -> None: assert "runs-on: ubuntu-latest" in workflow assert "timeout-minutes: 10" in workflow + + +def test_static_analysis_job_waits_for_tests() -> None: + """Security analysis should run only after the test gate passes.""" + + workflow = _workflow_text() + + assert ( + " static-analysis:\n" + " name: Static analysis\n" + " needs: test\n" + " runs-on: ubuntu-latest\n" + " timeout-minutes: 10\n" + ) in workflow + assert workflow.count("persist-credentials: false") == 2 + assert workflow.count('python-version: "3.11"') == 2 + assert workflow.count("actions/checkout@") == 2 + assert workflow.count("actions/setup-python@") == 2 + + +def test_static_analysis_job_writes_project_json_reports() -> None: + """Project sources should produce separate machine-readable reports.""" + + workflow = _workflow_text() + + assert "mkdir -p reports/ci" in workflow + assert ( + "securecode-analyzer src --format json" + in workflow + ) + assert ( + "> reports/ci/static-analysis-src.json" + in workflow + ) + assert ( + "securecode-analyzer tools --format json" + in workflow + ) + assert ( + "> reports/ci/static-analysis-tools.json" + in workflow + ) + + +def test_static_analysis_job_validates_controlled_demo() -> None: + """Known demo findings should be reported without breaking the gate.""" + + workflow = _workflow_text() + + assert ( + "securecode-analyzer sample_app --format json" + in workflow + ) + assert ( + "> reports/ci/static-analysis-sample-app.json" + in workflow + ) + assert 'if [ "$status" -ne 1 ]; then' in workflow + assert ( + "reports/ci/static-analysis-sample-app.json" + in workflow + ) + assert ( + "reports/sample-app/static-analysis.json" + in workflow + ) + assert ( + "python -m pytest " + "tests/test_sample_app_security_demo.py -q" + in workflow + )