Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
33 commits
Select commit Hold shift + click to select a range
57f7e5b
Add test to ensure cli-minimal-version is accurate
jjnesbitt Feb 19, 2026
0db90e4
Update cli-minimal-version
jjnesbitt Feb 19, 2026
8403e0f
Use cli-minimal-version in download dialog
jjnesbitt Feb 19, 2026
ccb3ca5
Add cli-requires-python field to /api/info
jjnesbitt Feb 19, 2026
90f488c
Specify CLI as an optional dependency
jjnesbitt Feb 19, 2026
7a214e4
Handle missing 'dandi' module, and specify fix
jjnesbitt Feb 19, 2026
fb659f7
Set asset to pending when its zarr is ingested
jjnesbitt Feb 27, 2026
4ab87d0
Merge pull request #2720 from dandi/ingest-zarr-updates-asset
jjnesbitt Mar 9, 2026
48445fd
Merge pull request #2715 from dandi/remove-dandi-cli-as-dependency
jjnesbitt Mar 9, 2026
3cedc2d
Merge pull request #2714 from dandi/gui-use-cli-minimum-version
jjnesbitt Mar 11, 2026
ab97a71
auto shipit - CHANGELOG.md etc
dandibot Mar 11, 2026
14b2171
Add required pytest marks for test_info tests
jjnesbitt Mar 11, 2026
d61d642
Merge pull request #2727 from dandi/2714-hotfix
jjnesbitt Mar 11, 2026
9ed9933
Upgrade to Resonant v0.48.1
brianhelba Mar 17, 2026
839a52c
Merge pull request #2734 from dandi/resonant-upgrade
jjnesbitt Mar 17, 2026
51453c7
Update dependency node to v24
renovate[bot] Mar 17, 2026
56d7e90
Merge pull request #2737 from dandi/renovate/node-24.x
waxlamp Mar 17, 2026
5cb3fb8
Update dependency @sentry/vue to v10
renovate[bot] Mar 17, 2026
fd49471
Merge pull request #2736 from dandi/renovate/major-10-sentry-javascri…
waxlamp Mar 17, 2026
bc6dbe9
Add Blog link to AppBar navigation
yarikoptic Mar 18, 2026
2264fb4
Merge pull request #2739 from dandi/enh-blog
jjnesbitt Mar 18, 2026
a4226c7
auto shipit - CHANGELOG.md etc
dandibot Mar 18, 2026
8de51b7
Update dependency ubuntu to v24
renovate[bot] Mar 18, 2026
9c866d3
Merge pull request #2738 from dandi/renovate/ubuntu-24.x
jjnesbitt Mar 18, 2026
cfd65ac
Install proper version of heroku-builds plugin
jjnesbitt Mar 18, 2026
6ad4333
Merge pull request #2741 from dandi/fix-heroku-build
jjnesbitt Mar 18, 2026
ff06361
Allow staff users to access dashboard views
jjnesbitt Mar 24, 2026
af8afcd
Require staff/superuser access for mailchimp csv endpoint
jjnesbitt Mar 24, 2026
3e004d2
Add tests for dashboard views
jjnesbitt Mar 24, 2026
4a935ce
Merge pull request #2752 from dandi/dashboard-required-perm
jjnesbitt Mar 24, 2026
f0a7d58
auto shipit - CHANGELOG.md etc
dandibot Mar 24, 2026
ef007fd
Merge branch 'master' into 180-sync-fork-mar-23-week
NEStock Mar 24, 2026
e970cdb
Merge pull request #182 from aplbrain/180-sync-fork-mar-23-week
NEStock Mar 24, 2026
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
4 changes: 2 additions & 2 deletions .copier-answers.resonant.yml
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
_commit: v0.47.1
_src_path: gh:kitware-resonant/cookiecutter-resonant
_commit: v0.48.1
_src_path: https://github.com/kitware-resonant/cookiecutter-resonant
core_app_name: api
include_example_code: false
project_name: DANDI Archive
Expand Down
2 changes: 1 addition & 1 deletion .devcontainer/devcontainer.json
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@
"ghcr.io/devcontainers-extra/features/heroku-cli:1.0.5": {},
"ghcr.io/devcontainers/features/github-cli:1": {},
"ghcr.io/devcontainers/features/node:1": {
"version": "20"
"version": "24"
}
},
"customizations": {
Expand Down
6 changes: 6 additions & 0 deletions .github/renovate.json5
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
{
$schema: 'https://docs.renovatebot.com/renovate-schema.json',
extends: [
'github>kitware-resonant/.github:renovate-project.json5',
],
}
2 changes: 1 addition & 1 deletion .github/workflows/auto-add-issues.yml
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ on:
jobs:
add-to-project:
name: Add issue to project
runs-on: ubuntu-22.04
runs-on: ubuntu-24.04
steps:
- uses: actions/add-to-project@v1.0.2
with:
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/backend-ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ permissions:
contents: read
jobs:
test:
runs-on: ubuntu-22.04
runs-on: ubuntu-24.04
services:
postgres:
image: postgres:latest
Expand Down
8 changes: 4 additions & 4 deletions .github/workflows/backend-production-deploy.yml
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ concurrency:
jobs:
# reset-release-branch:
# name: Update release branch
# runs-on: ubuntu-22.04
# runs-on: ubuntu-24.04
# steps:
# - uses: actions/checkout@v6
# with:
Expand All @@ -40,8 +40,8 @@ jobs:

production-deploy:
name: Deploy to Heroku
runs-on: ubuntu-22.04
#needs: reset-release-branch
runs-on: ubuntu-24.04
# needs: reset-release-branch
steps:
- uses: actions/checkout@v6
with:
Expand All @@ -55,7 +55,7 @@ jobs:
run: curl https://cli-assets.heroku.com/install.sh | sh

- name: Install builds plugin
run: heroku plugins:install heroku-builds
run: heroku plugins:install @heroku-cli/heroku-builds

- name: Build app into tarball
run: |
Expand Down
4 changes: 2 additions & 2 deletions .github/workflows/backend-staging-deploy.yml
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ concurrency:
jobs:
deploy:
name: Deploy to Heroku
runs-on: ubuntu-22.04
runs-on: ubuntu-24.04
steps:
- uses: actions/checkout@v6
with:
Expand All @@ -34,7 +34,7 @@ jobs:
run: curl https://cli-assets.heroku.com/install.sh | sh

- name: Install builds plugin
run: heroku plugins:install heroku-builds
run: heroku plugins:install @heroku-cli/heroku-builds

- name: Build app into tarball
run: |
Expand Down
4 changes: 2 additions & 2 deletions .github/workflows/cli-integration.yml
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ permissions:

jobs:
build-image:
runs-on: ubuntu-22.04
runs-on: ubuntu-24.04
steps:
- name: Check out this repository
uses: actions/checkout@v6
Expand All @@ -40,7 +40,7 @@ jobs:
path: dandiarchive-api.tgz

test:
runs-on: ubuntu-22.04
runs-on: ubuntu-24.04
needs: build-image
strategy:
fail-fast: false
Expand Down
8 changes: 4 additions & 4 deletions .github/workflows/frontend-ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -11,15 +11,15 @@ jobs:
defaults:
run:
working-directory: web
runs-on: ubuntu-22.04
runs-on: ubuntu-24.04
steps:
- uses: actions/checkout@v6
with:
fetch-depth: 0 # fetch history for all branches and tags

- uses: actions/setup-node@v6
with:
node-version: 20.x
node-version: 24.x

- name: Install Vue app
run: npm ci
Expand All @@ -35,7 +35,7 @@ jobs:

test-e2e:
name: E2E tests
runs-on: ubuntu-22.04
runs-on: ubuntu-24.04
services:
postgres:
image: postgres:latest
Expand Down Expand Up @@ -93,7 +93,7 @@ jobs:

- uses: actions/setup-node@v6
with:
node-version: 20
node-version: 24

- name: Install uv
uses: astral-sh/setup-uv@v7
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ on:
jobs:
release:
if: "!contains(github.event.head_commit.message, 'ci skip') && !contains(github.event.head_commit.message, 'skip ci')"
runs-on: ubuntu-22.04
runs-on: ubuntu-24.04
steps:
- uses: actions/checkout@v6
with:
Expand Down
48 changes: 48 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,51 @@
# v0.21.11 (Tue Mar 24 2026)

#### 🐛 Bug Fix

- Update dashboard permissions [#2752](https://github.com/dandi/dandi-archive/pull/2752) ([@jjnesbitt](https://github.com/jjnesbitt))
- Fix heroku build [#2741](https://github.com/dandi/dandi-archive/pull/2741) ([@jjnesbitt](https://github.com/jjnesbitt))
- Update dependency ubuntu to v24 [#2738](https://github.com/dandi/dandi-archive/pull/2738) ([@renovate[bot]](https://github.com/renovate[bot]))

#### Authors: 2

- [@renovate[bot]](https://github.com/renovate[bot])
- Jacob Nesbitt ([@jjnesbitt](https://github.com/jjnesbitt))

---

# v0.21.10 (Wed Mar 18 2026)

#### 🐛 Bug Fix

- Add Blog link to AppBar navigation [#2739](https://github.com/dandi/dandi-archive/pull/2739) ([@yarikoptic](https://github.com/yarikoptic))
- Update dependency @sentry/vue to v10 [#2736](https://github.com/dandi/dandi-archive/pull/2736) ([@renovate[bot]](https://github.com/renovate[bot]))
- Update dependency node to v24 [#2737](https://github.com/dandi/dandi-archive/pull/2737) ([@renovate[bot]](https://github.com/renovate[bot]))
- Upgrade to Resonant v0.48.1 [#2734](https://github.com/dandi/dandi-archive/pull/2734) ([@brianhelba](https://github.com/brianhelba))
- Add required pytest marks for test_info tests [#2727](https://github.com/dandi/dandi-archive/pull/2727) ([@jjnesbitt](https://github.com/jjnesbitt))

#### Authors: 4

- [@renovate[bot]](https://github.com/renovate[bot])
- Brian Helba ([@brianhelba](https://github.com/brianhelba))
- Jacob Nesbitt ([@jjnesbitt](https://github.com/jjnesbitt))
- Yaroslav Halchenko ([@yarikoptic](https://github.com/yarikoptic))

---

# v0.21.9 (Wed Mar 11 2026)

#### 🐛 Bug Fix

- Display the correct CLI and required python version in the GUI [#2714](https://github.com/dandi/dandi-archive/pull/2714) ([@jjnesbitt](https://github.com/jjnesbitt))
- Remove CLI as core dependency [#2715](https://github.com/dandi/dandi-archive/pull/2715) ([@jjnesbitt](https://github.com/jjnesbitt))
- Set asset to pending when its zarr is ingested [#2720](https://github.com/dandi/dandi-archive/pull/2720) ([@jjnesbitt](https://github.com/jjnesbitt))

#### Authors: 1

- Jacob Nesbitt ([@jjnesbitt](https://github.com/jjnesbitt))

---

# v0.21.8 (Fri Mar 06 2026)

#### 🐛 Bug Fix
Expand Down
14 changes: 11 additions & 3 deletions dandiapi/api/management/commands/extract_metadata.py
Original file line number Diff line number Diff line change
@@ -1,12 +1,11 @@
from __future__ import annotations

import importlib.util
import logging
from pathlib import Path
import sys
from typing import TYPE_CHECKING

from dandi.dandiapi import RemoteReadableAsset
from dandi.metadata.nwb import nwb2asset
from dandi.misctypes import Digest, DigestType
from dandischema.models import get_schema_version
from django.contrib.auth.models import User
from django.db import transaction
Expand All @@ -22,6 +21,15 @@

logger = logging.getLogger(__name__)

# The CLI only exists as an optional requirement, so ensure it's been specified correctly.
if importlib.util.find_spec('dandi') is None:
click.echo('Module "dandi" not found. Please run:\n\tuv sync --extra cli')
sys.exit(1)
else:
from dandi.dandiapi import RemoteReadableAsset
from dandi.metadata.nwb import nwb2asset
from dandi.misctypes import Digest, DigestType


@click.group()
def group():
Expand Down
84 changes: 84 additions & 0 deletions dandiapi/api/tests/test_dashboard.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
from __future__ import annotations

import pytest

from dandiapi.api.tests.factories import UserFactory


@pytest.mark.parametrize(
('is_staff', 'is_superuser'),
[
(False, False),
(False, True),
(True, False),
(True, True),
],
)
@pytest.mark.django_db
def test_dashboard_access(api_client, is_staff, is_superuser):
user = UserFactory.create(is_staff=is_staff, is_superuser=is_superuser)
api_client.force_login(user)
resp = api_client.get('/dashboard/')

should_pass = is_staff or is_superuser
assert resp.status_code == (200 if should_pass else 403)


@pytest.mark.django_db
def test_dashboard_access_unauthenticated(api_client):
resp = api_client.get('/dashboard/')
assert resp.status_code == 302


@pytest.mark.parametrize(
('is_staff', 'is_superuser'),
[
(False, False),
(False, True),
(True, False),
(True, True),
],
)
@pytest.mark.django_db
def test_user_approval_access(api_client, is_staff, is_superuser):
user = UserFactory.create(is_staff=is_staff, is_superuser=is_superuser)
api_client.force_login(user)

other_user = UserFactory.create()
resp = api_client.get(f'/dashboard/user/{other_user.username}/')

should_pass = is_staff or is_superuser
assert resp.status_code == (200 if should_pass else 403)


@pytest.mark.django_db
def test_user_approval_access_unauthenticated(api_client):
other_user = UserFactory.create()
resp = api_client.get(f'/dashboard/user/{other_user.username}/')
assert resp.status_code == 302


@pytest.mark.parametrize(
('is_staff', 'is_superuser'),
[
(False, False),
(False, True),
(True, False),
(True, True),
],
)
@pytest.mark.django_db
def test_mailchimp_view_access(api_client, is_staff, is_superuser):
user = UserFactory.create(is_staff=is_staff, is_superuser=is_superuser)
api_client.force_login(user)

resp = api_client.get('/dashboard/mailchimp/')

should_pass = is_staff or is_superuser
assert resp.status_code == (200 if should_pass else 403)


@pytest.mark.django_db
def test_mailchimp_view_access_unauthenticated(api_client):
resp = api_client.get('/dashboard/mailchimp/')
assert resp.status_code == 403
38 changes: 38 additions & 0 deletions dandiapi/api/tests/test_info.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,11 @@
from __future__ import annotations

import importlib.metadata

from dandischema.conf import get_instance_config
from packaging.specifiers import SpecifierSet
import pytest
import requests


@pytest.mark.django_db
Expand All @@ -16,3 +20,37 @@ def test_rest_info_instance_config_include_none(api_client):
resp.json()['instance_config'].keys()
== get_instance_config().model_dump(mode='json', exclude_none=False).keys()
)


@pytest.mark.django_db
def test_cli_minimal_version_matches_dandischema(api_client):
"""Test that local dandischema and minimal cli dandischema are compatible."""
# Get CLI version info from pypi
minimal_version = api_client.get('/api/info/').json()['cli-minimal-version']
data = requests.get(f'https://pypi.org/pypi/dandi/{minimal_version}/json').json()

# Extract the dandischema requirement
dandischema_requires = [x for x in data['info']['requires_dist'] if x.startswith('dandischema')]
assert len(dandischema_requires) == 1
dandischema_version: str = dandischema_requires[0]
version_range = SpecifierSet(
dandischema_version.split(';', maxsplit=1)[0].removeprefix('dandischema').strip()
)

# Ensure that local dandischema is compatible with the CLI version
local_version = importlib.metadata.version('dandischema')
assert version_range.contains(local_version)


@pytest.mark.django_db
def test_cli_requires_python_compatible_with_minimal_version(api_client):
"""Test that the CLI's required python version is compatible with the minimal version."""
info = api_client.get('/api/info/').json()
minimal_version: str = info['cli-minimal-version']
data = requests.get(f'https://pypi.org/pypi/dandi/{minimal_version}/json').json()

cli_requires_python: str = info['cli-requires-python']
dandischema_requires_python: str = data['info']['requires_python']

# Test for exact match
assert cli_requires_python == dandischema_requires_python
Loading
Loading