# ows-assets

ows-assets microservice handles asset management. Functionality includes:

* validation
* asset upload
* asset metadata

## Getting Started

### Installation

The installation is very straightforward, but before starting make sure you have python3.11 installed. If you use a Mac, you can install it using `brew`. A simple way to manage python versions is with pyenv.
```bash
$ brew update
$ brew install pyenv
$ pyenv install 3.11.6
$ pyenv local 3.11.6
```

Update your `.zshrc` to insert the pyenv shims directory at the beginning of `$PATH`

```bash
# pyenv path
$ export PYENV_ROOT="$HOME/.pyenv"
$ export PATH="$PYENV_ROOT/shims:$PATH"
```

Sanity check that the python3 path is `/Users/$USER/.pyenv/shims/python3`

```bash
$ which python3
```

### Configuration

Copy .env.shadow to .env and add the appropriate environment variables for your environment.

`cp .env.shadow .env`

Set the configurations if they are not already set in the .env file.

Then, the docker-compose.yml file will read the .env file and assign its content to environment variables.

### Running Locally

Run ows-assets inside a dev container. Before spinning up the container, you first need to:

1. Ensure you have [ECR access](https://www.notion.so/AWS-Access-f841b9dd815d4443a80e96a86c92cd2f#7a6624c58c6642abaecd804e5f25c820) set up.
2. Enable AWS access to the dev or prod account with [awsume](https://www.notion.so/AWS-Access-f841b9dd815d4443a80e96a86c92cd2f#beaec95488ad4473899a26a2b8cf603f).

Then, spin up the dev container:

```bash
$ docker compose up --build --remove-orphans dev
```

This will spin up a dev container, install/copy all required dependencies and app code inside the dev container, and start the application.

You can access the application at:

```
localhost:8888
```

Sanity check that the container is up and running by hitting the healthcheck endpoint:

```
localhost:8888/hello
```

Test away!

__⚠️ Note:__ Ensure you are on the VPN.

When you are done testing out your ~amazing~ code, make sure to stop any running containers:

```bash
docker compose down --remove-orphans
```

### Testing

To run tests within a Docker container, you first must ensure steps 1 and 2 from `1️⃣ Option 1` in `Running Locally` are complete, and ensure you are on the VPN.

To run unit tests and linting, run:

```bash
docker compose run --build --rm unit-lint
```

### Updating Snapshots

Some unit tests use [syrupy](https://github.com/syrupy-project/syrupy) for snapshot assertions. When you intentionally change behaviour that affects snapshot output, regenerate them with `--snapshot-update`.

To update all unit test snapshots:

```bash
docker compose run --build --rm update-snapshots
```

Review the diff in the generated `.ambr` files before committing — they live alongside the test files and should be committed with your changes.

### Integration Testing

To run integration tests inside a container, run:

```bash
docker compose run --build --rm integration
```

TODO: We can further optimize the integration tests in the future by breaking down the tests in to different files and having the non-destructive integration tests all run off of one created product and then parallelize them.

### Format Code

To format code to conform to styleguide, run:

```bash
docker compose run --build --rm format
```

### Update lockfile

To update the lockfile, run:

```bash
docker compose run --build -rm update-lockfile
```

### Clean up
You can clean up the containers by running:

```bash
docker compose down --remove-orphans
```

## Adding a New Asset Upload Type

### Steps

1. **DB migration** — insert the new type name into the `asset_upload_type` table.

2. **Constants** (`assets/constants/asset_upload_types.py`) — add a string constant for the new name and add it to `ALLOWED_UPLOAD_TYPES`. If it's an audio type (not image), `AUDIO_UPLOAD_TYPES` will pick it up automatically. If it's an image type, also add it to `IMAGE_UPLOAD_TYPES`.

3. **Logic** — add any type-specific handling needed in the relevant logic modules (e.g. `validators.py`, `asset_upload.py`).

### Gotchas

- **`ALLOWED_UPLOAD_TYPES` gates the API** — a type not in this list will be rejected by request validation before it ever reaches the DB. The DB row alone is not enough for uploads to work.
- **`get_asset_upload_type_map()` is cached per process** — it queries the DB once on first call and never refreshes. After adding the DB row, ows-assets must be redeployed for the new type to be visible in the in-memory map. Any call to `resolve_asset_upload_type_id("new_type")` before a redeploy will raise `AssetUploadTypeNotFound` even if the row exists.
