Releases: tardigrde/gcpath
v0.10.0
v0.10.0 (2026-03-29)
Bug Fixes
-
Address PR review comments and SonarCloud findings (
c756062) -
Remove unimplemented --show-labels/--show-tags from ancestors command
-
Deduplicate _matches_labels/_matches_tags into generic _matches_metadata
-
Deduplicate _format_labels/_format_tags into generic _format_metadata
-
Use scope_resource for tag lookups instead of always querying org root
-
Replace duplicated "organizations/" literal with _RESOURCE_PREFIX_ORGS constant
-
Sanitize user-controlled data from cache log message
-
Fix single-iteration loop in build_folder_ancestors (parsers.py)
-
Reduce cognitive complexity across cli.py, core.py, formatters.py,
loaders.py, and parsers.py by extracting helper functions
Co-Authored-By: Claude Opus 4.6 noreply@anthropic.com
- Findings (
3be86b0)
Chores
- Update uv.lock (
ea0a688)
https://claude.ai/code/session_01HugtU9fbaL97tbb7zaqNPL
- deps: Bump pyasn1 in the uv group across 1 directory (
8adfd85)
Bumps the uv group with 1 update in the / directory: pyasn1.
Updates pyasn1 from 0.6.2 to 0.6.3
updated-dependencies:
- dependency-name: pyasn1 dependency-version: 0.6.3
dependency-type: indirect
dependency-group: uv ...
Signed-off-by: dependabot[bot] support@github.com
Features
- Add GCP labels and tags support to CLI commands (
d428c9a)
Add opt-in support for GCP resource labels (key-value pairs) and resource tags (Tag Manager bindings) across CLI commands. Labels are fetched via an additional SQL column in Asset API queries (cheap). Tags require a separate Asset API query against TagBinding resources (expensive). Both are only fetched when explicitly requested via CLI flags.
New CLI options on ls, tree, find, ancestors: - --show-labels: display labels in output - --show-tags: display tags in output - --label key=value: filter by label (repeatable, ANDed) - --tag key=value: filter by tag (repeatable, ANDed)
Changes across the stack: - core.py: labels/tags fields on Folder and Project dataclasses - parsers.py: extract_labels() and has_labels param on parse functions - loaders.py: include_labels in SQL builders, load_tags_asset/apply_tags - cache.py: bump CACHE_VERSION to 2, serialize/deserialize labels+tags - serializers.py: include labels/tags in JSON/YAML output when non-empty - formatters.py: show labels/tags in tree view labels
https://claude.ai/code/session_01HugtU9fbaL97tbb7zaqNPL
Detailed Changes: v0.9.0...v0.10.0
v0.9.0
v0.9.0 (2026-03-19)
Bug Fixes
-
Address PR review feedback — narrow exception handling and improve consistency (
d358e26) -
Narrow bare
except Exceptionin_resolve_scope()to catch only
PermissionDenied,NotFound, andGCPathError -
Move
import fnmatchfrom local scope to top-level imports (PEP 8) -
Add detailed comment explaining base_segments depth calculation
-
Make PermissionDenied handling consistent in
_fetch_chain_link():
folders and projects now use graceful fallback like organizations
Co-Authored-By: Claude Opus 4.6 noreply@anthropic.com
-
Reduce cognitive complexity and extract constants for SonarCloud (
819f5dd) -
Extract _fetch_chain_link() from resolve_ancestry_chain() to reduce
cognitive complexity from 25 to under 15 -
Extract _search_hierarchy() from find command to reduce complexity
-
Extract _get_node_parent_name(), _get_child_folders() in formatters
to reduce build_tree_view() complexity from 18 to under 15 -
Extract _node_to_dict(), _get_child_folders() in serializers to
reduce serialize_tree_node() complexity from 18 to under 15 -
Add _PREFIX_ORGS/_PREFIX_FOLDERS/_PREFIX_PROJECTS constants in core.py
to replace duplicated string literals
Co-Authored-By: Claude Opus 4.6 noreply@anthropic.com
-
Resolve CI failures, CodeQL alerts, and eager client initialization (
d054977) -
Add missing resolve_ancestry mock to two tests that pass a positional
resource tols -l, which triggers _resolve_scope() → resolve_ancestry()
and fails in CI without GCP credentials -
Fix 4 CodeQL "Incomplete URL substring sanitization" alerts by replacing
"example.com" in result.stdoutsubstring checks with exact-match
alternatives (split()/list comprehension) -
Lazily initialize GCP API clients in resolve_ancestry() so only the
client needed for the given resource prefix triggers credential lookup
Co-Authored-By: Claude Opus 4.6 noreply@anthropic.com
-
Resolve remaining SonarCloud issues — constants and complexity (
6257f97) -
Replace all bare "organizations/", "folders/", "projects/" string
literals in core.py with _PREFIX_ORGS/_PREFIX_FOLDERS/_PREFIX_PROJECTS -
Simplify _search_hierarchy() by extracting _get_resource_display_name()
and _get_resource_path() helpers, using a flat candidate list with
list comprehension instead of nested loops
Co-Authored-By: Claude Opus 4.6 noreply@anthropic.com
- Use explicit equality checks to resolve CodeQL URL sanitization alerts (
26f4896)
Replace "example.com" in result.stdout.split() with any(token == "example.com" for token in ...) to avoid CodeQL's incomplete-url-substring-sanitization rule, which still triggers on in with split lists.
Co-Authored-By: Claude Opus 4.6 noreply@anthropic.com
Documentation
- Document find, ancestors, --type filter, -L depth limit, and structured output (
ce92751)
Add README sections for features from PR #26 (--json/--yaml structured output) and PR #28 (find command, ancestors command, --type filter on ls/tree, -L depth limit on ls -R). Updates Quick Start and Features summary accordingly.
Co-Authored-By: Claude Opus 4.6 noreply@anthropic.com
Features
- Add --type filter, find command, ancestors command, and -L depth limit (
25e1ded)
Add four new features to gcpath CLI:
--type/-tfilter onlsandtreecommands (folder, project, organization)findcommand for glob-style name search with optional type and scope filtersancestorscommand to show full ancestry chain from resource to org root--level/-Ldepth limit onls -Rfor recursive listing
Refactors scope resolution into shared _resolve_scope() helper to reduce duplication between ls and find commands.
Co-Authored-By: Claude Opus 4.6 noreply@anthropic.com
Detailed Changes: v0.8.0...v0.9.0
v0.8.0
v0.8.0 (2026-03-17)
Bug Fixes
-
Address PR review feedback — reduce duplication in serializers and CLI (
40ae2c6) -
Extract _get_dumper() helper to eliminate repeated dumper selection logic
-
Remove unused hierarchy and show_ids params from serialize_tree_node
-
Reuse serialize_resource() for project dicts instead of duplicating
Co-Authored-By: Claude Opus 4.6 (1M context) noreply@anthropic.com
- Extract duplicated string literals to constants in conftest.py (
ed34bc6)
Resolves SonarCloud S1192 issues for "organizations/123", "folders/1", and "folders/11" repeated in test hierarchy builder.
Co-Authored-By: Claude Opus 4.6 (1M context) noreply@anthropic.com
-
Resolve SonarCloud duplication and unused variable issues (
aa47ef5) -
Extract shared test hierarchy builder to conftest.py (eliminates
~40-line duplication between test_cli.py and test_serializers.py) -
Fix all 6 unused variable warnings in test_serializers.py
Co-Authored-By: Claude Opus 4.6 (1M context) noreply@anthropic.com
Features
- Add --json and --yaml structured output flags (
949d8e3)
Add global --json and --yaml flags for machine-readable output across all commands (ls, tree, name, path). This makes gcpath composable with jq, yq, shell scripts, and CI pipelines.
- New serializers.py module for dict-building and JSON/YAML dumping
- Mutually exclusive flags with clear error message
- Cache status message moved to stderr to avoid polluting structured output
- pyyaml>=6.0 added as dependency
Co-Authored-By: Claude Opus 4.6 (1M context) noreply@anthropic.com
Detailed Changes: v0.7.1...v0.8.0
v0.7.1
v0.7.1 (2026-03-17)
Bug Fixes
- Extract duplicated "folders/" literal to constant in loaders (
b292a3e)
SonarCloud S1192: the string "folders/" was duplicated 5 times. Extract to module-level _FOLDER_PREFIX constant.
Co-Authored-By: Claude Opus 4.6 (1M context) noreply@anthropic.com
- Resolve SonarCloud code quality issues (
054bdbe)
Addresses 19 of 31 SonarCloud findings:
S1192 (CRITICAL): Extract duplicated string literals into module-level constants - Added _RESOURCE_PREFIX_PROJECTS, _RESOURCE_PREFIX_FOLDERS, _RESOURCE_PREFIX_ORGS - Added _RESOURCE_PREFIXES tuple and _REFRESH_HELP constant - Replaced all occurrences in cli.py
S1871 (MAJOR): Merge duplicate branches - formatters.py: Merged Folder/Project branches in get_display_path and _get_node_label - parsers.py: Merged hasattr/get and isinstance/dict checks in extract_value
S3358 (MAJOR): Extract nested ternaries into if/else blocks - loaders.py: Refactored folder_parent and project parent_res determination logic
S3776 (CRITICAL): Reduce cognitive complexity with helper extraction - cli.py: Extracted _try_read_cache() from _load_hierarchy() - core.py: Extracted _find_orgless_project() from get_resource_name() - loaders.py: Extracted _build_single_ancestor_chain() from fix_folder_ancestors()
S7504 (MINOR): Remove unnecessary list() call - loaders.py: Changed list(node.folders.values()) to node.folders.values()
S2737 (MINOR): Remove bare except clause - core.py: Removed no-op try/except that just re-raised
S2772 (MINOR): Remove unneeded pass - tests/test_cli.py: Replaced pass with meaningful assertion
S1481 (MINOR): Fix unused variable - tests/test_formatters.py: Changed folders to _ for unused variable
Co-Authored-By: Claude Opus 4.6 noreply@anthropic.com
Testing
- Add coverage for extracted helper functions (
ab315ee)
Add direct tests for:
- _build_single_ancestor_chain (loaders.py)
- _find_orgless_project (core.py)
- _try_read_cache (cli.py)
Coverage improved from 87% to 88%
Co-Authored-By: Claude Opus 4.6 noreply@anthropic.com
- Add coverage for loader conditional branches and remove dead code (
37b7f01)
Cover the refactored if/elif/else branches in load_folders_asset and load_projects_asset that handle fallback parent resolution. Remove unreachable elif/else in the last else-branch where ancestors is guaranteed non-empty.
Co-Authored-By: Claude Opus 4.6 (1M context) noreply@anthropic.com
Detailed Changes: v0.7.0...v0.7.1
v0.7.0
v0.7.0 (2026-03-09)
Bug Fixes
-
Validate resource format and escape rich markup in stats command (
7728b16) -
Add explicit else branch for invalid resource formats (not
organizations/ or folders/) with a clear "Invalid resource format"
error message instead of silently loading the full hierarchy -
Escape user-supplied scope label with rich.markup.escape to prevent
markup injection via crafted resource name arguments -
Add test_stats_invalid_scope_error test case
https://claude.ai/code/session_01JxDqkYXvoag1R6LWBV8Mtq
Chores
- deps: Bump protobuf in the uv group across 1 directory (
176815d)
Bumps the uv group with 1 update in the / directory: protobuf.
Updates protobuf from 6.33.2 to 6.33.5
updated-dependencies:
- dependency-name: protobuf dependency-version: 6.33.5
dependency-type: indirect
dependency-group: uv ...
Signed-off-by: dependabot[bot] support@github.com
Features
- Add stats subcommand for folder/project counts in a scope (
9a28f93)
Adds a new stats CLI subcommand that reports the number of organizations, folders, and projects within a given scope (organization or folder). When no scope is provided, it reports totals across all accessible organizations. Projects are rejected as the starting scope since they are leaf nodes.
https://claude.ai/code/session_01JxDqkYXvoag1R6LWBV8Mtq
Detailed Changes: v0.6.1...v0.7.0
v0.6.1
v0.6.1 (2026-03-07)
Bug Fixes
- deps: Bump pyasn1 to 0.6.2 and urllib3 to 2.6.3 (
bd4c47c)
Fixes CVE-2026-23490 (pyasn1 OID decoder issue) and CVE-2026-21441 (urllib3 decompression-bomb bypass, High severity).
Co-Authored-By: Claude Sonnet 4.6 noreply@anthropic.com
Documentation
- Refocus README on CLI usage, add pipx install, remove roadmap (
cb03af6)
Move Python API section to the end as a secondary use case. Add pipx as a recommended installation option alongside pip and uv. Remove the roadmap section.
https://claude.ai/code/session_01E5TmezTsqmhrkBS6HdVSL9
Detailed Changes: v0.6.0...v0.6.1
v0.6.0
v0.6.0 (2026-03-07)
Chores
- deps: Bump protobuf in the uv group across 1 directory (
a21b624)
Bumps the uv group with 1 update in the / directory: protobuf.
Updates protobuf from 6.33.2 to 6.33.5
updated-dependencies:
- dependency-name: protobuf dependency-version: 6.33.5
dependency-type: indirect
dependency-group: uv ...
Signed-off-by: dependabot[bot] support@github.com
- deps: Configure Dependabot to use pip for updates (
322a771)
Features
-
Add Python API documentation and library usage examples (
aa65f59) -
Add comprehensive "Python API" section to README.md covering:
- Basic usage with Hierarchy.load() (both RM and Asset API modes)
- Path ↔ resource name conversion methods
- Lightweight single-resource lookup via Hierarchy.resolve_ancestry()
- Scoped loading for large or restricted hierarchies
- Error handling with GCPathError, ResourceNotFoundError, PathParsingError
- API reference table for all public symbols
-
Update pyproject.toml description to reflect library capability
-
Add "Topic :: Software Development :: Libraries :: Python Modules" classifier
https://claude.ai/code/session_01M3eDcpXVjivW3zbCXnvbmx
Detailed Changes: v0.5.1...v0.6.0
v0.5.1
v0.5.1 (2026-02-17)
Bug Fixes
- Make cache scope-aware so entrypoint loads are cached (
c288a51)
The cache was completely bypassed when an entrypoint was configured because _load_hierarchy() only read/wrote cache when scope_resource was None. Now the cache stores which scope it was built for and only serves hits when the scope matches, enabling instant subsequent commands with entrypoints.
Co-Authored-By: Claude Opus 4.6 noreply@anthropic.com
Detailed Changes: v0.5.0...v0.5.1
v0.5.0
v0.5.0 (2026-02-16)
Features
- Add folder entrypoint support for folder admins without org access (
e15c6ca)
Allow users who only have access to a folder (not the parent organization) to use ls, tree, diagram, and name commands by configuring a folder as the default entrypoint. When org loading fails and the scope is a folder, a fallback path creates a synthetic OrganizationNode and queries the Asset API directly from the folder scope.
Adds config subcommands (set-entrypoint, show, clear-entrypoint) and a global --entrypoint/-e flag.
Co-Authored-By: Claude Opus 4.6 noreply@anthropic.com
Detailed Changes: v0.4.1...v0.5.0
v0.4.1
v0.4.1 (2026-02-16)
Bug Fixes
- Add missing v0.4.0 CHANGELOG entry and pin PSR to v9 (
0d35cec)
The v0.4.0 release was created by PSR v10.x (pulled via unpinned --with python-semantic-release) which silently skipped changelog generation due to breaking template changes from v9.
- Add the v0.4.0 CHANGELOG entry manually
- Pin PSR to >=9,<10 in release workflow to prevent version drift
- Revert changelog config key to v9 format
Co-Authored-By: Claude Opus 4.6 noreply@anthropic.com
Detailed Changes: v0.4.0...v0.4.1