Skip to content

chore(deps): bump actions/checkout from 4 to 6 #82

chore(deps): bump actions/checkout from 4 to 6

chore(deps): bump actions/checkout from 4 to 6 #82

Workflow file for this run

name: CI
on:
push:
branches: ["**"]
pull_request:
branches: [main]
concurrency:
group: ci-${{ github.ref }}
cancel-in-progress: true
env:
PYTHON_VERSION: "3.11"
IMAGE_NAME: bessai-edge-gateway
jobs:
# ─────────────────────────────────────────────────────────────────
# Job 1: Lint
# ─────────────────────────────────────────────────────────────────
lint:
name: Lint (ruff)
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v6
- uses: actions/setup-python@v5
with:
python-version: ${{ env.PYTHON_VERSION }}
cache: pip
- name: Install ruff
run: pip install ruff
- name: Run ruff check
run: ruff check src/ tests/
- name: Run ruff format check
run: ruff format --check src/ tests/
# ─────────────────────────────────────────────────────────────────
# Job 2: Type check
# ─────────────────────────────────────────────────────────────────
typecheck:
name: Type check (mypy)
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v6
- uses: actions/setup-python@v5
with:
python-version: ${{ env.PYTHON_VERSION }}
cache: pip
- name: Install dependencies
run: pip install -r requirements.txt -r requirements-dev.txt
- name: Run mypy
run: mypy src/ --ignore-missing-imports --no-error-summary
# ─────────────────────────────────────────────────────────────────
# Job 3: Unit tests
# ─────────────────────────────────────────────────────────────────
test:
name: Tests (pytest)
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v6
- uses: actions/setup-python@v5
with:
python-version: ${{ env.PYTHON_VERSION }}
cache: pip
- name: Install dependencies
run: pip install -r requirements.txt -r requirements-dev.txt
- name: Run tests with coverage
run: |
pytest tests/ -v --tb=short \
--cov=src \
--cov-report=xml \
--cov-report=term-missing \
--cov-fail-under=70
- name: Upload coverage to Codecov
if: always()
uses: codecov/codecov-action@v4
with:
file: coverage.xml
flags: unittests
fail_ci_if_error: false
# ─────────────────────────────────────────────────────────────────
# Job 4: Interoperability Contract Tests (BESSAI-SPEC-001 Category A)
# No hardware needed — uses SimulatorDriver
# ─────────────────────────────────────────────────────────────────
interop:
name: Interop Contract Tests (BESSAI-SPEC-001)
runs-on: ubuntu-latest
needs: [test]
steps:
- uses: actions/checkout@v6
- uses: actions/setup-python@v5
with:
python-version: ${{ env.PYTHON_VERSION }}
cache: pip
- name: Install dependencies
run: pip install -r requirements.txt -r requirements-dev.txt
- name: Run BESSAI-SPEC-001 Category A contract tests
env:
SITE_ID: CI-INTEROP-TEST
INVERTER_IP: "127.0.0.1"
run: |
pytest tests/interop/test_driver_contract.py \
-v --tb=short \
-m "not slow" \
--junit-xml=interop-results.xml
- name: Upload interop test results
if: always()
uses: actions/upload-artifact@v4
with:
name: interop-test-results
path: interop-results.xml
# ─────────────────────────────────────────────────────────────────
# Job 5: Security — SAST + Dependency audit
# ─────────────────────────────────────────────────────────────────
security:
name: Security (bandit + pip-audit)
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v6
- uses: actions/setup-python@v5
with:
python-version: ${{ env.PYTHON_VERSION }}
cache: pip
- name: Install security tools
run: pip install bandit pip-audit
- name: Run bandit SAST
run: |
bandit -r src/ \
--severity-level medium \
--confidence-level medium \
--format json \
--output bandit-report.json || true
bandit -r src/ \
--severity-level medium \
--confidence-level medium \
--exit-zero
- name: Upload bandit report
if: always()
uses: actions/upload-artifact@v4
with:
name: bandit-report
path: bandit-report.json
- name: Run pip-audit (dependency vulnerability scan)
run: |
pip-audit \
--requirement requirements.txt \
--format json \
--output pip-audit-report.json || true
pip-audit \
--requirement requirements.txt \
--ignore-vuln PYSEC-2022-42969
- name: Upload pip-audit report
if: always()
uses: actions/upload-artifact@v4
with:
name: pip-audit-report
path: pip-audit-report.json
# ─────────────────────────────────────────────────────────────────
# Job 5: Terraform validate (no GCP credentials needed)
# ─────────────────────────────────────────────────────────────────
terraform-validate:
name: Terraform validate
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v6
- name: Setup Terraform
uses: hashicorp/setup-terraform@v3
with:
terraform_version: "~> 1.7"
- name: Terraform init (local backend only)
run: terraform -chdir=infrastructure/terraform init -backend=false
- name: Terraform validate
run: terraform -chdir=infrastructure/terraform validate
- name: Terraform fmt check
run: terraform -chdir=infrastructure/terraform fmt -check -recursive
# ─────────────────────────────────────────────────────────────────
# Job 6: Helm lint & template validation
# ─────────────────────────────────────────────────────────────────
helm-lint:
name: Helm lint & template
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v6
- name: Set up Helm
uses: azure/setup-helm@v4
with:
version: "3.14.0"
- name: Helm lint
run: helm lint infrastructure/helm/bessai-edge/
- name: Helm template dry-run
run: |
helm template bessai-test infrastructure/helm/bessai-edge/ \
--set config.inverterIp=10.0.1.50 \
--set config.siteId=CI-TEST \
| head -60
# ─────────────────────────────────────────────────────────────────
# Job 7: Docker build (validates the image builds correctly)
# ─────────────────────────────────────────────────────────────────
docker-build:
name: Docker build
runs-on: ubuntu-latest
needs: [lint, test]
outputs:
image-digest: ${{ steps.build.outputs.digest }}
steps:
- uses: actions/checkout@v6
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
- name: Build image (no push)
id: build
uses: docker/build-push-action@v5
with:
context: .
file: infrastructure/docker/Dockerfile
platforms: linux/amd64,linux/arm64
push: false
tags: ${{ env.IMAGE_NAME }}:${{ github.sha }}
cache-from: type=gha
cache-to: type=gha,mode=max
# ─────────────────────────────────────────────────────────────────
# Job 8: Trivy container security scan
# ─────────────────────────────────────────────────────────────────
trivy:
name: Container scan (Trivy)
runs-on: ubuntu-latest
needs: [docker-build]
permissions:
security-events: write # Required to upload SARIF to GitHub Security tab
steps:
- uses: actions/checkout@v6
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
- name: Build image for scanning
uses: docker/build-push-action@v5
with:
context: .
file: infrastructure/docker/Dockerfile
platforms: linux/amd64
push: false
load: true
tags: ${{ env.IMAGE_NAME }}:scan
cache-from: type=gha
- name: Run Trivy vulnerability scanner
uses: aquasecurity/trivy-action@master
with:
image-ref: "${{ env.IMAGE_NAME }}:scan"
format: "sarif"
output: "trivy-results.sarif"
severity: "CRITICAL,HIGH"
exit-code: "0" # Don't fail CI — upload results for visibility
- name: Upload Trivy scan results to GitHub Security tab
uses: github/codeql-action/upload-sarif@v4
if: always()
with:
sarif_file: "trivy-results.sarif"
category: "trivy-container"
# ─────────────────────────────────────────────────────────────────
# Job 9: Push to GCP Artifact Registry (only on main)
# ─────────────────────────────────────────────────────────────────
docker-push:
name: Push to Artifact Registry
runs-on: ubuntu-latest
needs: [docker-build, security, trivy]
if: github.ref == 'refs/heads/main' && github.event_name == 'push'
permissions:
contents: read
id-token: write # Required for Workload Identity Federation
steps:
- uses: actions/checkout@v6
- name: Authenticate to Google Cloud
uses: google-github-actions/auth@v2
with:
workload_identity_provider: ${{ secrets.GCP_WORKLOAD_IDENTITY_PROVIDER }}
service_account: ${{ secrets.GCP_SERVICE_ACCOUNT }}
- name: Configure Docker for Artifact Registry
run: gcloud auth configure-docker ${{ secrets.GCP_REGION }}-docker.pkg.dev --quiet
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
- name: Build and push
uses: docker/build-push-action@v5
with:
context: .
file: infrastructure/docker/Dockerfile
platforms: linux/amd64,linux/arm64
push: true
tags: |
${{ secrets.GCP_REGION }}-docker.pkg.dev/${{ secrets.GCP_PROJECT_ID }}/bessai/${{ env.IMAGE_NAME }}:latest
${{ secrets.GCP_REGION }}-docker.pkg.dev/${{ secrets.GCP_PROJECT_ID }}/bessai/${{ env.IMAGE_NAME }}:${{ github.sha }}
cache-from: type=gha
cache-to: type=gha,mode=max