Metadata-Version: 2.5
Name: djangocloud-cli
Version: 0.1.10
Summary: Deploy a Django app from the command line: djangocloud login, djangocloud deploy, djangocloud logs.
Project-URL: Homepage, https://djangocloud.dev
Project-URL: Source, https://github.com/two-trick-pony-NL/djangocloud-cli
Project-URL: Issues, https://github.com/two-trick-pony-NL/djangocloud-cli/issues
Author-email: Peter van Doorn <peter@petervandoorn.com>
License-Expression: MIT
License-File: LICENSE
Keywords: aws,cli,deploy,django,lightsail
Classifier: Development Status :: 3 - Alpha
Classifier: Environment :: Console
Classifier: Framework :: Django
Classifier: Framework :: Django :: 4.2
Classifier: Framework :: Django :: 5.0
Classifier: Framework :: Django :: 5.1
Classifier: Framework :: Django :: 5.2
Classifier: Intended Audience :: Developers
Classifier: Operating System :: OS Independent
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Topic :: Software Development
Requires-Python: >=3.10
Requires-Dist: questionary>=2.0
Requires-Dist: rich>=13
Description-Content-Type: text/markdown

<img width="800" alt="og-image" src="https://github.com/user-attachments/assets/061d5725-dfba-49b9-906e-79a3e938dfb7" />


**Deploying a Django app shouldn't be a hassle.**

No Dockerfiles. No load balancers. No server to babysit. You add one package to your project, sign in, and
[DjangoCloud](https://djangocloud.dev) takes care of the rest, running your app on AWS.

```
pip install djangocloud-cli
djangocloud login
djangocloud deploy
```

No settings to change. (Prefer `python manage.py djangocloud ...`? See [Two ways to run it](#two-ways-to-run-it).)

That's the whole idea: a few commands, from the project you already have.

> **Early release.** Sign-in, linking, packaging and uploading work, and the deploy streams its progress back to
> your terminal. Image builds on DjangoCloud's side are still being finished, so a deploy may stop at that step.
> Follow along at [djangocloud.dev](https://djangocloud.dev).

You need a [DjangoCloud](https://djangocloud.dev) account with a card on file to create projects.

## What it looks like

```
$ djangocloud deploy
You're not signed in yet.
Open https://djangocloud.dev/dashboard/cli/?code=ABCD-EFGH and check that the code is ABCD-EFGH.
✓ Signed in as you@example.com
? Which project is this?  Create a new project
? Server size  Nano  0.25 vCPU, 0.5 GB RAM  ~$7/month on AWS
? AWS bills you about $7/month for this server, directly in your own AWS account. Continue? Yes
✓ Linked to my-shop (.djangocloud/config.json)
Deploying my-shop
✓ Wrote build settings to .djangocloud/config.json
  found wsgi_module = config.wsgi:application
✓ Packed 148 files (212 KB). .env and .git are never uploaded.
✓ Uploaded. Release v1 started.
  Building v1
  v1 is live
✓ v1 is live.
```

## Features

### Two ways to run it

**`djangocloud <command>`** works as soon as the package is installed. There is nothing to add to your project, and it
still works when your settings won't load.

**`python manage.py djangocloud <command>`** does the same thing from inside your project, but Django only finds a
management command in an installed app. Add the app first, or you will see `Unknown command: 'djangocloud'`:

```python
INSTALLED_APPS = [
    ...,
    "djangocloud_cli",
]
```

The rest of this page writes `djangocloud`; use whichever form you prefer. Run it with no arguments, or use `help`,
to see every command.

| Command | What it does |
|---|---|
| `setup` | Guided first run: create your account, add a card, choose hosted or your own AWS, connect your AWS keys |
| `login` | Sign in by approving a code in your browser |
| `logout` | Forget the stored token |
| `whoami` | Show who you're signed in as, and which project this folder deploys to |
| `link` | Pick or create the project this folder deploys to |
| `unlink` | Detach this folder from its project |
| `deploy` | Link the folder if needed, pack it, upload it and stream the release until it is live (`--github` deploys the linked repo's latest commit instead) |
| `logs` | Show a project's logs; `-f` follows them, `--source app\|build\|release`, `--since 2h`, `-n 200` |
| `status` | Is it live and answering? Shows the URL, size and latest releases; `--json` for scripts |
| `scale` | Change the server size and number of instances: `--size small --instances 3`; `-y` skips the question, `--no-wait` returns once queued |
| `teardown` | Delete a project and what it created in AWS. You type its name to confirm (`--yes` for scripts) |
| `help [command]` | Help for everything, or for one command |

### Status and logs

```
$ djangocloud status
My Shop  ● Live
  v2 is live.
  URL       https://my-shop.example.com
  Size      Nano × 1 · eu-central-1
  Checked   3 min ago

  Releases
    v2   active      2 h ago  b3f9c1a  live
    v1   superseded  1 d ago

$ djangocloud logs -f --source app
```

`status` exits with 1 when the server is not responding, so it works as a check in a script. Both commands act on the
project this folder is linked to, or on `--project <slug>`. `logs -f` keeps streaming until you press Ctrl-C.

### Guided setup

`djangocloud setup` (also offered automatically before your first project) walks through it, and picks up where it
stopped if you run it again:

1. **Account.** No account yet? Choose "No, create one": the sign-up page opens in your browser and returns to the
   login approval. Nothing is typed into the terminal.
2. **Card.** Opens Stripe Checkout in your browser and waits until the card is on file.
3. **Hosted or your own AWS.** Hosted means we run it in an AWS environment made for you; there are no keys to hand
   over. Your own AWS asks for an IAM access key (the secret is hidden as you type, and goes to DjangoCloud once, over
   HTTPS), checks it against AWS, and asks for a region. You can print the IAM policy the key needs to see exactly what it is allowed to do.

In scripts: `djangocloud --no-input setup --own-cloud --region eu-west-1` with `AWS_ACCESS_KEY_ID` and
`AWS_SECRET_ACCESS_KEY` in the environment (the keys are never accepted as flags). The card step needs a browser.

### Smooth, guided project creation

Arrow-key menus, clear prices up front and no surprises. Nothing is created until you confirm.

### Your folder remembers its project

`.djangocloud/config.json` records which project a folder deploys to. It holds no secrets, and a `.gitignore` inside
the folder keeps it out of your repository. After the first run there are no prompts.

### What gets uploaded

The folder is packed into a `.tar.gz` that is the same every time for the same files. In a git repository that is
what git sees (your `.gitignore` is respected); otherwise junk is skipped. Whatever `.gitignore` says, these never go
up: `.env` and `.env.*` (except `.env.example`), `.git`, virtualenvs, `node_modules`, `*.sqlite3`, `*.pem`, `*.key` and
caches. Set your environment variables in the dashboard, not in the upload.

### Build settings

The first deploy detects your setup and writes it to the `"build"` block of `.djangocloud/config.json`. That file is
then the source of truth, so edit it to change how your app is built:

```json
{
  "build": {
    "wsgi_module": "config.wsgi:application",
    "django_settings_module": "config.settings",
    "python_version": "3.13",
    "package_manager": "pip",
    "requirements_file": "requirements.txt",
    "system_packages": ["libpq-dev"],
    "collectstatic": true,
    "release_command": "python manage.py migrate --noinput",
    "port": 8000,
    "workers": 2,
    "healthcheck_path": "/"
  }
}
```

The server checks every setting and lists all problems at once. The full list with defaults is at
`/api/v1/build-config`. If your WSGI app can't be detected in CI, pass `--wsgi-module config.wsgi:application`.

### Safe sign-in

Login uses a short code you approve in the browser, so no password or key is ever typed into the terminal. The token
is stored in `~/.config/djangocloud/credentials.json`, readable only by you. You can see and revoke tokens any time
under **Command line** in your dashboard.

### Works in CI, no questions asked

For GitHub Actions and similar, create a token under **Command line → Token for CI** and save it as the repository
secret `DJANGOCLOUD_TOKEN`. `--no-input` makes the CLI never prompt and never open a browser, and fail with a clear
message if something is missing.

```yaml
- run: pip install djangocloud-cli
- run: djangocloud deploy --no-input --project my-shop
  env:
    DJANGOCLOUD_TOKEN: ${{ secrets.DJANGOCLOUD_TOKEN }}
```

To create a project from CI, give it everything up front: `--name "My Shop" --size nano`.

### Configuration

| Variable | Purpose |
|---|---|
| `DJANGOCLOUD_TOKEN` | API token for CI. Takes precedence over the stored login |
| `DJANGOCLOUD_NO_INPUT` | Same as `--no-input` (set it to `1`) |
| `DJANGOCLOUD_API` | API base URL (default `https://djangocloud.dev/api/v1`) |

## Requirements

Python 3.10 or newer and Django 4.2 or newer.

## Development

```
uv sync
uv run pytest
uv run ruff check          # includes security (bandit), pytest-style, pathlib and simplification rules
uv run ruff format --check
```

Every push to `main` is released automatically: the tests run, the patch version goes up by one (0.1.1 becomes
0.1.2), the package is published to PyPI and a GitHub Release is created. There are no version numbers to edit.

For a bigger bump, tag it yourself before the next push (`git tag v0.2.0 && git push --tags`) and releases continue
from there. Put `[skip release]` in a commit message to skip releasing that commit.

## License

MIT. See [LICENSE](LICENSE).
