ros2_documentation icon indicating copy to clipboard operation
ros2_documentation copied to clipboard

Inline Code Examples / Tutorials discussion

Open InvincibleRMC opened this issue 4 months ago • 8 comments

A lot of the code examples like minimal_publisher are just copied from ros2_examples repo. If we could read the raw files from either the built deb, a submodule or, just downloading off of GitHub. We then could use literalinclude to avoid the duplication. The end goal would be to reduce maintainer burden of having to manual copy code.

My use case would be adding Python type hints to the examples and have them automatically update here as well.

InvincibleRMC avatar Sep 02 '25 23:09 InvincibleRMC

There has been discussion on this enhancement. I was hoping that literalinclude could support the URL, so that we can just point the URL for the source code with appropriate branch, but i do not think that it supports that. for now, i do not think of any other options instead of downloading them from GitHub as you suggested. I believe it is still great enhancement to reduce maintenance burden.

fujitatomoya avatar Sep 03 '25 00:09 fujitatomoya

The job is generate from here. I'm not familiar with the build farm and its functions. But I imagine we could add a clone step to get the raw files then use literalinclude with some function in conf.py to determine file location.

InvincibleRMC avatar Sep 03 '25 00:09 InvincibleRMC

i guess that is the one of the ways. something else we need to care is that, each developer should be able to do that in local environment before the commit, and github action too. for supporting those use cases, maybe being independent from build farm would be better? 🤔

fujitatomoya avatar Sep 03 '25 01:09 fujitatomoya

I've looked into this in the past. There is a remote-literal-include which is able to fetch content at build time and supports URLs (ie: to github.com repositories). See #2828.

The challenge I remember is not so much how to do this, but what to remote include (ie: which version), and how to deal with source code changing, but documentation not being updated at the same time.

See the discussion on that PR and #2444, which was coincidentally started by @fujitatomoya.

gavanderhoorn avatar Sep 03 '25 06:09 gavanderhoorn

@gavanderhoorn thanks for pointing that PR and discussion. bad memory... sorry about that 😓 now it is coming back to me. and that makes sense to track the related source code change which is referred by the documentation, otherwise it can be broken documentation. besides that, backports could be more difficult to resolve the conflict. those requirements also come to https://github.com/ros2/ros2_documentation/pull/5840... maybe we should give another look at https://github.com/ros2/ros2_documentation/pull/2828?

fujitatomoya avatar Sep 03 '25 06:09 fujitatomoya

thanks for pointing that PR and discussion. bad memory... sorry about that 😓

no need to apologise. I only remembered because it was my own PR (and issue).

that makes sense to track the related source code change which is referred by the documentation, otherwise it can be broken documentation. besides that, backports could be more difficult to resolve the conflict.

as I wrote earlier: it's a trade-off by documentation becoming stale due to untracked/unnoticed changes and 'freezing' documentation to make sure it documents a particular 'state'.

those requirements also come to #5840... maybe we should give another look at #2828?

perhaps, I believe a choice should be made about what we prefer, and then we can decide how to implement it.

PS: re: stale due to changes not being picked up on: I had (a draft of) a script that compared the hashes passed to remote-literal-include with the HEAD of the specific branch they belonged to. If they didn't match, it would output a WARN. Including that in a (scheduled) CI run could help improve visibility of documentation 'breaking'.

gavanderhoorn avatar Sep 09 '25 07:09 gavanderhoorn

Some thoughts, mostly reiterating what was said:

My use case would be adding Python type hints to the examples and have them automatically update here as well.

I'm not sure about the approach in #5840 (IIUC): always using the latest version of all files and warning at build-time if the file has changed (by comparing old hash vs new hash) means we have to fix/update tutorials as soon as the original file changes. That would make maintaining the docs a constant "race." I think it is preferable to instead point to stable versions of source code files (i.e., specific commits) so that the docs are always in a valid state and make updating them easier.

I see two separate (but complementary?) goals:

  1. Including the source content (e.g., source code for tutorial) semi-directly through automation instead of manually maintaining a copy here.
    • I think we could still download files once and keep a cache of them in this repo to avoid downloading a bunch of files when building the docs, but maybe it's not worth the extra effort.
  2. Having a mechanism to check for a new version of the included file to make sure the docs don't lag behind. The docs shouldn't automatically use the newest version, since that might break tutorials/examples.

These could be combined into one step. Or, as @gavanderhoorn mentioned above, part 2 could be a separate periodically-scheduled job that checks for includes pointing to not-the-latest-version-for-the-given-distro.

christophebedard avatar Sep 23 '25 20:09 christophebedard

Notes @mjcarroll asked me to make.

TLDR;

3 Questions to answer? (Adding one from the above comment)

  1. Best way to reivent git?
  2. Best way to automatically detect drift between repos and correct?
  3. Should documentation be distributed or monorepo?

Solutions

  1. Don't reinvent git Using git submodules is much faster than using any of the other methods since it just downloads whole repos rather than individual files at a time, even though it downloads unused files e.g. CONTRIBUTING.md. For downloading 99% of the files with entire history ~10s and depth 1 was ~9.5s

  2. For detecting drift Use GitHub Dependabot so every 1-2 weeks will generate a pull request if changes are detected within a submodule.

    Could create a custom GitHub Action to something similar to Dependabot if extra features are desired e.g. only generate a pull request if and only if a new tagged version is released to better follow semantic versioning.

  3. Both have pros and cons Monorepo is what we have right now and would require fewer changes. Instead of using the lineno as in #5840, use blocks instead. This would make it so that adding a new import, for example, wouldn't constitute a change in this repo only adding or removing a block would. While switching over to the new style a medium one time effort to add these blocks would be needed.

    Distributed would be nicer but, need a lot of work. Rather than have one sphinx monorepo basically add sub sphinx projects to examples/tutorials/etc. So that when a file is modify the corresponding documentation could be updated within the same pr. Then this repo only needs to be modifiy to add/delete entire documentation pages. This would require moving lots of .rst documenatation files as well as setup sphinx subprojects in every repo we include inline code from. Double checking dependencies I believe all of them have apt packages and exist in rhel. You might also need to add ament versions of the doc8 and codespell linters to these subprojects since I'm not sure ROS's opionion on using these sorts of linters and ros2_documentation currently enforces them.

InvincibleRMC avatar Sep 30 '25 17:09 InvincibleRMC