gerrit-clone 2.0.2__tar.gz → 2.2.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (77) hide show
  1. {gerrit_clone-2.0.2 → gerrit_clone-2.2.0}/.pre-commit-config.yaml +5 -5
  2. {gerrit_clone-2.0.2 → gerrit_clone-2.2.0}/PKG-INFO +26 -5
  3. {gerrit_clone-2.0.2 → gerrit_clone-2.2.0}/README.md +25 -4
  4. {gerrit_clone-2.0.2 → gerrit_clone-2.2.0}/action.yaml +44 -1
  5. {gerrit_clone-2.0.2 → gerrit_clone-2.2.0}/pyproject.toml +0 -6
  6. {gerrit_clone-2.0.2 → gerrit_clone-2.2.0}/src/gerrit_clone/cli.py +418 -110
  7. gerrit_clone-2.2.0/src/gerrit_clone/content_filter.py +1321 -0
  8. {gerrit_clone-2.0.2 → gerrit_clone-2.2.0}/src/gerrit_clone/file_logging.py +7 -1
  9. {gerrit_clone-2.0.2 → gerrit_clone-2.2.0}/src/gerrit_clone/mirror_manager.py +145 -71
  10. {gerrit_clone-2.0.2 → gerrit_clone-2.2.0}/src/gerrit_clone/models.py +66 -10
  11. {gerrit_clone-2.0.2 → gerrit_clone-2.2.0}/src/gerrit_clone/netrc.py +7 -4
  12. {gerrit_clone-2.0.2 → gerrit_clone-2.2.0}/src/gerrit_clone/refresh_manager.py +18 -3
  13. {gerrit_clone-2.0.2 → gerrit_clone-2.2.0}/src/gerrit_clone/refresh_worker.py +722 -45
  14. {gerrit_clone-2.0.2 → gerrit_clone-2.2.0}/tests/integration/test_github_clone.py +7 -0
  15. {gerrit_clone-2.0.2 → gerrit_clone-2.2.0}/tests/test_clone_manager_github_refresh.py +1 -1
  16. {gerrit_clone-2.0.2 → gerrit_clone-2.2.0}/tests/test_config.py +48 -0
  17. gerrit_clone-2.2.0/tests/test_content_filter.py +1260 -0
  18. {gerrit_clone-2.0.2 → gerrit_clone-2.2.0}/tests/test_file_logging_changes.py +36 -1
  19. {gerrit_clone-2.0.2 → gerrit_clone-2.2.0}/tests/test_mirror_manager.py +292 -0
  20. {gerrit_clone-2.0.2 → gerrit_clone-2.2.0}/tests/test_models.py +32 -0
  21. {gerrit_clone-2.0.2 → gerrit_clone-2.2.0}/tests/test_netrc.py +2 -4
  22. {gerrit_clone-2.0.2 → gerrit_clone-2.2.0}/tests/test_refresh_worker.py +715 -11
  23. {gerrit_clone-2.0.2 → gerrit_clone-2.2.0}/tests/test_worker.py +2 -2
  24. {gerrit_clone-2.0.2 → gerrit_clone-2.2.0}/tests/unit/test_discovery.py +4 -3
  25. {gerrit_clone-2.0.2 → gerrit_clone-2.2.0}/.gitignore +0 -0
  26. {gerrit_clone-2.0.2 → gerrit_clone-2.2.0}/IMPLEMENTATION.md +0 -0
  27. {gerrit_clone-2.0.2 → gerrit_clone-2.2.0}/LICENSE +0 -0
  28. {gerrit_clone-2.0.2 → gerrit_clone-2.2.0}/src/gerrit_clone/__init__.py +0 -0
  29. {gerrit_clone-2.0.2 → gerrit_clone-2.2.0}/src/gerrit_clone/clone_manager.py +0 -0
  30. {gerrit_clone-2.0.2 → gerrit_clone-2.2.0}/src/gerrit_clone/clone_utils.py +0 -0
  31. {gerrit_clone-2.0.2 → gerrit_clone-2.2.0}/src/gerrit_clone/concurrent_utils.py +0 -0
  32. {gerrit_clone-2.0.2 → gerrit_clone-2.2.0}/src/gerrit_clone/config.py +0 -0
  33. {gerrit_clone-2.0.2 → gerrit_clone-2.2.0}/src/gerrit_clone/discovery.py +0 -0
  34. {gerrit_clone-2.0.2 → gerrit_clone-2.2.0}/src/gerrit_clone/error_codes.py +0 -0
  35. {gerrit_clone-2.0.2 → gerrit_clone-2.2.0}/src/gerrit_clone/gerrit_api.py +0 -0
  36. {gerrit_clone-2.0.2 → gerrit_clone-2.2.0}/src/gerrit_clone/git_comparison.py +0 -0
  37. {gerrit_clone-2.0.2 → gerrit_clone-2.2.0}/src/gerrit_clone/git_utils.py +0 -0
  38. {gerrit_clone-2.0.2 → gerrit_clone-2.2.0}/src/gerrit_clone/github_api.py +0 -0
  39. {gerrit_clone-2.0.2 → gerrit_clone-2.2.0}/src/gerrit_clone/github_discovery.py +0 -0
  40. {gerrit_clone-2.0.2 → gerrit_clone-2.2.0}/src/gerrit_clone/github_worker.py +0 -0
  41. {gerrit_clone-2.0.2 → gerrit_clone-2.2.0}/src/gerrit_clone/logging.py +0 -0
  42. {gerrit_clone-2.0.2 → gerrit_clone-2.2.0}/src/gerrit_clone/output_utils.py +0 -0
  43. {gerrit_clone-2.0.2 → gerrit_clone-2.2.0}/src/gerrit_clone/pathing.py +0 -0
  44. {gerrit_clone-2.0.2 → gerrit_clone-2.2.0}/src/gerrit_clone/progress.py +0 -0
  45. {gerrit_clone-2.0.2 → gerrit_clone-2.2.0}/src/gerrit_clone/py.typed +0 -0
  46. {gerrit_clone-2.0.2 → gerrit_clone-2.2.0}/src/gerrit_clone/rate_limit.py +0 -0
  47. {gerrit_clone-2.0.2 → gerrit_clone-2.2.0}/src/gerrit_clone/reset_manager.py +0 -0
  48. {gerrit_clone-2.0.2 → gerrit_clone-2.2.0}/src/gerrit_clone/reset_models.py +0 -0
  49. {gerrit_clone-2.0.2 → gerrit_clone-2.2.0}/src/gerrit_clone/retry.py +0 -0
  50. {gerrit_clone-2.0.2 → gerrit_clone-2.2.0}/src/gerrit_clone/rich_status.py +0 -0
  51. {gerrit_clone-2.0.2 → gerrit_clone-2.2.0}/src/gerrit_clone/ssh_discovery.py +0 -0
  52. {gerrit_clone-2.0.2 → gerrit_clone-2.2.0}/src/gerrit_clone/unified_discovery.py +0 -0
  53. {gerrit_clone-2.0.2 → gerrit_clone-2.2.0}/src/gerrit_clone/worker.py +0 -0
  54. {gerrit_clone-2.0.2 → gerrit_clone-2.2.0}/tests/__init__.py +0 -0
  55. {gerrit_clone-2.0.2 → gerrit_clone-2.2.0}/tests/conftest.py +0 -0
  56. {gerrit_clone-2.0.2 → gerrit_clone-2.2.0}/tests/integration/__init__.py +0 -0
  57. {gerrit_clone-2.0.2 → gerrit_clone-2.2.0}/tests/integration/test_discovery_integration.py +0 -0
  58. {gerrit_clone-2.0.2 → gerrit_clone-2.2.0}/tests/test_action_cli_alignment.py +0 -0
  59. {gerrit_clone-2.0.2 → gerrit_clone-2.2.0}/tests/test_cli_netrc_options.py +0 -0
  60. {gerrit_clone-2.0.2 → gerrit_clone-2.2.0}/tests/test_clone_utils.py +0 -0
  61. {gerrit_clone-2.0.2 → gerrit_clone-2.2.0}/tests/test_gerrit_api.py +0 -0
  62. {gerrit_clone-2.0.2 → gerrit_clone-2.2.0}/tests/test_git_comparison.py +0 -0
  63. {gerrit_clone-2.0.2 → gerrit_clone-2.2.0}/tests/test_git_utils.py +0 -0
  64. {gerrit_clone-2.0.2 → gerrit_clone-2.2.0}/tests/test_github_api.py +0 -0
  65. {gerrit_clone-2.0.2 → gerrit_clone-2.2.0}/tests/test_logging.py +0 -0
  66. {gerrit_clone-2.0.2 → gerrit_clone-2.2.0}/tests/test_output_utils.py +0 -0
  67. {gerrit_clone-2.0.2 → gerrit_clone-2.2.0}/tests/test_pathing.py +0 -0
  68. {gerrit_clone-2.0.2 → gerrit_clone-2.2.0}/tests/test_project_filtering.py +0 -0
  69. {gerrit_clone-2.0.2 → gerrit_clone-2.2.0}/tests/test_rate_limit.py +0 -0
  70. {gerrit_clone-2.0.2 → gerrit_clone-2.2.0}/tests/test_refresh_manager.py +0 -0
  71. {gerrit_clone-2.0.2 → gerrit_clone-2.2.0}/tests/test_reset_manager.py +0 -0
  72. {gerrit_clone-2.0.2 → gerrit_clone-2.2.0}/tests/test_reset_models.py +0 -0
  73. {gerrit_clone-2.0.2 → gerrit_clone-2.2.0}/tests/test_retry.py +0 -0
  74. {gerrit_clone-2.0.2 → gerrit_clone-2.2.0}/tests/unit/__init__.py +0 -0
  75. {gerrit_clone-2.0.2 → gerrit_clone-2.2.0}/tests/unit/test_github_discovery.py +0 -0
  76. {gerrit_clone-2.0.2 → gerrit_clone-2.2.0}/tests/unit/test_github_worker.py +0 -0
  77. {gerrit_clone-2.0.2 → gerrit_clone-2.2.0}/tests/unit/test_unified_discovery.py +0 -0
