Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
99 changes: 37 additions & 62 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ env:
NODE_VERSION: '18'
REGISTRY: ghcr.io
IMAGE_NAME: ${{ github.repository }}
FORCE_JAVASCRIPT_ACTIONS_TO_NODE24: 'true'

jobs:
# Code Quality and Security Checks
Expand All @@ -33,20 +34,19 @@ jobs:
- name: Install dependencies
run: |
python -m pip install --upgrade pip
pip install -r requirements.txt
pip install black flake8 mypy bandit safety
pip install black flake8 bandit safety

- name: Code formatting check (Black)
run: black --check --diff src/ tests/
run: black --check --diff wifi_densepose/

- name: Linting (Flake8)
run: flake8 src/ tests/ --max-line-length=88 --extend-ignore=E203,W503
run: flake8 wifi_densepose/ --max-line-length=88 --extend-ignore=E203,W503

- name: Type checking (MyPy)
run: mypy src/ --ignore-missing-imports
- name: Syntax check
run: python -m compileall wifi_densepose/

- name: Security scan (Bandit)
run: bandit -r src/ -f json -o bandit-report.json
run: bandit -r wifi_densepose/ -f json -o bandit-report.json
continue-on-error: true

- name: Dependency vulnerability scan (Safety)
Expand All @@ -73,6 +73,18 @@ jobs:
- name: Install Rust toolchain
uses: dtolnay/rust-toolchain@stable

- name: Install system packages
run: |
sudo apt-get update
sudo apt-get install -y --no-install-recommends \
pkg-config \
libglib2.0-dev \
libgtk-3-dev \
libjavascriptcoregtk-4.1-dev \
libsoup-3.0-dev \
libudev-dev \
libwebkit2gtk-4.1-dev

- name: Cache cargo
uses: actions/cache@v4
with:
Expand All @@ -88,36 +100,13 @@ jobs:
working-directory: rust-port/wifi-densepose-rs
run: cargo test --workspace --no-default-features

# Unit and Integration Tests
# Cross-version smoke tests
test:
name: Tests
runs-on: ubuntu-latest
strategy:
matrix:
python-version: ['3.10', '3.11', '3.12']
services:
postgres:
image: postgres:15
env:
POSTGRES_PASSWORD: postgres
POSTGRES_DB: test_wifi_densepose
options: >-
--health-cmd pg_isready
--health-interval 10s
--health-timeout 5s
--health-retries 5
ports:
- 5432:5432

redis:
image: redis:7
options: >-
--health-cmd "redis-cli ping"
--health-interval 10s
--health-timeout 5s
--health-retries 5
ports:
- 6379:6379

steps:
- name: Checkout code
Expand All @@ -129,44 +118,31 @@ jobs:
python-version: ${{ matrix.python-version }}
cache: 'pip'

- name: Install dependencies
- name: Prepare test environment
run: |
python -m pip install --upgrade pip
pip install -r requirements.txt
pip install pytest-cov pytest-xdist

- name: Run unit tests
env:
DATABASE_URL: postgresql://postgres:postgres@localhost:5432/test_wifi_densepose
REDIS_URL: redis://localhost:6379/0
ENVIRONMENT: test
- name: Compile package
run: |
pytest tests/unit/ -v --cov=src --cov-report=xml --cov-report=html --junitxml=junit.xml
python -m compileall wifi_densepose/

- name: Run integration tests
env:
DATABASE_URL: postgresql://postgres:postgres@localhost:5432/test_wifi_densepose
REDIS_URL: redis://localhost:6379/0
ENVIRONMENT: test
- name: Import package smoke test
run: |
pytest tests/integration/ -v --junitxml=integration-junit.xml
python - <<'PY'
import wifi_densepose
print(wifi_densepose.__version__)
PY

- name: Upload coverage reports
uses: codecov/codecov-action@v4
with:
file: ./coverage.xml
flags: unittests
name: codecov-umbrella
- name: Docker entrypoint regression test
run: bash tests/test_docker_entrypoint.sh

- name: Upload test results
uses: actions/upload-artifact@v4
if: always()
with:
name: test-results-${{ matrix.python-version }}
path: |
junit.xml
integration-junit.xml
htmlcov/
tests/test_docker_entrypoint.sh

# Performance and Load Tests
performance-test:
Expand Down Expand Up @@ -210,6 +186,7 @@ jobs:
name: Docker Build & Test
runs-on: ubuntu-latest
needs: [code-quality, test, rust-tests]
if: github.event_name == 'pull_request' || github.ref == 'refs/heads/main' || github.ref == 'refs/heads/develop' || startsWith(github.ref, 'refs/heads/feature/') || startsWith(github.ref, 'refs/heads/feat/') || startsWith(github.ref, 'refs/heads/hotfix/')
steps:
- name: Checkout code
uses: actions/checkout@v4
Expand Down Expand Up @@ -310,26 +287,24 @@ jobs:
runs-on: ubuntu-latest
needs: [code-quality, test, rust-tests, performance-test, docker-build, docs]
if: always()
env:
SLACK_WEBHOOK_URL: ${{ secrets.SLACK_WEBHOOK_URL }}
steps:
- name: Notify Slack on success
if: ${{ secrets.SLACK_WEBHOOK_URL != '' && needs.code-quality.result == 'success' && needs.test.result == 'success' && needs.docker-build.result == 'success' }}
if: ${{ env.SLACK_WEBHOOK_URL != '' && needs.code-quality.result == 'success' && needs.test.result == 'success' && needs.docker-build.result == 'success' }}
uses: 8398a7/action-slack@v3
with:
status: success
channel: '#ci-cd'
text: '✅ CI pipeline completed successfully for ${{ github.ref }}'
env:
SLACK_WEBHOOK_URL: ${{ secrets.SLACK_WEBHOOK_URL }}

- name: Notify Slack on failure
if: ${{ secrets.SLACK_WEBHOOK_URL != '' && (needs.code-quality.result == 'failure' || needs.test.result == 'failure' || needs.docker-build.result == 'failure') }}
if: ${{ env.SLACK_WEBHOOK_URL != '' && (needs.code-quality.result == 'failure' || needs.test.result == 'failure' || needs.docker-build.result == 'failure') }}
uses: 8398a7/action-slack@v3
with:
status: failure
channel: '#ci-cd'
text: '❌ CI pipeline failed for ${{ github.ref }}'
env:
SLACK_WEBHOOK_URL: ${{ secrets.SLACK_WEBHOOK_URL }}

- name: Create GitHub Release
if: github.ref == 'refs/heads/main' && needs.docker-build.result == 'success'
Expand All @@ -346,4 +321,4 @@ jobs:
**Docker Image:**
`${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:${{ github.sha }}`
draft: false
prerelease: false
prerelease: false
66 changes: 35 additions & 31 deletions .github/workflows/security-scan.yml
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ on:

env:
PYTHON_VERSION: '3.11'
FORCE_JAVASCRIPT_ACTIONS_TO_NODE24: 'true'

jobs:
# Static Application Security Testing (SAST)
Expand All @@ -37,41 +38,36 @@ jobs:
- name: Install dependencies
run: |
python -m pip install --upgrade pip
pip install -r requirements.txt
pip install bandit semgrep safety
pip install bandit semgrep

- name: Run Bandit security scan
run: |
bandit -r src/ -f sarif -o bandit-results.sarif
bandit -r wifi_densepose scripts examples -f sarif -o bandit-results.sarif
continue-on-error: true

- name: Upload Bandit results to GitHub Security
uses: github/codeql-action/upload-sarif@v3
if: always()
if: ${{ always() && hashFiles('bandit-results.sarif') != '' }}
with:
sarif_file: bandit-results.sarif
category: bandit

- name: Run Semgrep security scan
uses: returntocorp/semgrep-action@v1
with:
config: >-
p/security-audit
p/secrets
p/python
p/docker
p/kubernetes
env:
SEMGREP_APP_TOKEN: ${{ secrets.SEMGREP_APP_TOKEN }}

- name: Generate Semgrep SARIF
run: |
semgrep --config=p/security-audit --config=p/secrets --config=p/python --sarif --output=semgrep.sarif src/
semgrep scan \
--config=p/security-audit \
--config=p/secrets \
--config=p/python \
--config=p/docker \
--config=p/kubernetes \
--sarif \
--output=semgrep.sarif \
wifi_densepose scripts examples
continue-on-error: true

- name: Upload Semgrep results to GitHub Security
uses: github/codeql-action/upload-sarif@v3
if: always()
if: ${{ always() && hashFiles('semgrep.sarif') != '' }}
with:
sarif_file: semgrep.sarif
category: semgrep
Expand All @@ -80,6 +76,8 @@ jobs:
dependency-scan:
name: Dependency Vulnerability Scan
runs-on: ubuntu-latest
env:
SNYK_TOKEN: ${{ secrets.SNYK_TOKEN }}
permissions:
security-events: write
actions: read
Expand Down Expand Up @@ -112,15 +110,16 @@ jobs:

- name: Run Snyk vulnerability scan
uses: snyk/actions/python@master
if: ${{ env.SNYK_TOKEN != '' }}
env:
SNYK_TOKEN: ${{ secrets.SNYK_TOKEN }}
SNYK_TOKEN: ${{ env.SNYK_TOKEN }}
with:
args: --sarif-file-output=snyk-results.sarif
continue-on-error: true

- name: Upload Snyk results to GitHub Security
uses: github/codeql-action/upload-sarif@v3
if: always()
if: ${{ always() && hashFiles('snyk-results.sarif') != '' }}
with:
sarif_file: snyk-results.sarif
category: snyk
Expand Down Expand Up @@ -252,6 +251,7 @@ jobs:
path: '.'
output_path: kics-results
output_formats: 'sarif'
ignore_on_exit: results
exclude_paths: '.git,node_modules'
exclude_queries: 'a7ef1e8c-fbf8-4ac1-b8c7-2c3b0e6c6c6c'

Expand Down Expand Up @@ -285,16 +285,9 @@ jobs:
extra_args: --debug --only-verified

- name: Run GitLeaks secret scan
uses: gitleaks/gitleaks-action@v2
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
GITLEAKS_LICENSE: ${{ secrets.GITLEAKS_LICENSE }}

- name: Run detect-secrets
run: |
pip install detect-secrets
detect-secrets scan --all-files --baseline .secrets.baseline
detect-secrets audit .secrets.baseline
continue-on-error: true

# License compliance scanning
Expand Down Expand Up @@ -356,7 +349,16 @@ jobs:
- name: Check for security headers in code
run: |
# Check for security-related configurations
grep -r "X-Frame-Options\|X-Content-Type-Options\|X-XSS-Protection\|Content-Security-Policy" src/ || echo "⚠️ Consider adding security headers"
scan_paths=()
[[ -d "wifi_densepose" ]] && scan_paths+=("wifi_densepose")
[[ -d "v1/src" ]] && scan_paths+=("v1/src")
if [[ ${#scan_paths[@]} -eq 0 ]]; then
echo "ℹ️ No Python source directories found — skipping header scan"
elif grep -r "X-Frame-Options\|X-Content-Type-Options\|X-XSS-Protection\|Content-Security-Policy" "${scan_paths[@]}"; then
echo "✅ Security-related headers/configuration found"
else
echo "⚠️ Consider adding security headers"
fi

- name: Validate Kubernetes security contexts
run: |
Expand All @@ -377,6 +379,8 @@ jobs:
runs-on: ubuntu-latest
needs: [sast, dependency-scan, container-scan, iac-scan, secret-scan, license-scan, compliance-check]
if: always()
env:
SECURITY_SLACK_WEBHOOK_URL: ${{ secrets.SECURITY_SLACK_WEBHOOK_URL }}
steps:
- name: Download all artifacts
uses: actions/download-artifact@v4
Expand All @@ -403,7 +407,7 @@ jobs:
path: security-summary.md

- name: Notify security team on critical findings
if: ${{ secrets.SECURITY_SLACK_WEBHOOK_URL != '' && (needs.sast.result == 'failure' || needs.dependency-scan.result == 'failure' || needs.container-scan.result == 'failure') }}
if: ${{ env.SECURITY_SLACK_WEBHOOK_URL != '' && (needs.sast.result == 'failure' || needs.dependency-scan.result == 'failure' || needs.container-scan.result == 'failure') }}
uses: 8398a7/action-slack@v3
with:
status: failure
Expand All @@ -415,7 +419,7 @@ jobs:
Workflow: ${{ github.workflow }}
Please review the security scan results immediately.
env:
SLACK_WEBHOOK_URL: ${{ secrets.SECURITY_SLACK_WEBHOOK_URL }}
SLACK_WEBHOOK_URL: ${{ env.SECURITY_SLACK_WEBHOOK_URL }}

- name: Create security issue on critical findings
if: needs.sast.result == 'failure' || needs.dependency-scan.result == 'failure'
Expand Down Expand Up @@ -446,4 +450,4 @@ jobs:
**Security Dashboard:** Check the Security tab for detailed findings.
`,
labels: ['security', 'vulnerability', 'urgent']
})
})
24 changes: 24 additions & 0 deletions SECURITY.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
# Security Policy

## Reporting a Vulnerability

Please do not open a public issue for suspected security vulnerabilities.

Send a private report with:

- a clear description of the issue
- affected files, commands, or deployment paths
- reproduction steps or proof of concept
- impact assessment and suggested remediation, if available

Use GitHub Security Advisories when possible, or contact the maintainers through the repository owner profile so the issue can be triaged privately first.

## Response Expectations

- We will acknowledge valid reports as soon as practical.
- We will investigate, reproduce, and scope the impact.
- We will coordinate a fix and disclosure timeline based on severity.

## Supported Versions

Security fixes are applied to the active default branch first. Older snapshots, experimental branches, and archived artifacts may not receive backports.
Loading