Skip to content

Commit b9dc94f

Browse files
Rewrite model check as validation check re #10079 (#11646)
* Rewrite model check as validation check re #10079 This model check should have been skippped by checking the `databases` kwarg provided when `check()` is called, but that reduces the circumstances on which this check is run to either: - manage.py migrate - manage.py check --databases So, given how infrequently this would be run, better to just implement this in our validation framework. This also prevents the possibility of failures when migrating.
1 parent f3390ef commit b9dc94f

File tree

10 files changed

+65
-83
lines changed

10 files changed

+65
-83
lines changed

.github/actions/build-and-test-branch/action.yml

+2-2
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ runs:
3333

3434
- name: Ensure frontend configuration files exist
3535
run: |
36-
python manage.py check --tag=compatibility
36+
python manage.py check
3737
shell: bash
3838

3939
- name: Install Arches applications
@@ -74,7 +74,7 @@ runs:
7474

7575
- name: Check for missing migrations
7676
run: |
77-
python manage.py makemigrations --check --skip-checks
77+
python manage.py makemigrations --check
7878
shell: bash
7979

8080
- name: Ensure previous Python coverage data is erased

arches/app/const.py

+2
Original file line numberDiff line numberDiff line change
@@ -4,13 +4,15 @@
44
IntegrityCheckDescriptions = {
55
1005: "Nodes with ontologies found in graphs without ontologies",
66
1012: "Node Groups without matching nodes",
7+
1014: "Publication missing for language",
78
}
89

910

1011
@unique
1112
class IntegrityCheck(Enum):
1213
NODE_HAS_ONTOLOGY_GRAPH_DOES_NOT = 1005
1314
NODELESS_NODE_GROUP = 1012
15+
PUBLICATION_MISSING_FOR_LANGUAGE = 1014
1416

1517
def __str__(self):
1618
return IntegrityCheckDescriptions[self.value]

arches/app/models/models.py

-33
Original file line numberDiff line numberDiff line change
@@ -613,39 +613,6 @@ def save(self, *args, **kwargs):
613613

614614
super(GraphModel, self).save(*args, **kwargs)
615615

616-
@classmethod
617-
def check(cls, **kwargs):
618-
errors = super().check(**kwargs)
619-
errors.extend(cls._check_publication_in_every_language())
620-
return errors
621-
622-
@classmethod
623-
def _check_publication_in_every_language(cls):
624-
errors = []
625-
system_languages = {lang[0] for lang in settings.LANGUAGES}
626-
627-
for graph in (
628-
cls.objects.filter(publication__isnull=False)
629-
.select_related("publication")
630-
.prefetch_related("publication__publishedgraph_set")
631-
):
632-
languages_with_a_publication = {
633-
published_graph.language_id
634-
for published_graph in graph.publication.publishedgraph_set.all()
635-
}
636-
missing_languages = system_languages - languages_with_a_publication
637-
if missing_languages:
638-
errors.append(
639-
checks.Error(
640-
"This graph is not published in all enabled languages.",
641-
hint="Run python manage.py graph publish --update",
642-
obj=graph,
643-
id="arches.E004", # TODO: enum in arches 8
644-
)
645-
)
646-
647-
return errors
648-
649616
def __str__(self):
650617
return str(self.name)
651618

arches/install/arches-templates/.github/actions/build-and-test-branch/action.yml

+2-2
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ runs:
3333

3434
- name: Ensure frontend configuration files exist
3535
run: |
36-
python manage.py check --tag=compatibility
36+
python manage.py check
3737
shell: bash
3838

3939
- name: Install Arches applications
@@ -74,7 +74,7 @@ runs:
7474

7575
- name: Check for missing migrations
7676
run: |
77-
python manage.py makemigrations --check --skip-checks
77+
python manage.py makemigrations --check
7878
shell: bash
7979

8080
- name: Ensure previous Python coverage data is erased

arches/management/commands/graph.py

+1-8
Original file line numberDiff line numberDiff line change
@@ -23,14 +23,7 @@
2323

2424

2525
class Command(BaseCommand):
26-
"""
27-
Commands for adding arches test users
28-
29-
"""
30-
31-
# Silence system checks since this command is the cure for
32-
# one of the system checks (arches.E004)
33-
requires_system_checks = []
26+
"""Commands for updating graphs."""
3427

