diff --git a/.github/workflows/ci-cd-fixed.yml b/.github/workflows/ci-cd-fixed.yml deleted file mode 100644 index e2e0402..0000000 --- a/.github/workflows/ci-cd-fixed.yml +++ /dev/null @@ -1,88 +0,0 @@ -name: CI/CD Pipeline - Fixed - -on: - pull_request: - branches: [ main ] - push: - branches: [ main ] - workflow_dispatch: - - inputs: - skip_tests: - description: 'Skip tests?' - required: true - default: 'false' - type: choice - options: ['true', 'false'] - force_deploy: - description: 'Force deploy?' - required: true - default: 'false' - type: choice - options: ['true', 'false'] - -permissions: - id-token: write - contents: read - -env: - AWS_REGION: eu-west-1 - ECR_REPOSITORY: neurobank-fastapi - AWS_ACCOUNT_ID: 120242956739 - AWS_ROLE_ARN: arn:aws:iam::120242956739:role/GitHubActionsOIDCRole - -jobs: - - test: - runs-on: ubuntu-latest - if: github.event.inputs.skip_tests != 'true' - steps: - - uses: actions/checkout@v6 - - uses: actions/setup-python@v6 - with: - python-version: '3.11' - - run: pip install -r requirements.txt - - run: pytest --cov=app --cov-report=xml - - - security: - runs-on: ubuntu-latest - if: github.event.inputs.skip_tests != 'true' - steps: - - uses: actions/checkout@v6 - - uses: actions/setup-python@v6 - with: - python-version: '3.11' - - run: pip install bandit safety -r requirements.txt - - run: bandit -r app/ --skip B101 || true - - run: safety scan || true - - - build-and-deploy: - needs: [ test, security ] - runs-on: ubuntu-latest - if: github.event.inputs.force_deploy == 'true' - steps: - - uses: actions/checkout@v6 - - uses: actions/setup-python@v6 - with: - python-version: '3.11' - - - name: Configure AWS (OIDC) - uses: aws-actions/configure-aws-credentials@v5 - with: - role-to-assume: ${{ env.AWS_ROLE_ARN }} - aws-region: ${{ env.AWS_REGION }} - - - uses: aws-actions/setup-sam@v2 - with: - use-installer: true - - - name: Build & Deploy - run: | - sam build - sam deploy \ - --no-confirm-changeset \ - --stack-name neurobank-api-fixed \ - --capabilities CAPABILITY_IAM \ - --parameter-overrides ApiKey=${{ secrets.API_KEY || 'emergency-key' }} diff --git a/.github/workflows/ci-cd.yml b/.github/workflows/ci-cd.yml deleted file mode 100644 index 38fa492..0000000 --- a/.github/workflows/ci-cd.yml +++ /dev/null @@ -1,143 +0,0 @@ -name: CI/CD Pipeline - -on: - pull_request: - branches: [ main ] - push: - branches: [ main ] - workflow_dispatch: - - inputs: - deploy_to_aws: - description: "Deploy to AWS?" - required: true - default: "false" - type: choice - options: - - "true" - - "false" - environment: - description: "Environment" - required: true - default: "staging" - type: choice - options: - - "staging" - - "production" - -permissions: - id-token: write - contents: read - -env: - AWS_REGION: eu-west-1 - ECR_REPOSITORY: neurobank-fastapi - AWS_ACCOUNT_ID: 120242956739 - AWS_ROLE_ARN: arn:aws:iam::120242956739:role/GitHubActionsOIDCRole - -jobs: - - test: - runs-on: ubuntu-latest - env: - CI: "true" - steps: - - uses: actions/checkout@v6 - - - uses: actions/setup-python@v6 - with: - python-version: "3.11" - - - name: Install dependencies - run: | - pip install -r requirements.txt - - - name: Run tests - run: | - pytest --cov=app --cov-report=xml --cov-report=html - - - uses: codecov/codecov-action@v5 - if: always() - with: - files: ./coverage.xml - - security: - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v6 - - - uses: actions/setup-python@v6 - with: - python-version: "3.11" - - - name: Install tools - run: | - pip install -r requirements.txt - pip install bandit safety - - - name: Bandit - run: bandit -r app/ -f json -o bandit-report.json --skip B101 || true - - - name: Safety - run: | - pip freeze > current-requirements.txt - safety scan --json --output safety-report.json --continue-on-error || true - - - uses: actions/upload-artifact@v4 - with: - name: security-reports - path: | - bandit-report.json - safety-report.json - - deployment-check: - needs: [test, security] - runs-on: ubuntu-latest - if: github.ref == 'refs/heads/main' - steps: - - name: Deployment readiness - run: | - echo "OK" - - build-and-deploy: - needs: [test, security] - runs-on: ubuntu-latest - if: github.event_name == 'workflow_dispatch' && github.event.inputs.deploy_to_aws == 'true' - steps: - - uses: actions/checkout@v6 - - - uses: aws-actions/configure-aws-credentials@v5 - with: - role-to-assume: ${{ env.AWS_ROLE_ARN }} - aws-region: ${{ env.AWS_REGION }} - role-session-name: GitHubActions-${{ github.run_id }} - - - run: aws sts get-caller-identity - - - uses: aws-actions/setup-sam@v2 - with: - use-installer: true - - - name: Ensure ECR repository exists - run: | - aws ecr describe-repositories --repository-names ${{ env.ECR_REPOSITORY }} || \ - aws ecr create-repository --repository-name ${{ env.ECR_REPOSITORY }} - - - uses: aws-actions/amazon-ecr-login@v2 - id: login-ecr - - - name: Build and push image - env: - REGISTRY: ${{ steps.login-ecr.outputs.registry }} - TAG: ${{ github.sha }} - run: | - docker build -t $REGISTRY/$ECR_REPOSITORY:$TAG . - docker push $REGISTRY/$ECR_REPOSITORY:$TAG - - - name: Deploy - run: | - sam build - sam deploy --no-confirm-changeset --no-fail-on-empty-changeset \ - --stack-name neurobank-api \ - --capabilities CAPABILITY_IAM \ - --region ${{ env.AWS_REGION }} diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml new file mode 100644 index 0000000..0c6a5b7 --- /dev/null +++ b/.github/workflows/deploy.yml @@ -0,0 +1,21 @@ +name: CD – Deploy to Railway + +on: + push: + branches: [main] + +jobs: + deploy: + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v4 + + - name: Install Railway CLI + run: | + curl -fsSL https://railway.app/install.sh | sh + + - name: Deploy to Railway + env: + RAILWAY_TOKEN: ${{ secrets.RAILWAY_TOKEN }} + run: railway up --ci diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml new file mode 100644 index 0000000..fca45ff --- /dev/null +++ b/.github/workflows/lint.yml @@ -0,0 +1,24 @@ +name: CI - Lint + +on: + pull_request: + branches: [main] + +jobs: + lint: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + + - uses: actions/setup-python@v5 + with: + python-version: "3.11" + + - name: Install linting tools + run: pip install black isort autoflake + + - name: Run Black + run: black --check app + + - name: Run isort + run: isort --check-only app diff --git a/.github/workflows/security.yml b/.github/workflows/security.yml new file mode 100644 index 0000000..d282069 --- /dev/null +++ b/.github/workflows/security.yml @@ -0,0 +1,29 @@ +name: CI – Security Scan + +on: + pull_request: + branches: [main] + push: + branches: + - "feature/**" + +jobs: + security: + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v4 + + - name: Setup Python + uses: actions/setup-python@v5 + with: + python-version: "3.11" + + - name: Install security tooling + run: pip install bandit safety + + - name: Run Bandit + run: bandit -r app -ll + + - name: Dependency vulnerability scan + run: safety check -r requirements.txt || true diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml new file mode 100644 index 0000000..bb4b010 --- /dev/null +++ b/.github/workflows/test.yml @@ -0,0 +1,30 @@ +name: CI – Test Suite + +on: + pull_request: + branches: [main] + push: + branches: + - "feature/**" + +jobs: + tests: + runs-on: ubuntu-latest + + steps: + - name: Checkout repository + uses: actions/checkout@v4 + + - name: Setup Python + uses: actions/setup-python@v5 + with: + python-version: "3.11" + + - name: Install dependencies + run: | + pip install --upgrade pip + pip install -r requirements.txt + pip install pytest pytest-asyncio pytest-cov + + - name: Run unit tests + run: pytest -q --disable-warnings --maxfail=1 diff --git a/.gitignore b/.gitignore index 04a68a2..34d5a8c 100644 --- a/.gitignore +++ b/.gitignore @@ -61,3 +61,4 @@ safety-report.json NeuroBank-FastAPI-Toolkit-1/ neurobank-fastapi.code-workspace +neurobank-fastapi.code-workspace diff --git a/app/config.py b/app/config.py index 17d8352..29f7135 100644 --- a/app/config.py +++ b/app/config.py @@ -15,7 +15,7 @@ class Settings(BaseSettings): app_version: str = "1.0.0" # Server Configuration - host: str = "0.0.0.0" + host: str = "0.0.0.0" # nosec B104 port: int = int(os.getenv("PORT", 8000)) # Environment Configuration diff --git a/app/main.py b/app/main.py index 3f00b62..2754b99 100644 --- a/app/main.py +++ b/app/main.py @@ -244,7 +244,7 @@ async def root(): uvicorn.run( "app.main:app", - host="0.0.0.0", + host="0.0.0.0", # nosec B104, port=port, workers=workers, loop="uvloop",