Docs Management Overview
Kubestellar Website Build Overview#
Websites#
We have two web sites, as follows.
https://kubestellar.io
. This is hosted by GoDaddy and administered by Andy Anderson. It contains a few redirects. The most important is thathttps://kubestellar.io/
redirects tohttps://docs.kubestellar.io/
.https://docs.kubestellar.io
. This is a GitHub pages website based on thegithub.com/kubestellar/kubestellar/
repository.
A contributor may have their own copy of the website, at https://${repo_owner}.github.io/${fork_name}
, if they have set up the fork properly to render the webpages. See the section below on Serving up documents globally from a fork of the repo via GitHub.
GitHub pages#
Our documentation is powered by mike and MkDocs. MkDocs is powered by Python-Markdown. These are immensely configurable and extensible. You can see our MkDocs configuration in docs/mkdocs.yml
. Following are some of the choices we have made.
- The MkDocs theme is Material for MkDocs.
- MkDocs plugin awesome-pages for greater control over how navigation links are shown.
- MkDocs plugin macros.
- Our own slightly improved vintage of the
include-markdown
MkDocs plugin, allowing the source to be factored into re-used files. - Python-Markdown extension SuperFences, supporting fenced code blocks that play nice with other markdown features.
- Python-Markdown extension Highlight, for syntax highlighting of fenced code.
- Pygments for even fancier code highlighting.
- MkDocs plugin mkdocs-static-i18n to support multiple languages. We currently only have documentation in English. If you're interested in contributing translations, please let us know!
Rendering and Previewing modifications to the website#
You may preview possible changes to the website by either rendering them globally from a fork on GitHub, or by downloading and rendering the documents locally.
Serving up documents globally from a fork of the repository via GitHub#
You can also take advantage of the "Generate and Push Docs" Action via the github web interface to create an online, shareable rendering of the website. This is particularly useful for documentation PRs, as it allows you to share a preview of your proposed changes directly via a URL to a working website. To take advantage of this action, you must ensure that you have forked the repository properly, so your fork includes the gh-pages branch required for the Action to run properly:
Creating a fork that can use the Generate and Push Docs Action#
- Log into your GitHub account via webbrowser
- Navigate to github.com/kubestellar/kubestellar
- Select the Forks dropdown and click on the plus sign to create a new fork
- In the resulting dialog select your account as the owner, pick a repository name for the fork, and be sure to uncheck the "copy the main branch only" box
If you already created a fork but only included the main branch#
You can remedy the problem by propagating the gh-pages branch into your fork using git commands
Generating a website rendered from a branch of your fork#
- Work on the documents in a branch of your fork of the repository, and commit the changes
- (If you have been working on a local copy of the files, push the changes to the fork, then log into the GitHub webpage for your fork)
- Switch to the Actions tab in the top menu bar of the repository page
- Select Generate and Push Docs from the list of Actions on the left
- Click on the Run Workflow button on the right
- Select the branch you wish to render and click on the second Run Workflow Button
- If that workflow completes successfully, it will automatically call the Pages build and deployment workflow.
- You can observe the progress of the workflows on the Actions page; a green checkmark circle indicates successful completion.
- After a minute or so, you should be able to preview your new version of the website at
https://${repo_owner}.github.io/${fork_name}/${branch_name}
Automatically generate webpages#
If you create a branch of your fork that begins with doc- (e.g. doc-myversion) the workflow will trigger automatically when you commit changes to the branch.
Switching between versions#
Each branch of your fork will render as its own version. You can use the release dropdown inside the rendered pages to quickly switch between versions.
Note: the main branch will render as https://${repo_owner}.github.io/${fork_name}/main
, NOT as "unreleased-development" which is a special alias on the main kubestellar.io website.
Removing outdated (draft branch) versions after rendering#
You can use mike
to remove versions, or replace gh-pages with a copy of the shared version.
More details on these techniques will be added here soon.
Serving up documents locally#
You can view and modify our documentation in your local development environment. Simply checkout one of our branches.
You can view and modify our documentation in the branch you have checked out by using mkdocs serve
from mkdocs. We have a Python requirements file in requirements.txt
, and a Makefile target that builds a Python virtual environment and installs the requirements there. You can either install those requirements into your global Python environment or use the Makefile target. To install those requirements into your global Python environment, do the following usual thing.
Alternatively, use the following commands to use the Makefile target to construct an adequate virtual environment and enter it.
Then, using your chosen environment with the requirements installed, build and serve the documents with the following command.
Then open a browser tohttp://localhost:8000/
Another way to view (not modify - this method reflects what has been deployed to the gh-pages
branch of our repo) all branches/versions of our documentation locally using 'mike' mike for mkdocs:
git clone git@github.com:kubestellar/kubestellar.git
cd kubestellar
git checkout main
cd docs
mike set-default main
cd ..
make serve-docs
http://localhost:8000/
Supported aliases for our documentation#
mike
has a concept of aliases. We currently maintain only one alias.
latest
(https://docs.kubestellar.io/latest), for the latest regular release.
The publishing workflow updates these aliases. The latest regular release is determined by picking the first version listed by mike list
that matches the regexp release-[0-9.]*
.
Publishing from the branch named "main"#
The branch named "main" also gets published as a "version" on the
website, but with a different name. This is not done by mike
aliasing, because that only adds a version. The branch named "main"
is published as the version named "unreleased-development".
Shortcut URLs#
We have a few shortcut urls that come in handy when referring others to our project:
note: You need to join our mailing list first to get access to some of the links that follow (https://docs.kubestellar.io/joinus)
- https://kubestellar.io/agenda - our community meeting agenda google doc
- https://kubestellar.io/blog - our medium reading list
- https://kubestellar.io/code - our current GitHub repo (wherever that is)
- https://kubestellar.io/community - our stable docs community page
- https://kubestellar.io/drive - our google drive
- https://kubestellar.io/joinus - our dev mailing list where you join and get our invites
- https://kubestellar.io/join_us - also, our dev mailing list
- https://kubestellar.io/linkedin - our linkedin filter (soon, our page)
- https://kubestellar.io/tv - our youtube channel
- https://kubestellar.io/youtube - also, our youtube channel
- https://kubestellar.io/infomercial - our infomercial that premieres on June 12th at 9am
and.. the very important… - https://kubestellar.io/quickstart - our 'stable' Getting Started recipe
Jinja templating#
Our documentation stack includes Jinja. The Jinja constructs --- {# comment #}, {{ expression }}, and {% statement %} --- can appear in the markdown sources.
File structure#
All documentation-related items live in docs
(with the small exception of various make
targets and some helper
scripts in hack
).
The structure of docs
is as follows:
Path | Description |
---|---|
config/$language/mkdocs.yml | Language-specific mkdocs configuration. |
content/$language | Language-specific website content. |
generated/branch | All generated content for all languages for the current version. |
generated/branch/$language | Generated content for a single language. Never added to git. |
generated/branch/index.html | Minimal index for the current version that redirects to the default language (en) |
overrides | Global (not language-specific) content. |
Dockerfile | Builds the kubestellar-docs image containing mkdocs + associated tooling. |
mkdocs.yml | Minimal mkdocs configuration for mike for multi-version support. |
requirements.txt | List of Python modules used to build the site. |
Global Variables#
There are many global variables defined in the docs/mkdocs.yml. The following are some very common variables you are encouraged to use in our documentation. Use of these variables/macros allows our documentation to have github branch context and take advantage of our evolution without breaking
- site_name: KubeStellar
- repo_url: https://github.com/kubestellar/kubestellar
- site_url: https://docs.kubestellar.io/release-0.25.1
- repo_default_file_path: kubestellar
- repo_short_name: kubestellar/kubestellar
- docs_url: https://docs.kubestellar.io
- repo_raw_url: https://raw.githubusercontent.com/kubestellar/kubestellar
- edit_uri: edit/main/docs/content/
- ks_branch: main
- ks_tag: latest
- ks_latest_regular_release: 0.25.1
- ks_latest_release: 0.25.1
to use a variables/macro in your documentation reference like this:
{{ config.<var_name> }}
and in context that can look something like this:
bash <(curl -s {{ config.repo_raw_url }}/{{ config.ks_branch }}/bootstrap/bootstrap-kubestellar.sh) --kubestellar-version {{ config.ks_tag }}
note:
- We also check for broken links as part of our PR pipeline. For more information check out our Broken Links Crawler
Navigation (website menu)#
The navigation for the documentation is also configured in docs/mkdocs.yml. The section which begins with nav: lays out the navigation structure and which markdown files correspond to each topic.
Page variables#
A markdown source file can contribute additional variables by defining them in name: value
lines at the start of the file, set off by lines of triple dashes. For example, suppose a markdown file begins with the following.
These variables can be referenced as {{ page.meta.short_name }} and {{ page.meta.manifest_name }}.
Including external markdown#
We make extensive use of 'include-markdown' to help us keep our documentation modular and up-to-date. To use 'include-markdown' you must add a block in your document that refers to a block in your external document content:
In your original markdown document, add a block that refers to the external markdown you want to include:
In the document you want to include, add the start and end tags you configured in the include-markdown block in your original document:
for more information on the 'include-markdown' plugin for mkdocs look here
Codeblocks#
mkdocs has some very helpful ways to include blocks of code in a style that makes it clear to our readers that console interaction is necessary in the documentation. There are options to include a plain codeblock (```), shell (shell), console (console - no used in our documentation), language or format-specific (yaml, etc.), and others. For more detailed information, checkout the mkdocs information on codeblocks.
NOTE: the docs-ecutable technology does not apply Jinja, at any stage; Jinja source inside executed code blocks will not be expanded by Jinja but rather seen directly by bash
.
Here are some examples of how we use codeblocks.
Seen and executed#
For a codeblock that can be 'tested' (and seen by the reader) as part of our CI, use the shell
block:
codeblock:
Executed but not seen#
(Think hard before hiding stuff from your reader.)
For a codeblock that should be 'tested', BUT not seen by the reader, use the .bash
with the plain codeblock, and the '.hide-me' style (great for hiding a sleep command that user does not need to run, but CI does):
codeblock:
Seen but not executed#
(To avoid confusing readers of the HTML, this should be used only for output seen in a shell session.)
For a codeblock that should not be 'tested' as part of our CI, use the .bash
with the plain codeblock, and without the '.hide-me' style:
codeblock:
Seen but not executed and no copy button#
For a codeblock that should not be 'tested', be seen by the reader, and not include a 'copy' icon (great for output-only instances), use the .bash
codeblock without the '.no-copy' style:
codeblock:
``` {.bash .no-copy}
I0412 15:15:57.867837 94634 shared_informer.go:282] Waiting for caches to sync for placement-translator
I0412 15:15:57.969533 94634 shared_informer.go:289] Caches are synced for placement-translator
I0412 15:15:57.970003 94634 shared_informer.go:282] Waiting for caches to sync for what-resolver
```
I0412 15:15:57.867837 94634 shared_informer.go:282] Waiting for caches to sync for placement-translator
I0412 15:15:57.969533 94634 shared_informer.go:289] Caches are synced for placement-translator
I0412 15:15:57.970003 94634 shared_informer.go:282] Waiting for caches to sync for what-resolver
Other language-specific highlighting#
For other language-specific highlighting (yaml, etc.), use the yaml codeblock
codeblock:
```yaml
nav:
- Home: index.md
- QuickStart: Getting-Started/quickstart.md
- Contributing:
- Guidelines: Contribution guidelines/CONTRIBUTING.md
```
nav:
- Home: index.md
- QuickStart: Getting-Started/quickstart.md
- Contributing:
- Guidelines: Contribution guidelines/CONTRIBUTING.md
Codeblock with a title#
For a codeblock that has a title, and will not be tested, use the 'title' parameter in conjunction with the plain codeblock (greater for showing or prescribing contents of files):
codeblock:
(other variations are possible, PR an update to the kubestellar.css file and, once approved, use the style on the plain codeblock in your documentation.)
Testing/Running Docs#
How do we ensure that our documented examples work? Simple, we 'execute' our documentation in our CI. We built automation called 'docs-ecutable' which can be invoked to test any markdown (.md) file in our repository. You could use it in your project as well - afterall it is opensource.
The way it works:#
- create your .md file as you normally would
- add codeblocks that can be tested, tested but hidden, or not tested at all:
- use 'shell' to indicate code you want to be tested
- use '.bash' with the plain codeblock, and the '.hide-md' style for code you want to be tested, but hidden from the reader (some like this, but its not cool if you want others to run your instructions without hiccups)
- use plain codeblock (```) if you want to show sample output that is not to be tested
- you can use 'include-markdown' blocks, and they will also be executed (or not), depending on the codeblock style you use in the included markdown files.
The GitHub Workflow:#
- One example of the GitHub Workflow is located in our kubestellar/kubestellar at https://github.com/kubestellar/kubestellar/blob/main/.github/workflows/docs-ecutable-where-resolver.yml
- An example workflow using the newer technology is located in our kubestellar/kubestellar repo at https://github.com/kubestellar/kubestellar/blob/main/.github/workflows/docs-ecutable-example1.yml
The original secret sauce:#
- The original code that made all this possible is at https://github.com/kubestellar/kubestellar/blob/main/docs/scripts/docs-ecutable.sh
- This code parses the .md file you give it to pull out all the 'shell' and '.bash .hide-me' blocks
- The code is smart enough to traverse the include-markdown blocks and include the 'shell' and '.bash .hide-me' blocks in them
- The Jinja constructs are not expanded by this code.
- It then creates a file called 'generate_script.sh' which is then run at the end of the docs-ecutable execution.
All of this is invoke in a target in our Makefile
You give the path from that follows the 'https://github.com/kubestellar/kubestellar/docs' path, and name of the .md file you want to 'execute'/'test' as the value for the MANIFEST variable:
make MANIFEST="'docs/content/Getting-Started/quickstart.md'" docs-ecutable
note: there are single and double-quotes used here to avoid issues with 'spaces' used in files names or directories. Use the single and double-quotes as specified in the quickstart example here.
The new and improved secret sauce:#
- The newer code for executing bash snippets in documentation is at https://github.com/kubestellar/kubestellar/blob/main/docs/scripts/execute-html.sh
- This code parses the HTML generated by MkDocs to extract all the fenced code blocks tagged for the "shell" language.
- This HTML scraping is relatively easy because it does not have to work on general HTML but only the HTML generated by our stack from our sources. The use of the option setting
pygments_lang_class: true
for the Python-Markdown extensionpymdownx.highlight
plays a critical role, getting the source language into the generated HTML. - Because it reads the generated HTML, invisible code blocks are not extracted.
- Because it reads the generated HTML, the Jinja constructs have their usual effects.
- This script is given the name of the HTML file to read and the current working directory to establish at the start of the extracted bash.
- It then creates a file called 'generated_script.sh' which is then run.
All of this is invoked in a target in our Makefile
.PHONY: execute-html
execute-html: venv
. $(VENV)/activate; \
cd docs; \
mkdocs build; \
scripts/execute-html.sh "$$PWD/.." "generated/$(MANIFEST)/index.html"
The make
target requires the variable MANIFEST
to be set to the directory that contains the generated index.html
file, relative to 'https://github.com/kubestellar/kubestellar/docs/generated'. This is the name of the markdown source file, relative to 'https://github.com/kubestellar/kubestellar/docs/content' and with the .md
extension dropped.
make MANIFEST="Coding Milestones/PoC2023q1/example1" execute-html
note: this target has no special needs for quoting --- which is not to deny the quoting that your shell needs.
Important files in our gh-pages branch#
index.html and home.html#
These appear in the branch named gh-pages
and redirect from the root to the version named latest
. The one named index.html
is managed by mike set-default
. The other should be kept consistent.
- https://github.com/kubestellar/kubestellar/blob/gh-pages/home.html
- https://github.com/kubestellar/kubestellar/blob/gh-pages/index.html
both files have content similar to:
<!DOCTYPE html>
<html>
<head>
<title>KubeStellar</title>
<meta http-equiv="content-type" content="text/html; charset=utf-8" >
<meta http-equiv="refresh" content="0; URL=https://docs.kubestellar.io/latest" />
</head>
Do not remove these files!
CNAME#
The CNAME file has to be in the gh-pages root to allow github to recognize the url tls cert served by our hosting provider. Do not remove this file!
the CNAME file must have the following content in it:
versions.json#
The versions.json file contains the version and alias information required by 'mike' to properly serve our doc site. This file is maintained by the 'mike' environment and should not be edited by hand.
[{"version": "release-0.22.0", "title": "release-0.22.0", "aliases": ["latest"]}, {"version": "release-0.22.0-rc3", "title": "release-0.22.0-rc3", "aliases": []}, {"version": "release-0.21.2", "title": "release-0.21.2", "aliases": []}, {"version": "release-0.21.2-rc1", "title": "release-0.21.2-rc1", "aliases": []}, {"version": "release-0.21.1", "title": "release-0.21.1", "aliases": []}, {"version": "release-0.21.0", "title": "release-0.21.0", "aliases": []}, {"version": "release-0.14", "title": "release-0.14", "aliases": []}]
In case of emergency#
If you find yourself in a jam and the pages are not showing up at kubestellar.io or docs.kubestellar.io, check the following 1) Is the index.html, home.html, CNAME, and versions.json file in the gh-pages branch alongside the folders for the compiled documents? If not, then recreate those files as indicated above (except for versions.json which is programmatically created by 'mike'). 2) Is GitHub settings for 'Pages' for the domain pointing at the https://docs.kubestellar.io url? If not, paste it in and check off 'enforce https'. This can happen if the CNAME file goes missing from the gh-pages branch.
How to recreate the gh-pages branch#
To recreate the gh-pages branch, do the following: - checkout the gh-pages branch to your local system
- delete all files in the branch and push it to GitHub - switch to the 'release' branch, switch to /docs and run 'mike deploy' for the release branch. Add the alias 'latest' for the latest release - switch back to the gh-pages branch and recreate the home.html, index.html, and CNAME files as needed (make sure you back out of the docs path first before switching to gh-pages because that path does not exist in that branch) - push the new files into gh-pages - go into the GitHub UI and go to the settings for the project and click on 'Pages' to add https://docs.kubestellar.io as the domain and check the box to enforce https.- if the above did not work, then you might have an issue with the GoDaddy domain (expired, files missing, etc.)
How to delete a rendering of a branch#
Use mike delete $branch_name
, either acting locally on your checked out gh-pages
branch (after pull and before git commit and push) or acting more directly on the remote repo using --remote
and --push
. See the mike delete command doc.
Publishing Workflow#
All documentation building and publishing is done using GitHub Actions in
.github/workflows/docs-gen-and-push.yml
. This workflow is triggered either manually or by a push to a branch named main
or release-<something>
or doc-<something>
. This workflow will actually do something ONLY if either (a) it is acting on the shared GitHub repository at github.com/kubestellar/kubestellar
and on behalf of the repository owner or (b) it is acting on a contributor's fork of that repo and on behalf of that same contributor. The published site appears at https://pages.github.io/kubestellar/${branch}
in case (a) and at https://${repo_owner}.github.io/${fork_name}/${branch}
in case (b). This workflow will build and publish a website version whose name is the same as the name of the branch that it is working on. This workflow will also update the relevant mike
alias, if necessary.
*Note that this particular page is rendered from the README.md file in the kubestellar/docs folder, but it is served here on the website at via an include directive