Skip to content

fix(cli): honor packOptions.filesIncluded for dot-prefixed paths - #1864

Open
jaideeppyne wants to merge 2 commits into
UiPath:mainfrom
jaideeppyne:fix/pack-honor-filesincluded-dot-paths
Open

fix(cli): honor packOptions.filesIncluded for dot-prefixed paths#1864
jaideeppyne wants to merge 2 commits into
UiPath:mainfrom
jaideeppyne:fix/pack-honor-filesincluded-dot-paths

Conversation

@jaideeppyne

Copy link
Copy Markdown

Description

Fixes #1855.

files_to_include (_cli/_utils/_project_files.py) is meant to honor packOptions.filesIncluded — documented as "Specific files to always include." But it prunes and skips dot-prefixed paths before the inclusion logic runs:

  • the directory loop does if d.startswith(".") or is_venv_dir(...): continue, so os.walk never descends into e.g. .config/;
  • the file loop does 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 droppeduipath pack exits 0 with those always-include files missing and an empty skipped list (unreportable data loss in the package).

Repro on main (the issue's script): included: ['plain/ASSET.md', 'pyproject.toml'], skipped: [].config/assets/demo/ASSET.md and .python-version are gone.

Fix

  • The walk now descends into a dot/venv directory only when a files_included entry lives under it (so .git/.venv stay pruned, but an explicitly-included subtree is reachable).
  • A hidden file is packed only when it's explicitly listed by name or relative path — never merely because its extension matches 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 skipped with every .git entry (an independent idea floated in the issue).

Tests

Added TestFilesToIncludeExplicitHiddenPaths: packs an explicit include inside .config/assets/ and a .python-version dotfile, and asserts non-listed hidden paths (.secret.md, .git/config.md) stay excluded. It fails on current main (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.

`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.
Copilot AI lite review requested due to automatic review settings August 18, 2026 05:55

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

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.

Comment on lines +530 to +534
# 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
Comment on lines +514 to +518
# 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
Comment on lines +60 to +71
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

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 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".

Comment on lines +480 to +483
has_included_descendant = any(
included == normalized_dir_rel_path
or included.startswith(normalized_dir_rel_path + "/")
for included in files_included

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1 Badge 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.
@jaideeppyne

Copy link
Copy Markdown
Author

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 filesIncluded (never by extension). Extended the regression test with a visible, non-listed .config/assets/other.md and asserted it stays excluded.

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

packOptions.filesIncluded is silently ignored for any path under a dot-prefixed directory

2 participants