3528
def add_arguments(self, parser):
3629
parser.add_argument(

arches/management/commands/packages.py

-3
Original file line numberDiff line numberDiff line change
@@ -73,9 +73,6 @@ class Command(BaseCommand):
7373
7474
"""
7575

76-
# Silence system checks: if run with -db, should always succeed.
77-
requires_system_checks = []
78-
7976
def add_arguments(self, parser):
8077
parser.add_argument(
8178
"-o",

arches/management/commands/setup_db.py

-3
Original file line numberDiff line numberDiff line change
@@ -36,9 +36,6 @@ class Command(BaseCommand):
3636
during development.
3737
"""
3838

39-
# Silence system checks: this command should always succeed.
40-
requires_system_checks = []
41-
4239
def add_arguments(self, parser):
4340

4441
parser.add_argument(

arches/management/commands/updateproject.py

-27
Original file line numberDiff line numberDiff line change
@@ -51,30 +51,3 @@ def update_to_v8(self):
5151
os.remove(declarations_test_file_path)
5252

5353
self.stdout.write("Done!")
54-
55-
# Update certain lines in GitHub Actions workflows.
56-
self.stdout.write("Updating GitHub Actions...")
57-
action_path = os.path.join(
58-
settings.APP_ROOT,
59-
"..",
60-
".github",
61-
"actions",
62-
"build-and-test-branch",
63-
"action.yml",
64-
)
65-
if os.path.exists(action_path):
66-
first_find = "python manage.py check\n"
67-
first_replace = "python manage.py check --tag=compatibility\n"
68-
second_find = "python manage.py makemigrations --check\n"
69-
second_replace = "python manage.py makemigrations --check --skip-checks\n"
70-
with open(action_path, "r") as f:
71-
content = f.readlines()
72-
for i, line in enumerate(content):
73-
if line.endswith(first_find):
74-
content[i] = line.replace(first_find, first_replace)
75-
elif line.endswith(second_find):
76-
content[i] = line.replace(second_find, second_replace)
77-
with open(action_path, "w") as f:
78-
f.writelines(content)
79-
80-
self.stdout.write("Done!")

arches/management/commands/validate.py

+52-4
Original file line numberDiff line numberDiff line change
@@ -18,19 +18,23 @@
1818

1919
from datetime import datetime
2020

21+
from django.conf import settings
22+
from django.contrib.postgres.aggregates import ArrayAgg
23+
from django.core.management import BaseCommand, CommandError, call_command
24+
from django.db import transaction
25+
from django.db.models import Exists, OuterRef, Q, Subquery
26+
2127
from arches import __version__
2228
from arches.app.const import IntegrityCheck
2329
from arches.app.models import models
24-
from django.core.management.base import BaseCommand, CommandError
25-
from django.db import transaction
26-
from django.db.models import Exists, OuterRef
2730

2831
# Command modes
2932
FIX = "fix"
3033
VALIDATE = "validate"
3134

3235
# Fix actions
3336
DELETE_QUERYSET = "delete queryset"
37+
UPDATE_GRAPH_PUBLICATIONS = "manage.py graph --update"
3438

3539

3640
class Command(BaseCommand):
@@ -116,6 +120,36 @@ def handle(self, *args, **options):
116120
),
117121
fix_action=DELETE_QUERYSET,
118122
)
123+
self.check_integrity(
124+
check=IntegrityCheck.PUBLICATION_MISSING_FOR_LANGUAGE, # 1014
125+
queryset=(
126+
models.GraphModel.objects.filter(
127+
isresource=True,
128+
publication__isnull=False,
129+
source_identifier=None,
130+
)
131+
.annotate(
132+
publications_in_system_languages=ArrayAgg(
133+
Subquery(
134+
models.PublishedGraph.objects.filter(
135+
pk=OuterRef("publication__publishedgraph"),
136+
)
137+
.values("language")
138+
.distinct()
139+
),
140+
filter=Q(
141+
publication__publishedgraph__language__in=[
142+
lang[0] for lang in settings.LANGUAGES
143+
]
144+
),
145+
)
146+
)
147+
.filter(
148+
publications_in_system_languages__len__lt=len(settings.LANGUAGES)
149+
)
150+
),
151+
fix_action=UPDATE_GRAPH_PUBLICATIONS,
152+
)
119153

120154
def check_integrity(self, check, queryset, fix_action):
121155
# 500 not set as a default earlier: None distinguishes whether verbose output implied
@@ -146,10 +180,24 @@ def check_integrity(self, check, queryset, fix_action):
146180
elif queryset.exists():
147181
fix_status = self.style.ERROR("No") # until actually fixed below
148182
# Perform fix action
149-
if fix_action is DELETE_QUERYSET:
183+
if fix_action == DELETE_QUERYSET:
150184
with transaction.atomic():
151185
queryset.delete()
152186
fix_status = self.style.SUCCESS("Yes")
187+
elif fix_action == UPDATE_GRAPH_PUBLICATIONS:
188+
call_command(
189+
"graph",
190+
"publish",
191+
"--update",
192+
"-g",
193+
",".join(
194+
str(pk) for pk in queryset.values_list("pk", flat=True)
195+
),
196+
verbosity=self.options["verbosity"],
197+
stdout=self.stdout,
198+
stderr=self.stderr,
199+
)
200+
fix_status = self.style.SUCCESS("Yes")
153201
else:
154202
raise NotImplementedError
155203
else:

releases/8.0.0.md

+6-1
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,6 @@ Arches 8.0.0 Release Notes
1919

2020
### Additional highlights
2121
- Add session-based REST APIs for login, logout [#11261](https://github.com/archesproject/arches/issues/11261)
22-
- Add system check advising next action when enabling additional languages without updating graphs [#10079](https://github.com/archesproject/arches/issues/10079)
2322
- Improve handling of longer model names [#11317](https://github.com/archesproject/arches/issues/11317)
2423
- Support more expressive plugin URLs [#11320](https://github.com/archesproject/arches/issues/11320)
2524
- Make node aliases not nullable [#10437](https://github.com/archesproject/arches/issues/10437)
@@ -107,6 +106,12 @@ JavaScript:
107106
108107
4. Update your Graph publications and Resource instances to point to the newly published Graphs by running `python manage.py graph publish --update -ui`
109108
109+
1. Also consider running validation checks:
110+
```
111+
python manage.py validate
112+
python manage.py validate --fix [error]
113+
```
114+
110115
5. Within your project with your Python 3 virtual environment activated:
111116
```
112117
python manage.py es reindex_database

0 commit comments

Comments
 (0)