Skip to content

The documented PYTHON_VENV_DIR_DOCS override is relative, but the tasks run in the caller's directory #47

Description

@nolte

Summary

src/taskfile-include-mkdocs.yaml documents its override example with a relative path, while both of its tasks run in the caller's directory and activate the interpreter through a bare source. A consumer who copies the documented example gets a module that only works when task is invoked from the repository root, and fails everywhere else with a shell error that names nothing about the cause.

The module's own default is fine — ~/.venvs/docs is absolute, so it resolves identically from any directory. Only the documented override is affected, which makes this a documentation defect with a runtime consequence rather than a broken default.

Where it is

src/taskfile-include-mkdocs.yaml on develop:

  • :17 — the usage comment shows PYTHON_VENV_DIR_DOCS: .venv
  • :35 and :45start and build both declare dir: '{{.USER_WORKING_DIR}}', so they run in the directory task was invoked from, not in the consumer's root
  • :39 and :47 — both activate through a bare source {{.PYTHON_VENV_DIR_DOCS}}/bin/activate

A relative value therefore resolves against whatever directory the caller happened to be in.

Reproduction

Consumer Taskfile at a repository root with a project-local .venv, following the documented example:

includes:
  mkdocs:
    taskfile: "{{.TASK_COLLECTION_BASE}}/taskfile-include-mkdocs.yaml"
    vars:
      PYTHON_VENV_DIR_DOCS: .venv
  • task docs from the repository root: works.
  • task docs from any subdirectory: source .venv/bin/activate runs with the subdirectory as cwd, the file isn't there, and the task dies on a shell error that mentions neither the module, nor the variable, nor the override.

The trap in the obvious fix

Reaching for {{.TASKFILE_DIR}} to make the value absolute makes it worse, not better. Measured against Task 3.52.0, inside an includes: vars: block:

Override Local include Remote include (how this collection is consumed)
{{.TASKFILE_DIR}}/{{.VENV}} the included module's directory, not the consumer's empty string, so the value collapses to /.venv
{{.ROOT_DIR}}/{{.VENV}} consumer's root consumer's root

Both were checked from the repository root and from a subdirectory. So the remote shape — the one every consumer of this collection uses — turns a TASKFILE_DIR-based override into /.venv, which fails from every directory including the root. That is strictly worse than the relative form this issue is about, and it's the natural first attempt at a fix.

{{.ROOT_DIR}} resolved correctly in all four combinations. Its one limitation: it points at the parent when a parent Taskfile includes the consumer's, so a nested setup has to pass the path explicitly.

Suggested fix

Change the usage comment at :17 to show the absolute form, and say why in one line, so a consumer copying it doesn't have to rediscover the interaction with dir: '{{.USER_WORKING_DIR}}':

#   includes:
#     mkdocs:
#       taskfile: "{{.TASK_COLLECTION_BASE}}/taskfile-include-mkdocs.yaml"
#       vars:
#         # Absolute: the tasks below run in the caller's directory, so a
#         # relative value resolves against wherever `task` was invoked.
#         PYTHON_VENV_DIR_DOCS: "{{.ROOT_DIR}}/.venv"

Fixing the documentation is enough; the tasks themselves don't need to change. Pinning the tasks' own dir: would be a separate, larger decision with its own consumer impact.

Why this is worth fixing upstream

nolte/claude-shared ships a reference consumer at spec/project/taskfile/templates/Taskfile.yml whose spec MUSTs every scaffolding artefact to adapt it. That template followed the documented example here and inherited the defect, which then had to be corrected downstream (nolte/claude-shared#549). The downstream fix makes one consumer robust; correcting the documented example here stops the next consumer from walking into it.

Related: #42, which established that the module's variables must be written in the default form for consumer overrides to arrive at all. This issue is about the value a consumer is told to pass, not about whether the override reaches the command.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions