-
Notifications
You must be signed in to change notification settings - Fork 22
Update requirements and dependency badge #153
Conversation
@@ -98,7 +98,8 @@ test_unit: clean static_external | |||
|
|||
# Check whether migrations need to be generated | |||
test_migrations_missing: clean | |||
! honcho -e .env.test run ./manage.py makemigrations --dry-run --exit | |||
(psql -lqt | cut -d \| -f 1 | grep -qw opencraft) || (createdb --encoding utf-8 --template template0 opencraft) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If I understand correctly, this new line creates the DB if it doesn't exist, right? Why is this needed here?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@antoviaque Yup, that's what it does. As for why it's necessary, cf. ac9be4f: After the updates, makemigrations
fails with "OperationalError: database ... does not exist" if the target database does not exist (this is actually what I would expect). I first noticed this on CircleCI, and then also verified it locally, by changing DATABASE_URL
in .env.test
to point to a database that didn't exist on my Vagrant box and running make test_migrations_missing
. Didn't get any errors with the old dependencies/master, and saw the error mentioned above after switching back to the new dependencies/this branch.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@itsjeyd Any idea why this is happening now, and didn't happen in the past? It looks like this should always have been an issue. I can't figure out by what mechanism the DB was created on CircleCI before this PR.
In any case, the make target test_migrations_missing
seems like a weird place for the implicit creation of the database. If this is indeed necessary, it can be simplified to
createdb --encoding utf-8 --template template0 opencraft 2> /dev/null || true
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@smarnach I don't know why the behavior changed, but I'm assuming it has something to do with the (Django) upgrade. As mentioned earlier, it's possible to reproduce the before/after behavior that CircleCI showed locally: In .env.test
, set DATABASE_URL
to point to a database that doesn't exist (e.g., DATABASE_URL='postgres://localhost/foo'
). Then try running make test_migrations_missing
- on a Vagrant snapshot with dependencies from
master
installed - on a Vagrant snapshot with dependencies from this branch (
update-dependencies
) installed
In the first instance, you won't get any errors. In the second instance, the command will error out with
django.db.utils.OperationalError: FATAL: database "foo" does not exist
This (combined with the fact that I also couldn't find any code that would create an "opencraft" database on CircleCI) makes me think that there never was an "opencraft" database on CircleCI, and that we didn't notice because make test_migrations_missing
succeeded anyway.
I simplified the command according to your suggestions.
# (via `self.action`) inside this method will fail with an `AttributeError`. | ||
# We guard against that here by using `getattr` to retrieve the value | ||
# of the `action` field. | ||
if getattr(self, 'action', None) == 'retrieve': | ||
suffix = "Details" | ||
return "Instance {}".format(suffix) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
To understand this better, why do we change the view name depending on the action? Is there a broader fix/refactoring which would allow to prevent burying ourselves further here?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@antoviaque We change the view name to get a better/more specific heading displayed in the browsable API. When overriding get_view_name
, we get "Instance List" on /api/v1/instance/
, and "Instance Details" on /api/v1/instance/{pk}/
:
When not overriding get_view_name
, we get "Instance List" on api/v1/instance/
(same as before), but on /api/v1/instance/{pk}/
we get "Instance Instance":
I'm not that familiar with DRT, so I'm not sure if there is a broader fix/refactoring that we could apply here (if there is, it would probably also take care of the breadcrumbs issue that I laid out in the PR description).
EDIT: Of course, assuming that we don't want to expose the browsable API to end users, we could also decide that we don't care about "Instance Details" vs. "Instance Instance", and just remove any custom get_view_name
implementations.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm in favour of removing the get_view_name()
methods. They don't seem to be worth the trouble.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@smarnach I agree -- removed those methods in a7a0712.
CC @antoviaque
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
+1 for the solution - thanks!
# (via `self.action`) inside this method will fail with an `AttributeError`. | ||
# We guard against that here by using `getattr` to retrieve the value | ||
# of the `action` field. | ||
if getattr(self, 'action', None) == 'retrieve': |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The duplication of the hacky fix & its explanation comment make me double down on my question in instance/api/instance.py
@@ -45,7 +46,7 @@ | |||
# Keep the secret key used in production secret | |||
SECRET_KEY = env('SECRET_KEY') | |||
|
|||
ALLOWED_HOSTS = env.json('ALLOWED_HOSTS', default='[]') | |||
ALLOWED_HOSTS = json.loads(env.json('ALLOWED_HOSTS', default='[]')) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Isn't env.json()
already supposed to deserialize the variable string?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@antoviaque You'd think that it would, and the docs are terse; but I double-checked this in the shell and found that it does indeed return a string:
In [9]: import environ
In [11]: env = environ.Env()
In [12]: bar = env.json('BAR', default='[]')
In [13]: bar
Out[13]: '[]'
In [14]: type(bar)
Out[14]: str
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It returns a string because the default value is a string. Please remove the quotes from the default value, and remove the call to json.loads()
.
85a9426
to
ac9be4f
Compare
Rebased from 85a9426. |
@itsjeyd I've done a first pass over this PR. I'll manually test once the comments are addressed. |
Thanks @smarnach! I'll address your comments later on today (have been working on fixing additional warnings that came up when running commands with |
See #153 for relevant discussions.
@smarnach Thanks for the review! I addressed your comments, please have another look. |
test_migrations_missing: clean | ||
! honcho -e .env.test run ./manage.py makemigrations --dry-run --exit | ||
createdb --encoding utf-8 --template template0 opencraft 2> /dev/null || true |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can this be put in its own create_db
rule, and the rule added as a dependency for test_migrations_missing? Or, better, rather than always get test_migrations_missing
to execute it, add make create_db
just for circleci in
Line 15 in 8572619
pre: |
# (via `self.action`) inside this method will fail with an `AttributeError`. | ||
# We guard against that here by using `getattr` to retrieve the value | ||
# of the `action` field. | ||
if getattr(self, 'action', None) == 'retrieve': | ||
suffix = "Details" | ||
return "Instance {}".format(suffix) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
+1 for the solution - thanks!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for the changes! One last remark for the DB creation for CircleCI in the Makefile, but all good on my side once this is addressed.
…tion. The PR containing the commit that we were referencing (mfogel/django-simple-email-confirmation#14) was closed, but the latest upstream version contains commits that implement Django 1.8+ compatibility.
They were failing with "TypeError: the JSON object must be str, not 'bytes'".
They were failing with "TypeError: 'Connection' object is not callable".
Fixes error keeping `make shell` from successfully starting up a shell.
`test_get_view_name` tests for `InstanceViewSet` and `OpenEdXAppServerViewSet` were failing with AttributeError: 'ViewSet' object has no attribute 'action'.
…owedHost exception. We didn't run into this problem before when running the development server because up until Django 1.10.3, ALLOWED_HOSTS wasn't checked at all if DEBUG=True (cf. https://docs.djangoproject.com/en/1.10/ref/settings/#allowed-hosts). Now, the host is validated against ['localhost', '127.0.0.1', '[::1]'] if DEBUG=True *and* ALLOWED_HOSTS is an empty list.
Set PyYAML, selenium, Werkzeug dependencies to most recent versions required by Jasmine.
Was failing with "django.db.utils.OperationalError: FATAL: database "opencraft" does not exist" on CircleCI. Target now creates default database if it does not exist.
…PYTHONWARNINGS=all.
From https://docs.djangoproject.com/en/1.10/releases/1.10/#features-removed-in-1-10: "Session verification is enabled regardless of whether or not 'django.contrib.auth.middleware.SessionAuthenticationMiddleware' is in MIDDLEWARE_CLASSES. SessionAuthenticationMiddleware no longer has any purpose and can be removed from MIDDLEWARE_CLASSES. It's kept as a stub until Django 2.0 as a courtesy for users who don’t read this note."
… DisallowedHost exception.
See #153 for relevant discussions.
f147b8e
to
79c0ebf
Compare
cfa640b
to
7e75b24
Compare
@itsjeyd @antoviaque I've looked into the database creation issue. CircleCI should figure out what database to create from the DATABASE_URL environment variable. This seems to be still working, since the unit tests, which also use the database, are passing fine before the test_migrations_missing target fails. I'm currently looking into alternative solutions for this problem, but will go for the change Xavier suggested if I can't come up with anything cleaner. I also noticed that we still have a TODO in the Vagrantfile to use the official Ubuntu image. I think we should address this TODO as part of this PR, and I started working on it. |
@smarnach As far as I can tell the official Ubuntu image is still broken - at least Ned was having issues with it last week (cf the ops channel). Imho this is outside the scope of this issue, I'd rather just make sure this doesn't spillover. |
@antoviaque OK, fine with me. I've already taken a quick look, and it doesn't seem to be straight-forward to switch to the official image, so I'll just leave it as it is. |
2c8c3b0
to
c37da1c
Compare
579fa80
to
c33a45e
Compare
Actually, |
I couldn't figure out why the database is working for the unit tests, but not working for testing for missing migrations. I tried several approaches, but the only thing that works is what Xavier suggested. The build is green now, and the only change I made was addressing Xavier's comment, so I'm merging this PR now. |
cf. OC-2024
Notes
I could not update PyYAML, selenium, and Werkzeug to the most recent versions available, since Jasmine currently still depends on slightly older versions.
Do not ignore overridden View.get_view_name() in breadcrumbs encode/django-rest-framework#3273 changed the way breadcrumbs are generated for browsable API pages: Before, DRT would call a generic
get_view_name
function to obtain view names to use for individual breadcrumbs. That function only uses information that it can obtain from the view class, and does not depend on theaction
attribute being set on the view. Now, the code that generates breadcrumbs instantiates a view based on the view class and calls the (overridden)get_view_name
function on it. This broke a couple of tests for the instance and app server APIs (OpenEdXInstanceAPITestCase.test_view_name
andOpenEdXAppServerAPITestCase.test_view_name
), because our custom implementations ofget_view_name
(InstanceViewSet.get_view_name
andOpenEdXAppServerViewSet.get_view_name
) depended on theaction
attribute being set. DRT will only set the.action
attribute on a view in the context of a request, so when the breadcrumbs code calledget_view_name
on a newly instantiatedInstanceViewSet
orOpenEdXAppServerViewSet
, that call would fail withAttributeError: 'ViewSet' object has no attribute 'action'.
.faa6214 fixes this issue by using
getattr
to retrieve the value of theaction
field, allowing the breadcrumbs code to finish successfully. However, a small problem remains: When generating breadcrumbs using the new method, DRT itself can not distinguish between list and detail views of anInstanceViewSet
/OpenEdXAppServerViewSet
(sincesuffix
isNone
). This results in breadcrumbs being displayed ason the details page of an instance. On
master
(which uses an older version of DRT that precedes Do not ignore overridden View.get_view_name() in breadcrumbs encode/django-rest-framework#3273) we instead got:It's possible that I'm missing something, but given that we can only use the value of the
action
attribute to determine an appropriate view name in the context of a request, I'm not sure how we could go about determining an appropriate view name in the context of breadcrumbs generation.There's always the option of sticking with an older version of DRT, or using a custom fork that reverts the changes from Do not ignore overridden View.get_view_name() in breadcrumbs encode/django-rest-framework#3273; but at this point, that would mean using a significantly older version of DRT (3.3.3 vs. 3.5.3), or introducing additional overhead for maintaining a separate fork.
Update: Custom
get_view_name
methods have been removed completely, cf. relevant discussion starting with Update requirements and dependency badge #153 (comment). Keeping this note for future reference.Test instructions
make shell
locally to see that it starts up successfully.DisallowedHost
exception). Note that if you run management commands withPYTHONWARNINGS=all
, you'll still see some warnings, but they concern code installed into the venv; they are not triggered by instance manager code.Reviewers