fix(cli): honor packOptions.filesIncluded for dot-prefixed paths - #1864
fix(cli): honor packOptions.filesIncluded for dot-prefixed paths#1864jaideeppyne wants to merge 2 commits into
Conversation
`files_to_include` pruned every dot-prefixed directory from `os.walk` and skipped every dotfile *before* the inclusion logic that is supposed to honor `packOptions.filesIncluded` (documented as "specific files to always include"). So any explicit include under a dot-directory (e.g. `.config/assets/x.md`) or a named dotfile (e.g. `.python-version`) was silently dropped — `uipath pack` exited 0 with those files missing and an empty `skipped` list. Now the walk descends into a dot/venv directory when a `files_included` entry lives under it, and a hidden file is packed when it is explicitly listed by name or relative path. Default behavior is preserved: dot/venv directories are still pruned and hidden files are still excluded unless explicitly requested (never merely by matching an included extension). Adds a regression test that packs an explicit include inside `.config/assets/` and a `.python-version` dotfile while asserting non-listed hidden paths (`.secret.md`, `.git/config.md`) stay excluded. It fails on the current code and passes with this change; the existing hidden-file-exclusion tests still pass. Fixes UiPath#1855.
There was a problem hiding this comment.
Pull request overview
Note
Copilot was unable to run its full agentic suite in this review.
This PR fixes a packaging regression so that explicitly listed packOptions.filesIncluded entries are honored even when they are dotfiles or live under dot-prefixed directories (previously pruned during the directory walk).
Changes:
- Add regression coverage ensuring explicit includes under dot paths are packed.
- Update project file discovery to descend into dot/venv directories when an explicitly-included path exists under them.
- Change hidden-file handling so dotfiles can still be included when explicitly listed.
Reviewed changes
Copilot reviewed 2 out of 2 changed files in this pull request and generated 3 comments.
| File | Description |
|---|---|
| packages/uipath/tests/cli/test_files_to_include.py | Adds regression test for explicitly included dotfiles and files under dot-directories. |
| packages/uipath/src/uipath/_cli/_utils/_project_files.py | Adjusts directory walking and inclusion logic to honor explicit includes under hidden/venv paths. |
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
| # Check inclusion: by extension (visible files only), or when the | ||
| # file is explicitly listed by filename / relative path. | ||
| should_include = ( | ||
| file_extension in file_extensions_included | ||
| or ( | ||
| file in files_included and normalized_rel_path == file | ||
| ) # filename match for base directory only | ||
| or normalized_rel_path | ||
| in files_included # path match for subdirectories | ||
| ) | ||
| not file.startswith(".") and file_extension in file_extensions_included | ||
| ) or explicitly_included |
| # A file is explicitly requested when it matches a `files_included` | ||
| # entry by filename (base directory only) or by relative path. | ||
| explicitly_included = ( | ||
| file in files_included and normalized_rel_path == file | ||
| ) or normalized_rel_path in files_included |
| pack_options = PackOptions( | ||
| filesIncluded=[".config/assets/asset.md", ".python-version"] | ||
| ) | ||
|
|
||
| included, _ = files_to_include(pack_options, project_dir, include_uv_lock=False) | ||
| rel_paths = {f.relative_path.replace(os.sep, "/") for f in included} | ||
|
|
||
| assert ".config/assets/asset.md" in rel_paths | ||
| assert ".python-version" in rel_paths | ||
| # Hidden paths that were not explicitly included stay excluded. | ||
| assert ".secret.md" not in rel_paths | ||
| assert ".git/config.md" not in rel_paths |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 173e6de19f
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| has_included_descendant = any( | ||
| included == normalized_dir_rel_path | ||
| or included.startswith(normalized_dir_rel_path + "/") | ||
| for included in files_included |
There was a problem hiding this comment.
Restrict traversal to explicitly included hidden paths
When filesIncluded contains a path such as .config/assets/asset.md, this predicate admits the entire .config directory into os.walk; every non-hidden descendant and sibling beneath it is then processed by the normal extension allowlist. Consequently, an unlisted .config/secrets.json or .config/other/tool.py is packed and pushed as well, defeating the default hidden-directory exclusion and potentially publishing sensitive configuration. Traversal through a hidden or virtual-environment directory should retain the exceptional-path context so only explicitly requested files and their ancestor directories are admitted.
Useful? React with 👍 / 👎.
…ot/venv dirs Per the Copilot/Codex review: when the walk descends into a dot/venv directory because an explicit `files_included` entry lives under it, other *visible* files in that subtree were still picked up by the extension allowlist — leaking unrelated hidden/venv contents (e.g. `.config/secrets.json`-adjacent files). Track whether the current directory sits under a pruned (dot-prefixed or venv) ancestor, and in that case include a file only when it is explicitly listed in `files_included` — never merely by extension. Explicit includes and normal (non-hidden) tree files are unaffected. Extends the regression test with a visible, non-listed `.config/assets/other.md` and asserts it stays excluded.
|
Good catch, thanks — fixed in f3dd86f. Descending into a dot/venv directory for an explicit include no longer lets other visible files there be picked up by extension: I track whether the current directory is under a pruned (dot/venv) ancestor and, in that case, include a file only when it's explicitly listed in |
Description
Fixes #1855.
files_to_include(_cli/_utils/_project_files.py) is meant to honorpackOptions.filesIncluded— documented as "Specific files to always include." But it prunes and skips dot-prefixed paths before the inclusion logic runs:if d.startswith(".") or is_venv_dir(...): continue, soos.walknever descends into e.g..config/;if file.startswith("."): continue, so dotfiles never reach the inclusion check.As a result, an explicit include living under a dot-directory (e.g.
.config/assets/x.md) or a named dotfile (e.g..python-version) is silently dropped —uipath packexits0with those always-include files missing and an emptyskippedlist (unreportable data loss in the package).Repro on
main(the issue's script):included: ['plain/ASSET.md', 'pyproject.toml'],skipped: []—.config/assets/demo/ASSET.mdand.python-versionare gone.Fix
files_includedentry lives under it (so.git/.venvstay pruned, but an explicitly-included subtree is reachable).fileExtensionsIncluded.Default behavior is unchanged: dot/venv directories are still pruned and hidden files are still excluded unless explicitly requested. I deliberately kept the diff focused — honoring explicit includes closes the silent-data-loss path without flooding
skippedwith every.gitentry (an independent idea floated in the issue).Tests
Added
TestFilesToIncludeExplicitHiddenPaths: packs an explicit include inside.config/assets/and a.python-versiondotfile, and asserts non-listed hidden paths (.secret.md,.git/config.md) stay excluded. It fails on currentmain(assert '.config/assets/asset.md' in set()) and passes with this change. The two existing hidden-file-exclusion tests still pass — no regression to the default.