Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .copier-answers.resonant.yml
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
_commit: v0.48.1
_commit: v0.51.1
_src_path: https://github.com/kitware-resonant/cookiecutter-resonant
core_app_name: api
include_example_code: false
Expand Down
91 changes: 91 additions & 0 deletions .devcontainer/devcontainer.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
// For format details, see https://aka.ms/devcontainer.json. For config options, see the
// README at: https://github.com/devcontainers/templates/tree/main/src/docker-existing-docker-compose
{
<<<<<<< before updating
"name": "DANDI Archive Django",
"dockerComposeFile": [
"../docker-compose.yml",
Expand Down Expand Up @@ -78,4 +79,94 @@
"--all-extras",
"--all-groups"
]
=======
"name": "DANDI Archive",
"dockerComposeFile": [
"../docker-compose.yml",
"../docker-compose.override.yml",
"./docker-compose.devcontainer.yml"
],
"service": "django",
"overrideCommand": true,
// The "vscode" user and remoteUser are set by the base image label (devcontainers/base).
"workspaceFolder": "/home/vscode/dandiapi",
"features": {
"ghcr.io/devcontainers/features/git-lfs:1": {},
"ghcr.io/devcontainers/features/node:2": {
"version": "24",
// Work around https://github.com/devcontainers/features/pull/1625
"pnpmVersion": "none"
},
"ghcr.io/rails/devcontainer/features/postgres-client:1": {
"version": 18
},
"ghcr.io/devcontainers/features/terraform:1": {},
"ghcr.io/devcontainers/features/aws-cli:1": {},
"ghcr.io/devcontainers/features/github-cli:1": {},
"ghcr.io/devcontainers-extra/features/heroku-cli:1": {}
},
"customizations": {
"vscode": {
"extensions": [
// Python
"ms-python.python",
"ms-python.vscode-pylance",
"ms-python.debugpy",
"ms-python.mypy-type-checker",
"charliermarsh.ruff",
// Django
"batisteo.vscode-django",
"augustocdias.tasks-shell-input",
// Other file formats
"editorconfig.editorconfig",
"mikestead.dotenv",
"tamasfe.even-better-toml",
"timonwong.shellcheck",
// Infrastructure
"ms-azuretools.vscode-containers",
"hashicorp.terraform",
"github.vscode-github-actions",
// Remove AWS extension, as only the CLI is wanted; see: https://github.com/devcontainers/features/issues/1228
"-AmazonWebServices.aws-toolkit-vscode"
],
"settings": {
"containers.containerClient": "com.microsoft.visualstudio.containers.docker",
// Container-specific Python paths
"python.defaultInterpreterPath": "/home/vscode/venv/bin/python",
// Disable automatic Python venv activation in new terminals.
"python-envs.terminal.autoActivationType": "off",
// Ensure that `envFile` from any user settings is ignored; Docker Compose provides it.
"python.envFile": "",
// Reduce file watcher overhead for generated/cache directories.
"files.watcherExclude": {
"**/__pycache__/**": true,
"**/.pytest_cache/**": true,
"**/node_modules/**": true
}
}
}
},
// Prevent a prompt every time the debugger opens a port or Django auto-restarts.
"otherPortsAttributes": {
"onAutoForward": "silent"
},
"portsAttributes": {
"8000": {
"label": "Django",
// Show a dialog if the port isn't free.
"requireLocalPort": true,
"onAutoForward": "silent"
}
},
// Install a global Python and create a venv before VSCode extensions start,
// to prevent prompts and ensure test discovery works on first load.
"onCreateCommand": {
"python": ["uv", "python", "install", "--default"],
"venv": ["uv", "sync", "--all-extras", "--all-groups"]
},
// Ensure it is re-synced on restarts.
"updateContentCommand": {
"venv": ["uv", "sync", "--all-extras", "--all-groups"]
}
>>>>>>> after updating
}
10 changes: 10 additions & 0 deletions .devcontainer/docker-compose.devcontainer.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
services:
django:
# Don't expose ports, devcontainer forwarding is superior, since we can just bind to localhost.
ports: !reset []
# Don't auto-run the default command, launch.json or the terminal will be used.
command: !reset []

