nixos/glitchtip: init module (#386013)

This commit is contained in:
Sandro
2025-03-05 01:23:43 +01:00
committed by GitHub
20 changed files with 3856 additions and 16 deletions
@@ -141,6 +141,8 @@
- [Zipline](https://zipline.diced.sh/), a ShareX/file upload server that is easy to use, packed with features, and with an easy setup. Available as [services.zipline](#opt-services.zipline.enable).
- [GlitchTip](https://glitchtip.com/), an open source Sentry API compatible error tracking platform. Available as [services.glitchtip](#opt-services.glitchtip.enable).
- [Stash](https://github.com/stashapp/stash), An organizer for your adult videos/images, written in Go. Available as [services.stash](#opt-services.stash.enable).
- [vsmartcard-vpcd](https://frankmorgner.github.io/vsmartcard/virtualsmartcard/README.html), a virtual smart card driver. Available as [services.vsmartcard-vpcd](#opt-services.vsmartcard-vpcd.enable).
+1
View File
@@ -1502,6 +1502,7 @@
./services/web-apps/gancio.nix
./services/web-apps/gerrit.nix
./services/web-apps/glance.nix
./services/web-apps/glitchtip.nix
./services/web-apps/gotify-server.nix
./services/web-apps/gotosocial.nix
./services/web-apps/grav.nix
@@ -0,0 +1,293 @@
{
config,
pkgs,
lib,
...
}:
let
cfg = config.services.glitchtip;
pkg = cfg.package;
inherit (pkg.passthru) python;
environment = lib.mapAttrs (
_: value:
if value == true then
"True"
else if value == false then
"False"
else
toString value
) cfg.settings;
in
{
meta.maintainers = with lib.maintainers; [
defelo
felbinger
];
options = {
services.glitchtip = {
enable = lib.mkEnableOption "GlitchTip";
package = lib.mkPackageOption pkgs "glitchtip" { };
user = lib.mkOption {
type = lib.types.str;
description = "The user account under which GlitchTip runs.";
default = "glitchtip";
};
group = lib.mkOption {
type = lib.types.str;
description = "The group under which GlitchTip runs.";
default = "glitchtip";
};
listenAddress = lib.mkOption {
type = lib.types.str;
description = "The address to listen on.";
default = "127.0.0.1";
example = "0.0.0.0";
};
port = lib.mkOption {
type = lib.types.port;
description = "The port to listen on.";
default = 8000;
};
settings = lib.mkOption {
description = ''
Configuration of GlitchTip. See <https://glitchtip.com/documentation/install#configuration> for more information.
'';
default = { };
defaultText = lib.literalExpression ''
{
DEBUG = 0;
DEBUG_TOOLBAR = 0;
DATABASE_URL = lib.mkIf config.services.glitchtip.database.createLocally "postgresql://@/glitchtip";
REDIS_URL = lib.mkIf config.services.glitchtip.redis.createLocally "unix://''${config.services.redis.servers.glitchtip.unixSocket}";
CELERY_BROKER_URL = lib.mkIf config.services.glitchtip.redis.createLocally "redis+socket://''${config.services.redis.servers.glitchtip.unixSocket}";
}
'';
example = {
GLITCHTIP_DOMAIN = "https://glitchtip.example.com";
DATABASE_URL = "postgres://postgres:postgres@postgres/postgres";
};
type = lib.types.submodule {
freeformType =
with lib.types;
attrsOf (oneOf [
str
int
bool
]);
options = {
GLITCHTIP_DOMAIN = lib.mkOption {
type = lib.types.str;
description = "The URL under which GlitchTip is externally reachable.";
example = "https://glitchtip.example.com";
};
ENABLE_USER_REGISTRATION = lib.mkOption {
type = lib.types.bool;
description = ''
When true, any user will be able to register. When false, user self-signup is disabled after the first user is registered. Subsequent users must be created by a superuser on the backend and organization invitations may only be sent to existing users.
'';
default = false;
};
ENABLE_ORGANIZATION_CREATION = lib.mkOption {
type = lib.types.bool;
description = ''
When false, only superusers will be able to create new organizations after the first. When true, any user can create a new organization.
'';
default = false;
};
};
};
};
environmentFiles = lib.mkOption {
type = lib.types.listOf lib.types.path;
default = [ ];
example = [ "/run/secrets/glitchtip.env" ];
description = ''
Files to load environment variables from in addition to [](#opt-services.glitchtip.settings).
This is useful to avoid putting secrets into the nix store.
See <https://glitchtip.com/documentation/install#configuration> for more information.
'';
};
database.createLocally = lib.mkOption {
type = lib.types.bool;
default = true;
description = ''
Whether to enable and configure a local PostgreSQL database server.
'';
};
redis.createLocally = lib.mkOption {
type = lib.types.bool;
default = true;
description = ''
Whether to enable and configure a local Redis instance.
'';
};
gunicorn.extraArgs = lib.mkOption {
type = lib.types.listOf lib.types.str;
default = [ ];
description = "Extra arguments for gunicorn.";
};
celery.extraArgs = lib.mkOption {
type = lib.types.listOf lib.types.str;
default = [ ];
description = "Extra arguments for celery.";
};
};
};
config = lib.mkIf cfg.enable {
services.glitchtip.settings = {
DEBUG = lib.mkDefault 0;
DEBUG_TOOLBAR = lib.mkDefault 0;
PYTHONPATH = "${python.pkgs.makePythonPath pkg.propagatedBuildInputs}:${pkg}/lib/glitchtip";
DATABASE_URL = lib.mkIf cfg.database.createLocally "postgresql://@/glitchtip";
REDIS_URL = lib.mkIf cfg.redis.createLocally "unix://${config.services.redis.servers.glitchtip.unixSocket}";
CELERY_BROKER_URL = lib.mkIf cfg.redis.createLocally "redis+socket://${config.services.redis.servers.glitchtip.unixSocket}";
GLITCHTIP_VERSION = pkg.version;
};
systemd.services =
let
commonService = {
wantedBy = [ "multi-user.target" ];
wants = [ "network-online.target" ];
requires =
lib.optional cfg.database.createLocally "postgresql.service"
++ lib.optional cfg.redis.createLocally "redis-glitchtip.service";
after =
[ "network-online.target" ]
++ lib.optional cfg.database.createLocally "postgresql.service"
++ lib.optional cfg.redis.createLocally "redis-glitchtip.service";
inherit environment;
};
commonServiceConfig = {
User = cfg.user;
Group = cfg.group;
RuntimeDirectory = "glitchtip";
StateDirectory = "glitchtip";
EnvironmentFile = cfg.environmentFiles;
WorkingDirectory = "${pkg}/lib/glitchtip";
# hardening
AmbientCapabilities = "";
CapabilityBoundingSet = [ "" ];
DevicePolicy = "closed";
LockPersonality = true;
MemoryDenyWriteExecute = true;
NoNewPrivileges = true;
PrivateDevices = true;
PrivateTmp = true;
PrivateUsers = true;
ProcSubset = "pid";
ProtectClock = true;
ProtectControlGroups = true;
ProtectHome = true;
ProtectHostname = true;
ProtectKernelLogs = true;
ProtectKernelModules = true;
ProtectKernelTunables = true;
ProtectProc = "invisible";
ProtectSystem = "strict";
RemoveIPC = true;
RestrictAddressFamilies = [ "AF_INET AF_INET6 AF_UNIX" ];
RestrictNamespaces = true;
RestrictRealtime = true;
RestrictSUIDSGID = true;
SystemCallArchitectures = "native";
SystemCallFilter = [
"@system-service"
"~@privileged"
"~@resources"
];
UMask = "0077";
};
in
{
glitchtip = commonService // {
description = "GlitchTip";
preStart = ''
${lib.getExe pkg} migrate
'';
serviceConfig = commonServiceConfig // {
ExecStart = ''
${lib.getExe python.pkgs.gunicorn} \
--bind=${cfg.listenAddress}:${toString cfg.port} \
${lib.concatStringsSep " " cfg.gunicorn.extraArgs} \
glitchtip.wsgi
'';
};
};
glitchtip-worker = commonService // {
description = "GlitchTip Job Runner";
serviceConfig = commonServiceConfig // {
ExecStart = ''
${lib.getExe python.pkgs.celery} \
-A glitchtip worker \
-B -s /run/glitchtip/celerybeat-schedule \
${lib.concatStringsSep " " cfg.celery.extraArgs}
'';
};
};
};
services.postgresql = lib.mkIf cfg.database.createLocally {
enable = true;
ensureDatabases = [ "glitchtip" ];
ensureUsers = [
{
name = "glitchtip";
ensureDBOwnership = true;
}
];
};
services.redis.servers.glitchtip.enable = cfg.redis.createLocally;
users.users = lib.mkIf (cfg.user == "glitchtip") {
glitchtip = {
home = "/var/lib/glitchtip";
group = cfg.group;
extraGroups = lib.optionals cfg.redis.createLocally [ "redis-glitchtip" ];
isSystemUser = true;
};
};
users.groups = lib.mkIf (cfg.group == "glitchtip") { glitchtip = { }; };
environment.systemPackages =
let
glitchtip-manage = pkgs.writeShellScriptBin "glitchtip-manage" ''
set -o allexport
${lib.toShellVars environment}
${lib.concatMapStringsSep "\n" (f: "source ${f}") cfg.environmentFiles}
${config.security.wrapperDir}/sudo -E -u ${cfg.user} ${lib.getExe pkg} "$@"
'';
in
[ glitchtip-manage ];
};
}
+1
View File
@@ -434,6 +434,7 @@ in {
gitolite-fcgiwrap = handleTest ./gitolite-fcgiwrap.nix {};
glance = runTest ./glance.nix;
glances = runTest ./glances.nix;
glitchtip = runTest ./glitchtip.nix;
glusterfs = handleTest ./glusterfs.nix {};
gnome = handleTest ./gnome.nix {};
gnome-extensions = handleTest ./gnome-extensions.nix {};
+103
View File
@@ -0,0 +1,103 @@
{ lib, ... }:
let
domain = "http://glitchtip.local:8000";
in
{
name = "glitchtip";
meta.maintainers = with lib.maintainers; [
defelo
felbinger
];
nodes.machine =
{ pkgs, ... }:
{
services.glitchtip = {
enable = true;
port = 8000;
settings.GLITCHTIP_DOMAIN = domain;
environmentFiles = [
(builtins.toFile "glitchtip.env" ''
SECRET_KEY=8Hz7YCGzo7fiicHb8Qr22ZqwoIB7lSRx
'')
];
};
environment.systemPackages = [ pkgs.sentry-cli ];
networking.hosts."127.0.0.1" = [ "glitchtip.local" ];
};
interactive.nodes.machine = {
services.glitchtip.listenAddress = "0.0.0.0";
networking.firewall.allowedTCPPorts = [ 8000 ];
virtualisation.forwardPorts = [
{
from = "host";
host.port = 8000;
guest.port = 8000;
}
];
};
testScript = ''
import json
import re
import time
machine.wait_for_unit("glitchtip.service")
machine.wait_for_unit("glitchtip-worker.service")
machine.wait_for_open_port(8000)
origin_url = "${domain}"
cookie_jar_path = "/tmp/cookies.txt"
curl = f"curl -b {cookie_jar_path} -c {cookie_jar_path} -fS -H 'Origin: {origin_url}'"
# create superuser account
machine.succeed("DJANGO_SUPERUSER_PASSWORD=password glitchtip-manage createsuperuser --no-input --email=admin@example.com")
# login
machine.fail(f"{curl} -s {origin_url}/_allauth/browser/v1/auth/session") # get the csrf token, returns a 401
csrf_token = machine.succeed(f"grep csrftoken {cookie_jar_path} | cut -f7").rstrip()
machine.succeed(f"{curl} {origin_url}/_allauth/browser/v1/auth/login -s -H 'X-Csrftoken: {csrf_token}' -H 'Content-Type: application/json' -d '{{\"email\": \"admin@example.com\", \"password\": \"password\"}}'")
resp = json.loads(machine.succeed(f"{curl} {origin_url}/api/0/users/me/"))
assert resp["email"] == "admin@example.com"
assert resp["isSuperuser"] is True
# create organization
csrf_token = machine.succeed(f"grep csrftoken {cookie_jar_path} | cut -f7").rstrip()
machine.succeed(f"{curl} {origin_url}/api/0/organizations/ -s -H 'X-Csrftoken: {csrf_token}' -H 'Content-Type: application/json' -d '{{\"name\": \"main\"}}'")
resp = json.loads(machine.succeed(f"{curl} {origin_url}/api/0/organizations/"))
assert len(resp) == 1
assert resp[0]["name"] == "main"
assert resp[0]["slug"] == "main"
# create team
csrf_token = machine.succeed(f"grep csrftoken {cookie_jar_path} | cut -f7").rstrip()
machine.succeed(f"{curl} {origin_url}/api/0/organizations/main/teams/ -s -H 'X-Csrftoken: {csrf_token}' -H 'Content-Type: application/json' -d '{{\"slug\": \"test\"}}'")
# create project
csrf_token = machine.succeed(f"grep csrftoken {cookie_jar_path} | cut -f7").rstrip()
machine.succeed(f"{curl} {origin_url}/api/0/teams/main/test/projects/ -s -H 'X-Csrftoken: {csrf_token}' -H 'Content-Type: application/json' -d '{{\"name\": \"test\"}}'")
# fetch dsn
resp = json.loads(machine.succeed(f"{curl} {origin_url}/api/0/projects/main/test/keys/"))
assert len(resp) == 1
assert re.match(r"^http://[\da-f]+@glitchtip\.local:8000/\d+$", dsn := resp[0]["dsn"]["public"])
# send event
machine.succeed(f"SENTRY_DSN={dsn} sentry-cli send-event -m 'hello world'")
for _ in range(20):
resp = json.loads(machine.succeed(f"{curl} {origin_url}/api/0/organizations/main/issues/?query=is:unresolved"))
if len(resp) != 0: break
time.sleep(1)
assert len(resp) == 1
assert resp[0]["title"] == "hello world"
assert int(resp[0]["count"]) == 1
'';
}
+54
View File
@@ -0,0 +1,54 @@
{
lib,
fetchFromGitLab,
buildNpmPackage,
jq,
moreutils,
}:
buildNpmPackage rec {
pname = "glitchtip-frontend";
version = "4.2.5";
src = fetchFromGitLab {
owner = "glitchtip";
repo = "glitchtip-frontend";
tag = "v${version}";
hash = "sha256-yLpDjHnt8ZwpT+KlmEtXMYgrpnbYlVzJ/MZMELVO/j8=";
};
npmDepsHash = "sha256-sR/p/JRVuaemN1euZ/VrJ0j1q7fkS/Zi6R1m6lPvygs=";
postPatch = ''
${lib.getExe jq} '. + {
"devDependencies": .devDependencies | del(.cypress, ."cypress-localstorage-commands")
}' package.json | ${lib.getExe' moreutils "sponge"} package.json
'';
buildPhase = ''
runHook preBuild
npm run build-prod
runHook postBuild
'';
installPhase = ''
runHook preInstall
cp -r dist/glitchtip-frontend/browser $out/
runHook postInstall
'';
meta = {
description = "Frontend for GlitchTip";
homepage = "https://glitchtip.com";
changelog = "https://gitlab.com/glitchtip/glitchtip-frontend/-/releases/v${version}";
license = lib.licenses.mit;
maintainers = with lib.maintainers; [
defelo
felbinger
];
};
}
+130
View File
@@ -0,0 +1,130 @@
{
lib,
python313,
fetchFromGitLab,
callPackage,
stdenv,
makeWrapper,
nixosTests,
}:
let
python = python313.override {
packageOverrides = final: prev: {
django = final.django_5;
django-extensions = prev.django-extensions.overridePythonAttrs { doCheck = false; };
};
};
pythonPackages =
with python.pkgs;
[
aiohttp
anonymizeip
boto3
brotli
celery
celery-batches
dj-stripe
django
django-allauth
django-anymail
django-cors-headers
django-csp
django-environ
django-extensions
django-import-export
django-ipware
django-ninja
django-organizations
django-prometheus
django-redis
django-sql-utils
django-storages
google-cloud-logging
gunicorn
orjson
psycopg
pydantic
sentry-sdk
symbolic
user-agents
uvicorn
uwsgi-chunked
whitenoise
]
++ celery.optional-dependencies.redis
++ django-allauth.optional-dependencies.mfa
++ django-allauth.optional-dependencies.socialaccount
++ django-redis.optional-dependencies.hiredis
++ django-storages.optional-dependencies.boto3
++ django-storages.optional-dependencies.azure
++ django-storages.optional-dependencies.google
++ psycopg.optional-dependencies.c
++ psycopg.optional-dependencies.pool
++ pydantic.optional-dependencies.email;
frontend = callPackage ./frontend.nix { };
in
stdenv.mkDerivation (finalAttrs: {
pname = "glitchtip";
version = "4.2.5";
pyproject = true;
src = fetchFromGitLab {
owner = "glitchtip";
repo = "glitchtip-backend";
tag = "v${finalAttrs.version}";
hash = "sha256-OTf2rvx+ONnB7pLB7rinztXL7l2eZfIuI7PosCXaOH8=";
};
propagatedBuildInputs = pythonPackages;
nativeBuildInputs = [
makeWrapper
python
];
buildPhase = ''
runHook preBuild
export DEBUG=0
export DEBUG_TOOLBAR=0
ln -s ${finalAttrs.passthru.frontend} dist
python3 manage.py collectstatic
runHook postBuild
'';
installPhase = ''
runHook preInstall
mkdir -p $out/lib
cp -r . $out/lib/glitchtip
chmod +x $out/lib/glitchtip/manage.py
makeWrapper $out/lib/glitchtip/manage.py $out/bin/glitchtip-manage \
--prefix PYTHONPATH : "$PYTHONPATH"
runHook postInstall
'';
passthru = {
inherit frontend python;
tests = { inherit (nixosTests) glitchtip; };
updateScript = ./update.sh;
};
meta = {
description = "Open source Sentry API compatible error tracking platform";
homepage = "https://glitchtip.com";
changelog = "https://gitlab.com/glitchtip/glitchtip-backend/-/blob/v${finalAttrs.version}/CHANGELOG";
license = lib.licenses.mit;
maintainers = with lib.maintainers; [
defelo
felbinger
];
mainProgram = "glitchtip-manage";
};
})
+5
View File
@@ -0,0 +1,5 @@
#!/usr/bin/env nix-shell
#!nix-shell -i bash -p nix-update
nix-update glitchtip
nix-update glitchtip.frontend
@@ -0,0 +1,33 @@
{
lib,
fetchFromGitHub,
buildPythonPackage,
setuptools,
pytestCheckHook,
}:
buildPythonPackage rec {
pname = "anonymizeip";
version = "1.0.0";
pyproject = true;
src = fetchFromGitHub {
owner = "samuelmeuli";
repo = "anonymize-ip";
tag = "v${version}";
hash = "sha256-54q2R14Pdnw4FAmBufeq5NozsqC7C4W6QQPcjTSkM48=";
};
build-system = [ setuptools ];
nativeCheckInputs = [ pytestCheckHook ];
pythonImportsCheck = [ "anonymizeip" ];
meta = {
description = "Python library for anonymizing IP addresses";
homepage = "https://github.com/samuelmeuli/anonymize-ip";
license = lib.licenses.mit;
maintainers = with lib.maintainers; [ defelo ];
};
}
@@ -0,0 +1,37 @@
{
lib,
fetchFromGitHub,
buildPythonPackage,
setuptools,
celery,
}:
buildPythonPackage rec {
pname = "celery-batches";
version = "0.9";
pyproject = true;
src = fetchFromGitHub {
owner = "clokep";
repo = "celery-batches";
tag = "v${version}";
hash = "sha256-w7k8VPtJf9VRB8lJC/ENk3kIMPITd+qRIXm1KrCktgc=";
};
build-system = [ setuptools ];
dependencies = [ celery ];
# requires a running celery
doCheck = false;
pythonImportsCheck = [ "celery_batches" ];
meta = {
description = "Allows processing of multiple Celery task requests together";
homepage = "https://github.com/clokep/celery-batches";
changelog = "https://github.com/clokep/celery-batches/blob/v${version}/CHANGELOG.rst";
license = lib.licenses.bsd3;
maintainers = with lib.maintainers; [ defelo ];
};
}
@@ -0,0 +1,122 @@
{
lib,
buildPythonPackage,
fetchFromGitHub,
poetry-core,
django,
stripe,
mysqlclient,
psycopg2,
pytest-django,
pytestCheckHook,
}:
buildPythonPackage rec {
pname = "dj-stripe";
version = "2.9.0";
pyproject = true;
src = fetchFromGitHub {
owner = "dj-stripe";
repo = "dj-stripe";
tag = version;
hash = "sha256-ijTzSid5B79mAi7qUFSGL5+4PfmBStDWayzjW1iwRww=";
};
build-system = [ poetry-core ];
dependencies = [
django
stripe
];
passthru.optional-dependencies = {
mysql = [ mysqlclient ];
postgres = [ psycopg2 ];
};
env = {
DJANGO_SETTINGS_MODULE = "tests.settings";
DJSTRIPE_TEST_DB_VENDOR = "sqlite";
};
nativeCheckInputs = [
pytest-django
pytestCheckHook
];
pytestFlagsArray = [
"--deselect=tests/test_customer.py::TestCustomer::test_customer_sync_unsupported_source"
"--deselect=tests/test_customer.py::TestCustomer::test_upcoming_invoice_plan"
"--deselect=tests/test_customer.py::TestCustomerLegacy::test_upcoming_invoice"
"--deselect=tests/test_event_handlers.py::TestCustomerEvents::test_customer_default_source_deleted"
"--deselect=tests/test_event_handlers.py::TestCustomerEvents::test_customer_deleted"
"--deselect=tests/test_event_handlers.py::TestCustomerEvents::test_customer_source_double_delete"
"--deselect=tests/test_event_handlers.py::TestPlanEvents::test_plan_created"
"--deselect=tests/test_event_handlers.py::TestPlanEvents::test_plan_deleted"
"--deselect=tests/test_event_handlers.py::TestPlanEvents::test_plan_updated_request_object"
"--deselect=tests/test_event_handlers.py::TestTaxIdEvents::test_tax_id_created"
"--deselect=tests/test_event_handlers.py::TestTaxIdEvents::test_tax_id_deleted"
"--deselect=tests/test_event_handlers.py::TestTaxIdEvents::test_tax_id_updated"
"--deselect=tests/test_invoice.py::InvoiceTest::test_upcoming_invoice"
"--deselect=tests/test_invoice.py::InvoiceTest::test_upcoming_invoice_with_subscription"
"--deselect=tests/test_invoice.py::InvoiceTest::test_upcoming_invoice_with_subscription_plan"
"--deselect=tests/test_invoice.py::TestInvoiceDecimal::test_decimal_tax_percent"
"--deselect=tests/test_plan.py::PlanCreateTest::test_create_from_djstripe_product"
"--deselect=tests/test_plan.py::PlanCreateTest::test_create_from_product_id"
"--deselect=tests/test_plan.py::PlanCreateTest::test_create_from_stripe_product"
"--deselect=tests/test_plan.py::PlanCreateTest::test_create_with_metadata"
"--deselect=tests/test_price.py::PriceCreateTest::test_create_from_djstripe_product"
"--deselect=tests/test_price.py::PriceCreateTest::test_create_from_product_id"
"--deselect=tests/test_price.py::PriceCreateTest::test_create_from_stripe_product"
"--deselect=tests/test_price.py::PriceCreateTest::test_create_with_metadata"
"--deselect=tests/test_settings.py::TestSubscriberModelRetrievalMethod::test_bad_callback"
"--deselect=tests/test_settings.py::TestSubscriberModelRetrievalMethod::test_no_callback"
"--deselect=tests/test_settings.py::TestStripeApiVersion::test_global_stripe_api_version"
"--deselect=tests/test_subscription.py::TestSubscriptionDecimal::test_decimal_application_fee_percent"
"--deselect=tests/test_tax_id.py::TestTaxIdStr::test___str__"
"--deselect=tests/test_tax_id.py::TestTransfer::test__api_create"
"--deselect=tests/test_tax_id.py::TestTransfer::test__api_create_no_customer"
"--deselect=tests/test_tax_id.py::TestTransfer::test__api_create_no_id_kwarg"
"--deselect=tests/test_tax_id.py::TestTransfer::test_api_list"
"--deselect=tests/test_tax_id.py::TestTransfer::test_api_retrieve"
"--deselect=tests/test_tax_rates.py::TestTaxRateDecimal::test_decimal_tax_percent"
"--deselect=tests/test_transfer_reversal.py::TestTransfer::test_api_list"
"--deselect=tests/test_transfer_reversal.py::TestTransfer::test_api_retrieve"
"--deselect=tests/test_usage_record.py::TestUsageRecord::test___str__"
"--deselect=tests/test_usage_record.py::TestUsageRecord::test__api_create"
"--deselect=tests/test_usage_record_summary.py::TestUsageRecordSummary::test___str__"
"--deselect=tests/test_usage_record_summary.py::TestUsageRecordSummary::test_api_list"
"--deselect=tests/test_usage_record_summary.py::TestUsageRecordSummary::test_sync_from_stripe_data"
"--deselect=tests/test_views.py::TestConfirmCustomActionView::test__cancel_subscription_instances_stripe_invalid_request_error"
"--deselect=tests/test_views.py::TestConfirmCustomActionView::test__release_subscription_schedule_stripe_invalid_request_error"
"--deselect=tests/test_views.py::TestConfirmCustomActionView::test__cancel_subscription_schedule_stripe_invalid_request_error"
"--deselect=tests/test_webhooks.py::TestWebhookEventTrigger::test___str__"
"--deselect=tests/test_webhooks.py::TestWebhookEventTrigger::test_webhook_error"
"--deselect=tests/test_webhooks.py::TestWebhookEventTrigger::test_webhook_good_connect_account"
"--deselect=tests/test_webhooks.py::TestWebhookEventTrigger::test_webhook_good_platform_account"
"--deselect=tests/test_webhooks.py::TestWebhookEventTrigger::test_webhook_invalid_verify_signature_fail"
"--deselect=tests/test_webhooks.py::TestWebhookEventTrigger::test_webhook_no_signature"
"--deselect=tests/test_webhooks.py::TestWebhookEventTrigger::test_webhook_no_validation_pass"
"--deselect=tests/test_webhooks.py::TestWebhookEventTrigger::test_webhook_remote_addr_is_empty_string"
"--deselect=tests/test_webhooks.py::TestWebhookEventTrigger::test_webhook_remote_addr_is_none"
"--deselect=tests/test_webhooks.py::TestWebhookEventTrigger::test_webhook_reraise_exception"
"--deselect=tests/test_webhooks.py::TestWebhookEventTrigger::test_webhook_retrieve_event_fail"
"--deselect=tests/test_webhooks.py::TestWebhookEventTrigger::test_webhook_retrieve_event_pass"
"--deselect=tests/test_webhooks.py::TestWebhookEventTrigger::test_webhook_test_event"
"--deselect=tests/test_webhooks.py::TestWebhookEventTrigger::test_webhook_verify_signature_pass"
"--deselect=tests/test_webhooks.py::TestWebhookEventTrigger::test_webhook_with_custom_callback"
"--deselect=tests/test_webhooks.py::TestWebhookEventTrigger::test_webhook_with_transfer_event_duplicate"
"--deselect=tests/test_webhooks.py::TestGetRemoteIp::test_get_remote_ip_remote_addr_is_none"
];
pythonImportsCheck = [ "djstripe" ];
meta = {
description = "Stripe Models for Django";
homepage = "https://github.com/dj-stripe/dj-stripe";
changelog = "https://github.com/dj-stripe/dj-stripe/releases/tag/${version}";
license = lib.licenses.mit;
maintainers = with lib.maintainers; [ defelo ];
};
}
@@ -25,10 +25,14 @@
qrcode,
# tests
django-ninja,
djangorestframework,
pillow,
pytestCheckHook,
psycopg2,
pytest-asyncio,
pytest-django,
pytestCheckHook,
pyyaml,
# passthru tests
dj-rest-auth,
@@ -36,7 +40,7 @@
buildPythonPackage rec {
pname = "django-allauth";
version = "65.3.1";
version = "65.4.1";
pyproject = true;
disabled = pythonOlder "3.8";
@@ -45,16 +49,12 @@ buildPythonPackage rec {
owner = "pennersr";
repo = "django-allauth";
tag = version;
hash = "sha256-IgadrtOQt3oY2U/+JWBs5v97aaWz5oinz5QUdGXBqO4=";
hash = "sha256-z5vaNopIk1CAV+TpH/V3Y6lXf7ztU4QeHZ9OTSPCgc0=";
};
nativeBuildInputs = [
gettext
];
nativeBuildInputs = [ gettext ];
build-system = [
setuptools
];
build-system = [ setuptools ];
dependencies = [
asgiref
@@ -83,10 +83,14 @@ buildPythonPackage rec {
pythonImportsCheck = [ "allauth" ];
nativeCheckInputs = [
django-ninja
djangorestframework
pillow
pytestCheckHook
psycopg2
pytest-asyncio
pytest-django
pytestCheckHook
pyyaml
] ++ lib.flatten (builtins.attrValues optional-dependencies);
disabledTests = [
@@ -94,16 +98,14 @@ buildPythonPackage rec {
"test_login"
];
passthru.tests = {
inherit dj-rest-auth;
};
passthru.tests = { inherit dj-rest-auth; };
meta = with lib; {
meta = {
changelog = "https://github.com/pennersr/django-allauth/blob/${version}/ChangeLog.rst";
description = "Integrated set of Django applications addressing authentication, registration, account management as well as 3rd party (social) account authentication";
downloadPage = "https://github.com/pennersr/django-allauth";
homepage = "https://www.intenct.nl/projects/django-allauth";
license = licenses.mit;
maintainers = with maintainers; [ derdennisop ];
license = lib.licenses.mit;
maintainers = with lib.maintainers; [ derdennisop ];
};
}
@@ -0,0 +1,47 @@
{
lib,
buildPythonPackage,
fetchFromGitHub,
setuptools,
wheel,
django,
django-modeltranslation,
}:
buildPythonPackage rec {
pname = "django-autoslug";
version = "1.9.9";
pyproject = true;
src = fetchFromGitHub {
owner = "justinmayer";
repo = "django-autoslug";
tag = "v${version}";
hash = "sha256-IRLY4VaKYXVkSgU/zdY+PSmGrcFB2FlE5L7j0FqisRM=";
};
build-system = [
setuptools
wheel
];
dependencies = [ django ];
nativeCheckInputs = [ django-modeltranslation ];
checkPhase = ''
runHook preCheck
python run_tests.py
runHook postCheck
'';
meta = {
description = "AutoSlugField for Django";
homepage = "https://github.com/justinmayer/django-autoslug";
changelog = "https://github.com/justinmayer/django-autoslug/blob/v${version}/CHANGELOG.rst";
license = lib.licenses.lgpl3Only;
maintainers = with lib.maintainers; [ defelo ];
};
}
@@ -0,0 +1,51 @@
{
lib,
buildPythonPackage,
fetchFromGitHub,
hatchling,
django,
django-extensions,
pytest-django,
pytestCheckHook,
mock,
mock-django,
django-autoslug,
}:
buildPythonPackage rec {
pname = "django-organizations";
version = "2.5.0";
pyproject = true;
src = fetchFromGitHub {
owner = "bennylope";
repo = "django-organizations";
tag = version;
hash = "sha256-lgri6CCITp1oYCwpH8vrUglphXOmwZ3KX5G/L29akrs=";
};
build-system = [ hatchling ];
dependencies = [
django
django-extensions
];
nativeCheckInputs = [
pytest-django
pytestCheckHook
mock
mock-django
django-autoslug
];
pythonImportsCheck = [ "organizations" ];
meta = {
description = "Multi-user accounts for Django projects";
homepage = "https://github.com/bennylope/django-organizations";
changelog = "https://github.com/bennylope/django-organizations/blob/${version}/HISTORY.rst";
license = lib.licenses.bsd2;
maintainers = with lib.maintainers; [ defelo ];
};
}
@@ -0,0 +1,53 @@
{
lib,
buildPythonPackage,
fetchFromGitHub,
hatchling,
django,
sqlparse,
pytestCheckHook,
pytest-django,
}:
buildPythonPackage rec {
pname = "django-sql-utils";
version = "0.7.0";
pyproject = true;
src = fetchFromGitHub {
owner = "martsberger";
repo = "django-sql-utils";
tag = version;
hash = "sha256-OjKPxoWYheu8UQ14KvyiQyHISAQjJep+N4HRc4Msa1w=";
};
postPatch = ''
echo -e "\n[tool.hatch.build.targets.wheel]\npackages = [ \"sql_util\" ]" >> pyproject.toml
'';
build-system = [ hatchling ];
dependencies = [
django
sqlparse
];
env = {
DJANGO_SETTINGS_MODULE = "sql_util.tests.test_sqlite_settings";
};
nativeCheckInputs = [
pytestCheckHook
pytest-django
];
pythonImportsCheck = [ "sql_util" ];
meta = {
description = "SQL utilities for Django";
homepage = "https://github.com/martsberger/django-sql-utils";
changelog = "https://github.com/martsberger/django-sql-utils/releases/tag/${version}";
license = lib.licenses.mit;
maintainers = with lib.maintainers; [ defelo ];
};
}
@@ -0,0 +1,42 @@
{
lib,
buildPythonPackage,
fetchFromGitHub,
setuptools,
wheel,
django,
mock,
}:
buildPythonPackage {
pname = "mock-django";
version = "0.6.10";
pyproject = true;
src = fetchFromGitHub {
owner = "dcramer";
repo = "mock-django";
rev = "1168d3255e0d67fbf74a9c71feaccbdafef59d21";
hash = "sha256-sjrRxu2754sAaXZRlAfBhdLFHqiRlqPHVPQv4B6oArw=";
};
build-system = [
setuptools
wheel
];
dependencies = [
django
mock
];
# tests are based on nose, which is not supported anymore
doCheck = false;
meta = {
description = "Simple library for mocking certain Django behavior, such as the ORM";
homepage = "https://github.com/dcramer/mock-django";
license = lib.licenses.asl20;
maintainers = with lib.maintainers; [ defelo ];
};
}
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,76 @@
{
lib,
buildPythonPackage,
fetchFromGitHub,
setuptools-rust,
rustPlatform,
rustc,
cargo,
milksnake,
cffi,
pytestCheckHook,
nixosTests,
}:
buildPythonPackage rec {
pname = "symbolic";
version = "10.2.1"; # glitchtip currently only works with symbolic 10.x
pyproject = true;
src = fetchFromGitHub {
owner = "getsentry";
repo = "symbolic";
tag = version;
hash = "sha256-3u4MTzaMwryGpFowrAM/MJOmnU8M+Q1/0UtALJib+9A=";
# for some reason the `py` directory in the tarball is empty, so we fetch the source via git instead
forceFetchGit = true;
};
cargoDeps = rustPlatform.fetchCargoVendor {
inherit
pname
version
src
postPatch
;
hash = "sha256-cpIVzgcxKfEA5oov6/OaXqknYsYZUoduLTn2qIXGL5U=";
};
nativeBuildInputs = [
setuptools-rust
rustPlatform.cargoSetupHook
rustc
cargo
milksnake
];
dependencies = [ cffi ];
postPatch = ''
ln -s ${./Cargo.lock} Cargo.lock
'';
preBuild = ''
cd py
'';
preCheck = ''
cd ..
'';
nativeCheckInputs = [ pytestCheckHook ];
pytestFlagsArray = [ "py" ];
pythonImportsCheck = [ "symbolic" ];
passthru.tests = { inherit (nixosTests) glitchtip; };
meta = {
description = "Python library for dealing with symbol files and more";
homepage = "https://github.com/getsentry/symbolic";
changelog = "https://github.com/getsentry/symbolic/blob/${version}/CHANGELOG.md";
license = lib.licenses.mit;
maintainers = with lib.maintainers; [ defelo ];
};
}
@@ -0,0 +1,33 @@
{
lib,
buildPythonPackage,
fetchFromGitHub,
setuptools,
}:
buildPythonPackage rec {
pname = "uwsgi-chunked";
version = "0.1.8";
pyproject = true;
src = fetchFromGitHub {
owner = "btimby";
repo = "uwsgi-chunked";
tag = version;
hash = "sha256-5TNCnQhnT1gAblgs+AAW62HoNDPM54hpxgCnYl07j3I=";
};
build-system = [ setuptools ];
# requires running containers via docker
doCheck = false;
pythonImportsCheck = [ "uwsgi_chunked" ];
meta = {
description = "WSGI application wrapper that handles Transfer-Encoding: chunked";
homepage = "https://github.com/btimby/uwsgi-chunked";
license = lib.licenses.mit;
maintainers = with lib.maintainers; [ defelo ];
};
}
+18
View File
@@ -600,6 +600,8 @@ self: super: with self; {
amshan = callPackage ../development/python-modules/amshan { };
anonymizeip = callPackage ../development/python-modules/anonymizeip { };
anchor-kr = callPackage ../development/python-modules/anchor-kr { };
ancp-bids = callPackage ../development/python-modules/ancp-bids { };
@@ -2157,6 +2159,8 @@ self: super: with self; {
celery = callPackage ../development/python-modules/celery { };
celery-batches = callPackage ../development/python-modules/celery-batches { };
celery-redbeat = callPackage ../development/python-modules/celery-redbeat { };
celery-singleton = callPackage ../development/python-modules/celery-singleton { };
@@ -3460,6 +3464,8 @@ self: super: with self; {
django-autocomplete-light = callPackage ../development/python-modules/django-autocomplete-light { };
django-autoslug = callPackage ../development/python-modules/django-autoslug { };
django-axes = callPackage ../development/python-modules/django-axes { };
django-bootstrap3 = callPackage ../development/python-modules/django-bootstrap3 { };
@@ -3620,6 +3626,8 @@ self: super: with self; {
django-oauth-toolkit = callPackage ../development/python-modules/django-oauth-toolkit { };
django-organizations = callPackage ../development/python-modules/django-organizations { };
django-otp = callPackage ../development/python-modules/django-otp { };
django-otp-webauthn = callPackage ../development/python-modules/django-otp-webauthn { };
@@ -3722,6 +3730,8 @@ self: super: with self; {
django-soft-delete = callPackage ../development/python-modules/django-soft-delete { };
django-sql-utils = callPackage ../development/python-modules/django-sql-utils { };
django-statici18n = callPackage ../development/python-modules/django-statici18n { };
django-storages = callPackage ../development/python-modules/django-storages { };
@@ -3774,6 +3784,8 @@ self: super: with self; {
dj-static = callPackage ../development/python-modules/dj-static { };
dj-stripe = callPackage ../development/python-modules/dj-stripe { };
dkimpy = callPackage ../development/python-modules/dkimpy { };
dlib = callPackage ../development/python-modules/dlib {
@@ -8525,6 +8537,8 @@ self: super: with self; {
mockito = callPackage ../development/python-modules/mockito { };
mock-django = callPackage ../development/python-modules/mock-django { };
mock-open = callPackage ../development/python-modules/mock-open { };
mock-services = callPackage ../development/python-modules/mock-services { };
@@ -16060,6 +16074,8 @@ self: super: with self; {
sybil = callPackage ../development/python-modules/sybil { };
symbolic = callPackage ../development/python-modules/symbolic { };
symengine = callPackage ../development/python-modules/symengine {
inherit (pkgs) symengine;
};
@@ -18048,6 +18064,8 @@ self: super: with self; {
uxsim = callPackage ../development/python-modules/uxsim { };
uwsgi-chunked = callPackage ../development/python-modules/uwsgi-chunked { };
vaa = callPackage ../development/python-modules/vaa { };
vacuum-map-parser-base = callPackage ../development/python-modules/vacuum-map-parser-base { };