diff --git a/.copier/.copier-answers.yml.jinja b/.copier/.copier-answers.yml.jinja deleted file mode 100644 index 0028a2398a..0000000000 --- a/.copier/.copier-answers.yml.jinja +++ /dev/null @@ -1 +0,0 @@ -{{ _copier_answers|to_json -}} diff --git a/.copier/update_dotenv.py b/.copier/update_dotenv.py deleted file mode 100644 index 6576885626..0000000000 --- a/.copier/update_dotenv.py +++ /dev/null @@ -1,26 +0,0 @@ -from pathlib import Path -import json - -# Update the .env file with the answers from the .copier-answers.yml file -# without using Jinja2 templates in the .env file, this way the code works as is -# without needing Copier, but if Copier is used, the .env file will be updated -root_path = Path(__file__).parent.parent -answers_path = Path(__file__).parent / ".copier-answers.yml" -answers = json.loads(answers_path.read_text()) -env_path = root_path / ".env" -env_content = env_path.read_text() -lines = [] -for line in env_content.splitlines(): - for key, value in answers.items(): - upper_key = key.upper() - if line.startswith(f"{upper_key}="): - if " " in value: - content = f"{upper_key}={value!r}" - else: - content = f"{upper_key}={value}" - new_line = line.replace(line, content) - lines.append(new_line) - break - else: - lines.append(line) -env_path.write_text("\n".join(lines)) diff --git a/.env b/.env index 1d44286e25..ed564598e3 100644 --- a/.env +++ b/.env @@ -13,14 +13,14 @@ FRONTEND_HOST=http://localhost:5173 # Environment: local, staging, production ENVIRONMENT=local -PROJECT_NAME="Full Stack FastAPI Project" -STACK_NAME=full-stack-fastapi-project +PROJECT_NAME="Service Data Platform" +STACK_NAME=sdp-project # Backend BACKEND_CORS_ORIGINS="http://localhost,http://localhost:5173,https://localhost,https://localhost:5173,http://localhost.tiangolo.com" -SECRET_KEY=changethis +SECRET_KEY=changeme123 FIRST_SUPERUSER=admin@example.com -FIRST_SUPERUSER_PASSWORD=changethis +FIRST_SUPERUSER_PASSWORD=changeme123 # Emails SMTP_HOST= @@ -36,7 +36,7 @@ POSTGRES_SERVER=localhost POSTGRES_PORT=5432 POSTGRES_DB=app POSTGRES_USER=postgres -POSTGRES_PASSWORD=changethis +POSTGRES_PASSWORD=changeme123 SENTRY_DSN= diff --git a/.gitignore b/.gitignore index a6dd346572..4b3884001c 100644 --- a/.gitignore +++ b/.gitignore @@ -4,3 +4,4 @@ node_modules/ /playwright-report/ /blob-report/ /playwright/.cache/ +*.tgz diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml deleted file mode 100644 index 512da0105c..0000000000 --- a/.pre-commit-config.yaml +++ /dev/null @@ -1,30 +0,0 @@ -# See https://pre-commit.com for more information -# See https://pre-commit.com/hooks.html for more hooks -repos: - - repo: https://github.com/pre-commit/pre-commit-hooks - rev: v4.4.0 - hooks: - - id: check-added-large-files - - id: check-toml - - id: check-yaml - args: - - --unsafe - - id: end-of-file-fixer - exclude: | - (?x)^( - frontend/src/client/.*| - backend/app/email-templates/build/.* - )$ - - id: trailing-whitespace - exclude: ^frontend/src/client/.* - - repo: https://github.com/charliermarsh/ruff-pre-commit - rev: v0.2.2 - hooks: - - id: ruff - args: - - --fix - - id: ruff-format - -ci: - autofix_commit_msg: 🎨 [pre-commit.ci] Auto format from pre-commit.com hooks - autoupdate_commit_msg: ⬆ [pre-commit.ci] pre-commit autoupdate diff --git a/LICENSE b/LICENSE deleted file mode 100644 index f11987b50c..0000000000 --- a/LICENSE +++ /dev/null @@ -1,21 +0,0 @@ -MIT License - -Copyright (c) 2019 SebastiΓ‘n RamΓ­rez - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. diff --git a/README.md b/README.md index afe124f3fb..0d55720644 100644 --- a/README.md +++ b/README.md @@ -1,8 +1,5 @@ # Full Stack FastAPI Template -Test -Coverage - ## Technology Stack and Features - ⚑ [**FastAPI**](https://fastapi.tiangolo.com) for the Python backend API. @@ -52,80 +49,6 @@ [![API docs](img/docs.png)](https://github.com/fastapi/full-stack-fastapi-template) -## How To Use It - -You can **just fork or clone** this repository and use it as is. - -✨ It just works. ✨ - -### How to Use a Private Repository - -If you want to have a private repository, GitHub won't allow you to simply fork it as it doesn't allow changing the visibility of forks. - -But you can do the following: - -- Create a new GitHub repo, for example `my-full-stack`. -- Clone this repository manually, set the name with the name of the project you want to use, for example `my-full-stack`: - -```bash -git clone git@github.com:fastapi/full-stack-fastapi-template.git my-full-stack -``` - -- Enter into the new directory: - -```bash -cd my-full-stack -``` - -- Set the new origin to your new repository, copy it from the GitHub interface, for example: - -```bash -git remote set-url origin git@github.com:octocat/my-full-stack.git -``` - -- Add this repo as another "remote" to allow you to get updates later: - -```bash -git remote add upstream git@github.com:fastapi/full-stack-fastapi-template.git -``` - -- Push the code to your new repository: - -```bash -git push -u origin master -``` - -### Update From the Original Template - -After cloning the repository, and after doing changes, you might want to get the latest changes from this original template. - -- Make sure you added the original repository as a remote, you can check it with: - -```bash -git remote -v - -origin git@github.com:octocat/my-full-stack.git (fetch) -origin git@github.com:octocat/my-full-stack.git (push) -upstream git@github.com:fastapi/full-stack-fastapi-template.git (fetch) -upstream git@github.com:fastapi/full-stack-fastapi-template.git (push) -``` - -- Pull the latest changes without merging: - -```bash -git pull --no-commit upstream master -``` - -This will download the latest changes from this template without committing them, that way you can check everything is right before committing. - -- If there are conflicts, solve them in your editor. - -- Once you are done, commit the changes: - -```bash -git merge --continue -``` - ### Configure You can then update configs in the `.env` files to customize your configurations. @@ -152,46 +75,6 @@ python -c "import secrets; print(secrets.token_urlsafe(32))" Copy the content and use that as password / secret key. And run that again to generate another secure key. -## How To Use It - Alternative With Copier - -This repository also supports generating a new project using [Copier](https://copier.readthedocs.io). - -It will copy all the files, ask you configuration questions, and update the `.env` files with your answers. - -### Install Copier - -You can install Copier with: - -```bash -pip install copier -``` - -Or better, if you have [`pipx`](https://pipx.pypa.io/), you can run it with: - -```bash -pipx install copier -``` - -**Note**: If you have `pipx`, installing copier is optional, you could run it directly. - -### Generate a Project With Copier - -Decide a name for your new project's directory, you will use it below. For example, `my-awesome-project`. - -Go to the directory that will be the parent of your project, and run the command with your project's name: - -```bash -copier copy https://github.com/fastapi/full-stack-fastapi-template my-awesome-project --trust -``` - -If you have `pipx` and you didn't install `copier`, you can run it directly: - -```bash -pipx run copier copy https://github.com/fastapi/full-stack-fastapi-template my-awesome-project --trust -``` - -**Note** the `--trust` option is necessary to be able to execute a [post-creation script](https://github.com/fastapi/full-stack-fastapi-template/blob/master/.copier/update_dotenv.py) that updates your `.env` files. - ### Input Variables Copier will ask you for some data, you might want to have at hand before generating the project. @@ -233,7 +116,3 @@ This includes using Docker Compose, custom local domains, `.env` configurations, ## Release Notes Check the file [release-notes.md](./release-notes.md). - -## License - -The Full Stack FastAPI Template is licensed under the terms of the MIT license. diff --git a/SECURITY.md b/SECURITY.md deleted file mode 100644 index 0045fb8182..0000000000 --- a/SECURITY.md +++ /dev/null @@ -1,29 +0,0 @@ -# Security Policy - -Security is very important for this project and its community. πŸ”’ - -Learn more about it below. πŸ‘‡ - -## Versions - -The latest version or release is supported. - -You are encouraged to write tests for your application and update your versions frequently after ensuring that your tests are passing. This way you will benefit from the latest features, bug fixes, and **security fixes**. - -## Reporting a Vulnerability - -If you think you found a vulnerability, and even if you are not sure about it, please report it right away by sending an email to: security@tiangolo.com. Please try to be as explicit as possible, describing all the steps and example code to reproduce the security issue. - -I (the author, [@tiangolo](https://twitter.com/tiangolo)) will review it thoroughly and get back to you. - -## Public Discussions - -Please restrain from publicly discussing a potential security vulnerability. πŸ™Š - -It's better to discuss privately and try to find a solution first, to limit the potential impact as much as possible. - ---- - -Thanks for your help! - -The community and I thank you for that. πŸ™‡ diff --git a/backend/Dockerfile b/backend/Dockerfile index 44c53f0365..581c2f2a76 100644 --- a/backend/Dockerfile +++ b/backend/Dockerfile @@ -1,43 +1,36 @@ -FROM python:3.10 +FROM python:3.11-slim ENV PYTHONUNBUFFERED=1 WORKDIR /app/ -# Install uv -# Ref: https://docs.astral.sh/uv/guides/integration/docker/#installing-uv -COPY --from=ghcr.io/astral-sh/uv:0.5.11 /uv /uvx /bin/ +# Install system dependencies +RUN apt-get update && apt-get install -y \ + gcc \ + && rm -rf /var/lib/apt/lists/* -# Place executables in the environment at the front of the path -# Ref: https://docs.astral.sh/uv/guides/integration/docker/#using-the-environment -ENV PATH="/app/.venv/bin:$PATH" +# Install Python dependencies +COPY requirements.txt . +RUN pip install --no-cache-dir -r requirements.txt -# Compile bytecode -# Ref: https://docs.astral.sh/uv/guides/integration/docker/#compiling-bytecode -ENV UV_COMPILE_BYTECODE=1 +# Copy application code +COPY ./scripts /app/scripts +COPY ./alembic.ini /app/ +COPY ./app /app/app -# uv Cache -# Ref: https://docs.astral.sh/uv/guides/integration/docker/#caching -ENV UV_LINK_MODE=copy +# Create a non-root user +RUN useradd -m -u 1000 appuser && \ + chown -R appuser:appuser /app -# Install dependencies -# Ref: https://docs.astral.sh/uv/guides/integration/docker/#intermediate-layers -RUN --mount=type=cache,target=/root/.cache/uv \ - --mount=type=bind,source=uv.lock,target=uv.lock \ - --mount=type=bind,source=pyproject.toml,target=pyproject.toml \ - uv sync --frozen --no-install-project +# Switch to non-root user +USER appuser +# Set environment variables ENV PYTHONPATH=/app +ENV ENVIRONMENT=production -COPY ./scripts /app/scripts - -COPY ./pyproject.toml ./uv.lock ./alembic.ini /app/ - -COPY ./app /app/app - -# Sync the project -# Ref: https://docs.astral.sh/uv/guides/integration/docker/#intermediate-layers -RUN --mount=type=cache,target=/root/.cache/uv \ - uv sync +# Expose port +EXPOSE 8000 -CMD ["fastapi", "run", "--workers", "4", "app/main.py"] +# Start the application +CMD ["python3.11", "-m", "uvicorn", "app.main:app", "--host", "0.0.0.0", "--port", "8000", "--log-level", "debug"] \ No newline at end of file diff --git a/backend/app/core/db.py b/backend/app/core/db.py index ba991fb36d..3cfd9d1f1a 100644 --- a/backend/app/core/db.py +++ b/backend/app/core/db.py @@ -30,4 +30,4 @@ def init_db(session: Session) -> None: password=settings.FIRST_SUPERUSER_PASSWORD, is_superuser=True, ) - user = crud.create_user(session=session, user_create=user_in) + user = crud.create_user(session=session, user_create=user_in) \ No newline at end of file diff --git a/backend/bdmas.zip b/backend/bdmas.zip new file mode 100644 index 0000000000..dd7f4d798b Binary files /dev/null and b/backend/bdmas.zip differ diff --git a/backend/requirements.txt b/backend/requirements.txt new file mode 100644 index 0000000000..48b6e07bd9 --- /dev/null +++ b/backend/requirements.txt @@ -0,0 +1,17 @@ +fastapi[standard]>=0.114.2,<1.0.0 +python-multipart>=0.0.7,<1.0.0 +email-validator>=2.1.0.post1,<3.0.0.0 +passlib[bcrypt]>=1.7.4,<2.0.0 +tenacity>=8.2.3,<9.0.0 +pydantic>2.0 +emails>=0.6,<1.0 +jinja2>=3.1.4,<4.0.0 +alembic<2.0.0,>=1.12.1 +httpx>=0.25.1,<1.0.0 +psycopg[binary]<4.0.0,>=3.1.13 +sqlmodel>=0.0.21,<1.0.0 +bcrypt==4.0.1 +pydantic-settings>=2.2.1,<3.0.0 +sentry-sdk[fastapi]>=1.40.6,<2.0.0 +PyJWT>=2.8.0,<3.0.0 +python-dotenv>=1.0.0 \ No newline at end of file diff --git a/copier.yml b/copier.yml deleted file mode 100644 index f98e3fc861..0000000000 --- a/copier.yml +++ /dev/null @@ -1,100 +0,0 @@ -project_name: - type: str - help: The name of the project, shown to API users (in .env) - default: FastAPI Project - -stack_name: - type: str - help: The name of the stack used for Docker Compose labels (no spaces) (in .env) - default: fastapi-project - -secret_key: - type: str - help: | - 'The secret key for the project, used for security, - stored in .env, you can generate one with: - python -c "import secrets; print(secrets.token_urlsafe(32))"' - default: changethis - -first_superuser: - type: str - help: The email of the first superuser (in .env) - default: admin@example.com - -first_superuser_password: - type: str - help: The password of the first superuser (in .env) - default: changethis - -smtp_host: - type: str - help: The SMTP server host to send emails, you can set it later in .env - default: "" - -smtp_user: - type: str - help: The SMTP server user to send emails, you can set it later in .env - default: "" - -smtp_password: - type: str - help: The SMTP server password to send emails, you can set it later in .env - default: "" - -emails_from_email: - type: str - help: The email account to send emails from, you can set it later in .env - default: info@example.com - -postgres_password: - type: str - help: | - 'The password for the PostgreSQL database, stored in .env, - you can generate one with: - python -c "import secrets; print(secrets.token_urlsafe(32))"' - default: changethis - -sentry_dsn: - type: str - help: The DSN for Sentry, if you are using it, you can set it later in .env - default: "" - -_exclude: - # Global - - .vscode - - .mypy_cache - # Python - - __pycache__ - - app.egg-info - - "*.pyc" - - .mypy_cache - - .coverage - - htmlcov - - .cache - - .venv - # Frontend - # Logs - - logs - - "*.log" - - npm-debug.log* - - yarn-debug.log* - - yarn-error.log* - - pnpm-debug.log* - - lerna-debug.log* - - node_modules - - dist - - dist-ssr - - "*.local" - # Editor directories and files - - .idea - - .DS_Store - - "*.suo" - - "*.ntvs*" - - "*.njsproj" - - "*.sln" - - "*.sw?" - -_answers_file: .copier/.copier-answers.yml - -_tasks: - - ["{{ _copier_python }}", .copier/update_dotenv.py] diff --git a/deployment.md b/deployment.md deleted file mode 100644 index eadf76ddae..0000000000 --- a/deployment.md +++ /dev/null @@ -1,309 +0,0 @@ -# FastAPI Project - Deployment - -You can deploy the project using Docker Compose to a remote server. - -This project expects you to have a Traefik proxy handling communication to the outside world and HTTPS certificates. - -You can use CI/CD (continuous integration and continuous deployment) systems to deploy automatically, there are already configurations to do it with GitHub Actions. - -But you have to configure a couple things first. πŸ€“ - -## Preparation - -* Have a remote server ready and available. -* Configure the DNS records of your domain to point to the IP of the server you just created. -* Configure a wildcard subdomain for your domain, so that you can have multiple subdomains for different services, e.g. `*.fastapi-project.example.com`. This will be useful for accessing different components, like `dashboard.fastapi-project.example.com`, `api.fastapi-project.example.com`, `traefik.fastapi-project.example.com`, `adminer.fastapi-project.example.com`, etc. And also for `staging`, like `dashboard.staging.fastapi-project.example.com`, `adminer.staging..fastapi-project.example.com`, etc. -* Install and configure [Docker](https://docs.docker.com/engine/install/) on the remote server (Docker Engine, not Docker Desktop). - -## Public Traefik - -We need a Traefik proxy to handle incoming connections and HTTPS certificates. - -You need to do these next steps only once. - -### Traefik Docker Compose - -* Create a remote directory to store your Traefik Docker Compose file: - -```bash -mkdir -p /root/code/traefik-public/ -``` - -Copy the Traefik Docker Compose file to your server. You could do it by running the command `rsync` in your local terminal: - -```bash -rsync -a docker-compose.traefik.yml root@your-server.example.com:/root/code/traefik-public/ -``` - -### Traefik Public Network - -This Traefik will expect a Docker "public network" named `traefik-public` to communicate with your stack(s). - -This way, there will be a single public Traefik proxy that handles the communication (HTTP and HTTPS) with the outside world, and then behind that, you could have one or more stacks with different domains, even if they are on the same single server. - -To create a Docker "public network" named `traefik-public` run the following command in your remote server: - -```bash -docker network create traefik-public -``` - -### Traefik Environment Variables - -The Traefik Docker Compose file expects some environment variables to be set in your terminal before starting it. You can do it by running the following commands in your remote server. - -* Create the username for HTTP Basic Auth, e.g.: - -```bash -export USERNAME=admin -``` - -* Create an environment variable with the password for HTTP Basic Auth, e.g.: - -```bash -export PASSWORD=changethis -``` - -* Use openssl to generate the "hashed" version of the password for HTTP Basic Auth and store it in an environment variable: - -```bash -export HASHED_PASSWORD=$(openssl passwd -apr1 $PASSWORD) -``` - -To verify that the hashed password is correct, you can print it: - -```bash -echo $HASHED_PASSWORD -``` - -* Create an environment variable with the domain name for your server, e.g.: - -```bash -export DOMAIN=fastapi-project.example.com -``` - -* Create an environment variable with the email for Let's Encrypt, e.g.: - -```bash -export EMAIL=admin@example.com -``` - -**Note**: you need to set a different email, an email `@example.com` won't work. - -### Start the Traefik Docker Compose - -Go to the directory where you copied the Traefik Docker Compose file in your remote server: - -```bash -cd /root/code/traefik-public/ -``` - -Now with the environment variables set and the `docker-compose.traefik.yml` in place, you can start the Traefik Docker Compose running the following command: - -```bash -docker compose -f docker-compose.traefik.yml up -d -``` - -## Deploy the FastAPI Project - -Now that you have Traefik in place you can deploy your FastAPI project with Docker Compose. - -**Note**: You might want to jump ahead to the section about Continuous Deployment with GitHub Actions. - -## Environment Variables - -You need to set some environment variables first. - -Set the `ENVIRONMENT`, by default `local` (for development), but when deploying to a server you would put something like `staging` or `production`: - -```bash -export ENVIRONMENT=production -``` - -Set the `DOMAIN`, by default `localhost` (for development), but when deploying you would use your own domain, for example: - -```bash -export DOMAIN=fastapi-project.example.com -``` - -You can set several variables, like: - -* `PROJECT_NAME`: The name of the project, used in the API for the docs and emails. -* `STACK_NAME`: The name of the stack used for Docker Compose labels and project name, this should be different for `staging`, `production`, etc. You could use the same domain replacing dots with dashes, e.g. `fastapi-project-example-com` and `staging-fastapi-project-example-com`. -* `BACKEND_CORS_ORIGINS`: A list of allowed CORS origins separated by commas. -* `SECRET_KEY`: The secret key for the FastAPI project, used to sign tokens. -* `FIRST_SUPERUSER`: The email of the first superuser, this superuser will be the one that can create new users. -* `FIRST_SUPERUSER_PASSWORD`: The password of the first superuser. -* `SMTP_HOST`: The SMTP server host to send emails, this would come from your email provider (E.g. Mailgun, Sparkpost, Sendgrid, etc). -* `SMTP_USER`: The SMTP server user to send emails. -* `SMTP_PASSWORD`: The SMTP server password to send emails. -* `EMAILS_FROM_EMAIL`: The email account to send emails from. -* `POSTGRES_SERVER`: The hostname of the PostgreSQL server. You can leave the default of `db`, provided by the same Docker Compose. You normally wouldn't need to change this unless you are using a third-party provider. -* `POSTGRES_PORT`: The port of the PostgreSQL server. You can leave the default. You normally wouldn't need to change this unless you are using a third-party provider. -* `POSTGRES_PASSWORD`: The Postgres password. -* `POSTGRES_USER`: The Postgres user, you can leave the default. -* `POSTGRES_DB`: The database name to use for this application. You can leave the default of `app`. -* `SENTRY_DSN`: The DSN for Sentry, if you are using it. - -## GitHub Actions Environment Variables - -There are some environment variables only used by GitHub Actions that you can configure: - -* `LATEST_CHANGES`: Used by the GitHub Action [latest-changes](https://github.com/tiangolo/latest-changes) to automatically add release notes based on the PRs merged. It's a personal access token, read the docs for details. -* `SMOKESHOW_AUTH_KEY`: Used to handle and publish the code coverage using [Smokeshow](https://github.com/samuelcolvin/smokeshow), follow their instructions to create a (free) Smokeshow key. - -### Generate secret keys - -Some environment variables in the `.env` file have a default value of `changethis`. - -You have to change them with a secret key, to generate secret keys you can run the following command: - -```bash -python -c "import secrets; print(secrets.token_urlsafe(32))" -``` - -Copy the content and use that as password / secret key. And run that again to generate another secure key. - -### Deploy with Docker Compose - -With the environment variables in place, you can deploy with Docker Compose: - -```bash -docker compose -f docker-compose.yml up -d -``` - -For production you wouldn't want to have the overrides in `docker-compose.override.yml`, that's why we explicitly specify `docker-compose.yml` as the file to use. - -## Continuous Deployment (CD) - -You can use GitHub Actions to deploy your project automatically. 😎 - -You can have multiple environment deployments. - -There are already two environments configured, `staging` and `production`. πŸš€ - -### Install GitHub Actions Runner - -* On your remote server, create a user for your GitHub Actions: - -```bash -sudo adduser github -``` - -* Add Docker permissions to the `github` user: - -```bash -sudo usermod -aG docker github -``` - -* Temporarily switch to the `github` user: - -```bash -sudo su - github -``` - -* Go to the `github` user's home directory: - -```bash -cd -``` - -* [Install a GitHub Action self-hosted runner following the official guide](https://docs.github.com/en/actions/hosting-your-own-runners/managing-self-hosted-runners/adding-self-hosted-runners#adding-a-self-hosted-runner-to-a-repository). - -* When asked about labels, add a label for the environment, e.g. `production`. You can also add labels later. - -After installing, the guide would tell you to run a command to start the runner. Nevertheless, it would stop once you terminate that process or if your local connection to your server is lost. - -To make sure it runs on startup and continues running, you can install it as a service. To do that, exit the `github` user and go back to the `root` user: - -```bash -exit -``` - -After you do it, you will be on the previous user again. And you will be on the previous directory, belonging to that user. - -Before being able to go the `github` user directory, you need to become the `root` user (you might already be): - -```bash -sudo su -``` - -* As the `root` user, go to the `actions-runner` directory inside of the `github` user's home directory: - -```bash -cd /home/github/actions-runner -``` - -* Install the self-hosted runner as a service with the user `github`: - -```bash -./svc.sh install github -``` - -* Start the service: - -```bash -./svc.sh start -``` - -* Check the status of the service: - -```bash -./svc.sh status -``` - -You can read more about it in the official guide: [Configuring the self-hosted runner application as a service](https://docs.github.com/en/actions/hosting-your-own-runners/managing-self-hosted-runners/configuring-the-self-hosted-runner-application-as-a-service). - -### Set Secrets - -On your repository, configure secrets for the environment variables you need, the same ones described above, including `SECRET_KEY`, etc. Follow the [official GitHub guide for setting repository secrets](https://docs.github.com/en/actions/security-guides/using-secrets-in-github-actions#creating-secrets-for-a-repository). - -The current Github Actions workflows expect these secrets: - -* `DOMAIN_PRODUCTION` -* `DOMAIN_STAGING` -* `STACK_NAME_PRODUCTION` -* `STACK_NAME_STAGING` -* `EMAILS_FROM_EMAIL` -* `FIRST_SUPERUSER` -* `FIRST_SUPERUSER_PASSWORD` -* `POSTGRES_PASSWORD` -* `SECRET_KEY` -* `LATEST_CHANGES` -* `SMOKESHOW_AUTH_KEY` - -## GitHub Action Deployment Workflows - -There are GitHub Action workflows in the `.github/workflows` directory already configured for deploying to the environments (GitHub Actions runners with the labels): - -* `staging`: after pushing (or merging) to the branch `master`. -* `production`: after publishing a release. - -If you need to add extra environments you could use those as a starting point. - -## URLs - -Replace `fastapi-project.example.com` with your domain. - -### Main Traefik Dashboard - -Traefik UI: `https://traefik.fastapi-project.example.com` - -### Production - -Frontend: `https://dashboard.fastapi-project.example.com` - -Backend API docs: `https://api.fastapi-project.example.com/docs` - -Backend API base URL: `https://api.fastapi-project.example.com` - -Adminer: `https://adminer.fastapi-project.example.com` - -### Staging - -Frontend: `https://dashboard.staging.fastapi-project.example.com` - -Backend API docs: `https://api.staging.fastapi-project.example.com/docs` - -Backend API base URL: `https://api.staging.fastapi-project.example.com` - -Adminer: `https://adminer.staging.fastapi-project.example.com` diff --git a/development.md b/development.md deleted file mode 100644 index d7d41d73f1..0000000000 --- a/development.md +++ /dev/null @@ -1,207 +0,0 @@ -# FastAPI Project - Development - -## Docker Compose - -* Start the local stack with Docker Compose: - -```bash -docker compose watch -``` - -* Now you can open your browser and interact with these URLs: - -Frontend, built with Docker, with routes handled based on the path: http://localhost:5173 - -Backend, JSON based web API based on OpenAPI: http://localhost:8000 - -Automatic interactive documentation with Swagger UI (from the OpenAPI backend): http://localhost:8000/docs - -Adminer, database web administration: http://localhost:8080 - -Traefik UI, to see how the routes are being handled by the proxy: http://localhost:8090 - -**Note**: The first time you start your stack, it might take a minute for it to be ready. While the backend waits for the database to be ready and configures everything. You can check the logs to monitor it. - -To check the logs, run (in another terminal): - -```bash -docker compose logs -``` - -To check the logs of a specific service, add the name of the service, e.g.: - -```bash -docker compose logs backend -``` - -## Local Development - -The Docker Compose files are configured so that each of the services is available in a different port in `localhost`. - -For the backend and frontend, they use the same port that would be used by their local development server, so, the backend is at `http://localhost:8000` and the frontend at `http://localhost:5173`. - -This way, you could turn off a Docker Compose service and start its local development service, and everything would keep working, because it all uses the same ports. - -For example, you can stop that `frontend` service in the Docker Compose, in another terminal, run: - -```bash -docker compose stop frontend -``` - -And then start the local frontend development server: - -```bash -cd frontend -npm run dev -``` - -Or you could stop the `backend` Docker Compose service: - -```bash -docker compose stop backend -``` - -And then you can run the local development server for the backend: - -```bash -cd backend -fastapi dev app/main.py -``` - -## Docker Compose in `localhost.tiangolo.com` - -When you start the Docker Compose stack, it uses `localhost` by default, with different ports for each service (backend, frontend, adminer, etc). - -When you deploy it to production (or staging), it will deploy each service in a different subdomain, like `api.example.com` for the backend and `dashboard.example.com` for the frontend. - -In the guide about [deployment](deployment.md) you can read about Traefik, the configured proxy. That's the component in charge of transmitting traffic to each service based on the subdomain. - -If you want to test that it's all working locally, you can edit the local `.env` file, and change: - -```dotenv -DOMAIN=localhost.tiangolo.com -``` - -That will be used by the Docker Compose files to configure the base domain for the services. - -Traefik will use this to transmit traffic at `api.localhost.tiangolo.com` to the backend, and traffic at `dashboard.localhost.tiangolo.com` to the frontend. - -The domain `localhost.tiangolo.com` is a special domain that is configured (with all its subdomains) to point to `127.0.0.1`. This way you can use that for your local development. - -After you update it, run again: - -```bash -docker compose watch -``` - -When deploying, for example in production, the main Traefik is configured outside of the Docker Compose files. For local development, there's an included Traefik in `docker-compose.override.yml`, just to let you test that the domains work as expected, for example with `api.localhost.tiangolo.com` and `dashboard.localhost.tiangolo.com`. - -## Docker Compose files and env vars - -There is a main `docker-compose.yml` file with all the configurations that apply to the whole stack, it is used automatically by `docker compose`. - -And there's also a `docker-compose.override.yml` with overrides for development, for example to mount the source code as a volume. It is used automatically by `docker compose` to apply overrides on top of `docker-compose.yml`. - -These Docker Compose files use the `.env` file containing configurations to be injected as environment variables in the containers. - -They also use some additional configurations taken from environment variables set in the scripts before calling the `docker compose` command. - -After changing variables, make sure you restart the stack: - -```bash -docker compose watch -``` - -## The .env file - -The `.env` file is the one that contains all your configurations, generated keys and passwords, etc. - -Depending on your workflow, you could want to exclude it from Git, for example if your project is public. In that case, you would have to make sure to set up a way for your CI tools to obtain it while building or deploying your project. - -One way to do it could be to add each environment variable to your CI/CD system, and updating the `docker-compose.yml` file to read that specific env var instead of reading the `.env` file. - -## Pre-commits and code linting - -we are using a tool called [pre-commit](https://pre-commit.com/) for code linting and formatting. - -When you install it, it runs right before making a commit in git. This way it ensures that the code is consistent and formatted even before it is committed. - -You can find a file `.pre-commit-config.yaml` with configurations at the root of the project. - -#### Install pre-commit to run automatically - -`pre-commit` is already part of the dependencies of the project, but you could also install it globally if you prefer to, following [the official pre-commit docs](https://pre-commit.com/). - -After having the `pre-commit` tool installed and available, you need to "install" it in the local repository, so that it runs automatically before each commit. - -Using `uv`, you could do it with: - -```bash -❯ uv run pre-commit install -pre-commit installed at .git/hooks/pre-commit -``` - -Now whenever you try to commit, e.g. with: - -```bash -git commit -``` - -...pre-commit will run and check and format the code you are about to commit, and will ask you to add that code (stage it) with git again before committing. - -Then you can `git add` the modified/fixed files again and now you can commit. - -#### Running pre-commit hooks manually - -you can also run `pre-commit` manually on all the files, you can do it using `uv` with: - -```bash -❯ uv run pre-commit run --all-files -check for added large files..............................................Passed -check toml...............................................................Passed -check yaml...............................................................Passed -ruff.....................................................................Passed -ruff-format..............................................................Passed -eslint...................................................................Passed -prettier.................................................................Passed -``` - -## URLs - -The production or staging URLs would use these same paths, but with your own domain. - -### Development URLs - -Development URLs, for local development. - -Frontend: http://localhost:5173 - -Backend: http://localhost:8000 - -Automatic Interactive Docs (Swagger UI): http://localhost:8000/docs - -Automatic Alternative Docs (ReDoc): http://localhost:8000/redoc - -Adminer: http://localhost:8080 - -Traefik UI: http://localhost:8090 - -MailCatcher: http://localhost:1080 - -### Development URLs with `localhost.tiangolo.com` Configured - -Development URLs, for local development. - -Frontend: http://dashboard.localhost.tiangolo.com - -Backend: http://api.localhost.tiangolo.com - -Automatic Interactive Docs (Swagger UI): http://api.localhost.tiangolo.com/docs - -Automatic Alternative Docs (ReDoc): http://api.localhost.tiangolo.com/redoc - -Adminer: http://localhost.tiangolo.com:8080 - -Traefik UI: http://localhost.tiangolo.com:8090 - -MailCatcher: http://localhost.tiangolo.com:1080 \ No newline at end of file diff --git a/docker-compose.override.yml b/docker-compose.override.yml deleted file mode 100644 index 0751abe901..0000000000 --- a/docker-compose.override.yml +++ /dev/null @@ -1,133 +0,0 @@ -services: - - # Local services are available on their ports, but also available on: - # http://api.localhost.tiangolo.com: backend - # http://dashboard.localhost.tiangolo.com: frontend - # etc. To enable it, update .env, set: - # DOMAIN=localhost.tiangolo.com - proxy: - image: traefik:3.0 - volumes: - - /var/run/docker.sock:/var/run/docker.sock - ports: - - "80:80" - - "8090:8080" - # Duplicate the command from docker-compose.yml to add --api.insecure=true - command: - # Enable Docker in Traefik, so that it reads labels from Docker services - - --providers.docker - # Add a constraint to only use services with the label for this stack - - --providers.docker.constraints=Label(`traefik.constraint-label`, `traefik-public`) - # Do not expose all Docker services, only the ones explicitly exposed - - --providers.docker.exposedbydefault=false - # Create an entrypoint "http" listening on port 80 - - --entrypoints.http.address=:80 - # Create an entrypoint "https" listening on port 443 - - --entrypoints.https.address=:443 - # Enable the access log, with HTTP requests - - --accesslog - # Enable the Traefik log, for configurations and errors - - --log - # Enable debug logging for local development - - --log.level=DEBUG - # Enable the Dashboard and API - - --api - # Enable the Dashboard and API in insecure mode for local development - - --api.insecure=true - labels: - # Enable Traefik for this service, to make it available in the public network - - traefik.enable=true - - traefik.constraint-label=traefik-public - # Dummy https-redirect middleware that doesn't really redirect, only to - # allow running it locally - - traefik.http.middlewares.https-redirect.contenttype.autodetect=false - networks: - - traefik-public - - default - - db: - restart: "no" - ports: - - "5432:5432" - - adminer: - restart: "no" - ports: - - "8080:8080" - - backend: - restart: "no" - ports: - - "8000:8000" - build: - context: ./backend - # command: sleep infinity # Infinite loop to keep container alive doing nothing - command: - - fastapi - - run - - --reload - - "app/main.py" - develop: - watch: - - path: ./backend - action: sync - target: /app - ignore: - - ./backend/.venv - - .venv - - path: ./backend/pyproject.toml - action: rebuild - # TODO: remove once coverage is done locally - volumes: - - ./backend/htmlcov:/app/htmlcov - environment: - SMTP_HOST: "mailcatcher" - SMTP_PORT: "1025" - SMTP_TLS: "false" - EMAILS_FROM_EMAIL: "noreply@example.com" - - mailcatcher: - image: schickling/mailcatcher - ports: - - "1080:1080" - - "1025:1025" - - frontend: - restart: "no" - ports: - - "5173:80" - build: - context: ./frontend - args: - - VITE_API_URL=http://localhost:8000 - - NODE_ENV=development - - playwright: - build: - context: ./frontend - dockerfile: Dockerfile.playwright - args: - - VITE_API_URL=http://backend:8000 - - NODE_ENV=production - ipc: host - depends_on: - - backend - - mailcatcher - env_file: - - .env - environment: - - VITE_API_URL=http://backend:8000 - - MAILCATCHER_HOST=http://mailcatcher:1080 - # For the reports when run locally - - PLAYWRIGHT_HTML_HOST=0.0.0.0 - - CI=${CI} - volumes: - - ./frontend/blob-report:/app/blob-report - - ./frontend/test-results:/app/test-results - ports: - - 9323:9323 - -networks: - traefik-public: - # For local dev, don't expect an external Traefik network - external: false diff --git a/docker-compose.traefik.yml b/docker-compose.traefik.yml deleted file mode 100644 index 886d6dcc2f..0000000000 --- a/docker-compose.traefik.yml +++ /dev/null @@ -1,77 +0,0 @@ -services: - traefik: - image: traefik:3.0 - ports: - # Listen on port 80, default for HTTP, necessary to redirect to HTTPS - - 80:80 - # Listen on port 443, default for HTTPS - - 443:443 - restart: always - labels: - # Enable Traefik for this service, to make it available in the public network - - traefik.enable=true - # Use the traefik-public network (declared below) - - traefik.docker.network=traefik-public - # Define the port inside of the Docker service to use - - traefik.http.services.traefik-dashboard.loadbalancer.server.port=8080 - # Make Traefik use this domain (from an environment variable) in HTTP - - traefik.http.routers.traefik-dashboard-http.entrypoints=http - - traefik.http.routers.traefik-dashboard-http.rule=Host(`traefik.${DOMAIN?Variable not set}`) - # traefik-https the actual router using HTTPS - - traefik.http.routers.traefik-dashboard-https.entrypoints=https - - traefik.http.routers.traefik-dashboard-https.rule=Host(`traefik.${DOMAIN?Variable not set}`) - - traefik.http.routers.traefik-dashboard-https.tls=true - # Use the "le" (Let's Encrypt) resolver created below - - traefik.http.routers.traefik-dashboard-https.tls.certresolver=le - # Use the special Traefik service api@internal with the web UI/Dashboard - - traefik.http.routers.traefik-dashboard-https.service=api@internal - # https-redirect middleware to redirect HTTP to HTTPS - - traefik.http.middlewares.https-redirect.redirectscheme.scheme=https - - traefik.http.middlewares.https-redirect.redirectscheme.permanent=true - # traefik-http set up only to use the middleware to redirect to https - - traefik.http.routers.traefik-dashboard-http.middlewares=https-redirect - # admin-auth middleware with HTTP Basic auth - # Using the environment variables USERNAME and HASHED_PASSWORD - - traefik.http.middlewares.admin-auth.basicauth.users=${USERNAME?Variable not set}:${HASHED_PASSWORD?Variable not set} - # Enable HTTP Basic auth, using the middleware created above - - traefik.http.routers.traefik-dashboard-https.middlewares=admin-auth - volumes: - # Add Docker as a mounted volume, so that Traefik can read the labels of other services - - /var/run/docker.sock:/var/run/docker.sock:ro - # Mount the volume to store the certificates - - traefik-public-certificates:/certificates - command: - # Enable Docker in Traefik, so that it reads labels from Docker services - - --providers.docker - # Do not expose all Docker services, only the ones explicitly exposed - - --providers.docker.exposedbydefault=false - # Create an entrypoint "http" listening on port 80 - - --entrypoints.http.address=:80 - # Create an entrypoint "https" listening on port 443 - - --entrypoints.https.address=:443 - # Create the certificate resolver "le" for Let's Encrypt, uses the environment variable EMAIL - - --certificatesresolvers.le.acme.email=${EMAIL?Variable not set} - # Store the Let's Encrypt certificates in the mounted volume - - --certificatesresolvers.le.acme.storage=/certificates/acme.json - # Use the TLS Challenge for Let's Encrypt - - --certificatesresolvers.le.acme.tlschallenge=true - # Enable the access log, with HTTP requests - - --accesslog - # Enable the Traefik log, for configurations and errors - - --log - # Enable the Dashboard and API - - --api - networks: - # Use the public network created to be shared between Traefik and - # any other service that needs to be publicly available with HTTPS - - traefik-public - -volumes: - # Create a volume to store the certificates, even if the container is recreated - traefik-public-certificates: - -networks: - # Use the previously created public network "traefik-public", shared with other - # services that need to be publicly available via this Traefik - traefik-public: - external: true diff --git a/docker-compose.yml b/docker-compose.yml deleted file mode 100644 index c92d5d4451..0000000000 --- a/docker-compose.yml +++ /dev/null @@ -1,171 +0,0 @@ -services: - - db: - image: postgres:12 - restart: always - healthcheck: - test: ["CMD-SHELL", "pg_isready -U ${POSTGRES_USER} -d ${POSTGRES_DB}"] - interval: 10s - retries: 5 - start_period: 30s - timeout: 10s - volumes: - - app-db-data:/var/lib/postgresql/data/pgdata - env_file: - - .env - environment: - - PGDATA=/var/lib/postgresql/data/pgdata - - POSTGRES_PASSWORD=${POSTGRES_PASSWORD?Variable not set} - - POSTGRES_USER=${POSTGRES_USER?Variable not set} - - POSTGRES_DB=${POSTGRES_DB?Variable not set} - - adminer: - image: adminer - restart: always - networks: - - traefik-public - - default - depends_on: - - db - environment: - - ADMINER_DESIGN=pepa-linha-dark - labels: - - traefik.enable=true - - traefik.docker.network=traefik-public - - traefik.constraint-label=traefik-public - - traefik.http.routers.${STACK_NAME?Variable not set}-adminer-http.rule=Host(`adminer.${DOMAIN?Variable not set}`) - - traefik.http.routers.${STACK_NAME?Variable not set}-adminer-http.entrypoints=http - - traefik.http.routers.${STACK_NAME?Variable not set}-adminer-http.middlewares=https-redirect - - traefik.http.routers.${STACK_NAME?Variable not set}-adminer-https.rule=Host(`adminer.${DOMAIN?Variable not set}`) - - traefik.http.routers.${STACK_NAME?Variable not set}-adminer-https.entrypoints=https - - traefik.http.routers.${STACK_NAME?Variable not set}-adminer-https.tls=true - - traefik.http.routers.${STACK_NAME?Variable not set}-adminer-https.tls.certresolver=le - - traefik.http.services.${STACK_NAME?Variable not set}-adminer.loadbalancer.server.port=8080 - - prestart: - image: '${DOCKER_IMAGE_BACKEND?Variable not set}:${TAG-latest}' - build: - context: ./backend - networks: - - traefik-public - - default - depends_on: - db: - condition: service_healthy - restart: true - command: bash scripts/prestart.sh - env_file: - - .env - environment: - - DOMAIN=${DOMAIN} - - FRONTEND_HOST=${FRONTEND_HOST?Variable not set} - - ENVIRONMENT=${ENVIRONMENT} - - BACKEND_CORS_ORIGINS=${BACKEND_CORS_ORIGINS} - - SECRET_KEY=${SECRET_KEY?Variable not set} - - FIRST_SUPERUSER=${FIRST_SUPERUSER?Variable not set} - - FIRST_SUPERUSER_PASSWORD=${FIRST_SUPERUSER_PASSWORD?Variable not set} - - SMTP_HOST=${SMTP_HOST} - - SMTP_USER=${SMTP_USER} - - SMTP_PASSWORD=${SMTP_PASSWORD} - - EMAILS_FROM_EMAIL=${EMAILS_FROM_EMAIL} - - POSTGRES_SERVER=db - - POSTGRES_PORT=${POSTGRES_PORT} - - POSTGRES_DB=${POSTGRES_DB} - - POSTGRES_USER=${POSTGRES_USER?Variable not set} - - POSTGRES_PASSWORD=${POSTGRES_PASSWORD?Variable not set} - - SENTRY_DSN=${SENTRY_DSN} - - backend: - image: '${DOCKER_IMAGE_BACKEND?Variable not set}:${TAG-latest}' - restart: always - networks: - - traefik-public - - default - depends_on: - db: - condition: service_healthy - restart: true - prestart: - condition: service_completed_successfully - env_file: - - .env - environment: - - DOMAIN=${DOMAIN} - - FRONTEND_HOST=${FRONTEND_HOST?Variable not set} - - ENVIRONMENT=${ENVIRONMENT} - - BACKEND_CORS_ORIGINS=${BACKEND_CORS_ORIGINS} - - SECRET_KEY=${SECRET_KEY?Variable not set} - - FIRST_SUPERUSER=${FIRST_SUPERUSER?Variable not set} - - FIRST_SUPERUSER_PASSWORD=${FIRST_SUPERUSER_PASSWORD?Variable not set} - - SMTP_HOST=${SMTP_HOST} - - SMTP_USER=${SMTP_USER} - - SMTP_PASSWORD=${SMTP_PASSWORD} - - EMAILS_FROM_EMAIL=${EMAILS_FROM_EMAIL} - - POSTGRES_SERVER=db - - POSTGRES_PORT=${POSTGRES_PORT} - - POSTGRES_DB=${POSTGRES_DB} - - POSTGRES_USER=${POSTGRES_USER?Variable not set} - - POSTGRES_PASSWORD=${POSTGRES_PASSWORD?Variable not set} - - SENTRY_DSN=${SENTRY_DSN} - - healthcheck: - test: ["CMD", "curl", "-f", "http://localhost:8000/api/v1/utils/health-check/"] - interval: 10s - timeout: 5s - retries: 5 - - build: - context: ./backend - labels: - - traefik.enable=true - - traefik.docker.network=traefik-public - - traefik.constraint-label=traefik-public - - - traefik.http.services.${STACK_NAME?Variable not set}-backend.loadbalancer.server.port=8000 - - - traefik.http.routers.${STACK_NAME?Variable not set}-backend-http.rule=Host(`api.${DOMAIN?Variable not set}`) - - traefik.http.routers.${STACK_NAME?Variable not set}-backend-http.entrypoints=http - - - traefik.http.routers.${STACK_NAME?Variable not set}-backend-https.rule=Host(`api.${DOMAIN?Variable not set}`) - - traefik.http.routers.${STACK_NAME?Variable not set}-backend-https.entrypoints=https - - traefik.http.routers.${STACK_NAME?Variable not set}-backend-https.tls=true - - traefik.http.routers.${STACK_NAME?Variable not set}-backend-https.tls.certresolver=le - - # Enable redirection for HTTP and HTTPS - - traefik.http.routers.${STACK_NAME?Variable not set}-backend-http.middlewares=https-redirect - - frontend: - image: '${DOCKER_IMAGE_FRONTEND?Variable not set}:${TAG-latest}' - restart: always - networks: - - traefik-public - - default - build: - context: ./frontend - args: - - VITE_API_URL=https://api.${DOMAIN?Variable not set} - - NODE_ENV=production - labels: - - traefik.enable=true - - traefik.docker.network=traefik-public - - traefik.constraint-label=traefik-public - - - traefik.http.services.${STACK_NAME?Variable not set}-frontend.loadbalancer.server.port=80 - - - traefik.http.routers.${STACK_NAME?Variable not set}-frontend-http.rule=Host(`dashboard.${DOMAIN?Variable not set}`) - - traefik.http.routers.${STACK_NAME?Variable not set}-frontend-http.entrypoints=http - - - traefik.http.routers.${STACK_NAME?Variable not set}-frontend-https.rule=Host(`dashboard.${DOMAIN?Variable not set}`) - - traefik.http.routers.${STACK_NAME?Variable not set}-frontend-https.entrypoints=https - - traefik.http.routers.${STACK_NAME?Variable not set}-frontend-https.tls=true - - traefik.http.routers.${STACK_NAME?Variable not set}-frontend-https.tls.certresolver=le - - # Enable redirection for HTTP and HTTPS - - traefik.http.routers.${STACK_NAME?Variable not set}-frontend-http.middlewares=https-redirect -volumes: - app-db-data: - -networks: - traefik-public: - # Allow setting it to false for testing - external: true diff --git a/frontend/Dockerfile b/frontend/Dockerfile index 8728c7b029..9e7a730c42 100644 --- a/frontend/Dockerfile +++ b/frontend/Dockerfile @@ -5,17 +5,21 @@ WORKDIR /app COPY package*.json /app/ +# Install dependencies RUN npm install +# Copy all source files COPY ./ /app/ -ARG VITE_API_URL=${VITE_API_URL} +# Set the API URL for the build +ARG VITE_API_URL=http://localhost:8000 +ENV VITE_API_URL=${VITE_API_URL} RUN npm run build # Stage 1, based on Nginx, to have only the compiled app, ready for production with Nginx -FROM nginx:1 +FROM nginx:alpine COPY --from=build-stage /app/dist/ /usr/share/nginx/html diff --git a/helm/Chart.yaml b/helm/Chart.yaml new file mode 100644 index 0000000000..0818bfed04 --- /dev/null +++ b/helm/Chart.yaml @@ -0,0 +1,6 @@ +apiVersion: v2 +name: sdp +description: A Helm chart for deploying the FastAPI fullstack application +type: application +version: 0.1.0 +appVersion: "1.0.0" \ No newline at end of file diff --git a/helm/templates/adminer-deployment.yaml b/helm/templates/adminer-deployment.yaml new file mode 100644 index 0000000000..8fb29310ba --- /dev/null +++ b/helm/templates/adminer-deployment.yaml @@ -0,0 +1,35 @@ +# Adminer Deployment +{{- if .Values.adminer.enabled }} +apiVersion: apps/v1 +kind: Deployment +metadata: + name: {{ .Release.Name }}-adminer + labels: + app: adminer +spec: + replicas: {{ .Values.adminer.replicaCount }} + selector: + matchLabels: + app: adminer + template: + metadata: + labels: + app: adminer + spec: + containers: + - name: adminer + image: "{{ .Values.adminer.image.repository }}:{{ .Values.adminer.image.tag }}" + imagePullPolicy: {{ .Values.adminer.image.pullPolicy }} + ports: + - containerPort: {{ .Values.adminer.service.port }} + volumeMounts: + {{- range .Values.adminer.volumeMounts }} + - name: {{ .name }} + mountPath: {{ .mountPath }} + {{- end }} + volumes: + {{- range .Values.adminer.volumes }} + - name: {{ .name }} + emptyDir: {} + {{- end }} +{{- end }} \ No newline at end of file diff --git a/helm/templates/adminer-service.yaml b/helm/templates/adminer-service.yaml new file mode 100644 index 0000000000..b5e07371d8 --- /dev/null +++ b/helm/templates/adminer-service.yaml @@ -0,0 +1,16 @@ +# Adminer Service +{{- if .Values.adminer.enabled }} +apiVersion: v1 +kind: Service +metadata: + name: {{ .Release.Name }}-adminer + labels: + app: adminer +spec: + type: {{ .Values.adminer.service.type }} + ports: + - port: {{ .Values.adminer.service.port }} + targetPort: {{ .Values.adminer.service.port }} + selector: + app: adminer +{{- end }} \ No newline at end of file diff --git a/helm/templates/backend-deployment.yaml b/helm/templates/backend-deployment.yaml new file mode 100644 index 0000000000..c5659175d2 --- /dev/null +++ b/helm/templates/backend-deployment.yaml @@ -0,0 +1,126 @@ +{{- if .Values.backend.enabled }} +apiVersion: apps/v1 +kind: Deployment +metadata: + name: {{ .Release.Name }}-backend + labels: + app.kubernetes.io/name: {{ .Release.Name }} + app.kubernetes.io/instance: {{ .Release.Name }} + app.kubernetes.io/component: backend +spec: + replicas: {{ .Values.backend.replicaCount }} + selector: + matchLabels: + app.kubernetes.io/name: {{ .Release.Name }} + app.kubernetes.io/instance: {{ .Release.Name }} + app.kubernetes.io/component: backend + template: + metadata: + labels: + app.kubernetes.io/name: {{ .Release.Name }} + app.kubernetes.io/instance: {{ .Release.Name }} + app.kubernetes.io/component: backend + spec: + initContainers: + - name: init-db + image: "{{ .Values.backend.image.repository }}:{{ .Values.backend.image.tag }}" + command: ["sh", "-c", "mkdir -p /app/data && chmod 777 /app/data"] + securityContext: + runAsUser: 0 + volumeMounts: + - name: app-db-data + mountPath: /app/data + - name: wait-for-prestart + image: postgres:12 + command: ['sh', '-c', 'until pg_isready -h {{ .Release.Name }}-db -p 5432 -U postgres -d app; do echo "waiting for database..."; sleep 2; done'] + env: + - name: PGPASSWORD + value: {{ .Values.db.env.POSTGRES_PASSWORD | quote }} + containers: + - name: backend + image: "{{ .Values.backend.image.repository }}:{{ .Values.backend.image.tag }}" + imagePullPolicy: {{ .Values.backend.image.pullPolicy }} + ports: + - name: http + containerPort: 8000 + protocol: TCP + resources: + {{- toYaml .Values.backend.resources | nindent 12 }} + envFrom: + - configMapRef: + name: {{ .Release.Name }}-config + - secretRef: + name: {{ .Release.Name }}-secrets + env: + - name: PYTHONPATH + value: "/app" + - name: PROJECT_NAME + value: {{ .Values.backend.env.PROJECT_NAME | quote }} + - name: ENVIRONMENT + value: {{ .Values.backend.env.ENVIRONMENT | quote }} + - name: FIRST_SUPERUSER + value: {{ .Values.backend.env.FIRST_SUPERUSER | quote }} + - name: FIRST_SUPERUSER_PASSWORD + value: {{ .Values.backend.env.FIRST_SUPERUSER_PASSWORD | quote }} + - name: FRONTEND_HOST + value: {{ .Values.backend.env.FRONTEND_HOST | quote }} + - name: SECRET_KEY + value: {{ .Values.backend.env.SECRET_KEY | quote }} + - name: BACKEND_CORS_ORIGINS + value: {{ .Values.backend.env.BACKEND_CORS_ORIGINS | quote }} + - name: SMTP_HOST + value: {{ .Values.backend.env.SMTP_HOST | quote }} + - name: SMTP_USER + value: {{ .Values.backend.env.SMTP_USER | quote }} + - name: SMTP_PASSWORD + value: {{ .Values.backend.env.SMTP_PASSWORD | quote }} + - name: EMAILS_FROM_EMAIL + value: {{ .Values.backend.env.EMAILS_FROM_EMAIL | quote }} + - name: SENTRY_DSN + value: {{ .Values.backend.env.SENTRY_DSN | quote }} + - name: POSTGRES_SERVER + value: {{ .Values.backend.env.POSTGRES_SERVER | quote }} + - name: POSTGRES_PORT + value: {{ .Values.backend.env.POSTGRES_PORT | quote }} + - name: POSTGRES_DB + value: {{ .Values.backend.env.POSTGRES_DB | quote }} + - name: POSTGRES_USER + value: {{ .Values.backend.env.POSTGRES_USER | quote }} + - name: POSTGRES_PASSWORD + value: {{ .Values.backend.env.POSTGRES_PASSWORD | quote }} + volumeMounts: + - name: app-db-data + mountPath: /app/data + command: ["sh", "-c"] + args: + - | + echo "Current directory: $(pwd)" && + echo "Python path: $PYTHONPATH" && + echo "Contents of /app: $(ls -la /app)" && + echo "Python version: $(python3.11 --version)" && + python3.11 -m app.backend_pre_start && + python3.11 -m uvicorn app.main:app --host 0.0.0.0 --port 8000 --log-level debug + startupProbe: + httpGet: + path: /api/v1/utils/health-check/ + port: http + failureThreshold: 30 + periodSeconds: 10 + livenessProbe: + httpGet: + path: /api/v1/utils/health-check/ + port: http + initialDelaySeconds: 30 + periodSeconds: 10 + failureThreshold: 3 + readinessProbe: + httpGet: + path: /api/v1/utils/health-check/ + port: http + initialDelaySeconds: 5 + periodSeconds: 10 + failureThreshold: 3 + volumes: + - name: app-db-data + emptyDir: {} +{{- end }} \ No newline at end of file diff --git a/helm/templates/backend-service.yaml b/helm/templates/backend-service.yaml new file mode 100644 index 0000000000..199d656e34 --- /dev/null +++ b/helm/templates/backend-service.yaml @@ -0,0 +1,17 @@ +apiVersion: v1 +kind: Service +metadata: + name: {{ .Release.Name }}-backend + labels: + app.kubernetes.io/name: {{ .Release.Name }}-backend + app.kubernetes.io/instance: {{ .Release.Name }} +spec: + type: {{ .Values.backend.service.type }} + ports: + - port: {{ .Values.backend.service.port }} + targetPort: http + protocol: TCP + name: http + selector: + app.kubernetes.io/name: {{ .Release.Name }}-backend + app.kubernetes.io/instance: {{ .Release.Name }} \ No newline at end of file diff --git a/helm/templates/configmap.yaml b/helm/templates/configmap.yaml new file mode 100644 index 0000000000..4e51c2fe97 --- /dev/null +++ b/helm/templates/configmap.yaml @@ -0,0 +1,15 @@ +apiVersion: v1 +kind: ConfigMap +metadata: + name: {{ .Release.Name }}-config +data: + DOMAIN: {{ .Values.global.domain | quote }} + ENVIRONMENT: {{ .Values.global.environment | quote }} + FRONTEND_HOST: {{ .Values.backend.env.FRONTEND_HOST | quote }} + BACKEND_CORS_ORIGINS: {{ .Values.backend.env.BACKEND_CORS_ORIGINS | default "*" | quote }} + SMTP_HOST: {{ .Values.backend.env.SMTP_HOST | default "" | quote }} + EMAILS_FROM_EMAIL: {{ .Values.backend.env.EMAILS_FROM_EMAIL | default "" | quote }} + POSTGRES_SERVER: {{ .Release.Name }}-db + POSTGRES_PORT: "5432" + SENTRY_DSN: {{ .Values.backend.env.SENTRY_DSN | default "" | quote }} + DATABASE_URL: postgresql://{{ .Values.db.env.POSTGRES_USER }}:{{ .Values.db.env.POSTGRES_PASSWORD }}@{{ .Release.Name }}-db:5432/{{ .Values.db.env.POSTGRES_DB }} \ No newline at end of file diff --git a/helm/templates/db-deployment.yaml b/helm/templates/db-deployment.yaml new file mode 100644 index 0000000000..42c87d18cb --- /dev/null +++ b/helm/templates/db-deployment.yaml @@ -0,0 +1,72 @@ +{{- if .Values.db.enabled }} +apiVersion: apps/v1 +kind: Deployment +metadata: + name: {{ .Release.Name }}-db + labels: + app.kubernetes.io/name: {{ .Release.Name }}-db + app.kubernetes.io/instance: {{ .Release.Name }} +spec: + replicas: 1 + selector: + matchLabels: + app.kubernetes.io/name: {{ .Release.Name }}-db + app.kubernetes.io/instance: {{ .Release.Name }} + template: + metadata: + labels: + app.kubernetes.io/name: {{ .Release.Name }}-db + app.kubernetes.io/instance: {{ .Release.Name }} + spec: + containers: + - name: postgres + image: "{{ .Values.db.image.repository }}:{{ .Values.db.image.tag }}" + imagePullPolicy: {{ .Values.db.image.pullPolicy }} + ports: + - name: postgres + containerPort: 5432 + protocol: TCP + envFrom: + - secretRef: + name: {{ .Release.Name }}-secrets + - configMapRef: + name: {{ .Release.Name }}-config + env: + - name: PGDATA + value: /var/lib/postgresql/data/pgdata + volumeMounts: + - name: postgres-data + mountPath: /var/lib/postgresql/data + resources: + {{- toYaml .Values.db.resources | nindent 12 }} + livenessProbe: + exec: + command: + - pg_isready + - -U + - "{{ .Values.db.env.POSTGRES_USER }}" + - -d + - "{{ .Values.db.env.POSTGRES_DB }}" + initialDelaySeconds: 30 + periodSeconds: 10 + timeoutSeconds: 5 + successThreshold: 1 + failureThreshold: 3 + readinessProbe: + exec: + command: + - pg_isready + - -U + - "{{ .Values.db.env.POSTGRES_USER }}" + - -d + - "{{ .Values.db.env.POSTGRES_DB }}" + initialDelaySeconds: 5 + periodSeconds: 10 + timeoutSeconds: 5 + successThreshold: 1 + failureThreshold: 3 + volumes: + - name: postgres-data + persistentVolumeClaim: + claimName: {{ .Release.Name }}-db-pvc +{{- end }} \ No newline at end of file diff --git a/helm/templates/db-pvc.yaml b/helm/templates/db-pvc.yaml new file mode 100644 index 0000000000..2f362b35db --- /dev/null +++ b/helm/templates/db-pvc.yaml @@ -0,0 +1,10 @@ +apiVersion: v1 +kind: PersistentVolumeClaim +metadata: + name: {{ .Release.Name }}-db-pvc +spec: + accessModes: + - ReadWriteOnce + resources: + requests: + storage: {{ .Values.db.persistence.size | default "10Gi" }} \ No newline at end of file diff --git a/helm/templates/db-service.yaml b/helm/templates/db-service.yaml new file mode 100644 index 0000000000..de5fa3cd44 --- /dev/null +++ b/helm/templates/db-service.yaml @@ -0,0 +1,13 @@ +apiVersion: v1 +kind: Service +metadata: + name: {{ .Release.Name }}-db +spec: + type: {{ .Values.db.service.type }} + selector: + app.kubernetes.io/name: {{ .Release.Name }}-db + app.kubernetes.io/instance: {{ .Release.Name }} + ports: + - protocol: TCP + port: {{ .Values.db.service.port }} + targetPort: {{ .Values.db.service.port }} \ No newline at end of file diff --git a/helm/templates/frontend-deployment.yaml b/helm/templates/frontend-deployment.yaml new file mode 100644 index 0000000000..089492e1ee --- /dev/null +++ b/helm/templates/frontend-deployment.yaml @@ -0,0 +1,31 @@ +{{- if .Values.frontend.enabled }} +apiVersion: apps/v1 +kind: Deployment +metadata: + name: {{ .Release.Name }}-frontend + labels: + app: {{ .Release.Name }}-frontend +spec: + replicas: {{ .Values.frontend.replicaCount }} + selector: + matchLabels: + app: {{ .Release.Name }}-frontend + template: + metadata: + labels: + app: {{ .Release.Name }}-frontend + spec: + containers: + - name: frontend + image: {{ .Values.frontend.image.repository }}:{{ .Values.frontend.image.tag }} + imagePullPolicy: {{ .Values.frontend.image.pullPolicy }} + ports: + - containerPort: 80 + resources: + {{- toYaml .Values.frontend.resources | nindent 12 }} + env: + {{- range $key, $value := .Values.frontend.env }} + - name: {{ $key }} + value: {{ $value | quote }} + {{- end }} +{{- end }} \ No newline at end of file diff --git a/helm/templates/frontend-service.yaml b/helm/templates/frontend-service.yaml new file mode 100644 index 0000000000..c52af00811 --- /dev/null +++ b/helm/templates/frontend-service.yaml @@ -0,0 +1,15 @@ +apiVersion: v1 +kind: Service +metadata: + name: {{ .Release.Name }}-frontend + labels: + app: {{ .Release.Name }}-frontend +spec: + type: {{ .Values.frontend.service.type }} + ports: + - port: {{ .Values.frontend.service.port }} + targetPort: 80 + protocol: TCP + name: http + selector: + app: {{ .Release.Name }}-frontend \ No newline at end of file diff --git a/helm/templates/ingress.yaml b/helm/templates/ingress.yaml new file mode 100644 index 0000000000..7307612b65 --- /dev/null +++ b/helm/templates/ingress.yaml @@ -0,0 +1,43 @@ +{{- if .Values.ingress.enabled -}} +apiVersion: networking.k8s.io/v1 +kind: Ingress +metadata: + name: {{ .Release.Name }}-ingress + annotations: + {{- with .Values.ingress.annotations }} + {{- toYaml . | nindent 4 }} + {{- end }} +spec: + ingressClassName: {{ .Values.ingress.className }} + {{- if .Values.ingress.tls }} + tls: + {{- range .Values.ingress.tls }} + - hosts: + {{- range .hosts }} + - {{ . | quote }} + {{- end }} + secretName: {{ .secretName }} + {{- end }} + {{- end }} + rules: + {{- range .Values.ingress.hosts }} + - host: {{ .host | quote }} + http: + paths: + {{- range .paths }} + - path: {{ .path }} + pathType: {{ .pathType }} + backend: + service: + name: {{ $.Release.Name }}-{{ .service }} + port: + {{- if eq .service "frontend" }} + number: {{ $.Values.frontend.service.port }} + {{- else if eq .service "backend" }} + number: {{ $.Values.backend.service.port }} + {{- else if eq .service "adminer" }} + number: {{ $.Values.adminer.service.port }} + {{- end }} + {{- end }} + {{- end }} +{{- end }} \ No newline at end of file diff --git a/helm/templates/prestart-job.yaml b/helm/templates/prestart-job.yaml new file mode 100644 index 0000000000..2b1c6b6baa --- /dev/null +++ b/helm/templates/prestart-job.yaml @@ -0,0 +1,73 @@ +{{- if .Values.prestart.enabled }} +apiVersion: batch/v1 +kind: Job +metadata: + name: {{ .Release.Name }}-prestart + labels: + app.kubernetes.io/name: {{ .Release.Name }} + app.kubernetes.io/instance: {{ .Release.Name }} + app.kubernetes.io/component: prestart +spec: + template: + metadata: + labels: + app.kubernetes.io/name: {{ .Release.Name }} + app.kubernetes.io/instance: {{ .Release.Name }} + app.kubernetes.io/component: prestart + spec: + initContainers: + - name: wait-for-db + image: postgres:12 + command: ['sh', '-c', 'until pg_isready -h {{ .Release.Name }}-db -p 5432 -U postgres -d app; do echo "waiting for database..."; sleep 2; done'] + env: + - name: PGPASSWORD + value: {{ .Values.db.env.POSTGRES_PASSWORD | quote }} + containers: + - name: prestart + image: {{ .Values.prestart.image.repository }}:{{ .Values.prestart.image.tag }} + imagePullPolicy: {{ .Values.prestart.image.pullPolicy }} + command: ["bash", "scripts/prestart.sh"] + env: + - name: PROJECT_NAME + value: {{ .Values.prestart.env.PROJECT_NAME | quote }} + - name: ENVIRONMENT + value: {{ .Values.prestart.env.ENVIRONMENT | quote }} + - name: FIRST_SUPERUSER + value: {{ .Values.prestart.env.FIRST_SUPERUSER | quote }} + - name: FIRST_SUPERUSER_PASSWORD + value: {{ .Values.prestart.env.FIRST_SUPERUSER_PASSWORD | quote }} + - name: FRONTEND_HOST + value: {{ .Values.prestart.env.FRONTEND_HOST | quote }} + - name: SECRET_KEY + value: {{ .Values.prestart.env.SECRET_KEY | quote }} + - name: BACKEND_CORS_ORIGINS + value: {{ .Values.prestart.env.BACKEND_CORS_ORIGINS | quote }} + - name: SMTP_HOST + value: {{ .Values.prestart.env.SMTP_HOST | quote }} + - name: SMTP_USER + value: {{ .Values.prestart.env.SMTP_USER | quote }} + - name: SMTP_PASSWORD + value: {{ .Values.prestart.env.SMTP_PASSWORD | quote }} + - name: EMAILS_FROM_EMAIL + value: {{ .Values.prestart.env.EMAILS_FROM_EMAIL | quote }} + - name: SENTRY_DSN + value: {{ .Values.prestart.env.SENTRY_DSN | quote }} + - name: POSTGRES_SERVER + value: {{ .Values.prestart.env.POSTGRES_SERVER | quote }} + - name: POSTGRES_PORT + value: {{ .Values.prestart.env.POSTGRES_PORT | quote }} + - name: POSTGRES_DB + value: {{ .Values.prestart.env.POSTGRES_DB | quote }} + - name: POSTGRES_USER + value: {{ .Values.prestart.env.POSTGRES_USER | quote }} + - name: POSTGRES_PASSWORD + value: {{ .Values.prestart.env.POSTGRES_PASSWORD | quote }} + resources: + limits: + cpu: {{ .Values.prestart.resources.limits.cpu }} + memory: {{ .Values.prestart.resources.limits.memory }} + requests: + cpu: {{ .Values.prestart.resources.requests.cpu }} + memory: {{ .Values.prestart.resources.requests.memory }} + restartPolicy: OnFailure +{{- end }} \ No newline at end of file diff --git a/helm/templates/secrets.yaml b/helm/templates/secrets.yaml new file mode 100644 index 0000000000..ad36605756 --- /dev/null +++ b/helm/templates/secrets.yaml @@ -0,0 +1,16 @@ +apiVersion: v1 +kind: Secret +metadata: + name: {{ .Release.Name }}-secrets +type: Opaque +data: + POSTGRES_SERVER: {{ .Values.db.env.POSTGRES_SERVER | quote }} + POSTGRES_PORT: {{ .Values.db.env.POSTGRES_PORT | quote }} + POSTGRES_DB: {{ .Values.db.env.POSTGRES_DB | b64enc }} + POSTGRES_USER: {{ .Values.db.env.POSTGRES_USER | b64enc }} + POSTGRES_PASSWORD: {{ .Values.db.env.POSTGRES_PASSWORD | b64enc }} + SECRET_KEY: {{ .Values.backend.env.SECRET_KEY | b64enc }} + FIRST_SUPERUSER: {{ .Values.backend.env.FIRST_SUPERUSER | b64enc }} + FIRST_SUPERUSER_PASSWORD: {{ .Values.backend.env.FIRST_SUPERUSER_PASSWORD | b64enc }} + SMTP_USER: {{ .Values.backend.env.SMTP_USER | default "" | b64enc }} + SMTP_PASSWORD: {{ .Values.backend.env.SMTP_PASSWORD | default "" | b64enc }} \ No newline at end of file diff --git a/helm/values.yaml b/helm/values.yaml new file mode 100644 index 0000000000..ff13d7c107 --- /dev/null +++ b/helm/values.yaml @@ -0,0 +1,214 @@ +# Global values +global: + environment: production + domain: example.com + +# Backend configuration +backend: + enabled: true + image: + repository: dperezsa/sdp-backend + tag: 1.0.0 + pullPolicy: IfNotPresent + replicaCount: 1 + resources: + limits: + cpu: 500m + memory: 512Mi + requests: + cpu: 200m + memory: 256Mi + service: + type: ClusterIP + port: 8000 + env: + PROJECT_NAME: Service Data Platform + ENVIRONMENT: production + FIRST_SUPERUSER: admin@example.com + FIRST_SUPERUSER_PASSWORD: changeme123 + FRONTEND_HOST: http://localhost:5173 + SECRET_KEY: changeme123 + BACKEND_CORS_ORIGINS: '["http://localhost", "https://dashboard.example.com"]' + SMTP_HOST: "" + SMTP_USER: "" + SMTP_PASSWORD: "" + EMAILS_FROM_EMAIL: "" + SENTRY_DSN: "" + POSTGRES_SERVER: sdp-db + POSTGRES_PORT: 5432 + POSTGRES_DB: app + POSTGRES_USER: postgres + POSTGRES_PASSWORD: changeme123 + volumeMounts: + - name: app-db-data + mountPath: /app/data + volumes: + - name: app-db-data + emptyDir: {} + +# Prestart configuration +prestart: + enabled: true + image: + repository: dperezsa/sdp-backend + tag: 1.0.0 + pullPolicy: IfNotPresent + resources: + limits: + cpu: 500m + memory: 512Mi + requests: + cpu: 200m + memory: 256Mi + env: + PROJECT_NAME: Service Data Platform + ENVIRONMENT: production + FIRST_SUPERUSER: admin@example.com + FIRST_SUPERUSER_PASSWORD: changeme123 + FRONTEND_HOST: http://localhost:5173 + SECRET_KEY: changeme123 + BACKEND_CORS_ORIGINS: '["http://localhost", "https://dashboard.example.com"]' + SMTP_HOST: "" + SMTP_USER: "" + SMTP_PASSWORD: "" + EMAILS_FROM_EMAIL: "" + SENTRY_DSN: "" + POSTGRES_SERVER: sdp-db + POSTGRES_PORT: 5432 + POSTGRES_DB: app + POSTGRES_USER: postgres + POSTGRES_PASSWORD: changeme123 + +# Frontend configuration +frontend: + enabled: true + image: + repository: dperezsa/sdp-frontend + tag: 1.0.0 + pullPolicy: IfNotPresent + replicaCount: 1 + resources: + limits: + cpu: 200m + memory: 256Mi + requests: + cpu: 100m + memory: 128Mi + service: + type: ClusterIP + port: 80 + env: + VITE_API_URL: http://{{ .Release.Name }}-backend.default.svc.cluster.local:8000 + +# Adminer configuration +adminer: + enabled: true + image: + repository: dperezsa/adminer + tag: latest + pullPolicy: IfNotPresent + replicaCount: 1 + resources: + limits: + cpu: 200m + memory: 256Mi + requests: + cpu: 100m + memory: 128Mi + service: + type: ClusterIP + port: 8080 + env: + ADMINER_DESIGN: pepa-linha-dark + volumeMounts: + - name: app-db-data + mountPath: /var/www/html/data + volumes: + - name: app-db-data + emptyDir: {} + +# Database configuration +db: + enabled: true + image: + repository: postgres + tag: "12" + pullPolicy: IfNotPresent + replicaCount: 1 + resources: + limits: + cpu: 500m + memory: 512Mi + requests: + cpu: 200m + memory: 256Mi + service: + type: ClusterIP + port: 5432 + env: + POSTGRES_PASSWORD: changeme123 + POSTGRES_DB: app + POSTGRES_USER: postgres + POSTGRES_HOST_AUTH_METHOD: trust + config: + PGDATA: /var/lib/postgresql/data/pgdata + volumeMounts: + - name: postgres-data + mountPath: /var/lib/postgresql/data + volumes: + - name: postgres-data + persistentVolumeClaim: + claimName: sdp-db-pvc + persistence: + size: 10Gi + postgresqlConfig: + max_connections: "100" + shared_buffers: "128MB" + effective_cache_size: "256MB" + maintenance_work_mem: "64MB" + checkpoint_completion_target: "0.9" + wal_buffers: "16MB" + default_statistics_target: "100" + random_page_cost: "1.1" + effective_io_concurrency: "200" + work_mem: "4MB" + min_wal_size: "1GB" + max_wal_size: "4GB" + max_worker_processes: "2" + max_parallel_workers_per_gather: "1" + max_parallel_workers: "2" + max_parallel_maintenance_workers: "2" + + +# Ingress configuration +ingress: + enabled: true + className: nginx + annotations: + cert-manager.io/cluster-issuer: letsencrypt-prod + hosts: + - host: dashboard.example.com + paths: + - path: / + pathType: Prefix + service: frontend + - host: api.example.com + paths: + - path: / + pathType: Prefix + service: backend + - host: adminer.example.com + paths: + - path: / + pathType: Prefix + service: adminer + tls: + - secretName: dashboard-tls + hosts: + - dashboard.example.com + - secretName: api-tls + hosts: + - api.example.com + - secretName: adminer-tls + hosts: + - adminer.example.com \ No newline at end of file diff --git a/k8s/.helmignore b/k8s/.helmignore new file mode 100644 index 0000000000..e69de29bb2 diff --git a/k8s/Chart.yaml b/k8s/Chart.yaml new file mode 100644 index 0000000000..0818bfed04 --- /dev/null +++ b/k8s/Chart.yaml @@ -0,0 +1,6 @@ +apiVersion: v2 +name: sdp +description: A Helm chart for deploying the FastAPI fullstack application +type: application +version: 0.1.0 +appVersion: "1.0.0" \ No newline at end of file diff --git a/k8s/templates/adminer-deployment.yaml b/k8s/templates/adminer-deployment.yaml new file mode 100644 index 0000000000..8fb29310ba --- /dev/null +++ b/k8s/templates/adminer-deployment.yaml @@ -0,0 +1,35 @@ +# Adminer Deployment +{{- if .Values.adminer.enabled }} +apiVersion: apps/v1 +kind: Deployment +metadata: + name: {{ .Release.Name }}-adminer + labels: + app: adminer +spec: + replicas: {{ .Values.adminer.replicaCount }} + selector: + matchLabels: + app: adminer + template: + metadata: + labels: + app: adminer + spec: + containers: + - name: adminer + image: "{{ .Values.adminer.image.repository }}:{{ .Values.adminer.image.tag }}" + imagePullPolicy: {{ .Values.adminer.image.pullPolicy }} + ports: + - containerPort: {{ .Values.adminer.service.port }} + volumeMounts: + {{- range .Values.adminer.volumeMounts }} + - name: {{ .name }} + mountPath: {{ .mountPath }} + {{- end }} + volumes: + {{- range .Values.adminer.volumes }} + - name: {{ .name }} + emptyDir: {} + {{- end }} +{{- end }} \ No newline at end of file diff --git a/k8s/templates/adminer-service.yaml b/k8s/templates/adminer-service.yaml new file mode 100644 index 0000000000..b5e07371d8 --- /dev/null +++ b/k8s/templates/adminer-service.yaml @@ -0,0 +1,16 @@ +# Adminer Service +{{- if .Values.adminer.enabled }} +apiVersion: v1 +kind: Service +metadata: + name: {{ .Release.Name }}-adminer + labels: + app: adminer +spec: + type: {{ .Values.adminer.service.type }} + ports: + - port: {{ .Values.adminer.service.port }} + targetPort: {{ .Values.adminer.service.port }} + selector: + app: adminer +{{- end }} \ No newline at end of file diff --git a/k8s/templates/backend-deployment.yaml b/k8s/templates/backend-deployment.yaml new file mode 100644 index 0000000000..c5659175d2 --- /dev/null +++ b/k8s/templates/backend-deployment.yaml @@ -0,0 +1,126 @@ +{{- if .Values.backend.enabled }} +apiVersion: apps/v1 +kind: Deployment +metadata: + name: {{ .Release.Name }}-backend + labels: + app.kubernetes.io/name: {{ .Release.Name }} + app.kubernetes.io/instance: {{ .Release.Name }} + app.kubernetes.io/component: backend +spec: + replicas: {{ .Values.backend.replicaCount }} + selector: + matchLabels: + app.kubernetes.io/name: {{ .Release.Name }} + app.kubernetes.io/instance: {{ .Release.Name }} + app.kubernetes.io/component: backend + template: + metadata: + labels: + app.kubernetes.io/name: {{ .Release.Name }} + app.kubernetes.io/instance: {{ .Release.Name }} + app.kubernetes.io/component: backend + spec: + initContainers: + - name: init-db + image: "{{ .Values.backend.image.repository }}:{{ .Values.backend.image.tag }}" + command: ["sh", "-c", "mkdir -p /app/data && chmod 777 /app/data"] + securityContext: + runAsUser: 0 + volumeMounts: + - name: app-db-data + mountPath: /app/data + - name: wait-for-prestart + image: postgres:12 + command: ['sh', '-c', 'until pg_isready -h {{ .Release.Name }}-db -p 5432 -U postgres -d app; do echo "waiting for database..."; sleep 2; done'] + env: + - name: PGPASSWORD + value: {{ .Values.db.env.POSTGRES_PASSWORD | quote }} + containers: + - name: backend + image: "{{ .Values.backend.image.repository }}:{{ .Values.backend.image.tag }}" + imagePullPolicy: {{ .Values.backend.image.pullPolicy }} + ports: + - name: http + containerPort: 8000 + protocol: TCP + resources: + {{- toYaml .Values.backend.resources | nindent 12 }} + envFrom: + - configMapRef: + name: {{ .Release.Name }}-config + - secretRef: + name: {{ .Release.Name }}-secrets + env: + - name: PYTHONPATH + value: "/app" + - name: PROJECT_NAME + value: {{ .Values.backend.env.PROJECT_NAME | quote }} + - name: ENVIRONMENT + value: {{ .Values.backend.env.ENVIRONMENT | quote }} + - name: FIRST_SUPERUSER + value: {{ .Values.backend.env.FIRST_SUPERUSER | quote }} + - name: FIRST_SUPERUSER_PASSWORD + value: {{ .Values.backend.env.FIRST_SUPERUSER_PASSWORD | quote }} + - name: FRONTEND_HOST + value: {{ .Values.backend.env.FRONTEND_HOST | quote }} + - name: SECRET_KEY + value: {{ .Values.backend.env.SECRET_KEY | quote }} + - name: BACKEND_CORS_ORIGINS + value: {{ .Values.backend.env.BACKEND_CORS_ORIGINS | quote }} + - name: SMTP_HOST + value: {{ .Values.backend.env.SMTP_HOST | quote }} + - name: SMTP_USER + value: {{ .Values.backend.env.SMTP_USER | quote }} + - name: SMTP_PASSWORD + value: {{ .Values.backend.env.SMTP_PASSWORD | quote }} + - name: EMAILS_FROM_EMAIL + value: {{ .Values.backend.env.EMAILS_FROM_EMAIL | quote }} + - name: SENTRY_DSN + value: {{ .Values.backend.env.SENTRY_DSN | quote }} + - name: POSTGRES_SERVER + value: {{ .Values.backend.env.POSTGRES_SERVER | quote }} + - name: POSTGRES_PORT + value: {{ .Values.backend.env.POSTGRES_PORT | quote }} + - name: POSTGRES_DB + value: {{ .Values.backend.env.POSTGRES_DB | quote }} + - name: POSTGRES_USER + value: {{ .Values.backend.env.POSTGRES_USER | quote }} + - name: POSTGRES_PASSWORD + value: {{ .Values.backend.env.POSTGRES_PASSWORD | quote }} + volumeMounts: + - name: app-db-data + mountPath: /app/data + command: ["sh", "-c"] + args: + - | + echo "Current directory: $(pwd)" && + echo "Python path: $PYTHONPATH" && + echo "Contents of /app: $(ls -la /app)" && + echo "Python version: $(python3.11 --version)" && + python3.11 -m app.backend_pre_start && + python3.11 -m uvicorn app.main:app --host 0.0.0.0 --port 8000 --log-level debug + startupProbe: + httpGet: + path: /api/v1/utils/health-check/ + port: http + failureThreshold: 30 + periodSeconds: 10 + livenessProbe: + httpGet: + path: /api/v1/utils/health-check/ + port: http + initialDelaySeconds: 30 + periodSeconds: 10 + failureThreshold: 3 + readinessProbe: + httpGet: + path: /api/v1/utils/health-check/ + port: http + initialDelaySeconds: 5 + periodSeconds: 10 + failureThreshold: 3 + volumes: + - name: app-db-data + emptyDir: {} +{{- end }} \ No newline at end of file diff --git a/k8s/templates/backend-service.yaml b/k8s/templates/backend-service.yaml new file mode 100644 index 0000000000..199d656e34 --- /dev/null +++ b/k8s/templates/backend-service.yaml @@ -0,0 +1,17 @@ +apiVersion: v1 +kind: Service +metadata: + name: {{ .Release.Name }}-backend + labels: + app.kubernetes.io/name: {{ .Release.Name }}-backend + app.kubernetes.io/instance: {{ .Release.Name }} +spec: + type: {{ .Values.backend.service.type }} + ports: + - port: {{ .Values.backend.service.port }} + targetPort: http + protocol: TCP + name: http + selector: + app.kubernetes.io/name: {{ .Release.Name }}-backend + app.kubernetes.io/instance: {{ .Release.Name }} \ No newline at end of file diff --git a/k8s/templates/configmap.yaml b/k8s/templates/configmap.yaml new file mode 100644 index 0000000000..4e51c2fe97 --- /dev/null +++ b/k8s/templates/configmap.yaml @@ -0,0 +1,15 @@ +apiVersion: v1 +kind: ConfigMap +metadata: + name: {{ .Release.Name }}-config +data: + DOMAIN: {{ .Values.global.domain | quote }} + ENVIRONMENT: {{ .Values.global.environment | quote }} + FRONTEND_HOST: {{ .Values.backend.env.FRONTEND_HOST | quote }} + BACKEND_CORS_ORIGINS: {{ .Values.backend.env.BACKEND_CORS_ORIGINS | default "*" | quote }} + SMTP_HOST: {{ .Values.backend.env.SMTP_HOST | default "" | quote }} + EMAILS_FROM_EMAIL: {{ .Values.backend.env.EMAILS_FROM_EMAIL | default "" | quote }} + POSTGRES_SERVER: {{ .Release.Name }}-db + POSTGRES_PORT: "5432" + SENTRY_DSN: {{ .Values.backend.env.SENTRY_DSN | default "" | quote }} + DATABASE_URL: postgresql://{{ .Values.db.env.POSTGRES_USER }}:{{ .Values.db.env.POSTGRES_PASSWORD }}@{{ .Release.Name }}-db:5432/{{ .Values.db.env.POSTGRES_DB }} \ No newline at end of file diff --git a/k8s/templates/db-deployment.yaml b/k8s/templates/db-deployment.yaml new file mode 100644 index 0000000000..42c87d18cb --- /dev/null +++ b/k8s/templates/db-deployment.yaml @@ -0,0 +1,72 @@ +{{- if .Values.db.enabled }} +apiVersion: apps/v1 +kind: Deployment +metadata: + name: {{ .Release.Name }}-db + labels: + app.kubernetes.io/name: {{ .Release.Name }}-db + app.kubernetes.io/instance: {{ .Release.Name }} +spec: + replicas: 1 + selector: + matchLabels: + app.kubernetes.io/name: {{ .Release.Name }}-db + app.kubernetes.io/instance: {{ .Release.Name }} + template: + metadata: + labels: + app.kubernetes.io/name: {{ .Release.Name }}-db + app.kubernetes.io/instance: {{ .Release.Name }} + spec: + containers: + - name: postgres + image: "{{ .Values.db.image.repository }}:{{ .Values.db.image.tag }}" + imagePullPolicy: {{ .Values.db.image.pullPolicy }} + ports: + - name: postgres + containerPort: 5432 + protocol: TCP + envFrom: + - secretRef: + name: {{ .Release.Name }}-secrets + - configMapRef: + name: {{ .Release.Name }}-config + env: + - name: PGDATA + value: /var/lib/postgresql/data/pgdata + volumeMounts: + - name: postgres-data + mountPath: /var/lib/postgresql/data + resources: + {{- toYaml .Values.db.resources | nindent 12 }} + livenessProbe: + exec: + command: + - pg_isready + - -U + - "{{ .Values.db.env.POSTGRES_USER }}" + - -d + - "{{ .Values.db.env.POSTGRES_DB }}" + initialDelaySeconds: 30 + periodSeconds: 10 + timeoutSeconds: 5 + successThreshold: 1 + failureThreshold: 3 + readinessProbe: + exec: + command: + - pg_isready + - -U + - "{{ .Values.db.env.POSTGRES_USER }}" + - -d + - "{{ .Values.db.env.POSTGRES_DB }}" + initialDelaySeconds: 5 + periodSeconds: 10 + timeoutSeconds: 5 + successThreshold: 1 + failureThreshold: 3 + volumes: + - name: postgres-data + persistentVolumeClaim: + claimName: {{ .Release.Name }}-db-pvc +{{- end }} \ No newline at end of file diff --git a/k8s/templates/db-pvc.yaml b/k8s/templates/db-pvc.yaml new file mode 100644 index 0000000000..2f362b35db --- /dev/null +++ b/k8s/templates/db-pvc.yaml @@ -0,0 +1,10 @@ +apiVersion: v1 +kind: PersistentVolumeClaim +metadata: + name: {{ .Release.Name }}-db-pvc +spec: + accessModes: + - ReadWriteOnce + resources: + requests: + storage: {{ .Values.db.persistence.size | default "10Gi" }} \ No newline at end of file diff --git a/k8s/templates/db-service.yaml b/k8s/templates/db-service.yaml new file mode 100644 index 0000000000..de5fa3cd44 --- /dev/null +++ b/k8s/templates/db-service.yaml @@ -0,0 +1,13 @@ +apiVersion: v1 +kind: Service +metadata: + name: {{ .Release.Name }}-db +spec: + type: {{ .Values.db.service.type }} + selector: + app.kubernetes.io/name: {{ .Release.Name }}-db + app.kubernetes.io/instance: {{ .Release.Name }} + ports: + - protocol: TCP + port: {{ .Values.db.service.port }} + targetPort: {{ .Values.db.service.port }} \ No newline at end of file diff --git a/k8s/templates/frontend-deployment.yaml b/k8s/templates/frontend-deployment.yaml new file mode 100644 index 0000000000..089492e1ee --- /dev/null +++ b/k8s/templates/frontend-deployment.yaml @@ -0,0 +1,31 @@ +{{- if .Values.frontend.enabled }} +apiVersion: apps/v1 +kind: Deployment +metadata: + name: {{ .Release.Name }}-frontend + labels: + app: {{ .Release.Name }}-frontend +spec: + replicas: {{ .Values.frontend.replicaCount }} + selector: + matchLabels: + app: {{ .Release.Name }}-frontend + template: + metadata: + labels: + app: {{ .Release.Name }}-frontend + spec: + containers: + - name: frontend + image: {{ .Values.frontend.image.repository }}:{{ .Values.frontend.image.tag }} + imagePullPolicy: {{ .Values.frontend.image.pullPolicy }} + ports: + - containerPort: 80 + resources: + {{- toYaml .Values.frontend.resources | nindent 12 }} + env: + {{- range $key, $value := .Values.frontend.env }} + - name: {{ $key }} + value: {{ $value | quote }} + {{- end }} +{{- end }} \ No newline at end of file diff --git a/k8s/templates/frontend-service.yaml b/k8s/templates/frontend-service.yaml new file mode 100644 index 0000000000..c52af00811 --- /dev/null +++ b/k8s/templates/frontend-service.yaml @@ -0,0 +1,15 @@ +apiVersion: v1 +kind: Service +metadata: + name: {{ .Release.Name }}-frontend + labels: + app: {{ .Release.Name }}-frontend +spec: + type: {{ .Values.frontend.service.type }} + ports: + - port: {{ .Values.frontend.service.port }} + targetPort: 80 + protocol: TCP + name: http + selector: + app: {{ .Release.Name }}-frontend \ No newline at end of file diff --git a/k8s/templates/ingress.yaml b/k8s/templates/ingress.yaml new file mode 100644 index 0000000000..7307612b65 --- /dev/null +++ b/k8s/templates/ingress.yaml @@ -0,0 +1,43 @@ +{{- if .Values.ingress.enabled -}} +apiVersion: networking.k8s.io/v1 +kind: Ingress +metadata: + name: {{ .Release.Name }}-ingress + annotations: + {{- with .Values.ingress.annotations }} + {{- toYaml . | nindent 4 }} + {{- end }} +spec: + ingressClassName: {{ .Values.ingress.className }} + {{- if .Values.ingress.tls }} + tls: + {{- range .Values.ingress.tls }} + - hosts: + {{- range .hosts }} + - {{ . | quote }} + {{- end }} + secretName: {{ .secretName }} + {{- end }} + {{- end }} + rules: + {{- range .Values.ingress.hosts }} + - host: {{ .host | quote }} + http: + paths: + {{- range .paths }} + - path: {{ .path }} + pathType: {{ .pathType }} + backend: + service: + name: {{ $.Release.Name }}-{{ .service }} + port: + {{- if eq .service "frontend" }} + number: {{ $.Values.frontend.service.port }} + {{- else if eq .service "backend" }} + number: {{ $.Values.backend.service.port }} + {{- else if eq .service "adminer" }} + number: {{ $.Values.adminer.service.port }} + {{- end }} + {{- end }} + {{- end }} +{{- end }} \ No newline at end of file diff --git a/k8s/templates/prestart-job.yaml b/k8s/templates/prestart-job.yaml new file mode 100644 index 0000000000..2b1c6b6baa --- /dev/null +++ b/k8s/templates/prestart-job.yaml @@ -0,0 +1,73 @@ +{{- if .Values.prestart.enabled }} +apiVersion: batch/v1 +kind: Job +metadata: + name: {{ .Release.Name }}-prestart + labels: + app.kubernetes.io/name: {{ .Release.Name }} + app.kubernetes.io/instance: {{ .Release.Name }} + app.kubernetes.io/component: prestart +spec: + template: + metadata: + labels: + app.kubernetes.io/name: {{ .Release.Name }} + app.kubernetes.io/instance: {{ .Release.Name }} + app.kubernetes.io/component: prestart + spec: + initContainers: + - name: wait-for-db + image: postgres:12 + command: ['sh', '-c', 'until pg_isready -h {{ .Release.Name }}-db -p 5432 -U postgres -d app; do echo "waiting for database..."; sleep 2; done'] + env: + - name: PGPASSWORD + value: {{ .Values.db.env.POSTGRES_PASSWORD | quote }} + containers: + - name: prestart + image: {{ .Values.prestart.image.repository }}:{{ .Values.prestart.image.tag }} + imagePullPolicy: {{ .Values.prestart.image.pullPolicy }} + command: ["bash", "scripts/prestart.sh"] + env: + - name: PROJECT_NAME + value: {{ .Values.prestart.env.PROJECT_NAME | quote }} + - name: ENVIRONMENT + value: {{ .Values.prestart.env.ENVIRONMENT | quote }} + - name: FIRST_SUPERUSER + value: {{ .Values.prestart.env.FIRST_SUPERUSER | quote }} + - name: FIRST_SUPERUSER_PASSWORD + value: {{ .Values.prestart.env.FIRST_SUPERUSER_PASSWORD | quote }} + - name: FRONTEND_HOST + value: {{ .Values.prestart.env.FRONTEND_HOST | quote }} + - name: SECRET_KEY + value: {{ .Values.prestart.env.SECRET_KEY | quote }} + - name: BACKEND_CORS_ORIGINS + value: {{ .Values.prestart.env.BACKEND_CORS_ORIGINS | quote }} + - name: SMTP_HOST + value: {{ .Values.prestart.env.SMTP_HOST | quote }} + - name: SMTP_USER + value: {{ .Values.prestart.env.SMTP_USER | quote }} + - name: SMTP_PASSWORD + value: {{ .Values.prestart.env.SMTP_PASSWORD | quote }} + - name: EMAILS_FROM_EMAIL + value: {{ .Values.prestart.env.EMAILS_FROM_EMAIL | quote }} + - name: SENTRY_DSN + value: {{ .Values.prestart.env.SENTRY_DSN | quote }} + - name: POSTGRES_SERVER + value: {{ .Values.prestart.env.POSTGRES_SERVER | quote }} + - name: POSTGRES_PORT + value: {{ .Values.prestart.env.POSTGRES_PORT | quote }} + - name: POSTGRES_DB + value: {{ .Values.prestart.env.POSTGRES_DB | quote }} + - name: POSTGRES_USER + value: {{ .Values.prestart.env.POSTGRES_USER | quote }} + - name: POSTGRES_PASSWORD + value: {{ .Values.prestart.env.POSTGRES_PASSWORD | quote }} + resources: + limits: + cpu: {{ .Values.prestart.resources.limits.cpu }} + memory: {{ .Values.prestart.resources.limits.memory }} + requests: + cpu: {{ .Values.prestart.resources.requests.cpu }} + memory: {{ .Values.prestart.resources.requests.memory }} + restartPolicy: OnFailure +{{- end }} \ No newline at end of file diff --git a/k8s/templates/secrets.yaml b/k8s/templates/secrets.yaml new file mode 100644 index 0000000000..ad36605756 --- /dev/null +++ b/k8s/templates/secrets.yaml @@ -0,0 +1,16 @@ +apiVersion: v1 +kind: Secret +metadata: + name: {{ .Release.Name }}-secrets +type: Opaque +data: + POSTGRES_SERVER: {{ .Values.db.env.POSTGRES_SERVER | quote }} + POSTGRES_PORT: {{ .Values.db.env.POSTGRES_PORT | quote }} + POSTGRES_DB: {{ .Values.db.env.POSTGRES_DB | b64enc }} + POSTGRES_USER: {{ .Values.db.env.POSTGRES_USER | b64enc }} + POSTGRES_PASSWORD: {{ .Values.db.env.POSTGRES_PASSWORD | b64enc }} + SECRET_KEY: {{ .Values.backend.env.SECRET_KEY | b64enc }} + FIRST_SUPERUSER: {{ .Values.backend.env.FIRST_SUPERUSER | b64enc }} + FIRST_SUPERUSER_PASSWORD: {{ .Values.backend.env.FIRST_SUPERUSER_PASSWORD | b64enc }} + SMTP_USER: {{ .Values.backend.env.SMTP_USER | default "" | b64enc }} + SMTP_PASSWORD: {{ .Values.backend.env.SMTP_PASSWORD | default "" | b64enc }} \ No newline at end of file diff --git a/k8s/values.yaml b/k8s/values.yaml new file mode 100644 index 0000000000..ff13d7c107 --- /dev/null +++ b/k8s/values.yaml @@ -0,0 +1,214 @@ +# Global values +global: + environment: production + domain: example.com + +# Backend configuration +backend: + enabled: true + image: + repository: dperezsa/sdp-backend + tag: 1.0.0 + pullPolicy: IfNotPresent + replicaCount: 1 + resources: + limits: + cpu: 500m + memory: 512Mi + requests: + cpu: 200m + memory: 256Mi + service: + type: ClusterIP + port: 8000 + env: + PROJECT_NAME: Service Data Platform + ENVIRONMENT: production + FIRST_SUPERUSER: admin@example.com + FIRST_SUPERUSER_PASSWORD: changeme123 + FRONTEND_HOST: http://localhost:5173 + SECRET_KEY: changeme123 + BACKEND_CORS_ORIGINS: '["http://localhost", "https://dashboard.example.com"]' + SMTP_HOST: "" + SMTP_USER: "" + SMTP_PASSWORD: "" + EMAILS_FROM_EMAIL: "" + SENTRY_DSN: "" + POSTGRES_SERVER: sdp-db + POSTGRES_PORT: 5432 + POSTGRES_DB: app + POSTGRES_USER: postgres + POSTGRES_PASSWORD: changeme123 + volumeMounts: + - name: app-db-data + mountPath: /app/data + volumes: + - name: app-db-data + emptyDir: {} + +# Prestart configuration +prestart: + enabled: true + image: + repository: dperezsa/sdp-backend + tag: 1.0.0 + pullPolicy: IfNotPresent + resources: + limits: + cpu: 500m + memory: 512Mi + requests: + cpu: 200m + memory: 256Mi + env: + PROJECT_NAME: Service Data Platform + ENVIRONMENT: production + FIRST_SUPERUSER: admin@example.com + FIRST_SUPERUSER_PASSWORD: changeme123 + FRONTEND_HOST: http://localhost:5173 + SECRET_KEY: changeme123 + BACKEND_CORS_ORIGINS: '["http://localhost", "https://dashboard.example.com"]' + SMTP_HOST: "" + SMTP_USER: "" + SMTP_PASSWORD: "" + EMAILS_FROM_EMAIL: "" + SENTRY_DSN: "" + POSTGRES_SERVER: sdp-db + POSTGRES_PORT: 5432 + POSTGRES_DB: app + POSTGRES_USER: postgres + POSTGRES_PASSWORD: changeme123 + +# Frontend configuration +frontend: + enabled: true + image: + repository: dperezsa/sdp-frontend + tag: 1.0.0 + pullPolicy: IfNotPresent + replicaCount: 1 + resources: + limits: + cpu: 200m + memory: 256Mi + requests: + cpu: 100m + memory: 128Mi + service: + type: ClusterIP + port: 80 + env: + VITE_API_URL: http://{{ .Release.Name }}-backend.default.svc.cluster.local:8000 + +# Adminer configuration +adminer: + enabled: true + image: + repository: dperezsa/adminer + tag: latest + pullPolicy: IfNotPresent + replicaCount: 1 + resources: + limits: + cpu: 200m + memory: 256Mi + requests: + cpu: 100m + memory: 128Mi + service: + type: ClusterIP + port: 8080 + env: + ADMINER_DESIGN: pepa-linha-dark + volumeMounts: + - name: app-db-data + mountPath: /var/www/html/data + volumes: + - name: app-db-data + emptyDir: {} + +# Database configuration +db: + enabled: true + image: + repository: postgres + tag: "12" + pullPolicy: IfNotPresent + replicaCount: 1 + resources: + limits: + cpu: 500m + memory: 512Mi + requests: + cpu: 200m + memory: 256Mi + service: + type: ClusterIP + port: 5432 + env: + POSTGRES_PASSWORD: changeme123 + POSTGRES_DB: app + POSTGRES_USER: postgres + POSTGRES_HOST_AUTH_METHOD: trust + config: + PGDATA: /var/lib/postgresql/data/pgdata + volumeMounts: + - name: postgres-data + mountPath: /var/lib/postgresql/data + volumes: + - name: postgres-data + persistentVolumeClaim: + claimName: sdp-db-pvc + persistence: + size: 10Gi + postgresqlConfig: + max_connections: "100" + shared_buffers: "128MB" + effective_cache_size: "256MB" + maintenance_work_mem: "64MB" + checkpoint_completion_target: "0.9" + wal_buffers: "16MB" + default_statistics_target: "100" + random_page_cost: "1.1" + effective_io_concurrency: "200" + work_mem: "4MB" + min_wal_size: "1GB" + max_wal_size: "4GB" + max_worker_processes: "2" + max_parallel_workers_per_gather: "1" + max_parallel_workers: "2" + max_parallel_maintenance_workers: "2" + + +# Ingress configuration +ingress: + enabled: true + className: nginx + annotations: + cert-manager.io/cluster-issuer: letsencrypt-prod + hosts: + - host: dashboard.example.com + paths: + - path: / + pathType: Prefix + service: frontend + - host: api.example.com + paths: + - path: / + pathType: Prefix + service: backend + - host: adminer.example.com + paths: + - path: / + pathType: Prefix + service: adminer + tls: + - secretName: dashboard-tls + hosts: + - dashboard.example.com + - secretName: api-tls + hosts: + - api.example.com + - secretName: adminer-tls + hosts: + - adminer.example.com \ No newline at end of file diff --git a/release-notes.md b/release-notes.md deleted file mode 100644 index 5420a98d89..0000000000 --- a/release-notes.md +++ /dev/null @@ -1,568 +0,0 @@ -# Release Notes - -## Latest Changes - -### Fixes - -* πŸ› Close sidebar drawer on user selection. PR [#1515](https://github.com/fastapi/full-stack-fastapi-template/pull/1515) by [@dtellz](https://github.com/dtellz). -* πŸ› Fix required password validation when editing user fields. PR [#1508](https://github.com/fastapi/full-stack-fastapi-template/pull/1508) by [@jpizquierdo](https://github.com/jpizquierdo). - -### Refactors - -* ♻️ Remove redundant field in inherited class. PR [#1520](https://github.com/fastapi/full-stack-fastapi-template/pull/1520) by [@tzway](https://github.com/tzway). -* 🎨 Add minor UI tweaks in Skeletons and other components. PR [#1507](https://github.com/fastapi/full-stack-fastapi-template/pull/1507) by [@alejsdev](https://github.com/alejsdev). -* 🎨 Add minor UI tweaks. PR [#1506](https://github.com/fastapi/full-stack-fastapi-template/pull/1506) by [@alejsdev](https://github.com/alejsdev). - -### Internal - -* πŸ”§ Add npm and docker package ecosystems to Dependabot configuration. PR [#1535](https://github.com/fastapi/full-stack-fastapi-template/pull/1535) by [@alejsdev](https://github.com/alejsdev). - -## 0.8.0 - -### Features - -* πŸ›‚ Migrate to Chakra UI v3 . PR [#1496](https://github.com/fastapi/full-stack-fastapi-template/pull/1496) by [@alejsdev](https://github.com/alejsdev). -* ✨ Add private, local only, API for usage in E2E tests. PR [#1429](https://github.com/fastapi/full-stack-fastapi-template/pull/1429) by [@patrick91](https://github.com/patrick91). -* ✨ Migrate to latest openapi-ts. PR [#1430](https://github.com/fastapi/full-stack-fastapi-template/pull/1430) by [@patrick91](https://github.com/patrick91). - -### Fixes - -* πŸ§‘β€πŸ”§ Replace correct value for 'htmlFor'. PR [#1456](https://github.com/fastapi/full-stack-fastapi-template/pull/1456) by [@wesenbergg](https://github.com/wesenbergg). - -### Refactors - -* ♻️ Redirect the user to `login` if we get 401/403. PR [#1501](https://github.com/fastapi/full-stack-fastapi-template/pull/1501) by [@alejsdev](https://github.com/alejsdev). -* πŸ› Refactor reset password test to create normal user instead of using super user. PR [#1499](https://github.com/fastapi/full-stack-fastapi-template/pull/1499) by [@alejsdev](https://github.com/alejsdev). -* ♻️ Replace email types from `str` to `EmailStr` in `config.py`. PR [#1492](https://github.com/fastapi/full-stack-fastapi-template/pull/1492) by [@jpizquierdo](https://github.com/jpizquierdo). -* πŸ”§ Remove unused context from router creation. PR [#1498](https://github.com/fastapi/full-stack-fastapi-template/pull/1498) by [@alejsdev](https://github.com/alejsdev). -* ♻️ Remove redundant item deletion code leveraging cascade delete. PR [#1481](https://github.com/fastapi/full-stack-fastapi-template/pull/1481) by [@nauanbek](https://github.com/nauanbek). -* ✏️ Fix a couple of spelling mistakes. PR [#1485](https://github.com/fastapi/full-stack-fastapi-template/pull/1485) by [@rjmunro](https://github.com/rjmunro). -* 🎨 Move `prefix` and `tags` to routers. PR [#1439](https://github.com/fastapi/full-stack-fastapi-template/pull/1439) by [@patrick91](https://github.com/patrick91). -* ♻️ Remove modify id script in favor of openapi-ts config. PR [#1434](https://github.com/fastapi/full-stack-fastapi-template/pull/1434) by [@patrick91](https://github.com/patrick91). -* πŸ‘· Improve Playwright CI speed: sharding (parallel runs), run in Docker to use cache, use env vars. PR [#1405](https://github.com/fastapi/full-stack-fastapi-template/pull/1405) by [@tiangolo](https://github.com/tiangolo). -* ♻️ Add PaginationFooter component. PR [#1381](https://github.com/fastapi/full-stack-fastapi-template/pull/1381) by [@saltie2193](https://github.com/saltie2193). -* ♻️ Refactored code to use encryption algorithm name from settings for consistency. PR [#1160](https://github.com/fastapi/full-stack-fastapi-template/pull/1160) by [@sameeramin](https://github.com/sameeramin). -* πŸ”Š Enable logging for email utils by default. PR [#1374](https://github.com/fastapi/full-stack-fastapi-template/pull/1374) by [@ihmily](https://github.com/ihmily). -* πŸ”§ Add `ENV PYTHONUNBUFFERED=1` to log output directly to Docker. PR [#1378](https://github.com/fastapi/full-stack-fastapi-template/pull/1378) by [@tiangolo](https://github.com/tiangolo). -* πŸ’‘ Remove unnecessary comment. PR [#1260](https://github.com/fastapi/full-stack-fastapi-template/pull/1260) by [@sebhani](https://github.com/sebhani). - -### Upgrades - -* ⬆️ Update Dockerfile to use uv version 0.5.11. PR [#1454](https://github.com/fastapi/full-stack-fastapi-template/pull/1454) by [@alejsdev](https://github.com/alejsdev). - -### Docs - -* πŸ“ Removing deprecated manual client SDK step. PR [#1494](https://github.com/fastapi/full-stack-fastapi-template/pull/1494) by [@chandy](https://github.com/chandy). -* πŸ“ Update Frontend README.md. PR [#1462](https://github.com/fastapi/full-stack-fastapi-template/pull/1462) by [@getmarkus](https://github.com/getmarkus). -* πŸ“ Update `frontend/README.md` to also remove Playwright when removing Frontend. PR [#1452](https://github.com/fastapi/full-stack-fastapi-template/pull/1452) by [@youben11](https://github.com/youben11). -* πŸ“ Update `deployment.md`, instructions to install GitHub Runner in non-root VMs. PR [#1412](https://github.com/fastapi/full-stack-fastapi-template/pull/1412) by [@tiangolo](https://github.com/tiangolo). -* πŸ“ Add MailCatcher to `development.md`. PR [#1387](https://github.com/fastapi/full-stack-fastapi-template/pull/1387) by [@tobiase](https://github.com/tobiase). - -### Internal - -* πŸ”§ Configure path alias for cleaner imports. PR [#1497](https://github.com/fastapi/full-stack-fastapi-template/pull/1497) by [@alejsdev](https://github.com/alejsdev). -* Bump vite from 5.0.13 to 5.4.14 in /frontend. PR [#1469](https://github.com/fastapi/full-stack-fastapi-template/pull/1469) by [@dependabot[bot]](https://github.com/apps/dependabot). -* ⬆ Bump astral-sh/setup-uv from 4 to 5. PR [#1453](https://github.com/fastapi/full-stack-fastapi-template/pull/1453) by [@dependabot[bot]](https://github.com/apps/dependabot). -* ⬆ Bump astral-sh/setup-uv from 3 to 4. PR [#1433](https://github.com/fastapi/full-stack-fastapi-template/pull/1433) by [@dependabot[bot]](https://github.com/apps/dependabot). -* ⬆ Bump tiangolo/latest-changes from 0.3.1 to 0.3.2. PR [#1418](https://github.com/fastapi/full-stack-fastapi-template/pull/1418) by [@dependabot[bot]](https://github.com/apps/dependabot). -* πŸ‘· Update issue manager workflow. PR [#1398](https://github.com/fastapi/full-stack-fastapi-template/pull/1398) by [@alejsdev](https://github.com/alejsdev). -* πŸ‘· Fix smokeshow, checkout files on CI. PR [#1395](https://github.com/fastapi/full-stack-fastapi-template/pull/1395) by [@tiangolo](https://github.com/tiangolo). -* πŸ‘· Update `labeler.yml`. PR [#1388](https://github.com/fastapi/full-stack-fastapi-template/pull/1388) by [@tiangolo](https://github.com/tiangolo). -* πŸ”§ Add .auth playwright folder to `.gitignore`. PR [#1383](https://github.com/fastapi/full-stack-fastapi-template/pull/1383) by [@justin-p](https://github.com/justin-p). -* ⬆️ Bump rollup from 4.6.1 to 4.22.5 in /frontend. PR [#1379](https://github.com/fastapi/full-stack-fastapi-template/pull/1379) by [@dependabot[bot]](https://github.com/apps/dependabot). -* ⬆ Bump astral-sh/setup-uv from 2 to 3. PR [#1364](https://github.com/fastapi/full-stack-fastapi-template/pull/1364) by [@dependabot[bot]](https://github.com/apps/dependabot). -* πŸ‘· Update pre-commit end-of-file-fixer hook to exclude email-templates. PR [#1296](https://github.com/fastapi/full-stack-fastapi-template/pull/1296) by [@goabonga](https://github.com/goabonga). -* ⬆ Bump tiangolo/issue-manager from 0.5.0 to 0.5.1. PR [#1332](https://github.com/fastapi/full-stack-fastapi-template/pull/1332) by [@dependabot[bot]](https://github.com/apps/dependabot). -* πŸ”§ Run task by the same Python environment used to run Copier. PR [#1157](https://github.com/fastapi/full-stack-fastapi-template/pull/1157) by [@waketzheng](https://github.com/waketzheng). -* πŸ‘· Tweak generate client to error out if there are errors. PR [#1377](https://github.com/fastapi/full-stack-fastapi-template/pull/1377) by [@tiangolo](https://github.com/tiangolo). -* πŸ‘· Generate and commit client only on same repo PRs, on forks, show the error. PR [#1376](https://github.com/fastapi/full-stack-fastapi-template/pull/1376) by [@tiangolo](https://github.com/tiangolo). - -## 0.7.1 - -### Highlights - -* Migrate from Poetry to [`uv`](https://github.com/astral-sh/uv). -* Simplifications and improvements for Docker Compose files, Traefik Dockerfiles. -* Make the API use its own domain `api.example.com` and the frontend use `dashboard.example.com`. This would make it easier to deploy them separately if you needed that. -* The backend and frontend on Docker Compose now listen on the same port as the local development servers, this way you can stop the Docker Compose services and run the local development servers without changing the frontend configuration. - -### Features - -* 🩺 Add DB healthcheck. PR [#1342](https://github.com/fastapi/full-stack-fastapi-template/pull/1342) by [@tiangolo](https://github.com/tiangolo). - -### Refactors - -* ♻️ Update settings to use top level `.env` file. PR [#1359](https://github.com/fastapi/full-stack-fastapi-template/pull/1359) by [@tiangolo](https://github.com/tiangolo). -* ⬆️ Migrate from Poetry to uv. PR [#1356](https://github.com/fastapi/full-stack-fastapi-template/pull/1356) by [@tiangolo](https://github.com/tiangolo). -* πŸ”₯ Remove logic for development dependencies and Jupyter, it was never documented, and I no longer use that trick. PR [#1355](https://github.com/fastapi/full-stack-fastapi-template/pull/1355) by [@tiangolo](https://github.com/tiangolo). -* ♻️ Use Docker Compose `watch`. PR [#1354](https://github.com/fastapi/full-stack-fastapi-template/pull/1354) by [@tiangolo](https://github.com/tiangolo). -* πŸ”§ Use plain base official Python Docker image. PR [#1351](https://github.com/fastapi/full-stack-fastapi-template/pull/1351) by [@tiangolo](https://github.com/tiangolo). -* 🚚 Move location of scripts to simplify file structure. PR [#1352](https://github.com/fastapi/full-stack-fastapi-template/pull/1352) by [@tiangolo](https://github.com/tiangolo). -* ♻️ Refactor prestart (migrations), move that to its own container. PR [#1350](https://github.com/fastapi/full-stack-fastapi-template/pull/1350) by [@tiangolo](https://github.com/tiangolo). -* ♻️ Include `FRONTEND_HOST` in CORS origins by default. PR [#1348](https://github.com/fastapi/full-stack-fastapi-template/pull/1348) by [@tiangolo](https://github.com/tiangolo). -* ♻️ Simplify domains with `api.example.com` for API and `dashboard.example.com` for frontend, improve local development with `localhost`. PR [#1344](https://github.com/fastapi/full-stack-fastapi-template/pull/1344) by [@tiangolo](https://github.com/tiangolo). -* πŸ”₯ Simplify Traefik, remove www-redirects that add complexity. PR [#1343](https://github.com/fastapi/full-stack-fastapi-template/pull/1343) by [@tiangolo](https://github.com/tiangolo). -* πŸ”₯ Enable support for Arm Docker images in Mac, remove old patch. PR [#1341](https://github.com/fastapi/full-stack-fastapi-template/pull/1341) by [@tiangolo](https://github.com/tiangolo). -* ♻️ Remove duplicate information in the ItemCreate model. PR [#1287](https://github.com/fastapi/full-stack-fastapi-template/pull/1287) by [@jjaakko](https://github.com/jjaakko). - -### Upgrades - -* ⬆️ Upgrade FastAPI. PR [#1349](https://github.com/fastapi/full-stack-fastapi-template/pull/1349) by [@tiangolo](https://github.com/tiangolo). - -### Docs - -* πŸ’‘ Add comments to Dockerfile with uv references. PR [#1357](https://github.com/fastapi/full-stack-fastapi-template/pull/1357) by [@tiangolo](https://github.com/tiangolo). -* πŸ“ Add Email Templates to `backend/README.md`. PR [#1311](https://github.com/fastapi/full-stack-fastapi-template/pull/1311) by [@alejsdev](https://github.com/alejsdev). - -### Internal - -* πŸ‘· Do not sync labels as it overrides manually added labels. PR [#1307](https://github.com/fastapi/full-stack-fastapi-template/pull/1307) by [@tiangolo](https://github.com/tiangolo). -* πŸ‘· Use uv cache on GitHub Actions. PR [#1366](https://github.com/fastapi/full-stack-fastapi-template/pull/1366) by [@tiangolo](https://github.com/tiangolo). -* πŸ‘· Update GitHub Actions format. PR [#1363](https://github.com/fastapi/full-stack-fastapi-template/pull/1363) by [@tiangolo](https://github.com/tiangolo). -* πŸ‘· Use `uv` for Python env to generate client. PR [#1362](https://github.com/fastapi/full-stack-fastapi-template/pull/1362) by [@tiangolo](https://github.com/tiangolo). -* πŸ‘· Run tests from Python environment (with `uv`), not from Docker container. PR [#1361](https://github.com/fastapi/full-stack-fastapi-template/pull/1361) by [@tiangolo](https://github.com/tiangolo). -* πŸ”¨ Update `generate-client.sh` script, make it fail on errors, fix generation. PR [#1360](https://github.com/fastapi/full-stack-fastapi-template/pull/1360) by [@tiangolo](https://github.com/tiangolo). -* πŸ‘· Add GitHub Actions workflow to lint backend apart from tests. PR [#1358](https://github.com/fastapi/full-stack-fastapi-template/pull/1358) by [@tiangolo](https://github.com/tiangolo). -* πŸ‘· Improve playwright CI job. PR [#1335](https://github.com/fastapi/full-stack-fastapi-template/pull/1335) by [@patrick91](https://github.com/patrick91). -* πŸ‘· Update `issue-manager.yml`. PR [#1329](https://github.com/fastapi/full-stack-fastapi-template/pull/1329) by [@tiangolo](https://github.com/tiangolo). -* πŸ’š Set `include-hidden-files` to `True` when using the `upload-artifact` GH action. PR [#1327](https://github.com/fastapi/full-stack-fastapi-template/pull/1327) by [@svlandeg](https://github.com/svlandeg). -* πŸ‘·πŸ» Auto-generate frontend client . PR [#1320](https://github.com/fastapi/full-stack-fastapi-template/pull/1320) by [@alejsdev](https://github.com/alejsdev). -* πŸ› Fix in `.github/labeler.yml`. PR [#1322](https://github.com/fastapi/full-stack-fastapi-template/pull/1322) by [@alejsdev](https://github.com/alejsdev). -* πŸ‘· Update `.github/labeler.yml`. PR [#1321](https://github.com/fastapi/full-stack-fastapi-template/pull/1321) by [@alejsdev](https://github.com/alejsdev). -* πŸ‘· Update `latest-changes` GitHub Action. PR [#1315](https://github.com/fastapi/full-stack-fastapi-template/pull/1315) by [@tiangolo](https://github.com/tiangolo). -* πŸ‘· Update configs for labeler. PR [#1308](https://github.com/fastapi/full-stack-fastapi-template/pull/1308) by [@tiangolo](https://github.com/tiangolo). -* πŸ‘· Update GitHub Action labeler to add only one label. PR [#1304](https://github.com/fastapi/full-stack-fastapi-template/pull/1304) by [@tiangolo](https://github.com/tiangolo). -* ⬆️ Bump axios from 1.6.2 to 1.7.4 in /frontend. PR [#1301](https://github.com/fastapi/full-stack-fastapi-template/pull/1301) by [@dependabot[bot]](https://github.com/apps/dependabot). -* πŸ‘· Update GitHub Action labeler dependencies. PR [#1302](https://github.com/fastapi/full-stack-fastapi-template/pull/1302) by [@tiangolo](https://github.com/tiangolo). -* πŸ‘· Update GitHub Action labeler permissions. PR [#1300](https://github.com/fastapi/full-stack-fastapi-template/pull/1300) by [@tiangolo](https://github.com/tiangolo). -* πŸ‘· Add GitHub Action label-checker. PR [#1299](https://github.com/fastapi/full-stack-fastapi-template/pull/1299) by [@tiangolo](https://github.com/tiangolo). -* πŸ‘· Add GitHub Action labeler. PR [#1298](https://github.com/fastapi/full-stack-fastapi-template/pull/1298) by [@tiangolo](https://github.com/tiangolo). -* πŸ‘· Add GitHub Action add-to-project. PR [#1297](https://github.com/fastapi/full-stack-fastapi-template/pull/1297) by [@tiangolo](https://github.com/tiangolo). -* πŸ‘· Update issue-manager. PR [#1288](https://github.com/fastapi/full-stack-fastapi-template/pull/1288) by [@tiangolo](https://github.com/tiangolo). - -## 0.7.0 - -Lots of new things! 🎁 - -* E2E tests with Playwright. -* Mailcatcher configuration, to develop and test email handling. -* Pagination. -* UUIDs for database keys. -* New user sign up. -* Support for deploying to multiple environments (staging, prod). -* Many refactors and improvements. -* Several dependency upgrades. - -### Features - -* ✨ Add User Settings e2e tests. PR [#1271](https://github.com/tiangolo/full-stack-fastapi-template/pull/1271) by [@alejsdev](https://github.com/alejsdev). -* ✨ Add Reset Password e2e tests. PR [#1270](https://github.com/tiangolo/full-stack-fastapi-template/pull/1270) by [@alejsdev](https://github.com/alejsdev). -* ✨ Add Sign Up e2e tests. PR [#1268](https://github.com/tiangolo/full-stack-fastapi-template/pull/1268) by [@alejsdev](https://github.com/alejsdev). -* ✨ Add Sign Up and make `OPEN_USER_REGISTRATION=True` by default. PR [#1265](https://github.com/tiangolo/full-stack-fastapi-template/pull/1265) by [@alejsdev](https://github.com/alejsdev). -* ✨ Add Login e2e tests. PR [#1264](https://github.com/tiangolo/full-stack-fastapi-template/pull/1264) by [@alejsdev](https://github.com/alejsdev). -* ✨ Add initial setup for frontend / end-to-end tests with Playwright. PR [#1261](https://github.com/tiangolo/full-stack-fastapi-template/pull/1261) by [@alejsdev](https://github.com/alejsdev). -* ✨ Add mailcatcher configuration. PR [#1244](https://github.com/tiangolo/full-stack-fastapi-template/pull/1244) by [@patrick91](https://github.com/patrick91). -* ✨ Introduce pagination in items. PR [#1239](https://github.com/tiangolo/full-stack-fastapi-template/pull/1239) by [@patrick91](https://github.com/patrick91). -* πŸ—ƒοΈ Add max_length validation for database models and input data. PR [#1233](https://github.com/tiangolo/full-stack-fastapi-template/pull/1233) by [@estebanx64](https://github.com/estebanx64). -* ✨ Add TanStack React Query devtools in dev build. PR [#1217](https://github.com/tiangolo/full-stack-fastapi-template/pull/1217) by [@tomerb](https://github.com/tomerb). -* ✨ Add support for deploying multiple environments (staging, production) to the same server. PR [#1128](https://github.com/tiangolo/full-stack-fastapi-template/pull/1128) by [@tiangolo](https://github.com/tiangolo). -* πŸ‘· Update CI GitHub Actions to allow running in private repos. PR [#1125](https://github.com/tiangolo/full-stack-fastapi-template/pull/1125) by [@tiangolo](https://github.com/tiangolo). - -### Fixes - -* πŸ› Fix welcome page to show logged-in user. PR [#1218](https://github.com/tiangolo/full-stack-fastapi-template/pull/1218) by [@tomerb](https://github.com/tomerb). -* πŸ› Fix local Traefik proxy network config to fix Gateway Timeouts. PR [#1184](https://github.com/tiangolo/full-stack-fastapi-template/pull/1184) by [@JoelGotsch](https://github.com/JoelGotsch). -* ♻️ Fix tests when first superuser password is changed in .env. PR [#1165](https://github.com/tiangolo/full-stack-fastapi-template/pull/1165) by [@billzhong](https://github.com/billzhong). -* πŸ› Fix bug when resetting password. PR [#1171](https://github.com/tiangolo/full-stack-fastapi-template/pull/1171) by [@alejsdev](https://github.com/alejsdev). -* πŸ› Fix 403 when the frontend has a directory without an index.html. PR [#1094](https://github.com/tiangolo/full-stack-fastapi-template/pull/1094) by [@tiangolo](https://github.com/tiangolo). - -### Refactors - -* 🚨 Fix Docker build warning. PR [#1283](https://github.com/tiangolo/full-stack-fastapi-template/pull/1283) by [@erip](https://github.com/erip). -* ♻️ Regenerate client to use UUID instead of id integers and update frontend. PR [#1281](https://github.com/tiangolo/full-stack-fastapi-template/pull/1281) by [@rehanabdul](https://github.com/rehanabdul). -* ♻️ Tweaks in frontend. PR [#1273](https://github.com/tiangolo/full-stack-fastapi-template/pull/1273) by [@alejsdev](https://github.com/alejsdev). -* ♻️ Add random password util and refactor tests. PR [#1277](https://github.com/tiangolo/full-stack-fastapi-template/pull/1277) by [@alejsdev](https://github.com/alejsdev). -* ♻️ Refactor models to use cascade delete relationships . PR [#1276](https://github.com/tiangolo/full-stack-fastapi-template/pull/1276) by [@alejsdev](https://github.com/alejsdev). -* πŸ”₯ Remove `USERS_OPEN_REGISTRATION` config, make registration enabled by default. PR [#1274](https://github.com/tiangolo/full-stack-fastapi-template/pull/1274) by [@alejsdev](https://github.com/alejsdev). -* πŸ”§ Reuse database url from config in alembic setup. PR [#1229](https://github.com/tiangolo/full-stack-fastapi-template/pull/1229) by [@patrick91](https://github.com/patrick91). -* πŸ”§ Update Playwright config and tests to use env variables. PR [#1266](https://github.com/tiangolo/full-stack-fastapi-template/pull/1266) by [@alejsdev](https://github.com/alejsdev). -* ♻️ Edit refactor db models to use UUID's instead of integer ID's. PR [#1259](https://github.com/tiangolo/full-stack-fastapi-template/pull/1259) by [@estebanx64](https://github.com/estebanx64). -* ♻️ Update form inputs width. PR [#1263](https://github.com/tiangolo/full-stack-fastapi-template/pull/1263) by [@alejsdev](https://github.com/alejsdev). -* ♻️ Replace deprecated utcnow() with now(timezone.utc) in utils module. PR [#1247](https://github.com/tiangolo/full-stack-fastapi-template/pull/1247) by [@jalvarezz13](https://github.com/jalvarezz13). -* 🎨 Format frontend. PR [#1262](https://github.com/tiangolo/full-stack-fastapi-template/pull/1262) by [@alejsdev](https://github.com/alejsdev). -* ♻️ Abstraction of specific AddModal component out of the Navbar. PR [#1246](https://github.com/tiangolo/full-stack-fastapi-template/pull/1246) by [@ajbloureiro](https://github.com/ajbloureiro). -* ♻️ Update `login.tsx` to prevent error if username or password are empty. PR [#1257](https://github.com/tiangolo/full-stack-fastapi-template/pull/1257) by [@jmondaud](https://github.com/jmondaud). -* ♻️ Refactor recover password. PR [#1242](https://github.com/tiangolo/full-stack-fastapi-template/pull/1242) by [@alejsdev](https://github.com/alejsdev). -* 🎨 Format and lint . PR [#1243](https://github.com/tiangolo/full-stack-fastapi-template/pull/1243) by [@alejsdev](https://github.com/alejsdev). -* 🎨 Run biome after OpenAPI client generation. PR [#1226](https://github.com/tiangolo/full-stack-fastapi-template/pull/1226) by [@tomerb](https://github.com/tomerb). -* ♻️ Update DeleteConfirmation component to use new service. PR [#1224](https://github.com/tiangolo/full-stack-fastapi-template/pull/1224) by [@alejsdev](https://github.com/alejsdev). -* ♻️ Update client services. PR [#1223](https://github.com/tiangolo/full-stack-fastapi-template/pull/1223) by [@alejsdev](https://github.com/alejsdev). -* βš’οΈ Add minor frontend tweaks. PR [#1210](https://github.com/tiangolo/full-stack-fastapi-template/pull/1210) by [@alejsdev](https://github.com/alejsdev). -* 🚚 Move assets to public folder. PR [#1206](https://github.com/tiangolo/full-stack-fastapi-template/pull/1206) by [@alejsdev](https://github.com/alejsdev). -* ♻️ Refactor redirect labels to simplify removing the frontend. PR [#1208](https://github.com/tiangolo/full-stack-fastapi-template/pull/1208) by [@tiangolo](https://github.com/tiangolo). -* πŸ”’οΈ Refactor migrate from python-jose to PyJWT. PR [#1203](https://github.com/tiangolo/full-stack-fastapi-template/pull/1203) by [@estebanx64](https://github.com/estebanx64). -* πŸ”₯ Remove duplicated code. PR [#1185](https://github.com/tiangolo/full-stack-fastapi-template/pull/1185) by [@alejsdev](https://github.com/alejsdev). -* ♻️ Add delete_user_me endpoint and corresponding test cases. PR [#1179](https://github.com/tiangolo/full-stack-fastapi-template/pull/1179) by [@alejsdev](https://github.com/alejsdev). -* βœ… Update test to add verification database records. PR [#1178](https://github.com/tiangolo/full-stack-fastapi-template/pull/1178) by [@estebanx64](https://github.com/estebanx64). -* 🚸 Use `useSuspenseQuery` to fetch members and show skeleton. PR [#1174](https://github.com/tiangolo/full-stack-fastapi-template/pull/1174) by [@patrick91](https://github.com/patrick91). -* 🎨 Format Utils. PR [#1173](https://github.com/tiangolo/full-stack-fastapi-template/pull/1173) by [@alejsdev](https://github.com/alejsdev). -* ✨ Use suspense for items page. PR [#1167](https://github.com/tiangolo/full-stack-fastapi-template/pull/1167) by [@patrick91](https://github.com/patrick91). -* 🚸 Mark login field as required. PR [#1166](https://github.com/tiangolo/full-stack-fastapi-template/pull/1166) by [@patrick91](https://github.com/patrick91). -* 🚸 Improve login. PR [#1163](https://github.com/tiangolo/full-stack-fastapi-template/pull/1163) by [@patrick91](https://github.com/patrick91). -* πŸ₯… Handle AxiosErrors in Login page. PR [#1162](https://github.com/tiangolo/full-stack-fastapi-template/pull/1162) by [@patrick91](https://github.com/patrick91). -* 🎨 Format frontend. PR [#1161](https://github.com/tiangolo/full-stack-fastapi-template/pull/1161) by [@alejsdev](https://github.com/alejsdev). -* ♻️ Regenerate frontend client. PR [#1156](https://github.com/tiangolo/full-stack-fastapi-template/pull/1156) by [@alejsdev](https://github.com/alejsdev). -* ♻️ Refactor rename ModelsOut to ModelsPublic. PR [#1154](https://github.com/tiangolo/full-stack-fastapi-template/pull/1154) by [@estebanx64](https://github.com/estebanx64). -* ♻️ Migrate frontend client generation from `openapi-typescript-codegen` to `@hey-api/openapi-ts`. PR [#1151](https://github.com/tiangolo/full-stack-fastapi-template/pull/1151) by [@alejsdev](https://github.com/alejsdev). -* πŸ”₯ Remove unused exports and update dependencies. PR [#1146](https://github.com/tiangolo/full-stack-fastapi-template/pull/1146) by [@alejsdev](https://github.com/alejsdev). -* πŸ”§ Update sentry dns initialization following the environment settings. PR [#1145](https://github.com/tiangolo/full-stack-fastapi-template/pull/1145) by [@estebanx64](https://github.com/estebanx64). -* ♻️ Refactor and tweaks, rename `UserCreateOpen` to `UserRegister` and others. PR [#1143](https://github.com/tiangolo/full-stack-fastapi-template/pull/1143) by [@alejsdev](https://github.com/alejsdev). -* 🎨 Format imports. PR [#1140](https://github.com/tiangolo/full-stack-fastapi-template/pull/1140) by [@alejsdev](https://github.com/alejsdev). -* ♻️ Refactor and remove `React.FC`. PR [#1139](https://github.com/tiangolo/full-stack-fastapi-template/pull/1139) by [@alejsdev](https://github.com/alejsdev). -* ♻️ Add email pattern and refactor in frontend. PR [#1138](https://github.com/tiangolo/full-stack-fastapi-template/pull/1138) by [@alejsdev](https://github.com/alejsdev). -* πŸ₯… Set up Sentry for FastAPI applications. PR [#1136](https://github.com/tiangolo/full-stack-fastapi-template/pull/1136) by [@estebanx64](https://github.com/estebanx64). -* πŸ”₯ Remove deprecated Docker Compose version key. PR [#1129](https://github.com/tiangolo/full-stack-fastapi-template/pull/1129) by [@tiangolo](https://github.com/tiangolo). -* 🎨 Format with Biome . PR [#1097](https://github.com/tiangolo/full-stack-fastapi-template/pull/1097) by [@alejsdev](https://github.com/alejsdev). -* 🎨 Update quote style in biome formatter. PR [#1095](https://github.com/tiangolo/full-stack-fastapi-template/pull/1095) by [@alejsdev](https://github.com/alejsdev). -* ♻️ Replace ESLint and Prettier with Biome to format and lint frontend. PR [#719](https://github.com/tiangolo/full-stack-fastapi-template/pull/719) by [@santigandolfo](https://github.com/santigandolfo). -* 🎨 Replace buttons styling for variants for consistency. PR [#722](https://github.com/tiangolo/full-stack-fastapi-template/pull/722) by [@alejsdev](https://github.com/alejsdev). -* πŸ› οΈ Improve `modify-openapi-operationids.js`. PR [#720](https://github.com/tiangolo/full-stack-fastapi-template/pull/720) by [@alejsdev](https://github.com/alejsdev). -* ♻️ Replace pytest-mock with unittest.mock and remove pytest-cov. PR [#717](https://github.com/tiangolo/full-stack-fastapi-template/pull/717) by [@estebanx64](https://github.com/estebanx64). -* πŸ› οΈ Minor changes in frontend. PR [#715](https://github.com/tiangolo/full-stack-fastapi-template/pull/715) by [@alejsdev](https://github.com/alejsdev). -* β™» Update Docker image to prevent errors in M1 Macs. PR [#710](https://github.com/tiangolo/full-stack-fastapi-template/pull/710) by [@dudil](https://github.com/dudil). -* ✏ Fix typo in variable names in `backend/app/api/routes/items.py` and `backend/app/api/routes/users.py`. PR [#711](https://github.com/tiangolo/full-stack-fastapi-template/pull/711) by [@disrupted](https://github.com/disrupted). - -### Upgrades - -* ⬆️ Update SQLModel to version `>=0.0.21`. PR [#1275](https://github.com/tiangolo/full-stack-fastapi-template/pull/1275) by [@alejsdev](https://github.com/alejsdev). -* ⬆️ Upgrade Traefik. PR [#1241](https://github.com/tiangolo/full-stack-fastapi-template/pull/1241) by [@tiangolo](https://github.com/tiangolo). -* ⬆️ Bump requests from 2.31.0 to 2.32.0 in /backend. PR [#1211](https://github.com/tiangolo/full-stack-fastapi-template/pull/1211) by [@dependabot[bot]](https://github.com/apps/dependabot). -* ⬆️ Bump jinja2 from 3.1.3 to 3.1.4 in /backend. PR [#1196](https://github.com/tiangolo/full-stack-fastapi-template/pull/1196) by [@dependabot[bot]](https://github.com/apps/dependabot). -* Bump gunicorn from 21.2.0 to 22.0.0 in /backend. PR [#1176](https://github.com/tiangolo/full-stack-fastapi-template/pull/1176) by [@dependabot[bot]](https://github.com/apps/dependabot). -* Bump idna from 3.6 to 3.7 in /backend. PR [#1168](https://github.com/tiangolo/full-stack-fastapi-template/pull/1168) by [@dependabot[bot]](https://github.com/apps/dependabot). -* πŸ†™ Update React Query to TanStack Query. PR [#1153](https://github.com/tiangolo/full-stack-fastapi-template/pull/1153) by [@patrick91](https://github.com/patrick91). -* Bump vite from 5.0.12 to 5.0.13 in /frontend. PR [#1149](https://github.com/tiangolo/full-stack-fastapi-template/pull/1149) by [@dependabot[bot]](https://github.com/apps/dependabot). -* Bump follow-redirects from 1.15.5 to 1.15.6 in /frontend. PR [#734](https://github.com/tiangolo/full-stack-fastapi-template/pull/734) by [@dependabot[bot]](https://github.com/apps/dependabot). - -### Docs - -* πŸ“ Update links from tiangolo repo to fastapi org repo. PR [#1285](https://github.com/fastapi/full-stack-fastapi-template/pull/1285) by [@tiangolo](https://github.com/tiangolo). -* πŸ“ Add End-to-End Testing with Playwright to frontend `README.md`. PR [#1279](https://github.com/tiangolo/full-stack-fastapi-template/pull/1279) by [@alejsdev](https://github.com/alejsdev). -* πŸ“ Update release-notes.md. PR [#1220](https://github.com/tiangolo/full-stack-fastapi-template/pull/1220) by [@alejsdev](https://github.com/alejsdev). -* ✏️ Update `README.md`. PR [#1205](https://github.com/tiangolo/full-stack-fastapi-template/pull/1205) by [@Craz1k0ek](https://github.com/Craz1k0ek). -* ✏️ Fix Adminer URL in `deployment.md`. PR [#1194](https://github.com/tiangolo/full-stack-fastapi-template/pull/1194) by [@PhilippWu](https://github.com/PhilippWu). -* πŸ“ Add `Enabling Open User Registration` to backend docs. PR [#1191](https://github.com/tiangolo/full-stack-fastapi-template/pull/1191) by [@alejsdev](https://github.com/alejsdev). -* πŸ“ Update release-notes.md. PR [#1164](https://github.com/tiangolo/full-stack-fastapi-template/pull/1164) by [@alejsdev](https://github.com/alejsdev). -* πŸ“ Update `README.md`. PR [#716](https://github.com/tiangolo/full-stack-fastapi-template/pull/716) by [@alejsdev](https://github.com/alejsdev). -* πŸ“ Update instructions to clone for a private repo, including updates. PR [#1127](https://github.com/tiangolo/full-stack-fastapi-template/pull/1127) by [@tiangolo](https://github.com/tiangolo). -* πŸ“ Add docs about CI keys, LATEST_CHANGES and SMOKESHOW_AUTH_KEY. PR [#1126](https://github.com/tiangolo/full-stack-fastapi-template/pull/1126) by [@tiangolo](https://github.com/tiangolo). -* ✏️ Fix file path in `backend/README.md` when not wanting to use migrations. PR [#1116](https://github.com/tiangolo/full-stack-fastapi-template/pull/1116) by [@leonlowitzki](https://github.com/leonlowitzki). -* πŸ“ Add documentation for pre-commit and code linting. PR [#718](https://github.com/tiangolo/full-stack-fastapi-template/pull/718) by [@estebanx64](https://github.com/estebanx64). -* πŸ“ Fix localhost URLs in `development.md`. PR [#1099](https://github.com/tiangolo/full-stack-fastapi-template/pull/1099) by [@efonte](https://github.com/efonte). -* ✏ Update header titles for consistency. PR [#708](https://github.com/tiangolo/full-stack-fastapi-template/pull/708) by [@codesmith-emmy](https://github.com/codesmith-emmy). -* πŸ“ Update `README.md`, dark mode screenshot position. PR [#706](https://github.com/tiangolo/full-stack-fastapi-template/pull/706) by [@alejsdev](https://github.com/alejsdev). - -### Internal - -* πŸ”§ Update deploy workflows to exclude the main repository. PR [#1284](https://github.com/tiangolo/full-stack-fastapi-template/pull/1284) by [@alejsdev](https://github.com/alejsdev). -* πŸ‘· Update issue-manager.yml GitHub Action permissions. PR [#1278](https://github.com/tiangolo/full-stack-fastapi-template/pull/1278) by [@tiangolo](https://github.com/tiangolo). -* ⬆️ Bump setuptools from 69.1.1 to 70.0.0 in /backend. PR [#1255](https://github.com/tiangolo/full-stack-fastapi-template/pull/1255) by [@dependabot[bot]](https://github.com/apps/dependabot). -* ⬆️ Bump certifi from 2024.2.2 to 2024.7.4 in /backend. PR [#1250](https://github.com/tiangolo/full-stack-fastapi-template/pull/1250) by [@dependabot[bot]](https://github.com/apps/dependabot). -* ⬆️ Bump urllib3 from 2.2.1 to 2.2.2 in /backend. PR [#1235](https://github.com/tiangolo/full-stack-fastapi-template/pull/1235) by [@dependabot[bot]](https://github.com/apps/dependabot). -* πŸ”§ Ignore `src/routeTree.gen.ts` in biome. PR [#1175](https://github.com/tiangolo/full-stack-fastapi-template/pull/1175) by [@patrick91](https://github.com/patrick91). -* πŸ‘· Update Smokeshow download artifact GitHub Action. PR [#1198](https://github.com/tiangolo/full-stack-fastapi-template/pull/1198) by [@tiangolo](https://github.com/tiangolo). -* πŸ”§ Update Node.js version in `.nvmrc`. PR [#1192](https://github.com/tiangolo/full-stack-fastapi-template/pull/1192) by [@alejsdev](https://github.com/alejsdev). -* πŸ”₯ Remove ESLint and Prettier from pre-commit config. PR [#1096](https://github.com/tiangolo/full-stack-fastapi-template/pull/1096) by [@alejsdev](https://github.com/alejsdev). -* πŸ”§ Update mypy config to ignore .venv directories. PR [#1155](https://github.com/tiangolo/full-stack-fastapi-template/pull/1155) by [@tiangolo](https://github.com/tiangolo). -* 🚨 Enable `ARG001` to prevent unused arguments. PR [#1152](https://github.com/tiangolo/full-stack-fastapi-template/pull/1152) by [@patrick91](https://github.com/patrick91). -* πŸ”₯ Remove isort configuration, since we use Ruff now. PR [#1144](https://github.com/tiangolo/full-stack-fastapi-template/pull/1144) by [@patrick91](https://github.com/patrick91). -* πŸ”§ Update pre-commit config to exclude generated client folder. PR [#1150](https://github.com/tiangolo/full-stack-fastapi-template/pull/1150) by [@alejsdev](https://github.com/alejsdev). -* πŸ”§ Change `.nvmrc` format. PR [#1148](https://github.com/tiangolo/full-stack-fastapi-template/pull/1148) by [@patrick91](https://github.com/patrick91). -* 🎨 Ignore alembic from ruff lint and format. PR [#1131](https://github.com/tiangolo/full-stack-fastapi-template/pull/1131) by [@estebanx64](https://github.com/estebanx64). -* πŸ”§ Add GitHub templates for discussions and issues, and security policy. PR [#1105](https://github.com/tiangolo/full-stack-fastapi-template/pull/1105) by [@alejsdev](https://github.com/alejsdev). -* ⬆ Bump dawidd6/action-download-artifact from 3.1.2 to 3.1.4. PR [#1103](https://github.com/tiangolo/full-stack-fastapi-template/pull/1103) by [@dependabot[bot]](https://github.com/apps/dependabot). -* πŸ”§ Add Biome to pre-commit config. PR [#1098](https://github.com/tiangolo/full-stack-fastapi-template/pull/1098) by [@alejsdev](https://github.com/alejsdev). -* πŸ”₯ Delete leftover celery file. PR [#727](https://github.com/tiangolo/full-stack-fastapi-template/pull/727) by [@dr-neptune](https://github.com/dr-neptune). -* βš™οΈ Update pre-commit config with Prettier and ESLint. PR [#714](https://github.com/tiangolo/full-stack-fastapi-template/pull/714) by [@alejsdev](https://github.com/alejsdev). - -## 0.6.0 - -Latest FastAPI, Pydantic, SQLModel πŸš€ - -Brand new frontend with React, TS, Vite, Chakra UI, TanStack Query/Router, generated client/SDK 🎨 - -CI/CD - GitHub Actions πŸ€– - -Test cov > 90% βœ… - -### Features - -* ✨ Adopt SQLModel, create models, start using it. PR [#559](https://github.com/tiangolo/full-stack-fastapi-template/pull/559) by [@tiangolo](https://github.com/tiangolo). -* ✨ Upgrade items router with new SQLModel models, simplified logic, and new FastAPI Annotated dependencies. PR [#560](https://github.com/tiangolo/full-stack-fastapi-template/pull/560) by [@tiangolo](https://github.com/tiangolo). -* ✨ Migrate from pgAdmin to Adminer. PR [#692](https://github.com/tiangolo/full-stack-fastapi-template/pull/692) by [@tiangolo](https://github.com/tiangolo). -* ✨ Add support for setting `POSTGRES_PORT`. PR [#333](https://github.com/tiangolo/full-stack-fastapi-template/pull/333) by [@uepoch](https://github.com/uepoch). -* ⬆ Upgrade Flower version and command. PR [#447](https://github.com/tiangolo/full-stack-fastapi-template/pull/447) by [@maurob](https://github.com/maurob). -* 🎨 Improve styles. PR [#673](https://github.com/tiangolo/full-stack-fastapi-template/pull/673) by [@alejsdev](https://github.com/alejsdev). -* 🎨 Update theme. PR [#666](https://github.com/tiangolo/full-stack-fastapi-template/pull/666) by [@alejsdev](https://github.com/alejsdev). -* πŸ‘· Add continuous deployment and refactors needed for it. PR [#667](https://github.com/tiangolo/full-stack-fastapi-template/pull/667) by [@tiangolo](https://github.com/tiangolo). -* ✨ Create endpoint to show password recovery email content and update email template. PR [#664](https://github.com/tiangolo/full-stack-fastapi-template/pull/664) by [@alejsdev](https://github.com/alejsdev). -* 🎨 Format with Prettier. PR [#646](https://github.com/tiangolo/full-stack-fastapi-template/pull/646) by [@alejsdev](https://github.com/alejsdev). -* βœ… Add tests to raise coverage to at least 90% and fix recover password logic. PR [#632](https://github.com/tiangolo/full-stack-fastapi-template/pull/632) by [@estebanx64](https://github.com/estebanx64). -* βš™οΈ Add Prettier and ESLint config with pre-commit. PR [#640](https://github.com/tiangolo/full-stack-fastapi-template/pull/640) by [@alejsdev](https://github.com/alejsdev). -* πŸ‘· Add coverage with Smokeshow to CI and badge. PR [#638](https://github.com/tiangolo/full-stack-fastapi-template/pull/638) by [@estebanx64](https://github.com/estebanx64). -* ✨ Migrate to TanStack Query (React Query) and TanStack Router. PR [#637](https://github.com/tiangolo/full-stack-fastapi-template/pull/637) by [@alejsdev](https://github.com/alejsdev). -* βœ… Add setup and teardown database for tests. PR [#626](https://github.com/tiangolo/full-stack-fastapi-template/pull/626) by [@estebanx64](https://github.com/estebanx64). -* ✨ Update new-frontend client. PR [#625](https://github.com/tiangolo/full-stack-fastapi-template/pull/625) by [@alejsdev](https://github.com/alejsdev). -* ✨ Add password reset functionality. PR [#624](https://github.com/tiangolo/full-stack-fastapi-template/pull/624) by [@alejsdev](https://github.com/alejsdev). -* ✨ Add private/public routing. PR [#621](https://github.com/tiangolo/full-stack-fastapi-template/pull/621) by [@alejsdev](https://github.com/alejsdev). -* πŸ”§ Add VS Code debug configs. PR [#620](https://github.com/tiangolo/full-stack-fastapi-template/pull/620) by [@tiangolo](https://github.com/tiangolo). -* ✨ Add `Not Found` page. PR [#595](https://github.com/tiangolo/full-stack-fastapi-template/pull/595) by [@alejsdev](https://github.com/alejsdev). -* ✨ Add new pages, components, panels, modals, and theme; refactor and improvements in existing components. PR [#593](https://github.com/tiangolo/full-stack-fastapi-template/pull/593) by [@alejsdev](https://github.com/alejsdev). -* ✨ Support delete own account and other tweaks. PR [#614](https://github.com/tiangolo/full-stack-fastapi-template/pull/614) by [@alejsdev](https://github.com/alejsdev). -* ✨ Restructure folders, allow editing of users/items, and implement other refactors and improvements. PR [#603](https://github.com/tiangolo/full-stack-fastapi-template/pull/603) by [@alejsdev](https://github.com/alejsdev). -* ✨ Add Copier, migrate from Cookiecutter, in a way that supports using the project as is, forking or cloning it. PR [#612](https://github.com/tiangolo/full-stack-fastapi-template/pull/612) by [@tiangolo](https://github.com/tiangolo). -* βž• Replace black, isort, flake8, autoflake with ruff and upgrade mypy. PR [#610](https://github.com/tiangolo/full-stack-fastapi-template/pull/610) by [@tiangolo](https://github.com/tiangolo). -* β™» Refactor items and services endpoints to return count and data, and add CI tests. PR [#599](https://github.com/tiangolo/full-stack-fastapi-template/pull/599) by [@estebanx64](https://github.com/estebanx64). -* ✨ Add support for updating items and upgrade SQLModel to 0.0.16 (which supports model object updates). PR [#601](https://github.com/tiangolo/full-stack-fastapi-template/pull/601) by [@tiangolo](https://github.com/tiangolo). -* ✨ Add dark mode to new-frontend and conditional sidebar items. PR [#600](https://github.com/tiangolo/full-stack-fastapi-template/pull/600) by [@alejsdev](https://github.com/alejsdev). -* ✨ Migrate to RouterProvider and other refactors . PR [#598](https://github.com/tiangolo/full-stack-fastapi-template/pull/598) by [@alejsdev](https://github.com/alejsdev). -* ✨ Add delete_user; refactor delete_item. PR [#594](https://github.com/tiangolo/full-stack-fastapi-template/pull/594) by [@alejsdev](https://github.com/alejsdev). -* ✨ Add state store to new frontend. PR [#592](https://github.com/tiangolo/full-stack-fastapi-template/pull/592) by [@alejsdev](https://github.com/alejsdev). -* ✨ Add form validation to Admin, Items and Login. PR [#616](https://github.com/tiangolo/full-stack-fastapi-template/pull/616) by [@alejsdev](https://github.com/alejsdev). -* ✨ Add Sidebar to new frontend. PR [#587](https://github.com/tiangolo/full-stack-fastapi-template/pull/587) by [@alejsdev](https://github.com/alejsdev). -* ✨ Add Login to new frontend. PR [#585](https://github.com/tiangolo/full-stack-fastapi-template/pull/585) by [@alejsdev](https://github.com/alejsdev). -* ✨ Include schemas in generated frontend client. PR [#584](https://github.com/tiangolo/full-stack-fastapi-template/pull/584) by [@alejsdev](https://github.com/alejsdev). -* ✨ Regenerate frontend client with recent changes. PR [#575](https://github.com/tiangolo/full-stack-fastapi-template/pull/575) by [@alejsdev](https://github.com/alejsdev). -* ♻️ Refactor API in `utils.py`. PR [#573](https://github.com/tiangolo/full-stack-fastapi-template/pull/573) by [@alejsdev](https://github.com/alejsdev). -* ✨ Update code for login API. PR [#571](https://github.com/tiangolo/full-stack-fastapi-template/pull/571) by [@tiangolo](https://github.com/tiangolo). -* ✨ Add client in frontend and client generation. PR [#569](https://github.com/tiangolo/full-stack-fastapi-template/pull/569) by [@alejsdev](https://github.com/alejsdev). -* 🐳 Set up Docker config for new-frontend. PR [#564](https://github.com/tiangolo/full-stack-fastapi-template/pull/564) by [@alejsdev](https://github.com/alejsdev). -* ✨ Set up new frontend with Vite, TypeScript and React. PR [#563](https://github.com/tiangolo/full-stack-fastapi-template/pull/563) by [@alejsdev](https://github.com/alejsdev). -* πŸ“Œ Add NodeJS version management and instructions. PR [#551](https://github.com/tiangolo/full-stack-fastapi-template/pull/551) by [@alejsdev](https://github.com/alejsdev). -* Add consistent errors for env vars not set. PR [#200](https://github.com/tiangolo/full-stack-fastapi-template/pull/200). -* Upgrade Traefik to version 2, keeping in sync with DockerSwarm.rocks. PR [#199](https://github.com/tiangolo/full-stack-fastapi-template/pull/199). -* Run tests with `TestClient`. PR [#160](https://github.com/tiangolo/full-stack-fastapi-template/pull/160). - -### Fixes - -* πŸ› Fix copier to handle string vars with spaces in quotes. PR [#631](https://github.com/tiangolo/full-stack-fastapi-template/pull/631) by [@estebanx64](https://github.com/estebanx64). -* πŸ› Fix allowing a user to update the email to the same email they already have. PR [#696](https://github.com/tiangolo/full-stack-fastapi-template/pull/696) by [@alejsdev](https://github.com/alejsdev). -* πŸ› Set up Sentry only when used. PR [#671](https://github.com/tiangolo/full-stack-fastapi-template/pull/671) by [@tiangolo](https://github.com/tiangolo). -* πŸ”₯ Remove unnecessary validation. PR [#662](https://github.com/tiangolo/full-stack-fastapi-template/pull/662) by [@alejsdev](https://github.com/alejsdev). -* πŸ› Fix bug when editing own user. PR [#651](https://github.com/tiangolo/full-stack-fastapi-template/pull/651) by [@alejsdev](https://github.com/alejsdev). -* πŸ› Add `onClose` to `SidebarItems`. PR [#589](https://github.com/tiangolo/full-stack-fastapi-template/pull/589) by [@alejsdev](https://github.com/alejsdev). -* πŸ› Fix positional argument bug in `init_db.py`. PR [#562](https://github.com/tiangolo/full-stack-fastapi-template/pull/562) by [@alejsdev](https://github.com/alejsdev). -* πŸ“Œ Fix flower Docker image, pin version. PR [#396](https://github.com/tiangolo/full-stack-fastapi-template/pull/396) by [@sanggusti](https://github.com/sanggusti). -* πŸ› Fix Celery worker command. PR [#443](https://github.com/tiangolo/full-stack-fastapi-template/pull/443) by [@bechtold](https://github.com/bechtold). -* πŸ› Fix Poetry installation in Dockerfile and upgrade Python version and packages to fix Docker build. PR [#480](https://github.com/tiangolo/full-stack-fastapi-template/pull/480) by [@little7Li](https://github.com/little7Li). - -### Refactors - -* πŸ”§ Add missing dotenv variables. PR [#554](https://github.com/tiangolo/full-stack-fastapi-template/pull/554) by [@tiangolo](https://github.com/tiangolo). -* βͺ Revert "βš™οΈ Add Prettier and ESLint config with pre-commit". PR [#644](https://github.com/tiangolo/full-stack-fastapi-template/pull/644) by [@alejsdev](https://github.com/alejsdev). -* πŸ™ˆ Add .prettierignore and include client folder. PR [#648](https://github.com/tiangolo/full-stack-fastapi-template/pull/648) by [@alejsdev](https://github.com/alejsdev). -* 🏷️ Add mypy to the GitHub Action for tests and fixed types in the whole project. PR [#655](https://github.com/tiangolo/full-stack-fastapi-template/pull/655) by [@estebanx64](https://github.com/estebanx64). -* πŸ”’οΈ Ensure the default values of "changethis" are not deployed. PR [#698](https://github.com/tiangolo/full-stack-fastapi-template/pull/698) by [@tiangolo](https://github.com/tiangolo). -* β—€ Revert "πŸ“Έ Rename Dashboard to Home and update screenshots". PR [#697](https://github.com/tiangolo/full-stack-fastapi-template/pull/697) by [@alejsdev](https://github.com/alejsdev). -* πŸ“Έ Rename Dashboard to Home and update screenshots. PR [#693](https://github.com/tiangolo/full-stack-fastapi-template/pull/693) by [@alejsdev](https://github.com/alejsdev). -* πŸ› Fixed items count when retrieving data for all items by user. PR [#695](https://github.com/tiangolo/full-stack-fastapi-template/pull/695) by [@estebanx64](https://github.com/estebanx64). -* πŸ”₯ Remove Celery and Flower, they are currently not used nor recommended. PR [#694](https://github.com/tiangolo/full-stack-fastapi-template/pull/694) by [@tiangolo](https://github.com/tiangolo). -* βœ… Add test for deleting user without privileges. PR [#690](https://github.com/tiangolo/full-stack-fastapi-template/pull/690) by [@alejsdev](https://github.com/alejsdev). -* ♻️ Refactor user update. PR [#689](https://github.com/tiangolo/full-stack-fastapi-template/pull/689) by [@alejsdev](https://github.com/alejsdev). -* πŸ“Œ Add Poetry lock to git. PR [#685](https://github.com/tiangolo/full-stack-fastapi-template/pull/685) by [@tiangolo](https://github.com/tiangolo). -* 🎨 Adjust color and spacing. PR [#684](https://github.com/tiangolo/full-stack-fastapi-template/pull/684) by [@alejsdev](https://github.com/alejsdev). -* πŸ‘· Avoid creating unnecessary *.pyc files with PYTHONDONTWRITEBYTECODE=1. PR [#677](https://github.com/tiangolo/full-stack-fastapi-template/pull/677) by [@estebanx64](https://github.com/estebanx64). -* πŸ”§ Add `SMTP_SSL` option for older SMTP servers. PR [#365](https://github.com/tiangolo/full-stack-fastapi-template/pull/365) by [@Metrea](https://github.com/Metrea). -* ♻️ Refactor logic to allow running pytest tests locally. PR [#683](https://github.com/tiangolo/full-stack-fastapi-template/pull/683) by [@tiangolo](https://github.com/tiangolo). -* β™» Update error messages. PR [#417](https://github.com/tiangolo/full-stack-fastapi-template/pull/417) by [@qu3vipon](https://github.com/qu3vipon). -* πŸ”§ Add a default Flower password. PR [#682](https://github.com/tiangolo/full-stack-fastapi-template/pull/682) by [@tiangolo](https://github.com/tiangolo). -* πŸ”§ Update VS Code debug config. PR [#676](https://github.com/tiangolo/full-stack-fastapi-template/pull/676) by [@tiangolo](https://github.com/tiangolo). -* ♻️ Refactor code structure for tests. PR [#674](https://github.com/tiangolo/full-stack-fastapi-template/pull/674) by [@tiangolo](https://github.com/tiangolo). -* πŸ”§ Set TanStack Router devtools only in dev mode. PR [#668](https://github.com/tiangolo/full-stack-fastapi-template/pull/668) by [@alejsdev](https://github.com/alejsdev). -* ♻️ Refactor email logic to allow re-using util functions for testing and development. PR [#663](https://github.com/tiangolo/full-stack-fastapi-template/pull/663) by [@tiangolo](https://github.com/tiangolo). -* πŸ’¬ Improve Delete Account description and confirmation. PR [#661](https://github.com/tiangolo/full-stack-fastapi-template/pull/661) by [@alejsdev](https://github.com/alejsdev). -* ♻️ Refactor email templates. PR [#659](https://github.com/tiangolo/full-stack-fastapi-template/pull/659) by [@alejsdev](https://github.com/alejsdev). -* πŸ“ Update deployment files and docs. PR [#660](https://github.com/tiangolo/full-stack-fastapi-template/pull/660) by [@tiangolo](https://github.com/tiangolo). -* πŸ”₯ Remove unused schemas. PR [#656](https://github.com/tiangolo/full-stack-fastapi-template/pull/656) by [@alejsdev](https://github.com/alejsdev). -* πŸ”₯ Remove old frontend. PR [#649](https://github.com/tiangolo/full-stack-fastapi-template/pull/649) by [@tiangolo](https://github.com/tiangolo). -* β™» Move project source files to top level from src, update Sentry dependency. PR [#630](https://github.com/tiangolo/full-stack-fastapi-template/pull/630) by [@estebanx64](https://github.com/estebanx64). -* β™» Refactor Python folder tree. PR [#629](https://github.com/tiangolo/full-stack-fastapi-template/pull/629) by [@estebanx64](https://github.com/estebanx64). -* ♻️ Refactor old CRUD utils and tests. PR [#622](https://github.com/tiangolo/full-stack-fastapi-template/pull/622) by [@alejsdev](https://github.com/alejsdev). -* πŸ”§ Update .env to allow local debug for the backend. PR [#618](https://github.com/tiangolo/full-stack-fastapi-template/pull/618) by [@tiangolo](https://github.com/tiangolo). -* ♻️ Refactor and update CORS, remove trailing slash from new Pydantic v2. PR [#617](https://github.com/tiangolo/full-stack-fastapi-template/pull/617) by [@tiangolo](https://github.com/tiangolo). -* 🎨 Format files with pre-commit and Ruff. PR [#611](https://github.com/tiangolo/full-stack-fastapi-template/pull/611) by [@tiangolo](https://github.com/tiangolo). -* 🚚 Refactor and simplify backend file structure. PR [#609](https://github.com/tiangolo/full-stack-fastapi-template/pull/609) by [@tiangolo](https://github.com/tiangolo). -* πŸ”₯ Clean up old files no longer relevant. PR [#608](https://github.com/tiangolo/full-stack-fastapi-template/pull/608) by [@tiangolo](https://github.com/tiangolo). -* β™» Re-structure Docker Compose files, discard Docker Swarm specific logic. PR [#607](https://github.com/tiangolo/full-stack-fastapi-template/pull/607) by [@tiangolo](https://github.com/tiangolo). -* ♻️ Refactor update endpoints and regenerate client for new-frontend. PR [#602](https://github.com/tiangolo/full-stack-fastapi-template/pull/602) by [@alejsdev](https://github.com/alejsdev). -* ✨ Add Layout to App. PR [#588](https://github.com/tiangolo/full-stack-fastapi-template/pull/588) by [@alejsdev](https://github.com/alejsdev). -* ♻️ Re-enable user update path operations for frontend client generation. PR [#574](https://github.com/tiangolo/full-stack-fastapi-template/pull/574) by [@alejsdev](https://github.com/alejsdev). -* ♻️ Remove type ignores and add `response_model`. PR [#572](https://github.com/tiangolo/full-stack-fastapi-template/pull/572) by [@alejsdev](https://github.com/alejsdev). -* ♻️ Refactor Users API and dependencies. PR [#561](https://github.com/tiangolo/full-stack-fastapi-template/pull/561) by [@alejsdev](https://github.com/alejsdev). -* ♻️ Refactor frontend Docker build setup, use plain NodeJS, use custom Nginx config, fix build for old Vue. PR [#555](https://github.com/tiangolo/full-stack-fastapi-template/pull/555) by [@tiangolo](https://github.com/tiangolo). -* ♻️ Refactor project generation, discard cookiecutter, use plain git/clone/fork. PR [#553](https://github.com/tiangolo/full-stack-fastapi-template/pull/553) by [@tiangolo](https://github.com/tiangolo). -* Refactor backend: - * Simplify configs for tools and format to better support editor integration. - * Add mypy configurations and plugins. - * Add types to all the codebase. - * Update types for SQLAlchemy models with plugin. - * Update and refactor CRUD utils. - * Refactor DB sessions to use dependencies with `yield`. - * Refactor dependencies, security, CRUD, models, schemas, etc. To simplify code and improve autocompletion. - * Change from PyJWT to Python-JOSE as it supports additional use cases. - * Fix JWT tokens using user email/ID as the subject in `sub`. - * PR [#158](https://github.com/tiangolo/full-stack-fastapi-template/pull/158). -* Simplify `docker-compose.*.yml` files, refactor deployment to reduce config files. PR [#153](https://github.com/tiangolo/full-stack-fastapi-template/pull/153). -* Simplify env var files, merge to a single `.env` file. PR [#151](https://github.com/tiangolo/full-stack-fastapi-template/pull/151). - -### Upgrades - -* πŸ“Œ Upgrade Poetry lock dependencies. PR [#702](https://github.com/tiangolo/full-stack-fastapi-template/pull/702) by [@tiangolo](https://github.com/tiangolo). -* ⬆️ Upgrade Python version and dependencies. PR [#558](https://github.com/tiangolo/full-stack-fastapi-template/pull/558) by [@tiangolo](https://github.com/tiangolo). -* ⬆ Bump tiangolo/issue-manager from 0.2.0 to 0.5.0. PR [#591](https://github.com/tiangolo/full-stack-fastapi-template/pull/591) by [@dependabot[bot]](https://github.com/apps/dependabot). -* Bump follow-redirects from 1.15.3 to 1.15.5 in /frontend. PR [#654](https://github.com/tiangolo/full-stack-fastapi-template/pull/654) by [@dependabot[bot]](https://github.com/apps/dependabot). -* Bump vite from 5.0.4 to 5.0.12 in /frontend. PR [#653](https://github.com/tiangolo/full-stack-fastapi-template/pull/653) by [@dependabot[bot]](https://github.com/apps/dependabot). -* Bump fastapi from 0.104.1 to 0.109.1 in /backend. PR [#687](https://github.com/tiangolo/full-stack-fastapi-template/pull/687) by [@dependabot[bot]](https://github.com/apps/dependabot). -* Bump python-multipart from 0.0.6 to 0.0.7 in /backend. PR [#686](https://github.com/tiangolo/full-stack-fastapi-template/pull/686) by [@dependabot[bot]](https://github.com/apps/dependabot). -* ⬆ Add `uvicorn[standard]` to include `watchgod` and `uvloop`. PR [#438](https://github.com/tiangolo/full-stack-fastapi-template/pull/438) by [@alonme](https://github.com/alonme). -* ⬆ Upgrade code to support pydantic V2. PR [#615](https://github.com/tiangolo/full-stack-fastapi-template/pull/615) by [@estebanx64](https://github.com/estebanx64). - -### Docs - -* πŸ¦‡ Add dark mode to `README.md`. PR [#703](https://github.com/tiangolo/full-stack-fastapi-template/pull/703) by [@alejsdev](https://github.com/alejsdev). -* 🍱 Update GitHub image. PR [#701](https://github.com/tiangolo/full-stack-fastapi-template/pull/701) by [@tiangolo](https://github.com/tiangolo). -* 🍱 Add GitHub image. PR [#700](https://github.com/tiangolo/full-stack-fastapi-template/pull/700) by [@tiangolo](https://github.com/tiangolo). -* 🚚 Rename project to Full Stack FastAPI Template. PR [#699](https://github.com/tiangolo/full-stack-fastapi-template/pull/699) by [@tiangolo](https://github.com/tiangolo). -* πŸ“ Update `README.md`. PR [#691](https://github.com/tiangolo/full-stack-fastapi-template/pull/691) by [@alejsdev](https://github.com/alejsdev). -* ✏ Fix typo in `development.md`. PR [#309](https://github.com/tiangolo/full-stack-fastapi-template/pull/309) by [@graue70](https://github.com/graue70). -* πŸ“ Add docs for wildcard domains. PR [#681](https://github.com/tiangolo/full-stack-fastapi-template/pull/681) by [@tiangolo](https://github.com/tiangolo). -* πŸ“ Add the required GitHub Actions secrets to docs. PR [#679](https://github.com/tiangolo/full-stack-fastapi-template/pull/679) by [@tiangolo](https://github.com/tiangolo). -* πŸ“ Update `README.md` and `deployment.md`. PR [#678](https://github.com/tiangolo/full-stack-fastapi-template/pull/678) by [@alejsdev](https://github.com/alejsdev). -* πŸ“ Update frontend `README.md`. PR [#675](https://github.com/tiangolo/full-stack-fastapi-template/pull/675) by [@alejsdev](https://github.com/alejsdev). -* πŸ“ Update deployment docs to use a different directory for traefik-public. PR [#670](https://github.com/tiangolo/full-stack-fastapi-template/pull/670) by [@tiangolo](https://github.com/tiangolo). -* πŸ“Έ Add new screenshots . PR [#657](https://github.com/tiangolo/full-stack-fastapi-template/pull/657) by [@alejsdev](https://github.com/alejsdev). -* πŸ“ Refactor README into separate README.md files for backend, frontend, deployment, development. PR [#639](https://github.com/tiangolo/full-stack-fastapi-template/pull/639) by [@tiangolo](https://github.com/tiangolo). -* πŸ“ Update README. PR [#628](https://github.com/tiangolo/full-stack-fastapi-template/pull/628) by [@tiangolo](https://github.com/tiangolo). -* πŸ‘· Update GitHub Action latest-changes and move release notes to independent file. PR [#619](https://github.com/tiangolo/full-stack-fastapi-template/pull/619) by [@tiangolo](https://github.com/tiangolo). -* πŸ“ Update internal README and referred files. PR [#613](https://github.com/tiangolo/full-stack-fastapi-template/pull/613) by [@tiangolo](https://github.com/tiangolo). -* πŸ“ Update README with in construction notice. PR [#552](https://github.com/tiangolo/full-stack-fastapi-template/pull/552) by [@tiangolo](https://github.com/tiangolo). -* Add docs about reporting test coverage in HTML. PR [#161](https://github.com/tiangolo/full-stack-fastapi-template/pull/161). -* Add docs about removing the frontend, for an API-only app. PR [#156](https://github.com/tiangolo/full-stack-fastapi-template/pull/156). - -### Internal - -* πŸ‘· Add Lint to GitHub Actions outside of tests. PR [#688](https://github.com/tiangolo/full-stack-fastapi-template/pull/688) by [@tiangolo](https://github.com/tiangolo). -* ⬆ Bump dawidd6/action-download-artifact from 2.28.0 to 3.1.2. PR [#643](https://github.com/tiangolo/full-stack-fastapi-template/pull/643) by [@dependabot[bot]](https://github.com/apps/dependabot). -* ⬆ Bump actions/upload-artifact from 3 to 4. PR [#642](https://github.com/tiangolo/full-stack-fastapi-template/pull/642) by [@dependabot[bot]](https://github.com/apps/dependabot). -* ⬆ Bump actions/setup-python from 4 to 5. PR [#641](https://github.com/tiangolo/full-stack-fastapi-template/pull/641) by [@dependabot[bot]](https://github.com/apps/dependabot). -* πŸ‘· Tweak test GitHub Action names. PR [#672](https://github.com/tiangolo/full-stack-fastapi-template/pull/672) by [@tiangolo](https://github.com/tiangolo). -* πŸ”§ Add `.gitattributes` file to ensure LF endings for `.sh` files. PR [#658](https://github.com/tiangolo/full-stack-fastapi-template/pull/658) by [@estebanx64](https://github.com/estebanx64). -* 🚚 Move new-frontend to frontend. PR [#652](https://github.com/tiangolo/full-stack-fastapi-template/pull/652) by [@alejsdev](https://github.com/alejsdev). -* πŸ”§ Add script for ESLint. PR [#650](https://github.com/tiangolo/full-stack-fastapi-template/pull/650) by [@alejsdev](https://github.com/alejsdev). -* βš™οΈ Add Prettier config. PR [#647](https://github.com/tiangolo/full-stack-fastapi-template/pull/647) by [@alejsdev](https://github.com/alejsdev). -* πŸ”§ Update pre-commit config. PR [#645](https://github.com/tiangolo/full-stack-fastapi-template/pull/645) by [@alejsdev](https://github.com/alejsdev). -* πŸ‘· Add dependabot. PR [#547](https://github.com/tiangolo/full-stack-fastapi-template/pull/547) by [@tiangolo](https://github.com/tiangolo). -* πŸ‘· Fix latest-changes GitHub Action token, strike 2. PR [#546](https://github.com/tiangolo/full-stack-fastapi-template/pull/546) by [@tiangolo](https://github.com/tiangolo). -* πŸ‘· Fix latest-changes GitHub Action token config. PR [#545](https://github.com/tiangolo/full-stack-fastapi-template/pull/545) by [@tiangolo](https://github.com/tiangolo). -* πŸ‘· Add latest-changes GitHub Action. PR [#544](https://github.com/tiangolo/full-stack-fastapi-template/pull/544) by [@tiangolo](https://github.com/tiangolo). -* Update issue-manager. PR [#211](https://github.com/tiangolo/full-stack-fastapi-template/pull/211). -* Add [GitHub Sponsors](https://github.com/sponsors/tiangolo) button. PR [#201](https://github.com/tiangolo/full-stack-fastapi-template/pull/201). -* Simplify scripts and development, update docs and configs. PR [#155](https://github.com/tiangolo/full-stack-fastapi-template/pull/155). - -## 0.5.0 - -* Make the Traefik public network a fixed default of `traefik-public` as done in DockerSwarm.rocks, to simplify development and iteration of the project generator. PR [#150](https://github.com/tiangolo/full-stack-fastapi-template/pull/150). -* Update to PostgreSQL 12. PR [#148](https://github.com/tiangolo/full-stack-fastapi-template/pull/148). by [@RCheese](https://github.com/RCheese). -* Use Poetry for package management. Initial PR [#144](https://github.com/tiangolo/full-stack-fastapi-template/pull/144) by [@RCheese](https://github.com/RCheese). -* Fix Windows line endings for shell scripts after project generation with Cookiecutter hooks. PR [#149](https://github.com/tiangolo/full-stack-fastapi-template/pull/149). -* Upgrade Vue CLI to version 4. PR [#120](https://github.com/tiangolo/full-stack-fastapi-template/pull/120) by [@br3ndonland](https://github.com/br3ndonland). -* Remove duplicate `login` tag. PR [#135](https://github.com/tiangolo/full-stack-fastapi-template/pull/135) by [@Nonameentered](https://github.com/Nonameentered). -* Fix showing email in dashboard when there's no user's full name. PR [#129](https://github.com/tiangolo/full-stack-fastapi-template/pull/129) by [@rlonka](https://github.com/rlonka). -* Format code with Black and Flake8. PR [#121](https://github.com/tiangolo/full-stack-fastapi-template/pull/121) by [@br3ndonland](https://github.com/br3ndonland). -* Simplify SQLAlchemy Base class. PR [#117](https://github.com/tiangolo/full-stack-fastapi-template/pull/117) by [@airibarne](https://github.com/airibarne). -* Update CRUD utils for users, handling password hashing. PR [#106](https://github.com/tiangolo/full-stack-fastapi-template/pull/106) by [@mocsar](https://github.com/mocsar). -* Use `.` instead of `source` for interoperability. PR [#98](https://github.com/tiangolo/full-stack-fastapi-template/pull/98) by [@gucharbon](https://github.com/gucharbon). -* Use Pydantic's `BaseSettings` for settings/configs and env vars. PR [#87](https://github.com/tiangolo/full-stack-fastapi-template/pull/87) by [@StephenBrown2](https://github.com/StephenBrown2). -* Remove `package-lock.json` to let everyone lock their own versions (depending on OS, etc). -* Simplify Traefik service labels PR [#139](https://github.com/tiangolo/full-stack-fastapi-template/pull/139). -* Add email validation. PR [#40](https://github.com/tiangolo/full-stack-fastapi-template/pull/40) by [@kedod](https://github.com/kedod). -* Fix typo in README. PR [#83](https://github.com/tiangolo/full-stack-fastapi-template/pull/83) by [@ashears](https://github.com/ashears). -* Fix typo in README. PR [#80](https://github.com/tiangolo/full-stack-fastapi-template/pull/80) by [@abjoker](https://github.com/abjoker). -* Fix function name `read_item` and response code. PR [#74](https://github.com/tiangolo/full-stack-fastapi-template/pull/74) by [@jcaguirre89](https://github.com/jcaguirre89). -* Fix typo in comment. PR [#70](https://github.com/tiangolo/full-stack-fastapi-template/pull/70) by [@daniel-butler](https://github.com/daniel-butler). -* Fix Flower Docker configuration. PR [#37](https://github.com/tiangolo/full-stack-fastapi-template/pull/37) by [@dmontagu](https://github.com/dmontagu). -* Add new CRUD utils based on DB and Pydantic models. Initial PR [#23](https://github.com/tiangolo/full-stack-fastapi-template/pull/23) by [@ebreton](https://github.com/ebreton). -* Add normal user testing Pytest fixture. PR [#20](https://github.com/tiangolo/full-stack-fastapi-template/pull/20) by [@ebreton](https://github.com/ebreton). - -## 0.4.0 - -* Fix security on resetting a password. Receive token as body, not query. PR [#34](https://github.com/tiangolo/full-stack-fastapi-template/pull/34). - -* Fix security on resetting a password. Receive it as body, not query. PR [#33](https://github.com/tiangolo/full-stack-fastapi-template/pull/33) by [@dmontagu](https://github.com/dmontagu). - -* Fix SQLAlchemy class lookup on initialization. PR [#29](https://github.com/tiangolo/full-stack-fastapi-template/pull/29) by [@ebreton](https://github.com/ebreton). - -* Fix SQLAlchemy operation errors on database restart. PR [#32](https://github.com/tiangolo/full-stack-fastapi-template/pull/32) by [@ebreton](https://github.com/ebreton). - -* Fix locations of scripts in generated README. PR [#19](https://github.com/tiangolo/full-stack-fastapi-template/pull/19) by [@ebreton](https://github.com/ebreton). - -* Forward arguments from script to `pytest` inside container. PR [#17](https://github.com/tiangolo/full-stack-fastapi-template/pull/17) by [@ebreton](https://github.com/ebreton). - -* Update development scripts. - -* Read Alembic configs from env vars. PR #9 by @ebreton. - -* Create DB Item objects from all Pydantic model's fields. - -* Update Jupyter Lab installation and util script/environment variable for local development. - -## 0.3.0 - -* PR #14: - * Update CRUD utils to use types better. - * Simplify Pydantic model names, from `UserInCreate` to `UserCreate`, etc. - * Upgrade packages. - * Add new generic "Items" models, crud utils, endpoints, and tests. To facilitate re-using them to create new functionality. As they are simple and generic (not like Users), it's easier to copy-paste and adapt them to each use case. - * Update endpoints/*path operations* to simplify code and use new utilities, prefix and tags in `include_router`. - * Update testing utils. - * Update linting rules, relax vulture to reduce false positives. - * Update migrations to include new Items. - * Update project README.md with tips about how to start with backend. - -* Upgrade Python to 3.7 as Celery is now compatible too. PR #10 by @ebreton. - -## 0.2.2 - -* Fix frontend hijacking /docs in development. Using latest https://github.com/tiangolo/node-frontend with custom Nginx configs in frontend. PR #6. - -## 0.2.1 - -* Fix documentation for *path operation* to get user by ID. PR #4 by @mpclarkson in FastAPI. - -* Set `/start-reload.sh` as a command override for development by default. - -* Update generated README. - -## 0.2.0 - -**PR #2**: - -* Simplify and update backend `Dockerfile`s. -* Refactor and simplify backend code, improve naming, imports, modules and "namespaces". -* Improve and simplify Vuex integration with TypeScript accessors. -* Standardize frontend components layout, buttons order, etc. -* Add local development scripts (to develop this project generator itself). -* Add logs to startup modules to detect errors early. -* Improve FastAPI dependency utilities, to simplify and reduce code (to require a superuser). - -## 0.1.2 - -* Fix path operation to update self-user, set parameters as body payload. - -## 0.1.1 - -Several bug fixes since initial publication, including: - -* Order of path operations for users. -* Frontend sending login data in the correct format. -* Add https://localhost variants to CORS. diff --git a/scripts/build-push.sh b/scripts/build-push.sh deleted file mode 100644 index 3fa3aa7e6b..0000000000 --- a/scripts/build-push.sh +++ /dev/null @@ -1,10 +0,0 @@ -#! /usr/bin/env sh - -# Exit in case of error -set -e - -TAG=${TAG?Variable not set} \ -FRONTEND_ENV=${FRONTEND_ENV-production} \ -sh ./scripts/build.sh - -docker-compose -f docker-compose.yml push diff --git a/scripts/build.sh b/scripts/build.sh deleted file mode 100644 index 21528c538e..0000000000 --- a/scripts/build.sh +++ /dev/null @@ -1,10 +0,0 @@ -#! /usr/bin/env sh - -# Exit in case of error -set -e - -TAG=${TAG?Variable not set} \ -FRONTEND_ENV=${FRONTEND_ENV-production} \ -docker-compose \ --f docker-compose.yml \ -build diff --git a/scripts/deploy.sh b/scripts/deploy.sh deleted file mode 100644 index 99faa96bf7..0000000000 --- a/scripts/deploy.sh +++ /dev/null @@ -1,15 +0,0 @@ -#! /usr/bin/env sh - -# Exit in case of error -set -e - -DOMAIN=${DOMAIN?Variable not set} \ -STACK_NAME=${STACK_NAME?Variable not set} \ -TAG=${TAG?Variable not set} \ -docker-compose \ --f docker-compose.yml \ -config > docker-stack.yml - -docker-auto-labels docker-stack.yml - -docker stack deploy -c docker-stack.yml --with-registry-auth "${STACK_NAME?Variable not set}" diff --git a/scripts/docker-build-push.sh b/scripts/docker-build-push.sh new file mode 100644 index 0000000000..bcf1eaf27a --- /dev/null +++ b/scripts/docker-build-push.sh @@ -0,0 +1,20 @@ +#!/bin/bash + +# Set your Docker Hub username +DOCKER_USERNAME="dperezsa" +VERSION="1.0.0" + +# Build backend image +echo "Building backend image..." +docker build -t ${DOCKER_USERNAME}/sdp-backend:${VERSION} -f backend/Dockerfile backend/ + +# Build frontend image +echo "Building frontend image..." +docker build -t ${DOCKER_USERNAME}/sdp-frontend:${VERSION} -f frontend/Dockerfile frontend/ + +# Push images to Docker Hub +echo "Pushing images to Docker Hub..." +docker push ${DOCKER_USERNAME}/sdp-backend:${VERSION} +docker push ${DOCKER_USERNAME}/sdp-frontend:${VERSION} + +echo "Done!" \ No newline at end of file diff --git a/scripts/helm-build.sh b/scripts/helm-build.sh new file mode 100644 index 0000000000..a34dd28c45 --- /dev/null +++ b/scripts/helm-build.sh @@ -0,0 +1,13 @@ +#!/usr/bin/env sh + +# Exit in case of error +set -e + +# Define variables +HELM_CHART_DIR="./helm" + +# Package the Helm chart +echo "Packaging Helm chart from $HELM_CHART_DIR..." +helm package $HELM_CHART_DIR + +echo "Helm chart packaged successfully!" diff --git a/scripts/helm-deploy.sh b/scripts/helm-deploy.sh new file mode 100644 index 0000000000..3841401f42 --- /dev/null +++ b/scripts/helm-deploy.sh @@ -0,0 +1,109 @@ +#!/usr/bin/env sh + +# Exit in case of error +set -e + +# Define variables +CHART_PACKAGE=$(ls *.tgz | head -n 1) # Automatically pick the first .tgz file +RELEASE_NAME="sdp" +NAMESPACE="default" +BACKEND_PORT=8000 +FRONTEND_PORT=5173 +ADMINER_PORT=8080 +TIMEOUT=360 # 6 minute timeout + +# Check if a chart package exists +if [ -z "$CHART_PACKAGE" ]; then + echo "Error: No .tgz file found. Please run build.sh first." + exit 1 +fi + +# Deploy the Helm chart +echo "Deploying Helm chart from package: $CHART_PACKAGE..." +helm upgrade --install $RELEASE_NAME $CHART_PACKAGE --namespace $NAMESPACE --timeout ${TIMEOUT}s --wait + +echo "Deployment completed successfully!" + +# Port forwarding section +echo "Starting port forwarding..." + +# Get pod names using go-template +echo "πŸ” Getting pod names..." +PODS=$(kubectl get pods -o go-template --template '{{range .items}}{{.metadata.name}}{{"\n"}}{{end}}') + +# Identify backend, frontend, and adminer pods +BACKEND_POD="" +FRONTEND_POD="" +ADMINER_POD="" + +for pod in $PODS; do + if echo "$pod" | grep -q "backend"; then + BACKEND_POD="$pod" + elif echo "$pod" | grep -q "frontend"; then + FRONTEND_POD="$pod" + elif echo "$pod" | grep -q "adminer"; then + ADMINER_POD="$pod" + fi +done + +# Report found pods +if [ -z "$BACKEND_POD" ]; then + echo "⚠️ Could not find backend pod, skipping..." +else + echo "βœ… Backend pod: $BACKEND_POD" +fi + +if [ -z "$FRONTEND_POD" ]; then + echo "⚠️ Could not find frontend pod, skipping..." +else + echo "βœ… Frontend pod: $FRONTEND_POD" +fi + +if [ -z "$ADMINER_POD" ]; then + echo "⚠️ Could not find adminer pod, skipping..." +else + echo "βœ… Adminer pod: $ADMINER_POD" +fi + +# Start port forwarding for available pods +echo "πŸ”Œ Starting port forwarding..." + +if [ -n "$BACKEND_POD" ]; then + kubectl port-forward pod/$BACKEND_POD $BACKEND_PORT:8000 & + BACKEND_PID=$! + echo "🌐 Backend API: http://localhost:$BACKEND_PORT" +else + BACKEND_PID="" +fi + +if [ -n "$FRONTEND_POD" ]; then + kubectl port-forward pod/$FRONTEND_POD $FRONTEND_PORT:80 & + FRONTEND_PID=$! + echo "πŸ–₯️ Frontend: http://localhost:$FRONTEND_PORT" + +else + FRONTEND_PID="" +fi + +if [ -n "$ADMINER_POD" ]; then + kubectl port-forward pod/$ADMINER_POD $ADMINER_PORT:80 & + ADMINER_PID=$! + echo "πŸ› οΈ Adminer: http://localhost:$ADMINER_PORT" +else + ADMINER_PID="" +fi + +# Cleanup on exit +cleanup() { + echo "πŸ›‘ Stopping port forwarding..." + # Only kill PIDs that exist + [ -n "$BACKEND_PID" ] && kill $BACKEND_PID 2>/dev/null || true + [ -n "$FRONTEND_PID" ] && kill $FRONTEND_PID 2>/dev/null || true + [ -n "$ADMINER_PID" ] && kill $ADMINER_PID 2>/dev/null || true + exit 0 +} +trap cleanup INT + +# Keep running +echo "🎯 Press Ctrl+C to stop" +wait \ No newline at end of file