celery:
# Celery will be started via launch.json or the terminal.
profiles: ["celery"]
3 changes: 3 additions & 0 deletions .editorconfig
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,9 @@ indent_size = 2
indent_size = 4
max_line_length = 100

[*.sh]
indent_size = 2

[*.toml]
indent_size = 2

Expand Down
104 changes: 104 additions & 0 deletions .vscode/launch.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
{
"version": "0.2.0",
"configurations": [
<<<<<<< before updating
// Put Django Server first so it's the default when starting debugging
{
"name": "Python: Django Server",
Expand Down Expand Up @@ -52,6 +53,109 @@
],
"console": "integratedTerminal",
"justMyCode": false
=======
{
"name": "Django: Server",
"type": "debugpy",
"request": "launch",
"program": "${workspaceFolder}/manage.py",
"args": ["runserver_plus", "--print-sql", "localhost:8000"],
"django": true,
"console": "integratedTerminal",
"justMyCode": false,
"presentation": {
"group": "2-services",
"order": 1
}
},
{
"name": "Django: Server (eager Celery)",
"type": "debugpy",
"request": "launch",
"program": "${workspaceFolder}/manage.py",
"args": ["runserver_plus", "--print-sql", "localhost:8000"],
"env": {
"DJANGO_CELERY_TASK_ALWAYS_EAGER": "true"
},
"django": true,
"console": "integratedTerminal",
"justMyCode": false,
"presentation": {
"group": "3-utilities",
"order": 1
}
},
{
"name": "Django: Management Command",
"type": "debugpy",
"request": "launch",
"program": "${workspaceFolder}/manage.py",
"args": ["${input:managementCommand}"],
"django": true,
"console": "integratedTerminal",
"justMyCode": false,
"presentation": {
"group": "3-utilities",
"order": 2
}
},
{
"name": "Celery: Worker",
"type": "debugpy",
"request": "launch",
"module": "celery",
"args": [
"--app",
"dandiapi.celery",
"worker",
"--loglevel",
"INFO",
"--without-mingle",
"--without-heartbeat",
"--without-gossip"
],
"console": "integratedTerminal",
"justMyCode": false,
"presentation": {
"group": "2-services",
"order": 2
}
},
{
"name": "Pytest: Debug",
"type": "debugpy",
"request": "launch",
"purpose": ["debug-test"],
"console": "integratedTerminal",
"django": true,
"justMyCode": false,
"presentation": {
"hidden": true
}
}
],
"compounds": [
{
"name": "Django + Celery",
"configurations": ["Django: Server", "Celery: Worker"],
"stopAll": true,
"presentation": {
"group": "1-compound",
"order": 1
}
}
],
"inputs": [
{
"id": "managementCommand",
"type": "command",
"command": "shellCommand.execute",
"args": {
"command": "./manage.py help --commands",
"description": "Django management command",
"allowCustomValues": true
}
>>>>>>> after updating
}
]
}
37 changes: 37 additions & 0 deletions .vscode/settings.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
{
// File cleanup
"files.trimTrailingWhitespace": true,
"files.insertFinalNewline": true,
"files.trimFinalNewlines": true,

// Python
"python.analysis.autoFormatStrings": true,
"python.testing.pytestEnabled": true,
"python.analysis.autoImportCompletions": true,
"python.analysis.gotoDefinitionInStringLiteral": true,
// Allow auto-importing from deeper symbols inside of Django.
"python.analysis.packageIndexDepths": [
{
"name": "django",
"depth": 6
}
],
"python.analysis.inlayHints.pytestParameters": true,

// Django templates
"emmet.includeLanguages": {
"django-html": "html"
},

// Type checking: Use Mypy and disable Pylance.
"mypy-type-checker.importStrategy": "fromEnvironment",
// Mypy daemon seems better, but is buggy in practice.
"mypy-type-checker.preferDaemon": false,
"mypy-type-checker.reportingScope": "file",
"python.analysis.typeCheckingMode": "off",

// Ruff
"[python]": {
"editor.defaultFormatter": "charliermarsh.ruff"
}
}
7 changes: 7 additions & 0 deletions Procfile
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
release: python ./manage.py migrate
<<<<<<< before updating
web: gunicorn --config gunicorn.conf.py dandiapi.wsgi
# celery-beat: REMAP_SIGTERM=SIGQUIT celery --app dandiapi.celery beat --loglevel INFO
# Rather than using a dedicated worker for Celery Beat, we simply use the -B option on the priority task worker.
Expand All @@ -9,3 +10,9 @@ web: gunicorn --config gunicorn.conf.py dandiapi.wsgi
worker: REMAP_SIGTERM=SIGQUIT celery --app dandiapi.celery worker --loglevel INFO --without-mingle --without-heartbeat --without-gossip --queues celery --beat
# The checksum-worker calculates blob checksums and updates zarr checksum files
checksum-worker: REMAP_SIGTERM=SIGQUIT celery --app dandiapi.celery worker --loglevel INFO --without-mingle --without-heartbeat --without-gossip --queues calculate_sha256,ingest_zarr_archive
=======
# Set `graceful_timeout` to shorter than the 30 second limit imposed by Heroku restarts
# Set `timeout` to shorter than the 30 second limit imposed by the Heroku router
web: gunicorn --bind 0.0.0.0:$PORT --graceful-timeout 25 --timeout 15 dandiapi.wsgi
worker: REMAP_SIGTERM=SIGQUIT celery --app dandiapi.celery worker --loglevel INFO --without-mingle --without-heartbeat --without-gossip
>>>>>>> after updating
35 changes: 35 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
# DANDI Archive

