Metadata-Version: 2.5
Name: pevx
Version: 2.0.0
Summary: Prudentia CLI - Development tools for Prudentia internal developers
Author-email: Adrianh Dao <doadrianh@gmail.com>
License: Proprietary
Classifier: Intended Audience :: Developers
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.12
Requires-Python: >=3.12
Requires-Dist: awscli>=1.45.28
Requires-Dist: click<8.2,>=8.1.3
Requires-Dist: filelock>=3.20.3
Requires-Dist: openapi-python-client<0.25.0,>=0.24.3
Requires-Dist: pyasn1>=0.6.4
Requires-Dist: tomlkit>=0.13.3
Requires-Dist: urllib3>=2.7.0
Requires-Dist: virtualenv>=20.36.1
Description-Content-Type: text/markdown

# Prudentia CLI (pevx)

> ## ⚠️ DEPRECATED — pevx is being retired org-wide (PRVS-3162)
>
> **Do not adopt `pevx` in new repositories, workflows, Dockerfiles, Makefiles or
> build scripts.** This repository is being retired across the whole organisation
> under **PRVS-3162**. Once every consumer has migrated, this repository will be
> archived and no further releases will be published.
>
> `pevx uv <cmd>` did exactly one useful thing: mint a CodeArtifact
> authorization token and export it to `uv` via two environment variables. Do
> that inline instead — no wrapper, no shim.
>
> ### Replacement recipe
>
> Mint the token and export the two index URLs, then call `uv` directly:
>
> ```bash
> TOKEN=$(aws codeartifact get-authorization-token \
>   --domain prudentia-sciences \
>   --domain-owner 545822668568 \
>   --region us-east-1 \
>   --query authorizationToken --output text)
>
> export UV_INDEX_URL=https://pypi.org/simple/
> export UV_EXTRA_INDEX_URL=https://aws:${TOKEN}@prudentia-sciences-545822668568.d.codeartifact.us-east-1.amazonaws.com/pypi/pypi-store/simple/
>
> uv sync --all-groups        # was: pevx uv sync --all-groups
> uv run pytest               # was: pevx uv run pytest
> ```
>
> In GitHub Actions, write the two variables to `$GITHUB_ENV` instead of
> `export`ing them, and mask the token — `$GITHUB_ENV` is job-scoped, so repeat
> the step in every job that needs it:
>
> ```yaml
> - name: Configure CodeArtifact auth for uv
>   run: |
>     TOKEN=$(aws codeartifact get-authorization-token \
>       --domain prudentia-sciences --domain-owner 545822668568 \
>       --region us-east-1 \
>       --query authorizationToken --output text)
>     echo "::add-mask::$TOKEN"
>     echo "UV_INDEX_URL=https://pypi.org/simple/" >> "$GITHUB_ENV"
>     echo "UV_EXTRA_INDEX_URL=https://aws:${TOKEN}@prudentia-sciences-545822668568.d.codeartifact.us-east-1.amazonaws.com/pypi/pypi-store/simple/" >> "$GITHUB_ENV"
> ```
>
> AWS credentials must be configured in the **same job** (or the same shell) as
> the token mint. Both index URLs are required: `pypi-store` has no external
> connection to PyPI, so public packages are fetched from `pypi.org` directly —
> that was true under `pevx` too, and is not a behaviour change.
>
> ### Canonical reference
>
> **[`prudentia-servicekit`'s README](https://github.com/Prudentia-Sciences/prudentia-servicekit#readme)
> is the canonical, maintained reference** for consuming private Python packages
> from CodeArtifact — Docker build variants, Lambda build scripts, and local
> developer setup included. Prefer it over the recipe above if the two ever
> disagree.

A development CLI tool for Prudentia internal developers.

## Prerequisites

### Git Hooks

This project uses [pre-commit](https://pre-commit.com/) to enforce code quality and commit standards.

#### Configured Hooks

- **pre-push**: Validates that branch names contain a JIRA link for the PRVS project
- **commit-msg**: Ensures commit messages contain a JIRA link for the PRVS project

#### Setup

1. Install dependencies (including pre-commit):

   ```bash
   uv sync --all-groups
   ```

1. Install hooks:

   ```bash
   uv run pre-commit install --install-hooks
   ```

#### Manual Hook Management

- Run hooks manually: `uv run pre-commit run --all-files`
- Update hooks: `uv run pre-commit autoupdate`

### AWS CLI

The AWS CLI is a system requirement for `pevx`. Install it following the [official AWS CLI installation guide](https://docs.aws.amazon.com/cli/latest/userguide/getting-started-install.html).

### AWS Configuration

Configure AWS CLI with Prudentia SSO:

```bash
aws configure sso
```

Follow the prompts to set up SSO authentication with your Prudentia credentials.

**AWS Profile Behavior:**

- `pevx` uses the default AWS profile (from `~/.aws/credentials` or `~/.aws/config`) unless otherwise specified

- To use a different profile, set the `AWS_PROFILE` environment variable:

  ```bash
  export AWS_PROFILE=my-profile
  pevx uv sync
  ```

  Or inline:

  ```bash
  AWS_PROFILE=my-profile pevx uv sync
  ```

## Installation

### From PyPI

```bash
pip install pevx
```

### Development Mode

Clone the repository and install in development mode using uv:

```bash
git clone https://github.com/Prudentia-Sciences/pevx
cd pevx
uv sync
```

## Usage

After installation, you can use the CLI with the `pevx` command:

```bash
# Show help
pevx --help

# Show version
pevx --version
```

## Available Commands

### `uv [args]`

Proxy to uv with AWS CodeArtifact authentication.

```bash
pevx uv add [package] --domain custom-domain --owner 123456789012 --repo custom-repo --region us-west-2
```

**Important:** This command requires access to the Prudentia 'Shared-Infra' AWS account. Ensure your AWS profile is configured with appropriate permissions for this account.

Default values:

- Domain: prudentia-sciences
- Domain Owner: 545822668568
- Repository: pypi-store
- Region: us-east-1

### `docker [args]`

Proxy to docker with AWS ECR authentication.

### `aws-each [args]`

Assume a role in each target AWS account using OIDC and run an AWS CLI command.

```bash
pevx aws-each --accounts '["111111111111","222222222222"]' s3 ls
```

Options:

- `--accounts`: JSON list of AWS account IDs (required, or set `TARGET_ACCOUNTS` env var)
- `--role-name`: IAM Role name to assume (default: `github-actions-backend-role`)
- `--continue-on-error/--fail-fast`: Continue with remaining accounts on failure

### `pyclient`

Generate a Python client from a FastAPI OpenAPI spec.

```bash
pevx pyclient --app-path app.main:app
```

Options:

- `--pyproject`: Path to pyproject.toml (default: `pyproject.toml`)
- `--app-path`: Python path to FastAPI app (default: `app.main:app`)
- `--project-name`: Distribution name for the generated client (default: the `[project]`
  name in `pyproject.toml`)

Set `--project-name` when the client must publish under a different name from the service
it is generated from, so that the two do not collide on publish:

```bash
pevx pyclient --project-name diligence-service-client
```

This renames three things together, not just the published distribution:

| | Without the option | With `--project-name diligence-service-client` |
|---|---|---|
| Distribution name | `diligence-service` | `diligence-service-client` |
| Output directory | `./diligence-service/` | `./diligence-service-client/` |
| Import package | `diligence_service` | `diligence_service_client` |

The directory rename is the one that catches callers out. Under `--meta poetry`,
`openapi-python-client` derives the output directory from the distribution name, so
anything that `cd`s into the generated tree afterwards - a build step, a CI workflow
input - has to use the same value. In `[dot-github] backend-release-publish.yml` that
means `client_project_name` and `client_package_directory` must be set in lockstep.

The version is deliberately not overridable: the client tracks the version of the service
it was generated from.

## Development

### Adding New Commands

1. Create a new file in the `src/pevx/commands/` directory for your command
1. Implement your command using Click
1. Import and register your command in `src/pevx/cli.py`

Example:

```python
# In src/pevx/commands/my_command.py
import click

@click.command()
def my_command():
    """Command description."""
    click.echo("Running my command")

# In src/pevx/cli.py, add:
from pevx.commands.my_command import my_command
cli.add_command(my_command)
```

### CI/CD and Versioning

This project uses semantic-release for automated versioning:

1. **Automated Testing**: Runs tests on Python 3.12
1. **Semantic Versioning**: Automatically determines version from commit messages
1. **Automated Publishing**: Builds and publishes to PyPI on new versions

#### Commit Message Format

Use conventional commit messages:

```
<type>(<scope>): <description>
```

Common types:

- `fix`: Bug fixes (PATCH bump)
- `feat`: New features (MINOR bump)
- `feat!`, `fix!`: Breaking changes (MAJOR bump)
