Skip to content

Mike patch - #75

Merged
chenkasirer merged 4 commits into
mainfrom
mike_patch
Dec 18, 2025
Merged

chenkasirer merged 4 commits into
mainfrom
mike_patch

Conversation

@chenkasirer

Copy link
Copy Markdown
Member

Here I'm shamelessly patching mike so that it doesn't overwrite our precious versions.json thus breaking the version selector of the old Sphinx websites.

What type of change is this?

  • Bug fix in a backwards-compatible manner.
  • New feature in a backwards-compatible manner.
  • Breaking change: bug fix or new feature that involve incompatible API changes.
  • Other (e.g. doc update, configuration, etc)

Checklist

Put an x in the boxes that apply. You can also fill these out after creating the PR. If you're unsure about any of them, don't hesitate to ask. We're here to help! This is simply a reminder of what we are going to look for before merging your code.

  • I added a line to the CHANGELOG.md file in the Unreleased section under the most fitting heading (e.g. Added, Changed, Removed).
  • I ran all tests on my computer and it's all green (i.e. invoke test).
  • I ran lint on my computer and there are no errors (i.e. invoke lint).
  • I added new functions/classes and made them available on a second-level import, e.g. compas.datastructures.Mesh.
  • I have added tests that prove my fix is effective or that my feature works.
  • I have added necessary documentation (if appropriate)

Copilot AI review requested due to automatic review settings December 17, 2025 20:53
@chenkasirer chenkasirer added the no changelog Disables the changelog checker label Dec 17, 2025

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

This PR implements a workaround for mike's documentation deployment tool to preserve custom fields in versions.json. The issue is that mike's VersionInfo class overwrites the entire versions.json file, removing fields that aren't part of its standard schema, which breaks the version selector for older Sphinx-based documentation sites. The solution monkey-patches mike's VersionInfo class to preserve these unknown fields during serialization and deserialization.

Key Changes:

  • Added _patch_versions_info() function that monkey-patches mike's VersionInfo class to preserve custom JSON fields
  • Created new mike_deploy invoke task that wraps mike's deployment with the patching applied
  • Updated GitHub Actions workflow to use the new invoke task instead of calling mike directly

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated 6 comments.

File Description
tasks.py Adds monkey-patching logic and new mike_deploy invoke task to preserve custom fields in versions.json when deploying documentation
.github/workflows/docs.yml Updates documentation deployment workflow to use new invoke mike-deploy task instead of calling mike directly

run: |
git fetch origin gh-pages --depth=1
mike deploy --push --update-aliases ${{ env.VERSION }} latest
invoke mike-deploy --version ${{ env.VERSION }} --push-to-origin true

Copilot AI Dec 17, 2025

Copy link

Choose a reason for hiding this comment

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

The workflow passes --push-to-origin true as a string, but the mike_deploy function expects push_to_origin to be a bool. Invoke will interpret the string "true" as a truthy value and convert it to boolean True, so this should work. However, for clarity and explicitness, consider passing it without the value (as a flag) like --push-to-origin since the parameter defaults to False. Alternatively, if you want to be explicit, the current approach works but relies on invoke's automatic type conversion.

Suggested change
invoke mike-deploy --version ${{ env.VERSION }} --push-to-origin true
invoke mike-deploy --version ${{ env.VERSION }} --push-to-origin

Copilot uses AI. Check for mistakes.
Comment thread tasks.py
Comment on lines +42 to +43
VersionInfo.from_json = patched_from_json
VersionInfo.to_json = patched_to_json

Copilot AI Dec 17, 2025

Copy link

Choose a reason for hiding this comment

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

The monkey-patch modifies the VersionInfo class globally for the entire process. If this function is called multiple times, the patching will occur multiple times, which is redundant but should not cause issues. However, consider adding a guard to prevent redundant patching, or document that this is intentional behavior. This would make the code more defensive and clearer about its intent.

Copilot uses AI. Check for mistakes.
Comment thread tasks.py

def _patch_versions_info():
# our `versions.json` contains some fields which aren't supported by mike's
# VersionInfo class. Unfortunately mike overwrites the entire content everytime which breaks the version selector of the old Sphinx sites.

Copilot AI Dec 17, 2025

Copy link

Choose a reason for hiding this comment

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

Typo in comment: "everytime" should be "every time" (two words).

Suggested change
# VersionInfo class. Unfortunately mike overwrites the entire content everytime which breaks the version selector of the old Sphinx sites.
# VersionInfo class. Unfortunately mike overwrites the entire content every time which breaks the version selector of the old Sphinx sites.

Copilot uses AI. Check for mistakes.
Comment thread tasks.py


@task(help={"version": "The library version for which the documentation is to be deployed (e.g., '1.0.0')", "push_to_origin": "Whether to push the changes to the origin remote"})
def mike_deploy(ctx, version: str, push_to_origin: bool = False):

Copilot AI Dec 17, 2025

Copy link

Choose a reason for hiding this comment

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

The mike_deploy task lacks a docstring describing its purpose, parameters, and usage. According to the coding guidelines, public API functions and classes should have numpy style docstrings. While this is an invoke task and not strictly a public API function, it's part of the public interface exposed to developers. Adding a docstring would improve usability, especially since this task performs a non-trivial operation (monkey-patching).

Copilot generated this review using guidance from repository custom instructions.
Comment thread tasks.py
from compas_pb.invocations import proto_docs


def _patch_versions_info():

Copilot AI Dec 17, 2025

Copy link

Choose a reason for hiding this comment

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

The _patch_versions_info function lacks a docstring explaining what it does, why it's needed, and the side effects of monkey-patching. This is particularly important for a function that modifies third-party library behavior at runtime. A docstring would help future maintainers understand the purpose and implications of this patch.

Suggested change
def _patch_versions_info():
def _patch_versions_info():
"""Monkey-patch ``mike.versions.VersionInfo`` to preserve unknown JSON fields.
This project stores additional metadata in ``versions.json`` which is not
supported by mike's built-in :class:`~mike.versions.VersionInfo` model.
By default, mike discards unknown fields on load and rewrites the file
on dump, which would remove this extra metadata and break the version
selector of existing Sphinx sites that rely on it.
This helper replaces :meth:`VersionInfo.from_json` and
:meth:`VersionInfo.to_json` at runtime so that:
* unknown keys encountered during ``from_json`` are stored on the instance
(via ``external_attrs``), and
* those keys are merged back into the output of ``to_json``.
Notes
-----
This is a process-wide monkey-patch: once applied, all subsequent uses of
:class:`mike.versions.VersionInfo` in the current process will use the
patched serialization methods. Call this function before invoking any
mike commands that load or write ``versions.json`` (for example,
inside the ``mike_deploy`` task).
"""

Copilot uses AI. Check for mistakes.
Comment thread tasks.py
quiet=False,
)

driver.deploy(None, args)

Copilot AI Dec 17, 2025

Copy link

Choose a reason for hiding this comment

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

The driver.deploy(None, args) call passes None as the first argument. This should be verified to ensure it's the correct usage of the mike driver API. If None represents a missing configuration or context, it might be worth adding a comment explaining why this is acceptable or if there's a better value to pass.

Copilot uses AI. Check for mistakes.

@gonzalocasas gonzalocasas left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Looks good! I think it's a good hack to get this going, perhaps moving forward, we should revert to use Mike without patching, and patch/tweak/update retroactively all the old version switcher

@chenkasirer
chenkasirer merged commit adafd1a into main Dec 18, 2025
23 of 24 checks passed
@chenkasirer
chenkasirer deleted the mike_patch branch December 18, 2025 14:38
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

no changelog Disables the changelog checker

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants