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
59 changes: 59 additions & 0 deletions .dockerignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
# Git
.git
.gitignore
.gitattributes

# CI/CD
.github

# Documentation
*.md
docs/

# Python
__pycache__
*.py[cod]
*$py.class
*.so
.Python
*.egg-info/
dist/
build/
*.egg

# Virtual environments
venv/
env/
ENV/
.venv

# Testing
.pytest_cache/
.coverage
htmlcov/
.tox/
tests/

# IDE
.vscode/
.idea/
*.swp
*.swo

# Terraform
terraform/
*.tfstate
*.tfvars

# OS
.DS_Store
Thumbs.db

# Logs
*.log
logs/

# Temporary files
*.tmp
*.bak
tmp/
26 changes: 26 additions & 0 deletions .flake8
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
[flake8]
max-line-length = 127
exclude =
.git,
__pycache__,
.venv,
venv,
env,
build,
dist,
*.egg-info,
.pytest_cache,
.tox,
terraform

# Error codes to ignore:
# E203 - whitespace before ':'
# E501 - line too long (handled by black)
# W503 - line break before binary operator
ignore = E203,E501,W503

# Complexity
max-complexity = 10

# Enable specific checks
select = E,W,F,C
128 changes: 128 additions & 0 deletions .github/workflows/ci-cd.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,128 @@
name: CI/CD

on:
push:
branches: [ main, develop ]
pull_request:
branches: [ main ]

jobs:
lint:
name: Code Linting
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4

- name: Set up Python
uses: actions/setup-python@v5
with:
python-version: '3.11'
cache: 'pip'

- name: Install dependencies
run: |
python -m pip install --upgrade pip
pip install flake8 pylint black isort
if [ -f requirements.txt ]; then pip install -r requirements.txt; fi

- name: Run flake8
run: |
flake8 scripts/ --count --select=E9,F63,F7,F82 --show-source --statistics
flake8 scripts/ --count --exit-zero --max-complexity=10 --max-line-length=127 --statistics

- name: Check code formatting with black
run: black --check scripts/

- name: Check import sorting with isort
run: isort --check-only scripts/

test:
name: Run Tests
runs-on: ubuntu-latest
needs: lint
steps:
- uses: actions/checkout@v4

- name: Set up Python
uses: actions/setup-python@v5
with:
python-version: '3.11'
cache: 'pip'

- name: Install dependencies
run: |
python -m pip install --upgrade pip
pip install pytest pytest-cov
if [ -f requirements.txt ]; then pip install -r requirements.txt; fi

- name: Run tests with coverage
run: |
pytest tests/ --cov=scripts --cov-report=xml --cov-report=term

- name: Upload coverage reports
uses: codecov/codecov-action@v4
with:
file: ./coverage.xml
flags: unittests
name: codecov-umbrella
fail_ci_if_error: false

docker:
name: Build Docker Image
runs-on: ubuntu-latest
needs: test
steps:
- uses: actions/checkout@v4

- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3

- name: Build Docker image
uses: docker/build-push-action@v5
with:
context: .
push: false
tags: portfolio-app:${{ github.sha }}
cache-from: type=gha
cache-to: type=gha,mode=max

- name: Test Docker image
run: |
docker build -t portfolio-app:test .
docker run --rm portfolio-app:test --help || true

deploy:
name: Deploy
runs-on: ubuntu-latest
needs: [lint, test, docker]
if: github.ref == 'refs/heads/main' && github.event_name == 'push'
steps:
- uses: actions/checkout@v4

- name: Configure AWS credentials
uses: aws-actions/configure-aws-credentials@v4
with:
aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }}
aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
aws-region: us-east-1

- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3

- name: Login to Amazon ECR
id: login-ecr
uses: aws-actions/amazon-ecr-login@v2
continue-on-error: true

- name: Build and push Docker image to ECR
if: steps.login-ecr.outcome == 'success'
uses: docker/build-push-action@v5
with:
context: .
push: true
tags: |
${{ steps.login-ecr.outputs.registry }}/portfolio-app:latest
${{ steps.login-ecr.outputs.registry }}/portfolio-app:${{ github.sha }}

- name: Deployment notification
run: echo "Deployment completed successfully"
98 changes: 98 additions & 0 deletions .github/workflows/sast.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
name: SAST Security Scan

on:
push:
branches: [ main, develop ]
pull_request:
branches: [ main, develop ]
schedule:
# Run daily at 2 AM UTC
- cron: '0 2 * * *'
workflow_dispatch:

permissions:
contents: read
security-events: write
actions: read
pull-requests: write

jobs:
security-scan:
name: SDLC Code Scanner Security Scan
runs-on: ubuntu-latest

steps:
- name: Checkout repository
uses: actions/checkout@v4

- name: Run SDLC Code Scanner
id: security-scan

uses: williambrady/portfolio-code-scanner@v1.1.1
with:
scan-path: '.'
output-formats: 'json,html,markdown,sarif'
fail-on-severity: 'HIGH'
verbose: 'false'

- name: Upload SARIF to GitHub Code Scanning
uses: github/codeql-action/upload-sarif@v3
if: always() && steps.security-scan.outputs.sarif-path != ''
with:
sarif_file: ${{ steps.security-scan.outputs.sarif-path }}
category: 'sdlc-code-scanner'

- name: Upload Scan Reports
uses: actions/upload-artifact@v4
if: always()
with:
name: security-scan-reports
path: .sdlc-code-scanner-reports/
retention-days: 30

- name: Post Scan Summary
if: always()
run: |
echo "### Security Scan Results" >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
echo "| Severity | Count |" >> $GITHUB_STEP_SUMMARY
echo "|----------|-------|" >> $GITHUB_STEP_SUMMARY
echo "| Critical | ${{ steps.security-scan.outputs.critical-count }} |" >> $GITHUB_STEP_SUMMARY
echo "| High | ${{ steps.security-scan.outputs.high-count }} |" >> $GITHUB_STEP_SUMMARY
echo "| Medium | ${{ steps.security-scan.outputs.medium-count }} |" >> $GITHUB_STEP_SUMMARY
echo "| Low | ${{ steps.security-scan.outputs.low-count }} |" >> $GITHUB_STEP_SUMMARY
echo "| **Total** | **${{ steps.security-scan.outputs.findings-count }}** |" >> $GITHUB_STEP_SUMMARY

- name: Comment PR with Results
if: github.event_name == 'pull_request' && always()
uses: actions/github-script@v7
with:
script: |
const findings = '${{ steps.security-scan.outputs.findings-count }}';
const critical = '${{ steps.security-scan.outputs.critical-count }}';
const high = '${{ steps.security-scan.outputs.high-count }}';
const medium = '${{ steps.security-scan.outputs.medium-count }}';
const low = '${{ steps.security-scan.outputs.low-count }}';
const status = '${{ steps.security-scan.outputs.scan-status }}';

const statusEmoji = status === 'passed' ? ':white_check_mark:' : ':x:';

const body = `## SDLC Code Scanner Security Scan ${statusEmoji}

| Severity | Count |
|----------|-------|
| Critical | ${critical} |
| High | ${high} |
| Medium | ${medium} |
| Low | ${low} |
| **Total** | **${findings}** |

*View the full report in the [Actions artifacts](${process.env.GITHUB_SERVER_URL}/${process.env.GITHUB_REPOSITORY}/actions/runs/${process.env.GITHUB_RUN_ID})*
`;

github.rest.issues.createComment({
issue_number: context.issue.number,
owner: context.repo.owner,
repo: context.repo.repo,
body: body
});
Loading
Loading