-
-
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
Build: implement build.commands
override of build commands
#9062
Comments
I just want to be clear here that if we are following the proposal that I've done in #8190 we cannot implement |
Sure, my description is by no means definitive. We just need to capture what you have planned, and communicate that for everyone. Feel free to expand on the description here or make new issues. |
build.commands
override of build commands
One point of feedback that I had here -- and this relates to the metadata.yaml conversation as well -- was that I'm not sure I'd need more control or complexity over our build environment. I used build.jobs to hack up support for Pelican, and really only felt that I needed some concept of a generic backend instead of the sphinx backend. I'm maybe describing a simpler version of A user might have a configuration file like: build:
jobs:
pre_build:
- pelican content
backend:
generic:
output:
html: ./output/ The generic builder doesn't do much of anything, except for perhaps moving files for syncing? To support Pelican, this was all I really found myself wanting. I had to hack up Sphinx to be no-op step, and had to hack up the paths maintained by the Sphinx backend, |
I want to avoid the concept of backends directly integrated with Read the Docs as much as possible. I don't want to integrate these backends in the application and that's why I separated this into these two concepts:
Mixing the two concepts makes it really confusing for the user because this distinction becomes gray. Besides, making the two of them work together will make the integration in our application a lot more complex; which is what I wanted to avoid originally. Your example with the UX that I have in mind (without the application knowing anything about backends) would be: # .readthedocs.yaml
build:
jobs:
commands:
- pip install pelican
- pelican build # metadata.yaml
output:
html: ./output/
|
Yeah, I'm caught up on the plan so far. However, I'm saying our plan might be a bit too rigid at the moment. I see a slightly more defined path with an additional step before implementing build commands. We have discussed build job hooks as a way to provide users with build flexibility, and build command overrides as a way to provide communities with the ability to support the documentation tools they maintain. I still agree with this plan as a long term approach, but think we would benefit greatly from a short term approach too. There is the strong possibility that with I suppose no matter what, the metadata yaml is still required if we accept built tarballs for projects. The UX of combining the build contract file with our configuration file is interesting but a separate conversation. For this use case, I'm not even convinced user configuration of the output files is necessary, but agree we'll want a file at some point. Anyways, until we get build command overrides, users have no ability to support arbitrary documentation tools without heinous hacks to Sphinx. The piece I'm describing above is a generic builder that collects files but does not execute commands. This seems like a technical piece required for build commands overrides either way, so is only complimentary to what we've defined so for for work. With the ability for users to determine the files uploaded to storage, we can fairly immediately support arbitrary tooling. This is also where we have to say "this is experimental and most features probably don't work yet, but give us feedback". My primary concern is this: we have a large number of unanswered questions about support for arbitrary tooling and need some way to ease in. Without some middle step, it seems we have to take a huge gamble all at once:
That's a big gamble and a lot of work. If we expand the generic builder a little in a middle step, and make it possible to support build file collection with a generic builder class, the steps then become:
A generic build class can start off without configuration even -- we can dictate to the user what hard coded files we copy. The only major difference in the plan seems to be the ability to opt in to a non-sphinx/mkdocs build class in our configuration. Even if we mark this as experimental, at least we have the ability to ease into a world where we support output besides mkdocs/sphinx. |
Can we break this out to an issue finally? That chain of design docs is overwhelming. edit: I've made a TBD placeholder at #9088 |
Setting this as need more information as we're not sure if/what we need. Still on the backlog though. .. Dammit no response bot. Whatever, design decision. |
Honestly, I don't like the idea of implementing a hybrid or something "in between" I originally proposed
Here you are basically describing Also, note the implementation of this specific use case of Besides, as we are not too good at deprecating things, and we finally keep maintaining it forever, I'd prefer to not implement something "in between", as I said before. By implementing this basic As an example, your use case will be just: build:
os: ubuntu-22.04
commands:
- pip install pelican
- pelican build
# in case pelican does not output files in the hardcoded ./output/ directory Read the Docs expects
- mv ./pelican-custom-output-folder/ ./output/ The resulting |
It seems like we can still do HTML parsing of the output folder, without any additional configuration information? For example, we could fail the build if the HTML doesn't have an I tend to agree with Manuel that I don't see a lot of value in the It feels like we're mostly having a conversation around convention or configuration:
I think both are fine. I think implementing I would argue though that we're getting ahead of ourselves, and I'd like to put this conversation on hold for 1-2 months, as we learn more about what people are doing with |
Let me rephrase this, because I'm not trying to focus on the config file, and it seems most of this discussion is on that piece. I understand what we've proposed for But the important part of my point above is that we also don't yet know if So, I was describing an alternate order of operations. Get a feature to support build tools in front of users early, even in experimental state, and see what users do with it. I think experiments are really important here, given the complexity of the change we're describing. After that, we definitely need first class support for generic HTML output, we definitely need a build contract file eventually, but The piece I was describing was a generic builder. Maybe it has configuration, but that is a secondary conversation. The builder backend:
This is the step that I'm talking about changing. We implement what would eventually be the generic builder that There is one extraneous piece required to get this going though, and that is a way to opt into the generic builder. I described this as
It seems to me we need a generic builder either way, thinking through the technical changes. I doesn't seem like you're proposing reusing the Sphinx/Mkdocs builder class for |
Also, it's worth considering that we have some dependent steps.
So the order of operations seems it should really be something closer to:
And most explicitly, I'm talking about taking on the first step in our short term roadmap and still pausing for a bit. We need time to accumulate information, and getting a feature in front of users and seeing what build tools are actually used is important data. Perhaps the compromise is implementing
I was originally describing configuration, but convention indeed seems like a better option for at least what I'm describing. I'm happy to also discuss that more in #9088 as an option. |
Anyways, I think we'd benefit from a follow up meeting here, and I've voiced that we'd benefit from closing up the open design doc PRs on this topic. The state of this work is a bit difficult to track as our plans mostly haven't made it out of draft PRs and meeting notes. Some of the unknowns, and things we haven't settled on, for the project that I have are:
Suppose there are more here, feel free to append. |
Strong 👍 on a meeting, as it feels like we're talking past each other a decent bit. I think we're all mostly agreeing, and just proposing different ways to get to similar outcomes. |
Yup, I'm not comparing outcomes here, they are the same effective outcome to the user. I'm only describing a difference in time frame, effort we spend, and when we take work on. We haven't talked about this, among other topics, in our planning and I think it's worth discussing. |
I'm 👍🏼 on a meeting. I do see the path to move forward pretty clear regarding That said, I wrote some comments that may help to explain a little more my position on this. Here they are,
This could be a good initial compromise that it's compatible with the path forward we already have in mind for the contract. I'm not opposed to it. However, this requires a little more work than without this initial integration as Anthony was suggesting which could give us a pretty quick experimental POC.
This makes sense to me.
I'd like to see this happening but without introducing a new concept like "backends", and if we can implement it as the first step of
This is exactly what I described in my previous comment. You can get exactly what you want using my proposed solution. There is no need to combine On what I'm describing here, note that by using
Right. I'm not proposing reusing the Sphinx/Mkdocs builder classes for
In the next iteration, once we have the contract defined, Read the Docs will parse the HTML output generated by the commands defined by the user and integrate that output with our features. |
I understand your points, but a meeting does probably help the most here. I know the plan so far, how the plan intended to solve this, and understand the conversations we already have had around this implementation. And to clarify, I'm not questioning the original design. I'm describing adding more granularity to our plan, and breaking out earlier implementation of the backend builder class it seems we're both describing. We aren't sure if we need I proposed exposing this via
It seems we're talking about the same piece then, a builder class to avoid sphinx/mkdoc command execution, but still collect files post-build. I'm just describing exposing this to users via |
This works for me. We can implement a simple initial version of This approach will quickly give us a good understanding of what people want, how they are using this to build docs with currently unsupported tools, etc. This data will help us to build better integrations with them and create a contract that supports them all in the future.
This is my main concern, here. I'm -1 on exposing this via
This vision, to me, has some good benefits by making a clear distinction between each of them. The user is able to immediately understand what's the solution that fits best for their own use case depending on how they build their docs. Also, this separation gives Read the Docs team the liberty to work on better support on "regular builder" without mixing any type of compatibility with "custom builder". It's also easier to communicate that "Read the Docs can't be responsible for any command executed at We could "allow people to override default commands via As I said before, this separation also helps us to see "regular builder" as the current product that integrates everything and has been working for +10 years, and "custom builder" as a new product where we can have some freedom to experiment with without breaking our main, well-tested, and successful product. Footnotes
|
I love this overview of the builders, and this is something we need to explain in our docs in some way to users. It's a great way to help users understand which of our "builder products" they want. |
We covered a few of these points in our meeting today. To summarize: Use casesWe have several project profile use cases we're actually talking about here. To build on the point above about our builder classes, those project profiles are:
Our goalsOur first goal is to enable experimental support for build.commands to unlock this usage for users. However, this is under the user contract that using this feature breaks a lot of RTD features. We'll use this period to see what users need or want, and see what users actually do with the feature. We'll use this to guide our plan for future work. Our next goal after this is to work towards first class support of HTML parsing and injection. We'll chip away here, as there is a lot of re-engineering work here -- search indexing, API injection, ads injection. Other notes
|
The intial phase of this issue is already implemented in #9150
We are ready to review it and I think it could be deployed soon as well. I think it covers our main goals for exploration and it could give us the feedback we need while keep discussing the other aspects of the more polished feature. |
I just wanted to mention that I'd rather use NGINX or build time for this because using Cloudflare to inject them will make local development not work. Also, at first sight, it seems better to inject them at build time over NGINX because that's what we have been doing for years and we know it works already. Using NGINX may bring a problem with the versions of those files: how do we distinguish between a new build that needs the newer version of the js and an old project that was built 5 years ago and requires the js from that date? |
Just noting that local development of Cloudflare workers is possible: https://developers.cloudflare.com/workers/learning/debugging-workers/ I'd also vote against Nginx, we have been moving logic out of Nginx for a while now. Build time injection does make sense so far though, and is sort of a way of versioning the injection. But a dynamic injection option does also leave some doors open for us to force changes without rebuilding the versions, if there are strong reasons to do this. |
In #8190 we started discussing a path forward for making our build processes more flexible for users.
The first addition to our build process is #9016, which allows for pre/post build step command execution that is configurable by the user. The
build.jobs
addition should support many more use cases for projects already. That is, projects could execute a command before Read the Docs executessphinx-build
, etc.The concept behind
build.commands
is that projects could override the actual commands we execute with their own commands -- so overridesphinx-build
entirely, not just execute commands before/after. This would be most useful to replacesphinx-build
with a build tool of your choice, however there are a number of implementations that expect Sphinx exclusively that we'd need to change.I'm trying to summarize a chain of several design discussions, but what would be left for this portion of the work is:
build.commands
and it's usageRefs #1083
Requires #9063
The text was updated successfully, but these errors were encountered: