diff --git a/.env.example b/.env.example deleted file mode 100644 index 2aa8dd5..0000000 --- a/.env.example +++ /dev/null @@ -1,2 +0,0 @@ -POSTGRES_PASSWORD="changethis" -REDIS_PASSWORD="changethis" diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 0000000..53f95df --- /dev/null +++ b/.gitattributes @@ -0,0 +1,6 @@ +* text=auto eol=lf +*.bat text eol=crlf +*.cmd text eol=crlf +*.ps1 text eol=crlf +docker/Dockerfile text eol=lf +docker/*.sh text eol=lf diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index d0a3bd6..092172f 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -60,8 +60,8 @@ jobs: - name: Setup test environment run: | touch .env - docker compose -f docker-compose.dev.yml down -v --remove-orphans - docker compose -f docker-compose.dev.yml up postgres redis -d --wait --remove-orphans + docker compose -f compose.yml -f compose-dev.yml down -v --remove-orphans + docker compose -f compose.yml -f compose-dev.yml up postgres redis -d --wait --remove-orphans poetry run make certs - name: Run tests @@ -77,7 +77,7 @@ jobs: - name: Teardown test environment run: | - docker compose -f docker-compose.dev.yml down -v --remove-orphans + docker compose -f compose.yml -f compose-dev.yml down -v --remove-orphans - name: Store coverage files uses: actions/upload-artifact@v4 diff --git a/.gitignore b/.gitignore index 7d19c4a..66f5203 100644 --- a/.gitignore +++ b/.gitignore @@ -160,8 +160,16 @@ cython_debug/ .idea/ # Environments -*.env -.dev.env -!.env.example -certs +*.env* +certs/ + +# Git worktrees +.worktrees/ + +# AI agents .codegraph/ +docs/adr/ +docs/superpowers/ +docs/glossary.md +compose-obs.yml +compose-prod.yml diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 0d6a98c..9e7b2a8 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -59,7 +59,9 @@ repos: hooks: - id: detect-secrets args: [ - '--baseline', '.secrets.baseline', + '--exclude-files', 'docs', + '--exclude-files', 'migrations', + '--exclude-files', 'alembic.ini', ] exclude: package.lock.json stages: [ pre-commit, pre-merge-commit, manual ] diff --git a/.secrets.baseline b/.secrets.baseline deleted file mode 100644 index 943aa6a..0000000 --- a/.secrets.baseline +++ /dev/null @@ -1,165 +0,0 @@ -{ - "version": "1.5.0", - "plugins_used": [ - { - "name": "ArtifactoryDetector" - }, - { - "name": "AWSKeyDetector" - }, - { - "name": "AzureStorageKeyDetector" - }, - { - "name": "Base64HighEntropyString", - "limit": 4.5 - }, - { - "name": "BasicAuthDetector" - }, - { - "name": "CloudantDetector" - }, - { - "name": "DiscordBotTokenDetector" - }, - { - "name": "GitHubTokenDetector" - }, - { - "name": "GitLabTokenDetector" - }, - { - "name": "HexHighEntropyString", - "limit": 3.0 - }, - { - "name": "IbmCloudIamDetector" - }, - { - "name": "IbmCosHmacDetector" - }, - { - "name": "IPPublicDetector" - }, - { - "name": "JwtTokenDetector" - }, - { - "name": "KeywordDetector", - "keyword_exclude": "" - }, - { - "name": "MailchimpDetector" - }, - { - "name": "NpmDetector" - }, - { - "name": "OpenAIDetector" - }, - { - "name": "PrivateKeyDetector" - }, - { - "name": "PypiTokenDetector" - }, - { - "name": "SendGridDetector" - }, - { - "name": "SlackDetector" - }, - { - "name": "SoftlayerDetector" - }, - { - "name": "SquareOAuthDetector" - }, - { - "name": "StripeDetector" - }, - { - "name": "TelegramBotTokenDetector" - }, - { - "name": "TwilioKeyDetector" - } - ], - "filters_used": [ - { - "path": "detect_secrets.filters.allowlist.is_line_allowlisted" - }, - { - "path": "detect_secrets.filters.common.is_baseline_file", - "filename": ".secrets.baseline" - }, - { - "path": "detect_secrets.filters.common.is_ignored_due_to_verification_policies", - "min_level": 2 - }, - { - "path": "detect_secrets.filters.heuristic.is_indirect_reference" - }, - { - "path": "detect_secrets.filters.heuristic.is_likely_id_string" - }, - { - "path": "detect_secrets.filters.heuristic.is_lock_file" - }, - { - "path": "detect_secrets.filters.heuristic.is_not_alphanumeric_string" - }, - { - "path": "detect_secrets.filters.heuristic.is_potential_uuid" - }, - { - "path": "detect_secrets.filters.heuristic.is_prefixed_with_dollar_sign" - }, - { - "path": "detect_secrets.filters.heuristic.is_sequential_string" - }, - { - "path": "detect_secrets.filters.heuristic.is_swagger_file" - }, - { - "path": "detect_secrets.filters.heuristic.is_templated_secret" - }, - { - "path": "detect_secrets.filters.regex.should_exclude_file", - "pattern": [ - "migrations/*" - ] - } - ], - "results": { - ".env.example": [ - { - "type": "Secret Keyword", - "filename": ".env.example", - "hashed_secret": "cdb0e76c1a69873cbdcdbe0a142d56c023dc9f22", - "is_verified": false, - "line_number": 1 - } - ], - "alembic.ini": [ - { - "type": "Basic Auth Credentials", - "filename": "alembic.ini", - "hashed_secret": "9d4e1e23bd5b727046a9e3b4b7db57bd8d6ee684", - "is_verified": false, - "line_number": 62 - } - ], - "app\\db\\config.py": [ - { - "type": "Basic Auth Credentials", - "filename": "app\\db\\config.py", - "hashed_secret": "cdb0e76c1a69873cbdcdbe0a142d56c023dc9f22", - "is_verified": false, - "line_number": 7 - } - ] - }, - "generated_at": "2026-05-29T10:11:37Z" -} diff --git a/Makefile b/Makefile index 11caafb..a466e75 100644 --- a/Makefile +++ b/Makefile @@ -7,15 +7,19 @@ certs: .PHONY: deps deps: - docker compose -f docker-compose.dev.yml up postgres redis -d --build --remove-orphans --wait + docker compose -f compose.yml -f compose-dev.yml up postgres redis -d --build --remove-orphans --wait .PHONY: up up: - docker compose -f docker-compose.dev.yml up --build --remove-orphans --wait + docker compose -f compose.yml -f compose-dev.yml up --build --remove-orphans --wait + +.PHONY: recreate +recreate: + docker compose -f compose.yml -f compose-dev.yml up --build --force-recreate --remove-orphans --wait .PHONY: start start: - docker compose -f docker-compose.dev.yml start + docker compose -f compose.yml -f compose-dev.yml start .PHONY: build build: @@ -23,19 +27,15 @@ build: .PHONY: up-obs up-obs: - docker compose -f docker-compose.dev.yml -f docker-compose.observability.yml up --build --remove-orphans --wait + docker compose -f compose-dev.yml -f compose-observability.yml up --build --remove-orphans --wait .PHONY: up-prod up-prod: - docker compose -f docker-compose.dev.yml -f docker-compose.prod.yml up --build --remove-orphans --wait + docker compose -f compose.yml -f compose-dev.yml -f compose-prod.yml up --build --remove-orphans --wait .PHONY: up-prod-obs up-prod-obs: - docker compose -f docker-compose.dev.yml -f docker-compose.prod.yml -f docker-compose.observability.yml up --build --remove-orphans --wait - -.PHONY: up-example -up-example: - docker compose -f docker-compose.example.yml up --build --remove-orphans --wait + docker compose -f compose.yml -f compose-dev.yml -f compose-prod.yml -f compose-obs.yml up --build --remove-orphans --wait .PHONY: test test: @@ -51,15 +51,15 @@ testcov: .PHONY: stop stop: - docker compose -f docker-compose.dev.yml stop + docker compose -f compose.yml -f compose-dev.yml stop .PHONY: down down: - docker compose -f docker-compose.dev.yml down + docker compose -f compose.yml -f compose-dev.yml down .PHONY: restart restart: - docker compose -f docker-compose.dev.yml restart + docker compose -f compose.yml -f compose-dev.yml restart .PHONY: lint lint: diff --git a/README.md b/README.md index 1e90e5c..2255809 100644 --- a/README.md +++ b/README.md @@ -54,7 +54,7 @@ ### Download the Compose file ```bash -wget https://raw.githubusercontent.com/everysoftware/fastid/refs/heads/master/docker-compose.yml +wget https://raw.githubusercontent.com/everysoftware/fastid/refs/heads/master/compose.yml ``` ### Generate keys diff --git a/compose-dev.yml b/compose-dev.yml new file mode 100644 index 0000000..c20d7c4 --- /dev/null +++ b/compose-dev.yml @@ -0,0 +1,24 @@ +services: + postgres: + ports: + - "5412:5432" + redis: + ports: + - "6312:6379" + mailpit: + ports: + - "8025:8025" + - "1025:1025" + fastid-app: + build: + context: . + dockerfile: docker/Dockerfile + target: dev + volumes: + - "./migrations:/opt/fastid/migrations" + - "./fastid:/opt/fastid/fastid" + - "./templates:/opt/fastid/templates" + - "./static:/opt/fastid/static" + +volumes: + pg_data: diff --git a/docker-compose.yml b/compose.yml similarity index 96% rename from docker-compose.yml rename to compose.yml index f59ffe3..c929f09 100644 --- a/docker-compose.yml +++ b/compose.yml @@ -61,7 +61,7 @@ services: - "./certs:/opt/fastid/certs" healthcheck: - test: [ "CMD", "curl", "-f", "http://localhost:8000/api/v1/readiness" ] + test: [ "CMD", "curl", "-f", "http://localhost:8000/readiness" ] interval: 30s timeout: 10s retries: 3 diff --git a/docker-compose.dev.yml b/docker-compose.dev.yml deleted file mode 100644 index 8cc7dd1..0000000 --- a/docker-compose.dev.yml +++ /dev/null @@ -1,84 +0,0 @@ -services: - postgres: - env_file: - - .env - image: postgres:16-alpine - environment: - POSTGRES_PASSWORD: ${POSTGRES_PASSWORD:?database password required} - POSTGRES_USER: ${POSTGRES_USER:-fastid} - POSTGRES_DB: ${POSTGRES_DB:-fastid} - volumes: - - pg_data:/var/lib/postgresql/data - ports: - - "5412:5432" - healthcheck: - test: ["CMD-SHELL", "pg_isready -U ${POSTGRES_USER} -d ${POSTGRES_DB}"] - interval: 10s - retries: 5 - start_period: 30s - timeout: 10s - - redis: - env_file: - - .env - image: redis:7-alpine - command: redis-server --requirepass ${REDIS_PASSWORD:?redis password required} - ports: - - "6312:6379" - healthcheck: - test: ["CMD", "redis-cli", "ping"] - interval: 10s - timeout: 5s - retries: 5 - - mailpit: - image: axllent/mailpit:v1.30.1 - ports: - - "8025:8025" - - "1025:1025" - healthcheck: - test: ["CMD", "wget", "--no-verbose", "--tries=1", "--spider", "http://localhost:8025/readyz"] - interval: 10s - timeout: 5s - retries: 5 - start_period: 10s - - fastid-app: - build: - context: . - dockerfile: docker/Dockerfile - target: dev - env_file: .env - ports: - - "8012:8000" - depends_on: - postgres: - condition: service_healthy - redis: - condition: service_healthy - mailpit: - condition: service_healthy - - environment: - FASTID_DB_URL: ${FASTID_DB_URL:-postgresql+asyncpg://${POSTGRES_USER:-fastid}:${POSTGRES_PASSWORD:?database password required}@postgres:5432/${POSTGRES_DB:-fastid}} - FASTID_REDIS_URL: ${FASTID_REDIS_URL:-redis://:${REDIS_PASSWORD:?redis password required}@redis:6379/0} - FASTID_SMTP_ENABLED: ${FASTID_SMTP_ENABLED:-true} - FASTID_SMTP_HOST: ${FASTID_SMTP_HOST:-mailpit} - FASTID_SMTP_PORT: ${FASTID_SMTP_PORT:-1025} - - volumes: - - "./migrations:/opt/fastid/migrations" - - "./fastid:/opt/fastid/fastid" - - "./templates:/opt/fastid/templates" - - "./static:/opt/fastid/static" - - "./certs:/opt/fastid/certs" - - healthcheck: - test: [ "CMD", "curl", "-f", "http://localhost:8000/api/v1/readiness" ] - interval: 30s - timeout: 10s - retries: 3 - start_period: 40s - -volumes: - pg_data: diff --git a/docker-compose.observability.yml b/docker-compose.observability.yml deleted file mode 100644 index aa1f573..0000000 --- a/docker-compose.observability.yml +++ /dev/null @@ -1,25 +0,0 @@ -x-logging: &default-logging - driver: loki - options: - loki-url: '${LOKI_URL:-http://localhost:3100/api/prom/push}' - loki-pipeline-stages: | - - multiline: - firstline: '^\d{4}-\d{2}-\d{2} \d{1,2}:\d{2}:\d{2}' - max_wait_time: 3s - - regex: - expression: '^(?P