<<<<<<< before updating
![](https://about.dandiarchive.org/assets/dandi_logo.svg)

## DANDI: Distributed Archives for Neurophysiology Data Integration
Expand Down Expand Up @@ -29,3 +30,37 @@ see the [DANDI Docs](https://docs.dandiarchive.org).
* To understand how to hack on the archive codebase:
- Django backend: [`DEVELOPMENT.md`](DEVELOPMENT.md)
- Vue frontend: [`web/README.md`](web/README.md)
=======
## Setup
1. Install [VS Code with dev container support](https://code.visualstudio.com/docs/devcontainers/containers#_installation).
1. Open the project in VS Code, then run `Dev Containers: Reopen in Container`
from the Command Palette (`Ctrl+Shift+P`).
1. Once the container is ready, open a terminal and run:
```sh
./manage.py migrate
./manage.py createsuperuser
```

## Run
Open the **Run and Debug** panel (`Ctrl+Shift+D`) and select a launch configuration:

* **Django: Server** - Starts the development server at http://localhost:8000/
* **Django: Server (eager Celery)** - Same, but Celery tasks run synchronously
in the web process (useful for debugging task code without a worker)
* **Celery: Worker** - Starts only the Celery worker
* **Django + Celery** - Starts both the server and a Celery worker
* **Django: Management Command** - Pick and run any management command

## Test
Run the full test suite from a terminal: `tox`

Auto-format code: `tox -e format`

Run and debug individual tests from the **Testing** panel (`Ctrl+Shift+;`).

## Rebuild
After changes to the Dockerfile, Docker Compose files, or `devcontainer.json`,
run `Dev Containers: Rebuild Container` from the Command Palette (`Ctrl+Shift+P`).

For dependency changes in `pyproject.toml`, just run `uv sync --all-extras --all-groups`.
>>>>>>> after updating
4 changes: 4 additions & 0 deletions dandiapi/settings/heroku_production.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,11 @@

# This needs to be set by the HTTPS terminating reverse proxy.
# Heroku and Render automatically set this.
<<<<<<< before updating
SECURE_PROXY_SSL_HEADER = ('HTTP_X_FORWARDED_PROTO', 'https')
=======
SECURE_PROXY_SSL_HEADER = ("HTTP_X_FORWARDED_PROTO", "https")
>>>>>>> after updating

# Inform rate limiting that "X-Forwarded-For" should be trusted, as it's appended by Heroku.
ALLAUTH_TRUSTED_PROXY_COUNT = 1
Loading
Loading