mkdocs
mkdocs copied to clipboard
Support multiple versions of docs.
I'd like to be able to host different docs for different versions of my code. I know there are services like ReadTheDocs that handle this for you, but it would be nice to be able to deploy all the versions to GitHub instead. This would make the gh-deploy script a bit more complex (and there'd need to be some way of switching versions when browsing), but I think it would be generally useful.
Maybe there's an argument to be made that GitHub Pages are for hosting the in-development version of your docs, and places like ReadTheDocs are for released versions; I'm not sure. My instinct is that all the versions of the docs should be hosted in the same place, though.
Any thoughts about this?
Yeah feature for the roadmap, absolutely.
Not sure if this really will actually have anything specifically to do with gh-deploy, but one way or another we'll want to support versioned docs at some point.
The thing I like about gh-deploy is that it's easy to use, and I don't have to think about uploading anything myself. As long as the interface is roughly similar, I'm happy.
I can't really imagine what this would look like. Any ideas?
The only thing I can think of is doing something like iterating through git tags and building the docs for each version into a subdirectory.
I was just thinking that gh-deploy (or whatever) would deploy docs for the current version (as specified by some variable in mkdocs.yml). Then all you'd need would be a file somewhere on the webserver with a list of all the deployed versions, and possibly which version should be shown by default.
Retitling ticket slightly. Milestoning this as 1.1.0 for now, as it's clearly something we want on the roadmap, but I wouldn't necessarily see it blocking what we'd consider a fully functional, stable, well docced 1.0 release.
FYI, you can get this already by hosting at readthedocs.org. They do a build for each branch that you want and provide cross-build navigation.
Update: I never got this to work right. Would be nice to get this in mkdocs.
I've started making a tool that makes this possible. It is a very rough and early alpha, but it is a good start. I just need to add a version switcher ala ReadTheDocs or the django docs and it should work well.
It is somewhat opinionated, as it assumes you want to build all tags and that you are using git. This is why I am building it externally for now, this could be changed but I didn't want to get blocked from experimentation.
http://d0ugal.github.io/mkdocs-versioned/
@d0ugal Sounds neat!
I agree with @d0ugal and think that the versioning of docs should be based on git tags as most docs are under git version control anyway. There are some important things to consider, though. Given that older versions might have older configs, one possible approach would be that only the config of latest should be used to build all older docs (one corner case would be that older versions could require special markdown extensions that were disabled in newer configs, so this needs to be thought through a bit how it can be solved). A version switcher like readthedocs has would be great, although this would make it mandatory to regenerate all old docs as well, when publishing new ones. So this would be another important thing to discuss. It would as well have the benefit that older docs can include a warning that these are for older versions and deprecated. (There are actually a lot of people reading old docs by accident)
To sum up the important points I would like to suggest for discussion:
- Use git tags for versioning?
- Only use current (latest) config?
- Have a version switcher in the docs/deprecation warnings?
Hey @dougal - that looks great, but I can't see any files listed in pypi? https://pypi.python.org/pypi/mkdocs-versioned/0.1.0.dev0 I get an error about 'No distributions at all found for mkdocs-versioned==0.1.0.dev0'. I attempted installing from your setup.py script in the repo (which seems to have worked), but can't see it on the commandline?
Scratch that, pip -e mkdocs-versioned seems to have done the job. Would be good to see it on pypi though.
@iwootten Hmm, yeah. It shouldn't really be on PyPI at all right now as it only vaguely works.
Ah, sorry didn't realise your documentation was ahead of itself right now.
@iwootten no worries, there is a fairly big fat warning near the top of the documentation :) http://d0ugal.github.io/mkdocs-versioned/
@d0ugal Are you intending to use mkdocs-versioned as a basis for a plugin that will help make versioning possible, or is it intended to be merged into mkdocs?
Personally, I think it should be handled via an external plugin as there are many different ways of versioning docs. I also don't see the value in rebuilding all of the docs, and especially not all tags.
Python's doc versioning is handled by a javascript file that adds a dropdown menu w/ the latest versions. This file only needs to be updated to include the latest a.b.C number or when an a.B.c release is deleted.
Yeah, I plan for it to be handled externally. I've said it a few times, but I forget where, so to quickly reiterate: that repo implements a pattern very similar to how ReadTheDocs versions Sphinx projects and it is also the pattern I want to use for MkDocs itself.
And to be clear, at the moment it uses private API's, I'd expect it to use a plugin API if the idea is to survive. However, that is dependant on #206
I also don't see the value in rebuilding all of the docs, and especially not all tags.
This depends on how your docs are deployed. For example, when deploying to PyPI, you are required to upload a zip file which contains all of your site's files. The contents of that file will replace everything from the previous upload. No other options are provided.
Of course, if I have a local cache of the previous builds, I could rely on that and only build the most recent version before zipping up the entire thing (all versions), but I don't always work from the same machine so my local builds could get out-of-sync and local builds sometimes need to be cleaned out/deleted. So yes, we definitely need to be able to build all tags every time. Of course, the option to restrict builds to certain tags/versions would be useful as well.
One thing I haven't seen mentioned here yet is how to address a project which was not using MkDocs in older versions/tags. For example, my project has been around for many years before MkDocs with many versions tagged in the git repo. Interestingly, most of those tags also have docs and a one-off command which will build those docs. I realize I could create by own script which steps through all tags and build the docs, but it would be nice to be able to use a single tool for pre-MkDocs and post-MkDocs versions.
I'm thinking perhaps a optional flag to set a cutoff tag and the option to define a build command for anything before that cutoff. Any tags before the cutoff would use the provided pre-cutoff command and any tags after the cutoff would use MkDocs.
Another issue is that prior to version 1.0, MkDocs is unstable and some older versions of some projects will be using what are now invalid configs or command line flags which are no longer supported by the CLI. Of course, the tagged version of some third-party project will not match MkDocs' versions, so it would be impossible for the script to determent which versions of the docs it can build.
And you can't require that some config file be added (or add a setting to the MkDocs config), as these tags are in past history of peoples repos. No one should be required to go through their projects and rewrite their history to add/change the MkDocs config for older versions. Besides, that would break forks/clones of the repos and is generally considered bad practice for version control systems.
I suppose a config in the current version could define various changes throughout history, and then the script could load that history and as it looped through tags it could adapt its behavior. But that sounds overly complex to me and probably not something anyone would want to maintain. That said, this is a real problem that exits in the real world. It wouldn't be right to completely ignore it.
@waylan I see; wasn't aware of PyPi's requirements.
Regarding supporting non-mkdocs and pre-1.0 mkdocs versions, I don't think any of that should be handled by such a versioning plugin because you run the risk of adding too much bloat in order to support every possible scenario. Instead, something like this should be left to the project's developers to solve and could easily be handled via tox (or manually through virtualenv), allowing you to setup different environments and manually including commands to build from specific tags.
Regarding supporting non-mkdocs and pre-1.0 mkdocs versions, I don't think any of that should be handled by such a versioning plugin because you run the risk of adding too much bloat in order to support every possible scenario.
I don't disagree with you. I'm just saying that this is a real situation and it would be nice if it was acknowledged. Providing a way to explicitly specify which tags to built should work fine. Whether that is best achieved by specifying each tag individually, providing a cutoff (everything after a given tag), or providing start/stop tags (everything between), I don't know. And do you specify those tags via a config file, command line options, or both?
Personally, I would think the cutoff would be the simplest to implement. A single command line option could set the cutoff and every tag greater than or equal to the given tag would get built. IIRC, Distutils/Setuptools has some code for working with semantically versioned numbers (x.x.x) that could be used to sort/splice the list of tags. I would be okay with the restriction that the cutoff option only works with semantic versioning.
However, if someone wants to support multiple versions of MkDocs though-out their history they would need create their own script which created virtualenvs for each MkDocs version and build the docs for that version separately. As you suggest, something like Tox might work well for that. I suppose there would be no reason for this tool to support that scenario, making the start/stop option unnecessary.
What I did (or was going to do, I forget how far I got!), which was fairly easy, was build every tag with a mkdocs.yml. If the config didn't exist it was skipped and logged at DEBUG level.
Some tags failed because the config was really out of date and it didn't work with MkDocs anymore - these were logged with a warning.
I suppose that works as well.
It is reasonably good as a simple approach, but it does have a number of short comings like old tags start failing as MkDocs progresses - although, we have been quite good so far, so I don't expect many breakages and plan to avoid them as much as possible.
For example, when deploying to PyPI, you are required to upload a zip file which contains all of your site's files. The contents of that file will replace everything from the previous upload. ... So yes, we definitely need to be able to build all tags every time. Of course, the option to restrict builds to certain tags/versions would be useful as well.
It seems to me that this is a sign that the built docs should be under (some form of) version control.
I look at documentation as a part of packaging a release; building the HTML version of a release's docs isn't really that different from building a source (or binary) tarball of a release. In fact, you might want to package the HTMLized docs inside your tarballs.
Following this view, the docs should be built exactly once, when you create the release. If you're hosting your docs on GitHub pages, you might want to just add the docs in the appropriate subfolder and push it to your gh-pages branch. If you're hosting your docs on PyPI, you might have a similar branch of your repository that you can use to manage the sum of all versions of your docs.
This makes it easier to handle docs that change format over time or even just use an old, incompatible version of a single doc generator. It also makes a promise to the user that the docs for a release won't change. This is similar to the idea of "semantic versions": under semantic versioning, you wouldn't re-release your code with the same version, even if all you did was fix a tiny bug. I think there's even an argument for making a new point-release just for documentation fixes: it's a way of letting users know that there's new stuff. (I doubt most projects will be this strict about versioning, though.)
Upvoting this :+1:
+1 for this feature
+1
:+1: