Repository navigation
Description
🤖 Filed on behalf of @tdstein.
rsconnect write-manifest voila <dir> uses dirname(path) as the project directory. For a directory given without a trailing slash, such as proj, that is '', the working directory. This causes one of two problems:
- If the working directory has no
requirements.txt, the command fails even thoughproj/requirements.txtexists. - If the working directory has a
requirements.txt, the command succeeds but writesproj/manifest.jsonwith the working directory's requirements, not the project's. Nothing warns that the wrong dependencies were recorded.
proj/ (trailing slash) and proj/report.ipynb both work.
Steps to reproduce
With rsconnect-python 1.32.0:
mkdir -p proj
printf '{"cells":[],"metadata":{},"nbformat":4,"nbformat_minor":5}' > proj/report.ipynb
echo voila > proj/requirements.txt
rsconnect write-manifest voila projChecking arguments... [OK]
[ERROR]
Error: The requirements file 'requirements.txt' does not exist in ''.
Please create the file or specify a different file with --requirements-file.
To have the requirements file generated using pip freeze, pass --force-generate.
Then add an unrelated requirements.txt to the working directory:
echo pandas > requirements.txt
rsconnect write-manifest voila proj
md5 -q requirements.txt proj/requirements.txt
python -c "import json; print(json.load(open('proj/manifest.json'))['files']['requirements.txt'])"Creating manifest.json... [OK]
2f19884f14598d8de5efae75e6d86a7c
9dec73da42aacc7d693d84bbacf07dbe
{'checksum': '2f19884f14598d8de5efae75e6d86a7c'}
The manifest's requirements.txt checksum matches ./requirements.txt (pandas), not proj/requirements.txt (voila).
Cause
write_manifest_voila in rsconnect/main.py computes the base directory with dirname alone:
base_dir = dirname(path)deploy_voila in the same file handles a directory:
base_dir = path if isdir(path) else dirname(path)The same base_dir also sets manifest_path for the --overwrite check, so that check looks at ./manifest.json instead of proj/manifest.json.
Suggested fix
Use base_dir = path if isdir(path) else dirname(path) in write_manifest_voila, as deploy_voila does, and add a test that passes a directory with no trailing slash.
Context
Found while updating the Posit Connect docs to use the Posit CLI (posit connect write-manifest voila), which mounts this command. Checked against main at b1f5ca2.
Activity
tdstein commentedon Oct 27, 2026
Codex Workpad
Plan
Acceptance Criteria
Validation
python -m pytest -q tests/test_write_manifest_voila.py tests/test_environment.py tests/test_bundle.py tests/test_main.py tests/test_write_manifest_pyproject.pyruff format --check rsconnect/main.py tests/test_write_manifest_voila.pyruff check rsconnect/main.py tests/test_write_manifest_voila.pygit diff --check HEAD^ HEADEvidence
Reproduction
Notes
AGENTS.mdexists; reviewedCLAUDE.md.1a009cfeda4e22dd2d3806b328c4503e478673d8:pytest -q tests/test_write_manifest_voila.py tests/test_environment.py tests/test_bundle.py tests/test_main.py tests/test_write_manifest_pyproject.pypassed (310 passed, 10 skipped).ruff format --check rsconnect/main.py tests/test_write_manifest_voila.py,ruff check rsconnect/main.py tests/test_write_manifest_voila.py, andgit diff --checkpassed.1a009cfeda4e22dd2d3806b328c4503e478673d8.1a009cfeda4e22dd2d3806b328c4503e478673d8; 310 tests passed, 10 skipped, and Ruff and diff checks passed. No unresolved review threads.Confusions