@@ -51,7 +51,7 @@ repos:
51
51
  types: [yaml]
52
52
 
53
53
  - repo: https://github.com/astral-sh/ruff-pre-commit
54
- rev: 77039ccbba72c8aede339c5f8ae29b42aced0a2e # frozen: v0.15.18
54
+ rev: 01a675ea018f2fb714478a5ffb83fcea8374bb06 # frozen: v0.15.21
55
55
  hooks:
56
56
  - id: ruff
57
57
  files: ^(scripts|tests|custom_components)/.+\.py$
@@ -60,7 +60,7 @@ repos:
60
60
  files: ^(scripts|tests|custom_components)/.+\.py$
61
61
 
62
62
  - repo: https://github.com/pre-commit/mirrors-mypy
63
- rev: d2823d321df3af8f878f7ee3414dc94d037145b9 # frozen: v2.1.0
63
+ rev: 41e691678310dfd3833f7ab4e180ddb014310356 # frozen: v2.3.0
64
64
  hooks:
65
65
  - id: mypy
66
66
  additional_dependencies:
@@ -109,17 +109,17 @@ repos:
109
109
 
110
110
  # Requires a mirror, primary repo lacks .pre-commit-hooks.yaml
111
111
  - repo: https://github.com/DetachHead/basedpyright-prek-mirror
112
- rev: 5f6f2cb9fa8aec15105f77fd21e8dfe29838b16d # frozen: 1.39.8
112
+ rev: d55eabd2531b4f4a4c49c30fba627ce3a636ab79 # frozen: 1.39.9
113
113
  hooks:
114
114
  - id: basedpyright
115
115
 
116
116
  - repo: https://github.com/lfreleng-actions/gha-workflow-linter
117
- rev: bfc5489483353425f8e023902d91c3ae3584f955 # frozen: v1.2.0
117
+ rev: 4c3079dcb6e9e3c295f961ce5bd5b8585db698ca # frozen: v1.2.2
118
118
  hooks:
119
119
  - id: gha-workflow-linter
120
120
 
121
121
  - repo: https://github.com/python-jsonschema/check-jsonschema
122
- rev: 8ef330cbb7204d388aa7a620f9549bcea8009663 # frozen: 0.37.3
122
+ rev: 1a4bb160cab6417b3045e1b37b6b72449243e658 # frozen: 0.37.4
123
123
  hooks:
124
124
  - id: check-github-actions
125
125
  - id: check-github-workflows
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: gerrit-clone
3
- Version: 2.0.2
3
+ Version: 2.2.0
4
4
  Summary: A multi-threaded CLI tool for bulk cloning repositories from Gerrit servers
5
5
  Project-URL: Homepage, https://github.com/lfreleng-actions/gerrit-clone-action
6
6
  Project-URL: Documentation, https://github.com/lfreleng-actions/gerrit-clone-action#readme
@@ -57,16 +57,18 @@ reliability, speed, and CI/CD compatibility.
57
57
  - **Bulk Repository Discovery**: Fetches all projects via Gerrit REST API with
58
58
  intelligent filtering
59
59
  - **Multi-threaded Cloning**: Concurrent operations with auto-scaling thread
60
- pools (up to 32 workers for Gerrit, 64 for GitHub with 2x multiplier for
61
- network-limited operations)
60
+ pools (Gerrit uses a conservative auto-default of at most 8 concurrent SSH
61
+ sessions to avoid server-side throttling; GitHub uses up to 64 with a 2x
62
+ multiplier; override either with `--threads`)
62
63
  - **Hierarchy Preservation**: Maintains complete Gerrit project folder
63
64
  structure without flattening
64
65
  - **Complete Metadata Cloning**: Uses `git clone --mirror` by default to
65
66
  capture all refs, tags, and branches for complete repository backups
66
67
  - **GitHub Mirroring**: Mirror Gerrit repositories to GitHub organizations
67
68
  with automatic name transformation
68
- - **Robust Retry Logic**: Exponential backoff with jitter for transient
69
- network and server failures
69
+ - **Robust Retry Logic**: Exponential backoff with full jitter for transient
70
+ network and server failures, including a small bounded retry for Gerrit SSH
71
+ throttling that can surface as a transient "Permission denied" rejection
70
72
  - **SSH Integration**: Full SSH agent, identity file, and config support
71
73
  - **CI/CD Ready**: Non-interactive operation with structured JSON manifests
72
74
  - **Smart Filtering**: Automatically excludes system repos and archived
@@ -253,6 +255,25 @@ Automatically stash uncommitted changes before refresh:
253
255
  gerrit-clone refresh --output-path ~/onap --auto-stash
254
256
  ```
255
257
 
258
+ Force refresh (stash local changes, fix detached HEAD, restore feature-branch
259
+ checkouts to the default branch):
260
+
261
+ ```bash
262
+ gerrit-clone refresh --output-path ~/onap --force
263
+ ```
264
+
265
+ Hard reset: make local content exactly match the remote, discarding local-only
266
+ commits and any divergence. This is the single, explicit way to force-reset
267
+ local content and is a strict superset of `--force`:
268
+
269
+ ```bash
270
+ gerrit-clone refresh --output-path ~/onap --force-hard
271
+ ```
272
+
273
+ > **Note:** `--force-hard` is destructive: it permanently discards
274
+ > local-only commits on the default branch. It leaves other local
275
+ > branches untouched.
276
+
256
277
  Use rebase strategy instead of merge:
257
278
 
258
279
  ```bash
@@ -16,16 +16,18 @@ reliability, speed, and CI/CD compatibility.
16
16
  - **Bulk Repository Discovery**: Fetches all projects via Gerrit REST API with
17
17
  intelligent filtering
18
18
  - **Multi-threaded Cloning**: Concurrent operations with auto-scaling thread
19
- pools (up to 32 workers for Gerrit, 64 for GitHub with 2x multiplier for
20
- network-limited operations)
19
+ pools (Gerrit uses a conservative auto-default of at most 8 concurrent SSH
20
+ sessions to avoid server-side throttling; GitHub uses up to 64 with a 2x
21
+ multiplier; override either with `--threads`)
21
22
  - **Hierarchy Preservation**: Maintains complete Gerrit project folder
22
23
  structure without flattening
23
24
  - **Complete Metadata Cloning**: Uses `git clone --mirror` by default to
24
25
  capture all refs, tags, and branches for complete repository backups
25
26
  - **GitHub Mirroring**: Mirror Gerrit repositories to GitHub organizations
26
27
  with automatic name transformation
27
- - **Robust Retry Logic**: Exponential backoff with jitter for transient
28
- network and server failures
28
+ - **Robust Retry Logic**: Exponential backoff with full jitter for transient
29
+ network and server failures, including a small bounded retry for Gerrit SSH
30
+ throttling that can surface as a transient "Permission denied" rejection
29
31
  - **SSH Integration**: Full SSH agent, identity file, and config support
30
32
  - **CI/CD Ready**: Non-interactive operation with structured JSON manifests
31
33
  - **Smart Filtering**: Automatically excludes system repos and archived
@@ -212,6 +214,25 @@ Automatically stash uncommitted changes before refresh:
212
214
  gerrit-clone refresh --output-path ~/onap --auto-stash
213
215
  ```
214
216
 
217
+ Force refresh (stash local changes, fix detached HEAD, restore feature-branch
218
+ checkouts to the default branch):
219
+
220
+ ```bash
221
+ gerrit-clone refresh --output-path ~/onap --force
222
+ ```
223
+
224
+ Hard reset: make local content exactly match the remote, discarding local-only
225
+ commits and any divergence. This is the single, explicit way to force-reset
226
+ local content and is a strict superset of `--force`:
227
+
228
+ ```bash
229
+ gerrit-clone refresh --output-path ~/onap --force-hard
230
+ ```
231
+
232
+ > **Note:** `--force-hard` is destructive: it permanently discards
233
+ > local-only commits on the default branch. It leaves other local
234
+ > branches untouched.
235
+
215
236
  Use rebase strategy instead of merge:
216
237
 
217
238
  ```bash
