Skip to content

build(deps-dev): bump pygments from 2.19.2 to 2.20.0 #38

build(deps-dev): bump pygments from 2.19.2 to 2.20.0

build(deps-dev): bump pygments from 2.19.2 to 2.20.0 #38

Workflow file for this run

# SkyLink CI/CD Pipeline
# See docs/GITHUB_CI_SETUP.md for configuration instructions
name: SkyLink CI/CD
on:
push:
branches: [main, master, develop]
pull_request:
branches: [main, master]
release:
types: [published]
env:
REGISTRY: ghcr.io
IMAGE_NAME: ${{ github.repository }}
PYTHON_VERSION: "3.12"
jobs:
# ============================================
# LINT
# ============================================
lint:
name: Lint & Security Check
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Set up Python
uses: actions/setup-python@v5
with:
python-version: ${{ env.PYTHON_VERSION }}
- name: Install linters
run: pip install ruff black bandit
- name: Run Ruff
run: ruff check .
- name: Run Black
run: black --check .
- name: Run Bandit
run: bandit -r skylink -q --severity-level high
# ============================================
# TEST
# ============================================
test:
name: Unit Tests
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Set up Python
uses: actions/setup-python@v5
with:
python-version: ${{ env.PYTHON_VERSION }}
- name: Install Poetry
uses: snok/install-poetry@v1
with:
virtualenvs-create: true
virtualenvs-in-project: true
- name: Cache dependencies
uses: actions/cache@v4
with:
path: .venv
key: venv-${{ runner.os }}-${{ hashFiles('**/poetry.lock') }}
- name: Install dependencies
run: poetry install --no-interaction
- name: Generate test certificates
run: |
chmod +x scripts/generate_test_certs.sh
./scripts/generate_test_certs.sh || echo "Certificate generation skipped"
- name: Run tests
env:
PRIVATE_KEY_PEM: ${{ secrets.PRIVATE_KEY_PEM }}
PUBLIC_KEY_PEM: ${{ secrets.PUBLIC_KEY_PEM }}
run: |
poetry run pytest -q \
--junitxml=report.xml \
--cov=skylink \
--cov-report=xml \
--cov-report=term-missing \
--cov-fail-under=75
- name: Upload coverage to Codecov
uses: codecov/codecov-action@v4
with:
files: coverage.xml
fail_ci_if_error: false
- name: Upload test results
uses: actions/upload-artifact@v4
if: always()
with:
name: test-results
path: report.xml
# ============================================
# SECRET SCANNING (Gitleaks)
# ============================================
gitleaks:
name: Secret Scanning
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Run Gitleaks
uses: gitleaks/gitleaks-action@v2
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
# ============================================
# SCA (Dependency Audit)
# ============================================
sca:
name: Dependency Audit
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Set up Python
uses: actions/setup-python@v5
with:
python-version: ${{ env.PYTHON_VERSION }}
- name: Install Poetry and pip-audit
run: |
pip install poetry pip-audit poetry-plugin-export
poetry self add poetry-plugin-export || true
- name: Export requirements
run: poetry export -f requirements.txt --only main --without-hashes -o requirements.txt
- name: Run pip-audit
run: pip-audit -r requirements.txt --strict
# ============================================
# OPENAPI VALIDATION
# ============================================
openapi:
name: OpenAPI Validation
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Validate OpenAPI specs
run: |
docker run --rm -v ${{ github.workspace }}:/local \
openapitools/openapi-generator-cli:latest validate \
-i /local/openapi/gateway.yaml
# ============================================
# BUILD & PUSH
# ============================================
build:
name: Build & Push Image
runs-on: ubuntu-latest
needs: [lint, test, gitleaks, sca]
permissions:
contents: read
packages: write
outputs:
image_tag: ${{ steps.short_sha.outputs.sha }}
steps:
- uses: actions/checkout@v4
- name: Get short SHA
id: short_sha
run: echo "sha=$(echo ${{ github.sha }} | cut -c1-7)" >> $GITHUB_OUTPUT
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
- name: Log in to Container Registry
uses: docker/login-action@v3
with:
registry: ${{ env.REGISTRY }}
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Extract metadata
id: meta
uses: docker/metadata-action@v5
with:
images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}
tags: |
type=sha,prefix=
type=ref,event=branch
type=semver,pattern={{version}}
type=raw,value=latest,enable={{is_default_branch}}
- name: Build and push
id: build
uses: docker/build-push-action@v5
with:
context: .
file: ./Dockerfile.gateway
push: true
tags: ${{ steps.meta.outputs.tags }}
labels: ${{ steps.meta.outputs.labels }}
cache-from: type=gha
cache-to: type=gha,mode=max
# ============================================
# TRIVY SCAN
# ============================================
trivy:
name: Container Scan (Trivy)
runs-on: ubuntu-latest
needs: [build]
permissions:
contents: read
packages: read
continue-on-error: true
steps:
- uses: actions/checkout@v4
- name: Log in to Container Registry
uses: docker/login-action@v3
with:
registry: ${{ env.REGISTRY }}
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Pull image
run: docker pull ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:${{ needs.build.outputs.image_tag }}
- name: Run Trivy vulnerability scanner
uses: aquasecurity/trivy-action@master
with:
image-ref: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:${{ needs.build.outputs.image_tag }}
format: 'table'
severity: 'HIGH,CRITICAL'
exit-code: '0'
# ============================================
# SBOM
# ============================================
sbom:
name: Generate SBOM
runs-on: ubuntu-latest
needs: [test]
steps:
- uses: actions/checkout@v4
- name: Set up Python
uses: actions/setup-python@v5
with:
python-version: ${{ env.PYTHON_VERSION }}
- name: Install tools
run: |
pip install poetry cyclonedx-bom poetry-plugin-export
poetry self add poetry-plugin-export || true
- name: Export requirements
run: poetry export -f requirements.txt --without-hashes -o requirements.txt
- name: Generate SBOM
run: python -m cyclonedx_py requirements -i requirements.txt -o sbom.json
- name: Upload SBOM
uses: actions/upload-artifact@v4
with:
name: sbom
path: sbom.json
# ============================================
# DAST (ZAP Scan)
# ============================================
zap:
name: DAST (ZAP Scan)
runs-on: ubuntu-latest
needs: [build]
permissions:
contents: read
packages: read
continue-on-error: true
steps:
- uses: actions/checkout@v4
- name: Log in to Container Registry
uses: docker/login-action@v3
with:
registry: ${{ env.REGISTRY }}
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Pull and start application
run: |
docker pull ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:${{ needs.build.outputs.image_tag }}
docker run -d --name skylink -p 8000:8000 \
-e DEMO_MODE=true \
${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:${{ needs.build.outputs.image_tag }}
# Wait for app to be ready
echo "Waiting for application to start..."
for i in {1..30}; do
if curl -sf http://localhost:8000/health > /dev/null 2>&1; then
echo "Application is ready!"
break
fi
echo "Waiting for application... ($i/30)"
sleep 2
done
# Final check
curl -sf http://localhost:8000/health || (docker logs skylink && exit 1)
- name: Run ZAP Baseline Scan
run: |
docker run --rm --network host \
-v ${{ github.workspace }}:/zap/wrk:rw \
ghcr.io/zaproxy/zaproxy:stable \
zap-baseline.py -t http://localhost:8000 \
-r zap-report.html -I || true
- name: Upload ZAP Report
uses: actions/upload-artifact@v4
if: always()
with:
name: zap-report
path: zap-report.html
if-no-files-found: ignore
- name: Stop application
if: always()
run: docker stop skylink || true
# ============================================
# SIGN IMAGE (Cosign)
# ============================================
sign:
name: Sign Image
runs-on: ubuntu-latest
needs: [build, trivy]
if: github.event_name != 'pull_request'
permissions:
contents: read
packages: write
id-token: write
steps:
- uses: actions/checkout@v4
- name: Install Cosign
uses: sigstore/cosign-installer@v3
- name: Log in to Container Registry
uses: docker/login-action@v3
with:
registry: ${{ env.REGISTRY }}
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Sign image with keyless signing (Sigstore)
run: |
cosign sign --yes \
${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:${{ needs.build.outputs.image_tag }}
# ============================================
# ATTEST SBOM
# ============================================
attest:
name: Attest SBOM
runs-on: ubuntu-latest
needs: [build, sign, sbom]
if: github.event_name != 'pull_request'
permissions:
contents: read
packages: write
id-token: write
steps:
- uses: actions/checkout@v4
- name: Install Cosign
uses: sigstore/cosign-installer@v3
- name: Download SBOM
uses: actions/download-artifact@v4
with:
name: sbom
- name: Log in to Container Registry
uses: docker/login-action@v3
with:
registry: ${{ env.REGISTRY }}
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Attest SBOM with keyless signing
run: |
cosign attest --yes \
--predicate sbom.json --type cyclonedx \
${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:${{ needs.build.outputs.image_tag }}