Skip to content
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

new: Add generated documentation website #639

Open
wants to merge 41 commits into
base: dev
Choose a base branch
from

Conversation

lgarber-akamai
Copy link
Contributor

@lgarber-akamai lgarber-akamai commented Aug 30, 2024

📝 Description

This pull request implements a new generated documentation site that is automatically pushed to GitHub Pages.

The below preview URLs can be preview the documentation site in your browser:

Landing Page


Rendering

This PR uses Sphinx with the Read the Docs theme to render documentation. The Sphinx configuration and all relevant static files are stored under the docs directory.

Command Documentation Generation

Due to the complexity and abundance of CLI commands, the logic to generate documentation pages for CLI commands is located in the linodecli/documentation directory.

The linodecli/documentation/templates directory contains various Jinja2 templates which are dynamically rendered using the structures defined in linodecli/documentation/template_data.py.

CLI documentation pages are rendered to a user-defined directory when linode-cli generate-docs is called. This is an indirect dependency of the make generate-docs target, which will automatically render the command documentation into the docs/_generated directory before executing any Sphinx commands.


Publishing

To automatically publish the documentation to a publicly available URL, this PR adds a new documentation.yml GitHub Actions workflow file.

This workflow has three jobs:

  1. Build the documentation and upload it as an artifact

    • This runs on all pushes and PRs.
  2. Pull down the built docs from the first step and commit them to the _documentation branch

    • This only runs on releases and pushes to trusted branches (main, dev)
    • The _documentation branch automatically be created if it does not already exist.
      • This branch should be manually configured with force-push protections in place.
      • GitHub pages should be manually configured to publish from the this branch branch.
  3. Pull down the built docs from the first step and upload them as a release asset.

    • This only runs on releases.

The Documentation Branch

This PR uses a dedicated documentation branch because it allows us to make multiple versions of the documentation available at at time. Additionally, this allows us to manually rebase any sensitive/unwanted documentation details.

This branch stores all relevant versions as subdirectories, with the latest directory and index.html files being updated on-demand by job #2 (mentioned above).

✔️ Testing

The following test steps assume you have pulled down this PR locally and run make install.

Unit Testing

make testunit

Documentation Rendering

  1. Build the documentation for the Linode CLI locally using the generate-docs target:
make generate-docs
  1. Ensure the documentation generates successfully.

  2. Open the documentation index in your browser:

file:///path/to/my/linode-cli/docs/build/html/index.html
  1. Ensure all documentation is as expected.

Publishing

  1. Create a new/doc-generation branch on your fork containing the changes from this PR:
git checkout -b new/doc-generation
git push -u fork new/doc-generation
  1. Ensure the Build and Commit to Pages Branch jobs under the Build Documentation workflow run successfully under your fork.
  2. Navigate to the Settings -> Pages page of your fork.
  3. Set the source to Deploy from a branch, the target branch to the _documentation branch, and the path to / (root).
  4. Save your changes and wait for the rendered documentation to become available at MYGHUSERNAME.github.io/linode-cli/new/doc-generation.
  5. Ensure version in the top-left reflects the latest commit on your new/doc-generation branch.
  6. Publish a release pointing at your fork's new/doc-generation branch with the format vX.X.X.
  7. Wait for the release's documentation to become available at MYGHUSERNAME.github.io/linode-cli/latest.
  8. Ensure the version in the top-left reflects the published version.

📷 Preview

Configuration Page

Configuration Page

Create Command Update Command
Create Command Update Command
View Command List Command
View Command List Command

@lgarber-akamai lgarber-akamai added the new-feature for new features in the changelog. label Aug 30, 2024
@lgarber-akamai lgarber-akamai force-pushed the new/doc-generation branch 3 times, most recently from a28e46a to 9bb4769 Compare September 1, 2024 02:43
@lgarber-akamai lgarber-akamai changed the title new: Add generated documentation website & manpage new: Add generated documentation website Sep 3, 2024
@lgarber-akamai lgarber-akamai marked this pull request as ready for review September 6, 2024 15:19
@lgarber-akamai lgarber-akamai requested a review from a team as a code owner September 6, 2024 15:19
@lgarber-akamai lgarber-akamai requested review from ykim-1 and ezilber-akamai and removed request for a team, ykim-1 and ezilber-akamai September 6, 2024 15:19
@lgarber-akamai lgarber-akamai added the do-not-merge PRs that should not be merged until the commented issue is resolved label Sep 6, 2024

return self._handle_list_items(list_items, parsed)

def build_parser(
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I split this into multiple functions so we can extract the generated usage text for use in the docs

Comment on lines -125 to +147
relevant_lines = None

for i, line in enumerate(target_lines):
def __simplify(sentence: str) -> Optional[str]:
# Edge case for descriptions starting with a note
if line.lower().startswith("__note__"):
continue
if sentence.lower().startswith("__note__"):
return None

sentence = strip_techdocs_prefixes(sentence)

relevant_lines = target_lines[i:]
break
# Check that the sentence still has content after stripping prefixes
if len(sentence) < 2:
return None

if relevant_lines is None:
return sentence + "."

# Find the first relevant sentence
result = next(
simplified
for simplified in iter(
__simplify(sentence)
for sentence in REGEX_SENTENCE_DELIMITER.split(description)
)
if simplified is not None
)

if result is None:
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I overhauled the logic in this function to account for some new cases I ran into

Comment on lines +187 to +192
result_no_links, links = extract_markdown_links(result)

if len(links) > 0:
description += f" See: {'; '.join(links)}"
result_no_links += f" See: {'; '.join(links)}"

return unescape(markdown_to_rich_markup(description)), unescape(description)
return unescape(markdown_to_rich_markup(result_no_links)), unescape(result)
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This was updated to store one mostly unchanged version and one fully formatted version of the description, giving us more flexibility in the docs

@@ -40,7 +41,7 @@ def __init__(self, version, base_url, skip_config=False):
self.config = CLIConfig(self.base_url, skip_config=skip_config)
self.load_baked()

def bake(self, spec):
def bake(self, spec: Dict[str, Any], file: Optional[IO[bytes]] = None):
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These changes allow us to construct a mock CLI from a custom spec in unit tests

T = TypeVar("T")


def sorted_actions_smart(
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This doesn't live with the rest of the util functions because it can also be used in the command --help pages

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
do-not-merge PRs that should not be merged until the commented issue is resolved new-feature for new features in the changelog.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

1 participant