Metadata-Version: 2.4
Name: djd
Version: 1.0.7
Summary: A tool for managing Django + AWS ECS deployments
Author-email: Matthew Coleman <19colemanm@gmail.com>
License: MIT
Project-URL: Homepage, https://github.com/msc5/deploy
Project-URL: Repository, https://github.com/msc5/deploy
Requires-Python: >=3.10
Description-Content-Type: text/markdown
License-File: LICENSE
Requires-Dist: boto3>=1.26.0
Requires-Dist: django>=4.2
Requires-Dist: gitpython>=3.1.0
Requires-Dist: ipython>=8.0.0
Requires-Dist: jinja2>=3.1.0
Requires-Dist: pydantic>=2.13.3
Requires-Dist: pygithub>=2.0.0
Requires-Dist: python-dotenv>=1.0.0
Requires-Dist: pytz>=2023.3
Requires-Dist: rich>=13.0.0
Requires-Dist: typer>=0.9.0
Dynamic: license-file

<p align="center">
  <img src="https://cdn-icons-png.flaticon.com/512/5731/5731863.png" width=256 />
</p>

## djd

**djd** is a command line tool for creating and managing Django + AWS ECS deployments. It wraps
Terraform, AWS (via [Boto3](https://github.com/boto/boto3)), Docker, Git, and GitHub to coordinate
running deployments, building and uploading Docker images, and accessing infrastructure from the terminal.

## Installation

```bash
pip install djd
```

## Setup

`djd` reads infrastructure metadata from Terraform outputs, so Terraform must be initialized for your deployment before using most commands. Variables are loaded from `.env` in the project root, then from `config/.env` as a fallback, then from the process environment.

### Environment Variables

| Variable | Default | Description |
|----------|---------|-------------|
| `AWS_PROFILE` | `zag-dev-cli` | AWS credentials profile — **set this** |
| `AWS_REGION` | `us-east-1` | AWS region — **set this** |
| `REMOTE_REPO_NAME` | `msc5/sample-django-app` | GitHub repo (`owner/repo`) used for git operations and workflow dispatch — **set this** |
| `REMOTE_REPO_URL` | `git@github.com:{REMOTE_REPO_NAME}.git` | SSH URL for the remote repo (derived from `REMOTE_REPO_NAME` if not set) |
| `DEFAULT_SERVICES` | `web,worker` | Comma-separated ECS services targeted by deploy commands |
| `DOCKERFILE_PATH` | `Dockerfile` | Path to the Dockerfile |
| `TERRAFORM_PATH` | `terraform` | Path to the Terraform root directory |
| `GIT_COPY_PATH` | `.git-copy` | Local directory cloned from `REMOTE_REPO_URL`, used as Docker build context |
| `DEPLOY_PATH` | `.deploy` | Directory for local state and history cache |
| `STATE_PATH` | `.deploy/state.json` | Cached Terraform output state file |
| `HISTORY_PATH` | `.deploy/history.json` | S3 key for the deployment audit log |
| `MIGRATION_TIMEOUT_SECONDS` | `600` | How long to wait for a migration task before giving up |

### Required Terraform Outputs

`djd` runs `terraform output --json` in `{TERRAFORM_PATH}/deployments/{environment}/` on first use and caches the result in `STATE_PATH`. The following outputs must be present:

| Output | Description |
|--------|-------------|
| `cluster_id` | ECS cluster ARN or name |
| `ecr_image_uri` | Full ECR image URI including `:latest` tag (e.g. `123456789.dkr.ecr.us-east-1.amazonaws.com/staging:latest`) |
| `ecr_repository_name` | ECR repository name (used when promoting an image between environments) |
| `s3_bucket_name` | S3 bucket used to store the deployment history JSON |
| `{service}_service_name` | ECS service name for each service in `DEFAULT_SERVICES` (e.g. `web`, `worker`, `elasticsearch`) |

## Global Options

These options apply to every command and are placed before the subcommand name:

```bash
djd ENVIRONMENT [OPTIONS] COMMAND
# example use:
djd staging --debug run-deployment --no-migration
```

| Option | Default | Description |
|--------|---------|-------------|
| `--debug` | `False` | Enable verbose debug logging |
| `--confirm` | `False` | Show a confirmation prompt before destructive actions |
| `--refresh` | `1.0` | Polling interval in seconds for watch/migration commands |
| `--docker-context-path` | `.git-copy` | Path used as Docker build context |
| `--github-workflow` | `False` | Dispatch deployment via GitHub Actions instead of running locally |

## Commands

### `run-deployment` — Full deployment pipeline

The primary command. Builds a Docker image from the specified branch, pushes it to ECR, runs migrations, and force-deploys all services.

```bash
djd staging run-deployment
djd staging run-deployment --branch develop
djd staging run-deployment --no-migration        # skip migrations
djd staging run-deployment --no-build            # skip image build (re-deploy current image)
djd staging run-deployment --promote-image 123456789.dkr.ecr.us-east-1.amazonaws.com/other-env:latest
djd --github-workflow staging run-deployment --branch main
```

| Option | Default | Description |
|--------|---------|-------------|
| `--branch` | `main` | Git branch to build from |
| `--push / --no-push` | `True` | Push the built image to ECR |
| `--cache / --no-cache` | `True` | Use ECR layer cache during build |
| `--migration / --no-migration` | `True` | Run `migrate` before deploying |
| `--build / --no-build` | `True` | Build a new Docker image |
| `--promote-image` | — | Copy an existing ECR image instead of building |
| `services` (positional, variadic) | `$DEFAULT_SERVICES` | ECS services to force-deploy after build/migration |

---

### `show-services` — ECS service status

Displays a table of each service's deployment ID, task counts, status, and rollout state.

```bash
djd staging show-services
djd staging show-services web        # filter to specific service(s)
```

```
Deployment Status

  Deployment ID                    Service                          Latest       Created On                  Count             Status            Rollout State
 ─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
  ecs-svc/0938446537801788686      deploy-staging-web               *            2025-10-24 12:30:48 PM      0 -> 1 / 1        Primary           Completed
  ecs-svc/2070367854272485563      deploy-staging-worker            *            2025-10-24 12:30:48 PM      0 -> 0 / 0        Primary           Completed
```

---

### `show-tasks` — ECS task status

Displays all running tasks on the cluster with their task definition, health, and status.

```bash
djd staging show-tasks
djd staging show-tasks web           # filter to specific service(s)
```

```
Task Status

  Task ID                            Task Definition ID     Created At               Health Status          Status
 ────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
  b21dc0a1442740c5a00930a64d6b00cd   deploy-staging-web:2   2025-10-24 12:31:06 PM   Unknown                Running
```

---

### `watch-deployments` — Live deployment monitor

Polls ECS and prints a live-updating table until the latest deployments on all watched services reach `COMPLETED`.

```bash
djd staging watch-deployments
djd --refresh 5 staging watch-deployments web worker
```

Ctrl-C exits the watch loop without error.

---

### `force-deploy` — Trigger a new ECS deployment

Forces ECS to start a new deployment on the specified services using the current task definition (no image rebuild). Waits and watches until complete.

```bash
djd staging force-deploy
djd --confirm staging force-deploy web    # show current status and prompt before acting
```

---

### `run-migrations` — Run database migrations

Runs `manage.py migrate --no-input` as a one-off ECS task and tails its status until it exits. Aborts if the task fails to start or returns a non-zero stop code.

```bash
djd staging run-migrations
djd staging run-migrations --service web
```

| Option | Default | Description |
|--------|---------|-------------|
| `--service` | `web` | ECS service whose task definition and network config are used |

---

### `ssh` — Interactive shell

Opens `/bin/bash` inside the latest running task via ECS Exec.

```bash
djd staging ssh
djd staging ssh --service worker
```

| Option | Default | Description |
|--------|---------|-------------|
| `--service` | `web` | ECS service to target |

---

### `manage` — Django management command

Runs an arbitrary `manage.py` command in a running task via ECS Exec.

```bash
djd staging manage shell_plus
djd staging manage --service worker send_queued_emails
djd staging manage dbshell
```

| Option | Default | Description |
|--------|---------|-------------|
| `--service` | `web` | ECS service to target |
| `command` (positional) | required | Management command and any arguments |

---

### `history` — Deployment audit log

Shows a table of past deployments, migrations, and Docker builds logged to S3.

```bash
djd staging history
djd staging history --raw      # print raw JSON
```

---

### `docker-build` — Build and push a Docker image

Builds the image using `docker buildx` for `linux/amd64` and pushes it to the environment's ECR repository. Uses ECR as a layer cache by default.

```bash
djd staging docker-build
djd staging docker-build --branch develop --no-cache
djd staging docker-build --no-push      # build locally only
```

| Option | Default | Description |
|--------|---------|-------------|
| `--branch` | `main` | Git branch to pull before building |
| `--push / --no-push` | `True` | Push the built image to ECR |
| `--cache / --no-cache` | `True` | Use ECR layer cache |

---

### `docker-login` — Authenticate Docker with ECR

Fetches a temporary ECR password via the AWS CLI and runs `docker login`.

```bash
djd staging docker-login
```

---

### `tf` — Run Terraform commands

Runs an arbitrary Terraform subcommand in `terraform/deployments/{environment}/`.

```bash
djd staging tf plan
djd staging tf apply
djd staging tf output
```

---

### `stop-service` — Scale a service to zero

Sets `desiredCount = 0` on the specified services.

```bash
djd --confirm staging stop-service web worker
```