@@ -232,6 +232,29 @@ inputs:
232
232
  description: "File logging level (DEBUG, INFO, WARNING, ERROR, CRITICAL)"
233
233
  required: false
234
234
  default: "DEBUG"
235
+ remove-files:
236
+ description: >-
237
+ Comma-separated list of file path patterns to remove
238
+ from cloned repositories. Supports shell-style globs
239
+ (e.g. '.github/**', '*.jar') and regex patterns
240
+ (prefix with 'regex:'). Uses git filter-repo when
241
+ available, falls back to worktree-based removal.
242
+ required: false
243
+ git-filter:
244
+ description: >-
245
+ Replace tokens in git history for matching projects.
246
+ Format: 'project:token1,token2;project2:token3'.
247
+ Semicolons separate project entries. Colons separate
248
+ project patterns from comma-separated tokens.
249
+ required: false
250
+ redact-secrets:
251
+ description: >-
252
+ Scan repository content for well-known credential
253
+ patterns (e.g. GitLab PATs, GitHub PATs, AWS keys)
254
+ and replace them with safe placeholder values.
255
+ Uses git filter-repo to rewrite history.
256
+ required: false
257
+ default: "false"
235
258
  build-from-source:
236
259
  description: >-
237
260
  Build CLI from the action's own source instead of
@@ -460,6 +483,13 @@ runs:
460
483
  INPUT_LOG_FILE: ${{ inputs.log-file }}
461
484
  INPUT_DISABLE_LOG_FILE: ${{ inputs.disable-log-file }}
462
485
  INPUT_LOG_LEVEL: ${{ inputs.log-level }}
486
+ INPUT_REMOVE_FILES: ${{ inputs.remove-files }}
487
+ # Passed straight to the CLI via its GERRIT_GIT_FILTER envvar
488
+ # rather than as a --git-filter argument, so the value (which
489
+ # may embed credential tokens) is never echoed in the command
490
+ # line logged below.
491
+ GERRIT_GIT_FILTER: ${{ inputs.git-filter }}
492
+ INPUT_REDACT_SECRETS: ${{ inputs.redact-secrets }}
463
493
  run: |
464
494
  # WARNING: Do NOT use literal empty expression syntax (dollar
465
495
  # brace-brace with nothing inside) anywhere in this run block,
@@ -470,7 +500,7 @@ runs:
470
500
  # Use action-managed SSH agent socket if it exists; otherwise,
471
501
  # fall back to any existing SSH_AUTH_SOCK on the runner so that
472
502
  # SSH-based clones using the runner's default agent/keys still work.
473
- SSH_AGENT_SOCK="/tmp/ssh_agent_${{ github.run_id }}.sock"
503
+ SSH_AGENT_SOCK="/tmp/ssh_agent_${GITHUB_RUN_ID}.sock"
474
504
  if [ -S "$SSH_AGENT_SOCK" ]; then
475
505
  export SSH_AUTH_SOCK="$SSH_AGENT_SOCK"
476
506
  fi
@@ -638,6 +668,19 @@ runs:
638
668
  cmd+=(--config-file "${INPUT_CONFIG_FILE}")
639
669
  fi
640
670
 
671
+ # Content filtering options
672
+ if [ -n "$INPUT_REMOVE_FILES" ]; then
673
+ cmd+=(--remove-files "$INPUT_REMOVE_FILES")
674
+ fi
675
+
676
+ # The git filter value is supplied to the CLI through the
677
+ # GERRIT_GIT_FILTER environment variable (set in the step env
678
+ # above) so it never appears in the echoed command line.
679
+
680
+ if [ "$INPUT_REDACT_SECRETS" = "true" ]; then
681
+ cmd+=(--redact-secrets)
682
+ fi
683
+
641
684
  # Add include-projects options (supports multiple)
642
685
  # Use env var to avoid shell injection from expression
643
686
  # interpolation in command substitutions; normalize
@@ -346,9 +346,3 @@ dev = [
346
346
  "pytest-mock>=3.15.1",
347
347
  "types-pyyaml>=6.0.12.20250915",
348
348
  ]
349
-
350
- [tool.uv]
351
- # Supply-chain cooldown: do not resolve anything published in the last
352
- # 7 days (rolling window; uv records it as a relative span in uv.lock).
353
- # Requires uv >= 0.9.17 for the relative-duration ("7 days") form.
354
- exclude-newer = "7 days"