Problem/Motivation
In more complex installations, not all files will be stored on a "local" stream wrapper like public://
, but may be network-attached e.g. with Flysystem or another method of providing PHP an additional stream wrapper. At least in the case of Flysystem, these additional stream wrappers are added as read/writable, but are not "local," and so are excluded by rule by CDN. This is largely desirable, since some stream wrappers such as private://
should not be served by CDN as it might bypass access checks. However, if a site builder wishes to use non-local storage for publicly-accessible files, they must currently do a number of overrides of CDN, particularly in FileUrlGenerator.php
.
Proposed resolution
Site builders should be able to select additional stream wrappers for opt-in service by CDN module. The attached patch includes a refactor of the far-future file controller to be schema-aware, as well as changes to cdn_ui and the config schema.
Remaining tasks
By an initial read, the current tests should (?!) pass, since private files are still not served. The README likely needs updating to its sample Apache server config section re: far-future expiration.
User interface changes
The settings form is expanded to include selection of additional stream wrappers.
API changes
The URL signature of the far-future expiration service changes, however sites upgrading should just generate the "new" syntax. This will result in a period of CDN refresh as the edge servers would need to fetch previously-cached files in a new location.
The host-matching logic has also been moved to CdnSettings
so that other modules might determine CDN module's host-mapping. (E.g., I'm using this while implementing cdn_cloudfront_private.
Data model changes
Config schema changes, however since we're adding a new property and not changing any current schema this should not be an issue for existing installs?
Comment | File | Size | Author |
---|---|---|---|
#81 | 2870435-80.patch | 1.46 KB | Wim Leers |
#80 | 2870435-80.patch | 680 bytes | Wim Leers |
#80 | interdiff.txt | 680 bytes | Wim Leers |
#79 | 2870435-79.patch | 1.46 KB | Wim Leers |
#77 | 2870435-78.patch | 1.64 KB | Wim Leers |
Comments
Comment #3
Wim LeersThanks for creating this issue! And thank you especially for providing a complete argumentation, as well as a patch!
My key concern is that this is complicating the CDN module and the CDN UI module for a 1% use case. However, I see that you've already ensured that this only complicates the UI if there are actually additional stream wrappers installed.
public://
stream wrapper. Hence the failures.We can make this more strict:
[a-z]+
Accidental change?
This could use some clarification. I personally definitely don't quite understand this yet :)
Also, why
WRITE_VISIBLE
, why not justVISIBLE
?Let's change this to
stream_wrappers
.By making this list all CDN-enabled stream wrappers, we make the configuration more clear: no more "additional", and instead simply make it a declaration of all CDN-enabled stream wrappers. Much easier to understand.
Let's change this to list all eligible stream wrappers, including
public
. Let's just makepublic
checked by default, and impossible to uncheck.Let's use
:shipped:
, because it's impossible to use colons in actual scheme names.I'm afraid this is an oversimplification… Drupal's Page Cache and Dynamic Page Cache will contain cached responses. But those we could invalidate. What's worse, is that Varnish, company proxies and even Google's cache will contain cached responses too. And they'll be using the "old far future URLs". Which will no longer work. So this will definitely break things.
To work around this, I'd suggest using the existing
cdn.farfuture.download
route for shipped +public://
files. We'll need to introduce a separate route for other stream wrappers. Less elegant, but necessary to not break BC.Comment #4
bradjones1Thanks for the prompt response and awesome code review. I hope we get to meet/share a beer next week in Baltimore.
Re: comments above:
1 - Some of the failures actually appear to be related to #2870903: Fix regex in CdnIntegrationTest.php, others now fixed. (This patch includes those changes from that ticket.)
2 - This is more specific, now.
3 - Actually not accidental, it was duplicate of an identical line in that same code block. Incidental cleanup.
4, 5, 6 - This is revamped. Actually using LOCAL_NORMAL, since it excludes non-public/non-CDN safe things like translations and temporary files.
7 - I actually went with :relative:, since it's more descriptive re: the backwards compatibility.
8 - The new path is
/cdn/ff/...
and the/cdn/farfuture/...
path is rewritten in the incoming parser, with a test added.I'm not exactly sure I did the update hook correctly, but let me know your thoughts. the new config key is essentially for "extra" stream wrappers, since I am enforcing LOCAL_NORMAL wrappers be included by rule, on top of the configured wrappers. So it will start empty and then include a list of the additional wrappers. I could include the "always on" wrappers but it seems a byproduct of them being marked disabled in the UI is that they don't come up as checked. :-) I just didn't want to code in any assumptions about what wrappers are actually available locally, since there is #2724963: Make the public file system an optional configuration and #2514644: File inclusion weakness in stream wrappers, and StreamWrapperInterface composite constants are not clearly documented or tested for correctness that I'd like to see move forward to help with Drupal web heads not tied to local storage.
Didn't include an interdiff since there's more new than existing here. Thanks again.
Comment #6
bradjones1Pesky annotation.
Comment #7
bradjones1Comment #8
Wim LeersThere's no interdiff for #4 or #6. Here's one. For the next time, please see https://www.drupal.org/documentation/git/interdiff :)
It's pretty much essential in order for me to give feedback on changes since the last review!
Comment #9
Wim LeersAnd of course I then fail to post the correct interdiff :) Here's the right one!
Comment #10
Wim LeersFirst round of review. The more simpler/more obvious things.
There's no need for this if-test. Because new installations will have this new key, and only existing installations will run this update hook.
Therefore you can simplify this. See e.g.
\statistics_update_8002()
.This should not set
[]
as the default, but['public']
.If you're going to rewrite the incoming path (CLEVER!), then why even rename the route?
The new route name makes less sense IMO.
I'm not sure what the portion before the pipe is doing? Can you add a comment here?
I don't like that this class is now no longer just a "configuration interpreter". I'm curious to see why you chose to do this.
I think we should still deny access if no custom stream wrappers were installed. I.e. if only
public
is shown, then let's not expose this at all.To quote myself from #3:
That's no longer true in #6.
This is not true.
private://
is alsoLOCAL_NORMAL
, yet the CDN module is not enabled for it.Ahh, this is injecting the stream wrapper manager service so that the return value here can be dynamically computed!
If you set the default value to
['public']
, that'd be a non-issue.Oh wait, what?! This was in the wrong place before!? Great catch. I guess it was passing simply because the expected key did not exist in the expected place then.
Changing this is a lie?
private://
isLOCAL_NORMAL
too! See\Drupal\Core\StreamWrapper\PrivateStream::getType()
.Making it actually declarative, and defaulting to
['public']
solves this.update.php
, I'm seeing error messages. See attached screenshot. They do disappear after applying the updates. But that's of course less than ideal. Let's remember to fix that, hopefully the changes made because of my reviews will cause them to disappear without extra effort :) (Though I'm not at all sure that will be the case, I just want to avoid that you spend lots of time on this in vain!)Comment #11
Wim LeersHah, clever!
However, you've replaced the
strpos()
in the critical path with apreg_match()
in the critical path.Remember, inbound path processors run on every request! So this is not ideal.
I suggest you do the following:
That replaces it by two
strpos()
checks, which is simpler to understand, simpler to maintain and should be faster.Hrm… does this actually even make sense?
What if you're using Flysystem to store files on S3? Then this would cause the file to be downloaded from S3 to Drupal, and then be served via Symfony's
BinaryFileResponse
, which will then send it again.In such scenarios, it'd be far better to just point your origin pull CDN at your S3 domain, and then use those URLs instead…
This calls into question the entire point of this issue I'm afraid…
Did you consider this? What are your thoughts around this?
Comment #12
bradjones1Working on your technical feedback (thanks again) but to your last comment:
In short, yes, there is good reason to wrap Flysystem in CDN. S3 is only one of many storage backends supported by Flysystem, and not all of them work like S3. For instance, a Swift backend might not have a publicly-accessible URL, or we don't want to use it because it's not geo-balanced like our CDN. Or, I have a module that generates CloudFront URLs with signed cookies/query strings to leverage CDN+authz. In that case, you need Drupal to act effectively as an HTTP proxy in front of the storage providing middleware for the CDN. The point of using the CDN in this case is to of course bring the objects closer to the client while minimizing the reads from the Flysystem backend. So while this does mean piping the file through Drupal, we're doing so way less often than without the CDN.
One case where this isn't as efficient is with image styles, since CDN will initially refuse to rewrite the URL, but I think with some minimal effort you could write a hook to generate the file so it exists the first time CDN tries to get the file from Flysystem.
Does that help make the case a little better?
Comment #13
Wim LeersTurns out we had a similar discussion/issue at #1863310: CDN module should know how to deal with custom stream wrappers.
Drupal acting as a HTTP proxy will not work well: Drupal was not designed for that.
True for anonymously available content, but not for signed requests…
Yes and no. The anon use case might make sense, but the auth one definitely does not. You mention both. Can you elaborate a bit on your concrete use case?
Comment #14
Wim LeersPinged @bradjones1 on Twitter: https://twitter.com/wimleers/status/863081189690757120.
Comment #15
bradjones1Wim, thanks for the nudge. Been busy on a few projects but this is still on my radar. Hoped to talk to you at DrupalCon but... next time!
I think we're largely on the same page but the setup I propose and am using re: CDN and authenticated content doesn't require Drupal to serve the content directly, every time it's requested. In the case of CloudFront, you can use CDN along with a helper module (e.g., the one I've linked to sign CloudFront URLs) to bring the CDN hit rate to parity with non-authenticated content.
While it's not ideal to have Drupal serving files via PHP, it's been part of Drupal for a long time vis-a-vis "private" files, and modules like Flysystem have no option but to pipe the file through. You can, however, configure a CDN to limit access to certain files by signed cookie or URL, and then limit Drupal's serving of those paths to only the CDN by checking a special header, for instance. In other words, access to the file available on the CDN is controlled at the time of issuance for the signed cookie or URL, not at the time of file request.
Does that help explain the use case? I don't think CDN is the right module to put *all* this logic, but supporting additional stream wrappers and exposing some of the settings and other internal bits to reading by other configuration makes it rather trivial to generate CDN URLs and then sign them for use with a CDN that supports it.
Comment #16
bradjones1@wim - Ping re: your thoughts on above? Thanks.
Comment #17
bradjones1Rerolled.
Comment #18
Wim LeersDamn. This time I definitely dropped the ball. I'm very sorry for the long delay, Brad!
I first interpreted
as meaning "authentication between end user and the external file storage", but it sounds like it's really "authentication between Drupal and the external file storage". Meaning that all those files are safe to serve to anonymous users. That changes things of course.The more I read about this, the more I realized this is primarily about supporting https://www.drupal.org/project/flysystem. So I started looking at Flysystem's source code. That's where the
WRITE_VISIBLE
came from: from\Drupal\flysystem\FlysystemBridge::getType()
. What I see makes sense.This makes sense.
Conclusion
You convinced me. Let's do this.
I have a few hard requirements, to ensure the CDN module remains both stable and low-maintenance (because I'll be the one supporting this new feature in the future!):
public
andprivate
are installed (this used to be the case in the patch, but is currently broken)public
as a checkbox, but it must always be checked and always disabled (already the case)VISIBLE
) or notI think these are reasonable — and I'll help you get this patch to that point :)
Next steps
The current patch has
258 insertions, 81 deletions
as its diffstat. But quite a bit of this is due to refactoring. I'll already do some refactoring to make the patch simpler to review. Stay tuned.Comment #19
Wim LeersCreated #2891162: Refactor: extract logic from FileUrlGenerator::generate() into a new ::getCdnDomain() method to allow this patch to become simpler.
Comment #20
Wim LeersThings that stand out in the current patch:
Why this change?
This should be hidden unless there are non-default wrappers installed that are eligible for configuration here.
That's not actually true, only
public
is enabled by default.I think this should be:
Why is this app root suddenly needed? It's been working fine without that. So I'm confused. This seems an unrelated/out-of-scope change?
Why is this returning streamwrapper instances, rather than just streamwrapper schemes?
Should use
strpos()
, like I said before. This is in the critical path, so we can't regress performance here.This makes the code unnecessarily hard to read (and maintain).
Rather than an if/else, it'd be better to have multiple methods.
Also, it'd be great if any code that is there for BC would be in a separate method that can simply be deleted altogether (along with its invocation that will need to be deleted). That will make removing BC layers in the future much, much easier :)
Comment #21
Wim LeersI just realized something.
It looks like you've designed this to work with the
("Far Future") functionality enabled. That's fine. But it means that you're making one important assumption: that everybody has this enabled. If they don't have it enabled, there are severe consequences:public://
files, but also files stored in anything that Flysystem supports (thanks to Drupal just downloading the file from Flysystem and then serving it). But end users may not realize that this is the case, decide to turn of , and things would break horribly.What are your thoughts on this? My only thought about how this could be prevented is that the Flysystem module could provide a config override that ensures that
cannot be disabled.Comment #22
bradjones1Better late than never...Here's a re-roll to bring the above patch in #17 up with the latest -dev, next is to incorporate and respond to your feedback since then.
Comment #23
Wim Leers❤️ — looking forward to your feedback! I'm planning to tag a new release soon, so let's get this done (either committed, or agree that it's not a good match after all).
Comment #24
bradjones1So lots of feedback to cover, I'll start with #21 since it's more general:
I actually don't think that's necessarily true. E.g. for stream wrappers provided by a Flysystem implementation, the CDN domain just sits in front of Drupal like the other stream wrappers, because the URL the wrapper generates is something like
/_flysystem/wrapper/file
. I suppose it's possible that a different stream wrapper implementation would generate absolute URLs, however those I don't believe would be rewritten by CDN in the first place. It does raise the question of whether that makes checking the box for CDN treatment a false choice, but this whole thing is an advanced operation so in that case I think it's safe to assume the developer knows what he's doing. And CDN wouldn't necessarily know if the stream wrapper is going to generate absolute or relative URLs out of the box, so we can't exclude them from the checkbox options on that basis.Turning off forever cacheable files in my testing, at least with Flysystem, results in a "normally" rewritten CDN URL.
That said, I don't think there's any real to-do out of this point.
To your code review:
#access
testInstead of an interdiff you can just see and comment on my Pull Request at https://github.com/bradjones1/cdn/pull/1 - I've just included the master patch here.
Comment #25
bradjones1Comment #26
bradjones1Working further on the question of the URLs generated by stream wrappers, it's actually more likely than I implied earlier that the URL generated by, say, a flysystem plugin would be external. E.g., S3. However the point remains, if the URL that CDN sees is external, it wouldn't be rewritten. So this is probably best tested with a stream wrapper that returns a URL based on the site URL, e.g., Flysystem's Local plugin.
Comment #27
bradjones1A few tweaks to far-future security tokens per my local testing, commit at https://github.com/bradjones1/cdn/pull/1/commits/98bedbd676ee2457afbf363... and attaching new full patch.
Comment #31
bradjones1OK, this needed a lot more love but I'm pretty happy with where this ended up. Should be passing tests (it is locally) and code style fixes are made.
I would like your feedback on the approach I had to take with the far-future URL generation test; I actually ended up using the file:// stream wrapper since it's supported by PHP natively and, in a weird way, actually helps prove that this works with stream wrappers generally, not just the ones that ship from Drupal. I know you had to do some mocking of the stream wrapper manager, etc. in the unit test already, so if that's too cute, let me know what you'd rather do.
As per above, you can slice the interdiff at the Github PR's commit history if you like, and a full patch is attached.
Comment #32
bradjones1Additional test coverage.
Comment #33
bradjones1Related ticket that will need created if/when this merges: Allow CDN host selection to be mapped by stream wrapper. This is kind of blocked by the complexity in
CdnSettings::getLookupTable()
which has a@todo
to abstract.Comment #34
Wim Leers#24:
I did not realize that. Interesting! That means the CDN module would also have an effect even without
turned on.This is definitely not just possible, but a reality. And yes, in those cases, the CDN module would not rewrite those URLs, and that's exactly my point in #21: if you'd enable the CDN module for a stream wrapper with its own absolute HTTP URLs (which I think is the majority use case, Flysystem is the exception AFAICT), then it really has no effect at all, which is the misleading thing I'm concerned about!
That is indeed a "false choice" (a choice/setting without consequences). I don't think you can necessarily make this assumption. There were plenty of support requests about confusing things in the CDN module and its UI in the past, and that's something I intentionally fixed in the D8 port: https://wimleers.com/article/simplicity-maintainability-cdn-module-drupal-8.
#26:
Thanks for double-checking that. So then my concern definitely still stands.
I've explained why this is still a problem: it doesn't make sense for the user's mental model: it'd be a setting without any effect.
#32:
Do you mean different CDN domain per Drupal site/domain/host in a multi-site setup?
Comment #35
bradjones1Thanks for the review, Wim. If I'm understanding you correctly, the main item remaining here is managing UX on the enabling of additional stream wrappers that might result in an external URL?
What's your maintainerly preference then on how to properly handle that? My initial thought is that we could land on some quick test to apply to the stream wrappers before displaying them, and then append a warning of some sort?
Comment #36
bradjones1Updated per Wim's feedback at the Drupalcon sprints.
Comment #38
bradjones1substr() needs new target length for revised test stream wrapper.
Comment #40
bradjones1So while using cdn-module-test:// as the test stream wrapper in the unit test, it turns out I used file:// for a reason, which is revealed by the test failures; I have added the following comment block to explain:
The configuration UI changes we discussed on Friday remain, though.
Comment #41
Wim LeersSorry for taking longer than I'd hoped!
Unfortunately, that's also largely because there was quite a lot of work left to be done.
settings.php
additions.An easier way to test this is by installing the
file_test
module in core.update.php
. Along the lines of:Fixes:
DbUpdateController.php
actually no longer defines theMAINTENANCE_MODE
constant, sodoesn't actually work. IMHO this is a bug in core, but for now the CDN module will have to detect this.
cdn_update_8002()
doesn't actually install the default settings that the updatedcdn.settings.yml
contains.I already pointed this out in #10.1 and #10.2, more than a year ago… Fixed now.
file_test
module, which registers thedummy
,dummy-remote
anddummy-readonly
stream wrappers. This causes the tab to show up! 👍Unfortunately, it automatically checks the
dummy-remote
stream wrapper's checkbox, despite that not actually being enabled in configuration:This is not acceptable.
private
file system is installed, that's also listed (fine), disabled (fine), but also checked (VERY BAD!):CdnSettingsForm
. I ended up digging intoflysystem
again and in doing so found thatfrom #24 was not quite the whole story.
\Drupal\flysystem\FlysystemBridge
specifiesWRITE_VISIBLE
. That excludes theLOCAL
bit, because Flysystem can include remote data. It just happens to be that the flysystem setup you're using uses\Drupal\flysystem\Flysystem\Local
or\Drupal\flysystem\Flysystem\Ftp
.Of course, the blame hardly lies with you, but rather with both the Drupal stream wrapper system for being so confusing and especially the
flysystem
Drupal module and PHP library.Fortunately, the "check external URL" heuristic we discussed at DrupalCon seems to do the trick. Still, I'd like to see this confirmed by somebody with e.g.
flysystem
+ S3 buckets.public://
stream wrapper is always being removed 😨the reason to have the stream wrapper manager service injected into
CdnSettings
.I'm honestly a bit disappointed. You didn't actually test this patch as thoroughly as I previously had the impression. But I know that A) contributing is hard, B) contributing when stream wrappers is triply so! So I understand. Please review my reroll!
Finally, another patch review, for the files I touched above:
This is brittle, and also not quite right, at least not anymore. Now that the magic is gone (no more automatic whitelisting of all
LOCAL_NORMAL
stream wrappers), this logic needs to be updated. It needs to show this new vertical tab whenever there are any visible stream wrappers besides the ones in core.This is redundant.
Not by rule, but by default. Users who use just the module and not the UI are free to override this.
This is ambiguous. "CDN-enabled stream wrappers" is clearer.
Let's be more specific.
And that's just the UI + config + config schema + update path portions. I have not yet started reviewing or testing the functional changes in
FileUrlGenerator
.Now the UI looks like this (with
file_test
+flysystem
with two FTP adapters):Comment #42
Wim Leersd.o removed one file…
Comment #43
Wim LeersReverted the
phpcs.xml
changes, which are most definitely unwanted.These changes theoretically belong in a separate issue:
Comment #44
Wim LeersHigh-level review of the remainder:
Ideally these changes could be made simpler.
Ideally this could be made simpler.
Ideally we wouldn't need something like this.
The changes here are fairly complex. Tried to simplify.
This looks good.
This looks good.
This looks questionable. Should probably install the
file_test
module and use that module's stream wrappers?Also, overall, test coverage here seems superficial; it doesn't cover the test case of #18.4 for example AFAICT.
I'll try to post a detailed comment plus patch reroll later today.
Comment #45
Wim LeersFixed the first portion of what I called out in #43 as belonging in a separate issue in #2969048: Core's DbUpdateController does not define MAINTENANCE_MODE, causes CDN module to run even for update.php, and added test coverage there.
Comment #46
Wim LeersWhile working on this yesterday, I started thinking that this was too brittle:
What if instead, we could move this into validation constraints?
Well, we can, but it's new territory, despite Drupal 8 clearly being headed there.
So I decided to make the CDN module pave the path: #2969065: Use typed config validation constraints for validation of cdn.settings simple config.
That'd also make it much easier to write the necessary tests!
Comment #47
Wim LeersAlso, we discussed this at DrupalCon: this is the sort of major new feature that warrants a new major version. Which means … we only need to care about an update path, we don't need to care about BC layers. Which means that all the update path complexity could go away!
Before this can go in, we'll also need to investigate how the CDN module can support uses cases such as https://www.drupal.org/project/cdn_cloudfront_private. Any insight into that would be most appreciated.
Comment #48
bradjones1Re-roll
Comment #49
bradjones1Wim - this is a re-roll that requires #2969065: Use typed config validation constraints for validation of cdn.settings simple config - so I assume this will fail on its own. How do you want to handle that?
Comment #51
bradjones1Need more coffee. The above re-roll inadvertantly included changes from the other ticket. Trying again. Sprinting at DrupalCamp Colorado 2018 on this.
Comment #52
bradjones1So I think there's a bit of chicken-and-egg situation when trying to apply both the validation patch and this one; treat #50 as the re-rolled version of just this patch in #43, and the attached is a combined patch that includes this ticket plus the validation constraint code.
Comment #54
Wim LeersCommitted #2969065: Use typed config validation constraints for validation of cdn.settings simple config :)
Comment #55
Wim LeersRebased.
Comment #57
Wim LeersPair-programmed with @bradjones1 at DrupalCon Seattle to fix the current test failures 🥳
Comment #58
Wim LeersFixed the UI problems.
Only remaining thing: the validation constraint. Can follow the example set by #2969065: Use typed config validation constraints for validation of cdn.settings simple config :)
Comment #59
bradjones1Adding constraint validation and tests for same. Prompting testbot.
Comment #61
bradjones1Moving test into the Kernel directory and simplifying validation logic.
Comment #62
bradjones1Wim - dare I say this is good for your final review? I think I had to do the kernel test to get the modules loaded to provide the test wrappers, but other than that mostly a copy of your logic from the initial settings validation work.
Attached is an interdiff for -61 against our work at drupalcon.
Comment #63
bradjones1In continuing to use this locally I noticed a bit of a UI edge case, which should be covered by the enclosed updated patch; the private stream wrapper is not always enabled.
Comment #64
Wim LeersI was flying during comments #59 through #62, and sleeping for comment #63 :D
I promise I'll follow up here in the next few days.
Comment #65
Wim Leers\Drupal\cdn\Plugin\Validation\Constraint\CdnStreamWrapperConstraintValidator
into avalidator.constraint_validator
-tagged service to avoid service location and instead use service injection, but … Drupal core does not (yet?) use\Symfony\Component\Validator\DependencyInjection\AddConstraintValidatorsPass
in its container compilation process and hence that does not work. So leaving it as-is.Let's see if this passes all CS standards tests. If it does, I'll commit this!
Comment #66
Wim Leers2 remaining coding standards violations. Will fix those on commit. Will commit tomorrow, at a family gathering right now :)
Thanks so much for your willingness and patience to do things right, Brad! 🙏 👏
Comment #67
Wim LeersComment #68
Wim LeersI wanted to commit this just before going to sleep … and then in a final review of the entire patch I found lots more nits. 😓 Past midnight now, so not finishing this now.
This is what I found & fixed so far. All nits! Nothing more. But I want to get those done prior to commit. Just bear with me a little longer!
Comment #69
Wim LeersMore nits fixed:
fooBar
->foo_bar
@returns
->@return
(was already a problem in HEAD, not this patch's fault)Comment #70
Wim LeersAnd finally, changed some bits wrt
rawurldecode()
and naming that I found confusing. It's important that it makes sense to me, because I'll be maintaining this for years to come :)It's now more similar to the old code, both in variable naming and execution sequence.
Comment #71
Wim LeersI screwed up a
@deprecated
annotation in #69.Also … we should update the CDN UI tour! We completely forgot about that :)
It's pretty clear at this point that this is a major new feature for the CDN module, so updating issue metadata to reflect that.
Finally, I'd like one final manual test from @bradjones1 to ensure that my changes didn't break anything for him :)
Comment #72
bradjones1Nothing like testing 30k feet above the Pacific Ocean... LGTM on manual test - Let's do this!
Comment #73
Wim Leers🥳 Nice! 😃
I noticed yet one more thing we hadn't done yet (man, the list of best practices is looooong isn't it?): an update path test. Done.
When this comes back green in ~5 minutes, I'll finally commit it 💪
Comment #75
Wim Leers🚢
Comment #76
bradjones1Awesome! I take it you're tagging 3.3 along with this?
Comment #77
Wim LeersChange record created: https://www.drupal.org/node/3051642
Despite tests passing here (in #73), in automated testing I'm seeing 4 coding standards violations: https://www.drupal.org/pift-ci-job/1274957:
The attached patch should fix that. Except that there's a bug in
drupal/coder
, that will cause this to fail until A) the fix (#3050166: Contrib project version is not correctly matched in @deprecated tag) ships in a release, B) d.o updates to that release.Comment #78
Wim LeersThe remaining failures are indeed caused by #3050166: Contrib project version is not correctly matched in @deprecated tag.
Comment #79
Wim LeersTalked to
@deprecated
experts:Comment #80
Wim LeersD'oh.
Comment #81
Wim LeersComment #83
Wim Leers#76:
#77 introduced a last delay, but here we finally are: https://www.drupal.org/project/cdn/releases/8.x-3.3 😃
Comment #86
Wim LeersWe missed one detail here: #3065145: Follow-up for #2870435: Deprecated apache configuration provided in README.txt.
Comment #87
Wim LeersAnd one more detail: #3063498: Do not validate configuration while syncing (support installing from existing config.).