-
-
Notifications
You must be signed in to change notification settings - Fork 3.6k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Serve badges directly from local filesystem #4561
Conversation
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 like this approach, just one question.
readthedocs/projects/views/public.py
Outdated
if version_builds.exists(): | ||
last_build = version_builds[0] | ||
if last_build.success: | ||
file_path = static(badge_path % 'passing') |
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.
Do we still want static(badge_path % 'passing')
here instead of file_path = badge_path % 'passing? I thought we wanted to remove the
static` call?
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.
We definitely want to get rid of the static call.
readthedocs/projects/views/public.py
Outdated
version_builds = version.builds.filter(type='html', | ||
state='finished').order_by('-date') | ||
if version_builds.exists(): | ||
last_build = version_builds[0] |
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.
nitpick: .first()
can be used 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.
I suppose if we are cleaning up the existing code a bit, I might as well clean this up too.
# Unknown project | ||
unknown_project_url = reverse('project_badge', args=['fake-project']) | ||
res = self.client.get(unknown_project_url, {'version': 'latest'}) | ||
self.assertContains(res, 'unknown') |
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.
nitpick: can we add a check here that the Content-Type
header is the correct one, at least in one of these?
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.
Ok
readthedocs/projects/views/public.py
Outdated
else: | ||
file_path = static(badge_path % 'failing') | ||
|
||
with open(file_path) as fd: |
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.
Does it worth here to handle any possible exception when reading the file?
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 don't think that is necessary. If Python can't read a local file, we have big problems.
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.
Looks good, just some nitpicks
readthedocs/projects/views/public.py
Outdated
|
||
if version: | ||
version_builds = version.builds.filter(type='html', | ||
state='finished').order_by('-date') |
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.
This file was previously autolinted and this line reverts some of the autolinting -- you should be able to resolve with a pre-commit
pass.
readthedocs/projects/views/public.py
Outdated
else: | ||
file_path = badge_path % 'failing' | ||
|
||
with open(file_path) as fd: |
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.
Maybe protect with ioerror/oserror catch here? Logic can either return unknown image or at least a 4xx response instead of 5xx.
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 think a 5xx response is correct. Maybe a 503 instead of a 500, but definitely not a 4xx. This is a server error and not a client error.
If we can't read from the local filesystem, we can't return the unknown image except with a redirect. How about a 503 instead?
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 do wonder whether this is even necessary though. We don't protect against failing to read the local filesystem for Django templates. Is this really any different.
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.
ah true, i was considering a 4xx response from the perspective of nginx -- if the permissions were wrong or the files went away, nginx would return the respective 4xx response. agree that 5xx is maybe better for this though.
I think my only concern is to log something helpful, and perhaps avoid our default 5xx page if it makes sense.
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.
Let's do a 503 with some logging. That sounds like a plan.
This solves an issue that arose because the badges need to be explicitly not cached or have a very short cache TTL. When no cache-control headers are present (as on this badge for example), sometimes other intermediaries -- github in this case -- cache it too long. This PR keeps the cache rules and the response together in the code so this problem doesn't arise again like it did previously in #3323.
Similar to #4559 but reads from a local file instead of possibly remote one.
Fixes #4557