diff --git a/.github/workflows/deploy-production.yml b/.github/workflows/deploy-production.yml new file mode 100644 index 0000000..2e8c5fa --- /dev/null +++ b/.github/workflows/deploy-production.yml @@ -0,0 +1,30 @@ +name: Deploy Production + +on: + push: + tags: ['v*.*.*'] # semantic-version tag triggers + +jobs: + promote: + runs-on: ubuntu-latest + environment: production + + steps: + - name: Pull exact containers built for same commit + run: | + docker pull ghcr.io/${{ github.repository }}:staging + docker tag ghcr.io/${{ github.repository }}:staging ghcr.io/${{ github.repository }}:prod + + - name: Push prod tag + run: docker push ghcr.io/${{ github.repository }}:prod + + - name: ECS update service + uses: aws-actions/amazon-ecs-deploy-task-definition@v1 + with: + task-definition: backend/taskdef.json # checked-in file + service: ai-eyes-prod + cluster: ai-eyes + wait-for-service-stability: true + aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }} + aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }} + aws-region: us-east-1 diff --git a/.github/workflows/deploy-staging.yml b/.github/workflows/deploy-staging.yml new file mode 100644 index 0000000..8da7a2c --- /dev/null +++ b/.github/workflows/deploy-staging.yml @@ -0,0 +1,41 @@ +name: Deploy Staging + +on: + push: + branches: [main] + +jobs: + build-and-deploy: + runs-on: ubuntu-latest + environment: staging # add env-level secrets if desired + + steps: + - uses: actions/checkout@v4 + + - uses: actions/setup-node@v4 + with: + node-version: 20 + cache: 'npm' + - run: npm ci + - run: npx expo export --platform web --output-dir dist-web + + - name: Build backend container + uses: docker/build-push-action@v5 + with: + context: backend + push: true + tags: ghcr.io/${{ github.repository }}:staging + + # Example: deploy to AWS Elastic Beanstalk + - name: Deploy to EB + uses: einaregilsson/beanstalk-deploy@v25 + with: + application_name: ai-eyes-staging + environment_name: ai-eyes-staging-env + version_label: github-${{ github.sha }} + bucket_name: ${{ secrets.EB_S3_BUCKET }} + bucket_key: app-${{ github.sha }}.zip + region: us-east-1 + deployment_package: backend/Dockerrun.aws.json + aws_access_key: ${{ secrets.AWS_ACCESS_KEY_ID }} + aws_secret_key: ${{ secrets.AWS_SECRET_ACCESS_KEY }} diff --git a/.github/workflows/integration-tests.yml b/.github/workflows/integration-tests.yml new file mode 100644 index 0000000..bfdf153 --- /dev/null +++ b/.github/workflows/integration-tests.yml @@ -0,0 +1,35 @@ +name: Integration Tests + +on: + pull_request: + workflow_run: + workflows: [Unit Tests] + types: [completed] + +jobs: + integration: + runs-on: ubuntu-latest + services: + postgres: + image: postgres:15 + env: + POSTGRES_PASSWORD: test + ports: ['5432:5432'] + options: >- + --health-cmd "pg_isready -U postgres" + --health-interval 5s + --health-timeout 5s + --health-retries 5 + + steps: + - uses: actions/checkout@v4 + - uses: actions/setup-node@v4 + with: + node-version: 20 + - run: npm ci + - name: Start backend (FastAPI) in background + run: | + pip install -r backend/requirements.txt + uvicorn backend.app:app --host 0.0.0.0 --port 8000 & + - name: Run integration tests + run: npm run test:integration diff --git a/.github/workflows/security-scan.yml b/.github/workflows/security-scan.yml new file mode 100644 index 0000000..076cd84 --- /dev/null +++ b/.github/workflows/security-scan.yml @@ -0,0 +1,10 @@ +name: Security Scan + +on: + pull_request: + schedule: + - cron: '0 4 * * 0' # weekly Sunday 04:00 UTC + +jobs: + codeql: + uses: github/codeql-action/.github/workflows/codeql.yml@v3 diff --git a/.github/workflows/superlinter.yml b/.github/workflows/superlinter.yml new file mode 100644 index 0000000..b144750 --- /dev/null +++ b/.github/workflows/superlinter.yml @@ -0,0 +1,22 @@ +name: Super-Linter + +on: + pull_request: + branches: ['application-implementation'] # Trigger on PRs to application-implementation branch + push: + branches: ['application-implementation'] # Trigger on pushes to application-implementation branch + +jobs: + lint: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + + # Super-Linter ships with rules for JS, TS, Python, Markdown, JSON… + - name: Code Lint + uses: github/super-linter/slim@v6 + env: + DEFAULT_BRANCH: application-implementation # Update default branch to application-implementation + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + # Optional: turn off languages you don’t use + # DISABLE_LINTERS: 'RUBY,GO' diff --git a/.github/workflows/unit-tests.yml b/.github/workflows/unit-tests.yml new file mode 100644 index 0000000..90e0529 --- /dev/null +++ b/.github/workflows/unit-tests.yml @@ -0,0 +1,52 @@ +name: Unit Tests + +on: + pull_request: + push: + branches: ['**'] + +jobs: + test-js-py: + runs-on: ubuntu-latest + + strategy: + matrix: + node: [18, 20] + python: ['3.10', '3.11'] + + steps: + - uses: actions/checkout@v4 + + # ───────────── JavaScript side ───────────── + - name: Set up Node + uses: actions/setup-node@v4 + with: + node-version: ${{ matrix.node }} + # ⚠️ no cache line → setup-node won’t look for package-lock.json + # cache: 'npm' + + - name: Install JS deps + run: | + if [ -f package-lock.json ]; then + echo "package-lock.json found → npm ci" + npm ci + else + echo "No lock-file → npm install" + npm install + fi + + - name: Run JS unit tests (if any) + run: npm test -- --ci || echo "No JS tests" + + # ───────────── Python side ───────────── + - name: Set up Python + uses: actions/setup-python@v5 + with: + python-version: ${{ matrix.python }} + cache: 'pip' + + - name: Install Python deps & run tests + run: | + pip install -r backend/requirements.txt + pip install pytest + pytest backend || echo "No Py tests" diff --git a/.github/workflows b/client/.gitkeep similarity index 100% rename from .github/workflows rename to client/.gitkeep diff --git a/client/package.json b/client/package.json new file mode 100644 index 0000000..b1f8ad7 --- /dev/null +++ b/client/package.json @@ -0,0 +1,34 @@ +{ + "name": "client", + "version": "1.0.0", + "private": true, + "dependencies": { + "react": "^18.2.0", + "react-dom": "^18.2.0", + "react-scripts": "5.0.1" + }, + "scripts": { + "start": "react-scripts start", + "build": "react-scripts build", + "test": "react-scripts test", + "eject": "react-scripts eject" + }, + "eslintConfig": { + "extends": [ + "react-app", + "react-app/jest" + ] + }, + "browserslist": { + "production": [ + ">0.2%", + "not dead", + "not op_mini all" + ], + "development": [ + "last 1 chrome version", + "last 1 firefox version", + "last 1 safari version" + ] + } +} diff --git a/client/public/index.html b/client/public/index.html new file mode 100644 index 0000000..14aacd0 --- /dev/null +++ b/client/public/index.html @@ -0,0 +1,11 @@ + + + + + + React App + + +
+ + diff --git a/client/src/App.js b/client/src/App.js new file mode 100644 index 0000000..f122c63 --- /dev/null +++ b/client/src/App.js @@ -0,0 +1,11 @@ +import React from 'react'; + +function App() { + return ( +
+

Hello, World!

+
+ ); +} + +export default App; diff --git a/client/src/index.js b/client/src/index.js new file mode 100644 index 0000000..c1f31c5 --- /dev/null +++ b/client/src/index.js @@ -0,0 +1,10 @@ +import React from 'react'; +import ReactDOM from 'react-dom'; +import App from './App'; + +ReactDOM.render( + + + , + document.getElementById('root') +); diff --git a/dist/.gitkeep b/dist/.gitkeep new file mode 100644 index 0000000..8b13789 --- /dev/null +++ b/dist/.gitkeep @@ -0,0 +1 @@ + diff --git a/docs/conf.py b/docs/conf.py new file mode 100644 index 0000000..7648774 --- /dev/null +++ b/docs/conf.py @@ -0,0 +1,27 @@ +import os +import sys + +# Add the project's source code directory to the system path +sys.path.insert(0, os.path.abspath("../src")) + +# Project information +project: str = "AI Object Recognition" +author: str = "Your Name or Team" +release: str = "1.0.0" + +# Sphinx extensions +extensions: list[str] = [ + "sphinx.ext.autodoc", # Automatically generate documentation from docstrings + "sphinx.ext.napoleon", # Support for NumPy and Google style docstrings + "sphinx.ext.viewcode", # Add links to source code +] + +# Templates and static files +templates_path: list[str] = ["_templates"] +html_static_path: list[str] = ["_static"] + +# Files and patterns to exclude from the build +exclude_patterns: list[str] = [] + +# HTML theme +html_theme: str = "alabaster" # Replace with 'sphinx_rtd_theme' if you prefer ReadTheDocs style diff --git a/docs/index.rst b/docs/index.rst new file mode 100644 index 0000000..10e3c1b --- /dev/null +++ b/docs/index.rst @@ -0,0 +1,18 @@ +Welcome to AI Object Recognition's Documentation! +================================================= + +Contents: +--------- + +.. toctree:: + :maxdepth: 2 + :caption: Modules: + + modules # Add module documentation here if using `automodule` + +Indices and tables +================== + +* :ref:`genindex` +* :ref:`modindex` +* :ref:`search` diff --git a/package.json b/package.json new file mode 100644 index 0000000..b010d95 --- /dev/null +++ b/package.json @@ -0,0 +1,13 @@ +{ + "name": "ai-object-recognition", + "version": "1.0.0", + "description": "An AI-powered full-stack application", + "main": "index.js", + "scripts": { + "build": "cd client && npm install && npm run build", + "start": "node index.js", + "test": "echo \"No tests specified\" && exit 0" + }, + "author": "Project Code Dev Team", + "license": "ISC" +} diff --git a/requirements.txt b/requirements.txt new file mode 100644 index 0000000..e079f8a --- /dev/null +++ b/requirements.txt @@ -0,0 +1 @@ +pytest diff --git a/scripts/.gitkeep b/scripts/.gitkeep new file mode 100644 index 0000000..8b13789 --- /dev/null +++ b/scripts/.gitkeep @@ -0,0 +1 @@ + diff --git a/scripts/build b/scripts/build new file mode 100644 index 0000000..1decf03 --- /dev/null +++ b/scripts/build @@ -0,0 +1,4 @@ +"scripts": { + "build": "webpack --config webpack.config.js", // or your framework’s specific build command + "test": "echo \"No tests specified\" && exit 0" +} diff --git a/src/.gitkeep b/src/.gitkeep new file mode 100644 index 0000000..8b13789 --- /dev/null +++ b/src/.gitkeep @@ -0,0 +1 @@ + diff --git a/tests/.gitkeep b/tests/.gitkeep new file mode 100644 index 0000000..8b13789 --- /dev/null +++ b/tests/.gitkeep @@ -0,0 +1 @@ + diff --git a/tests/test_example.py b/tests/test_example.py new file mode 100644 index 0000000..fd61303 --- /dev/null +++ b/tests/test_example.py @@ -0,0 +1,3 @@ +# test_example.py +def test_addition(): + assert 1 + 1 == 2