gitlab-projects-settings 6.0.0__tar.gz → 6.1.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 (79) hide show
  1. {gitlab_projects_settings-6.0.0 → gitlab_projects_settings-6.1.0}/.gitlab-ci.yml +3 -1
  2. {gitlab_projects_settings-6.0.0 → gitlab_projects_settings-6.1.0}/CHANGELOG.md +39 -0
  3. {gitlab_projects_settings-6.0.0/gitlab_projects_settings.egg-info → gitlab_projects_settings-6.1.0}/PKG-INFO +14 -2
  4. {gitlab_projects_settings-6.0.0 → gitlab_projects_settings-6.1.0}/docs/prepare.sh +3 -2
  5. {gitlab_projects_settings-6.0.0 → gitlab_projects_settings-6.1.0/gitlab_projects_settings.egg-info}/PKG-INFO +14 -2
  6. {gitlab_projects_settings-6.0.0 → gitlab_projects_settings-6.1.0}/sonar-project.properties +3 -0
  7. {gitlab_projects_settings-6.0.0 → gitlab_projects_settings-6.1.0}/src/cli/entrypoint.py +77 -34
  8. {gitlab_projects_settings-6.0.0 → gitlab_projects_settings-6.1.0}/src/features/gitlab.py +164 -38
  9. {gitlab_projects_settings-6.0.0 → gitlab_projects_settings-6.1.0}/src/prints/colors.py +1 -1
  10. {gitlab_projects_settings-6.0.0 → gitlab_projects_settings-6.1.0}/.coveragerc +0 -0
  11. {gitlab_projects_settings-6.0.0 → gitlab_projects_settings-6.1.0}/.cz.yaml +0 -0
  12. {gitlab_projects_settings-6.0.0 → gitlab_projects_settings-6.1.0}/.gitattributes +0 -0
  13. {gitlab_projects_settings-6.0.0 → gitlab_projects_settings-6.1.0}/.gitignore +0 -0
  14. {gitlab_projects_settings-6.0.0 → gitlab_projects_settings-6.1.0}/.markdownlint.json +0 -0
  15. {gitlab_projects_settings-6.0.0 → gitlab_projects_settings-6.1.0}/.pre-commit-config.yaml +0 -0
  16. {gitlab_projects_settings-6.0.0 → gitlab_projects_settings-6.1.0}/.style.yapf +0 -0
  17. {gitlab_projects_settings-6.0.0 → gitlab_projects_settings-6.1.0}/.vscode/extensions.json +0 -0
  18. {gitlab_projects_settings-6.0.0 → gitlab_projects_settings-6.1.0}/.vscode/settings.json +0 -0
  19. {gitlab_projects_settings-6.0.0 → gitlab_projects_settings-6.1.0}/LICENSE +0 -0
  20. {gitlab_projects_settings-6.0.0 → gitlab_projects_settings-6.1.0}/README.md +0 -0
  21. {gitlab_projects_settings-6.0.0 → gitlab_projects_settings-6.1.0}/config/cliff.toml +0 -0
  22. {gitlab_projects_settings-6.0.0 → gitlab_projects_settings-6.1.0}/containers/build/Dockerfile +0 -0
  23. {gitlab_projects_settings-6.0.0 → gitlab_projects_settings-6.1.0}/containers/codestyle/Dockerfile +0 -0
  24. {gitlab_projects_settings-6.0.0 → gitlab_projects_settings-6.1.0}/containers/deploy/Dockerfile +0 -0
  25. {gitlab_projects_settings-6.0.0 → gitlab_projects_settings-6.1.0}/containers/pages/Dockerfile +0 -0
  26. {gitlab_projects_settings-6.0.0 → gitlab_projects_settings-6.1.0}/containers/rehost/images.txt +0 -0
  27. {gitlab_projects_settings-6.0.0 → gitlab_projects_settings-6.1.0}/containers/test-coverage-linux/Dockerfile +0 -0
  28. {gitlab_projects_settings-6.0.0 → gitlab_projects_settings-6.1.0}/containers/test-coverage-windows/Dockerfile +0 -0
  29. {gitlab_projects_settings-6.0.0 → gitlab_projects_settings-6.1.0}/containers/test-linux/Dockerfile +0 -0
  30. {gitlab_projects_settings-6.0.0 → gitlab_projects_settings-6.1.0}/docs/.pages.in +0 -0
  31. {gitlab_projects_settings-6.0.0 → gitlab_projects_settings-6.1.0}/docs/assets/images/favicon.png +0 -0
  32. {gitlab_projects_settings-6.0.0 → gitlab_projects_settings-6.1.0}/docs/assets/scripts/mkdocs-exporter.js +0 -0
  33. {gitlab_projects_settings-6.0.0 → gitlab_projects_settings-6.1.0}/docs/assets/stylesheets/custom.css +0 -0
  34. {gitlab_projects_settings-6.0.0 → gitlab_projects_settings-6.1.0}/docs/assets/stylesheets/pdf.scss +0 -0
  35. {gitlab_projects_settings-6.0.0 → gitlab_projects_settings-6.1.0}/docs/robots.txt +0 -0
  36. {gitlab_projects_settings-6.0.0 → gitlab_projects_settings-6.1.0}/docs/templates/covers/back.html.j2 +0 -0
  37. {gitlab_projects_settings-6.0.0 → gitlab_projects_settings-6.1.0}/docs/templates/covers/front.html.j2 +0 -0
  38. {gitlab_projects_settings-6.0.0 → gitlab_projects_settings-6.1.0}/gitlab_projects_settings.egg-info/SOURCES.txt +0 -0
  39. {gitlab_projects_settings-6.0.0 → gitlab_projects_settings-6.1.0}/gitlab_projects_settings.egg-info/dependency_links.txt +0 -0
  40. {gitlab_projects_settings-6.0.0 → gitlab_projects_settings-6.1.0}/gitlab_projects_settings.egg-info/entry_points.txt +0 -0
  41. {gitlab_projects_settings-6.0.0 → gitlab_projects_settings-6.1.0}/gitlab_projects_settings.egg-info/requires.txt +0 -0
  42. {gitlab_projects_settings-6.0.0 → gitlab_projects_settings-6.1.0}/gitlab_projects_settings.egg-info/top_level.txt +0 -0
  43. {gitlab_projects_settings-6.0.0 → gitlab_projects_settings-6.1.0}/mkdocs.yml +0 -0
  44. {gitlab_projects_settings-6.0.0 → gitlab_projects_settings-6.1.0}/mypy.ini +0 -0
  45. {gitlab_projects_settings-6.0.0 → gitlab_projects_settings-6.1.0}/requirements/build.txt +0 -0
  46. {gitlab_projects_settings-6.0.0 → gitlab_projects_settings-6.1.0}/requirements/coverage.txt +0 -0
  47. {gitlab_projects_settings-6.0.0 → gitlab_projects_settings-6.1.0}/requirements/deploy.txt +0 -0
  48. {gitlab_projects_settings-6.0.0 → gitlab_projects_settings-6.1.0}/requirements/pages.txt +0 -0
  49. {gitlab_projects_settings-6.0.0 → gitlab_projects_settings-6.1.0}/requirements/quality.txt +0 -0
  50. {gitlab_projects_settings-6.0.0 → gitlab_projects_settings-6.1.0}/requirements/runtime.txt +0 -0
  51. {gitlab_projects_settings-6.0.0 → gitlab_projects_settings-6.1.0}/requirements/tests.txt +0 -0
  52. {gitlab_projects_settings-6.0.0 → gitlab_projects_settings-6.1.0}/setup.cfg +0 -0
  53. {gitlab_projects_settings-6.0.0 → gitlab_projects_settings-6.1.0}/setup.py +0 -0
  54. {gitlab_projects_settings-6.0.0 → gitlab_projects_settings-6.1.0}/src/__init__.py +0 -0
  55. {gitlab_projects_settings-6.0.0 → gitlab_projects_settings-6.1.0}/src/__main__.py +0 -0
  56. {gitlab_projects_settings-6.0.0 → gitlab_projects_settings-6.1.0}/src/cli/__init__.py +0 -0
  57. {gitlab_projects_settings-6.0.0 → gitlab_projects_settings-6.1.0}/src/cli/main.py +0 -0
  58. {gitlab_projects_settings-6.0.0 → gitlab_projects_settings-6.1.0}/src/features/__init__.py +0 -0
  59. {gitlab_projects_settings-6.0.0 → gitlab_projects_settings-6.1.0}/src/package/__init__.py +0 -0
  60. {gitlab_projects_settings-6.0.0 → gitlab_projects_settings-6.1.0}/src/package/bundle.py +0 -0
  61. {gitlab_projects_settings-6.0.0 → gitlab_projects_settings-6.1.0}/src/package/settings.py +0 -0
  62. {gitlab_projects_settings-6.0.0 → gitlab_projects_settings-6.1.0}/src/package/updates.py +0 -0
  63. {gitlab_projects_settings-6.0.0 → gitlab_projects_settings-6.1.0}/src/package/version.py +0 -0
  64. {gitlab_projects_settings-6.0.0 → gitlab_projects_settings-6.1.0}/src/prints/__init__.py +0 -0
  65. {gitlab_projects_settings-6.0.0 → gitlab_projects_settings-6.1.0}/src/prints/boxes.py +0 -0
  66. {gitlab_projects_settings-6.0.0 → gitlab_projects_settings-6.1.0}/src/prints/themes.py +0 -0
  67. {gitlab_projects_settings-6.0.0 → gitlab_projects_settings-6.1.0}/src/system/__init__.py +0 -0
  68. {gitlab_projects_settings-6.0.0 → gitlab_projects_settings-6.1.0}/src/system/platform.py +0 -0
  69. {gitlab_projects_settings-6.0.0 → gitlab_projects_settings-6.1.0}/src/types/__init__.py +0 -0
  70. {gitlab_projects_settings-6.0.0 → gitlab_projects_settings-6.1.0}/src/types/environments.py +0 -0
  71. {gitlab_projects_settings-6.0.0 → gitlab_projects_settings-6.1.0}/src/types/gitlab.py +0 -0
  72. {gitlab_projects_settings-6.0.0 → gitlab_projects_settings-6.1.0}/src/types/namespaces.py +0 -0
  73. {gitlab_projects_settings-6.0.0 → gitlab_projects_settings-6.1.0}/src/types/strings.py +0 -0
  74. {gitlab_projects_settings-6.0.0 → gitlab_projects_settings-6.1.0}/tests/arguments/test.sh +0 -0
  75. {gitlab_projects_settings-6.0.0 → gitlab_projects_settings-6.1.0}/tests/colors/test.sh +0 -0
  76. {gitlab_projects_settings-6.0.0 → gitlab_projects_settings-6.1.0}/tests/macos/test.sh +0 -0
  77. {gitlab_projects_settings-6.0.0 → gitlab_projects_settings-6.1.0}/tests/settings/test.sh +0 -0
  78. {gitlab_projects_settings-6.0.0 → gitlab_projects_settings-6.1.0}/tests/versions/test.sh +0 -0
  79. {gitlab_projects_settings-6.0.0 → gitlab_projects_settings-6.1.0}/tests/windows/test.sh +0 -0
@@ -627,6 +627,7 @@ readme:
627
627
  changes:
628
628
  - 'CHANGELOG.md'
629
629
  - 'requirements/**/*'
630
+ - 'sonar-project.properties'
630
631
  - 'src/**/*'
631
632
  - 'tests/**/*'
632
633
  - if: $CI_COMMIT_TAG || $CI_PIPELINE_SOURCE == "trigger" || $CI_PIPELINE_SOURCE == "web" || $CI_COMMIT_REF_NAME != $CI_DEFAULT_BRANCH
@@ -728,6 +729,7 @@ sonarcloud:
728
729
  changes:
729
730
  - 'CHANGELOG.md'
730
731
  - 'requirements/**/*'
732
+ - 'sonar-project.properties'
731
733
  - 'src/**/*'
732
734
  - 'tests/**/*'
733
735
  when: always
@@ -881,7 +883,7 @@ pages:
881
883
  # Prepare documentation
882
884
  - |
883
885
  if [ ! -z "${CI_LOCAL:-}" ]; then
884
- find ./config/* ./docs/* ./mkdocs.yml ./README.md -not -path ./docs/assets/stylesheets/variables.scss -type f | entr -n sh ./docs/prepare.sh &
886
+ find ./config/* ./docs/.* ./docs/* ./mkdocs.yml ./README.md -not -path ./docs/assets/stylesheets/variables.scss -type f | entr -n sh ./docs/prepare.sh &
885
887
  echo -n "${!}" >./docs/.serve.pid
886
888
  sleep 2
887
889
  else
@@ -1,5 +1,44 @@
1
1
  # Changelog
2
2
 
3
+ <a name="6.1.0"></a>
4
+ ## [6.1.0](https://gitlab.com/RadianDevCore/tools/gitlab-projects-settings/compare/6.0.1...6.1.0) (2025-02-09)
5
+
6
+ ### ✨ Features
7
+
8
+ - **entrypoint, gitlab:** show already valid settings in green ([ed29b3a](https://gitlab.com/RadianDevCore/tools/gitlab-projects-settings/commit/ed29b3a24a86e9fd37cc5857c7f3010b77bb34fa))
9
+ - **entrypoint, gitlab:** show GitLab username upon authentication ([6beea96](https://gitlab.com/RadianDevCore/tools/gitlab-projects-settings/commit/6beea961771d3e3c58b0be3896d65d5353493adf))
10
+
11
+ ### 🐛 Bug Fixes
12
+
13
+ - **entrypoint:** prevent acces to projects shared with groups ([c2308cd](https://gitlab.com/RadianDevCore/tools/gitlab-projects-settings/commit/c2308cd8f5aceb3ba8c7f7733ab7f95f91676fcf))
14
+
15
+ ### 📚 Documentation
16
+
17
+ - **docs:** use '<span class=page-break>' instead of '<div>' ([fe38e5e](https://gitlab.com/RadianDevCore/tools/gitlab-projects-settings/commit/fe38e5ee4067f919191ce61b35c714a48ec927b3))
18
+ - **prepare:** avoid 'TOC' injection if 'hide: - toc' is used ([b05111b](https://gitlab.com/RadianDevCore/tools/gitlab-projects-settings/commit/b05111bc9f25a9dcf29db56fecfc8240a2cae575))
19
+
20
+ ### 🎨 Styling
21
+
22
+ - **colors:** ignore 'Colored' import 'Incompatible import' warning ([56cb0df](https://gitlab.com/RadianDevCore/tools/gitlab-projects-settings/commit/56cb0df63be7cebd812204f30609bb6b04dec94b))
23
+
24
+ ### ⚙️ Cleanups
25
+
26
+ - **sonar-project:** configure coverage checks in SonarCloud ([0a23f99](https://gitlab.com/RadianDevCore/tools/gitlab-projects-settings/commit/0a23f99271c9f3ef27b0d678ff2f7e635059a62d))
27
+
28
+ ### 🚀 CI
29
+
30
+ - **gitlab-ci:** run coverage jobs if 'sonar-project.properties' changes ([b3efefc](https://gitlab.com/RadianDevCore/tools/gitlab-projects-settings/commit/b3efefc5e958093797e54ed69aac9d27f33f834c))
31
+ - **gitlab-ci:** watch for 'docs/.*' changes in 'pages' jobs ([a4c1b0d](https://gitlab.com/RadianDevCore/tools/gitlab-projects-settings/commit/a4c1b0dbc07298e65815c62a3593bcc5039c1e10))
32
+
33
+
34
+ <a name="6.0.1"></a>
35
+ ## [6.0.1](https://gitlab.com/RadianDevCore/tools/gitlab-projects-settings/compare/6.0.0...6.0.1) (2025-01-01)
36
+
37
+ ### 🐛 Bug Fixes
38
+
39
+ - **gitlab:** catch 'StopIteration' exceptions upon missing boards ([e200557](https://gitlab.com/RadianDevCore/tools/gitlab-projects-settings/commit/e200557e86edc81c556421adb613e7d4e81c56ed))
40
+
41
+
3
42
  <a name="6.0.0"></a>
4
43
  ## [6.0.0](https://gitlab.com/RadianDevCore/tools/gitlab-projects-settings/compare/5.4.0...6.0.0) (2025-01-01)
5
44
 
@@ -1,6 +1,6 @@
1
- Metadata-Version: 2.1
1
+ Metadata-Version: 2.2
2
2
  Name: gitlab-projects-settings
3
- Version: 6.0.0
3
+ Version: 6.1.0
4
4
  Summary: Configure GitLab groups and projects settings automatically
5
5
  Home-page: https://gitlab.com/RadianDevCore/tools/gitlab-projects-settings
6
6
  Author: Adrian DC
@@ -33,6 +33,18 @@ Requires-Dist: python-gitlab>=4.4.0
33
33
  Requires-Dist: questionary>=2.0.1
34
34
  Requires-Dist: setuptools>=45.1.0
35
35
  Requires-Dist: update_checker>=0.18.0
36
+ Dynamic: author
37
+ Dynamic: author-email
38
+ Dynamic: classifier
39
+ Dynamic: description
40
+ Dynamic: description-content-type
41
+ Dynamic: home-page
42
+ Dynamic: keywords
43
+ Dynamic: license
44
+ Dynamic: project-url
45
+ Dynamic: requires-dist
46
+ Dynamic: requires-python
47
+ Dynamic: summary
36
48
 
37
49
  # gitlab-projects-settings
38
50
 
@@ -62,7 +62,8 @@ sed -i \
62
62
  # Inject 'toc' section (PDF only)
63
63
  find "${docs_path}/" -name '*.md' \
64
64
  | while read -r file_path; do
65
- if ! grep -q '\[TOC\]' "${file_path}" \
65
+ if ! grep -A1 '^hide:$' "${file_path}" | grep -q '^ - toc$' \
66
+ && ! grep -q '\[TOC\]' "${file_path}" \
66
67
  && ! grep -c '^## ' "${file_path}" | grep -q '^0$\|^1$' \
67
68
  && ! grep -q '^<!-- documentation no-toc -->$' "${file_path}" \
68
69
  && ! grep -q '^<!-- generated documentation section -->$' "${file_path}"; then
@@ -72,7 +73,7 @@ find "${docs_path}/" -name '*.md' \
72
73
  \
73
74
  [TOC]\
74
75
  \
75
- <div class="page-break"><\/div>/
76
+ <span class="page-break"><\/span>/
76
77
  }
77
78
  ' "${file_path}"
78
79
  fi
@@ -1,6 +1,6 @@
1
- Metadata-Version: 2.1
1
+ Metadata-Version: 2.2
2
2
  Name: gitlab-projects-settings
3
- Version: 6.0.0
3
+ Version: 6.1.0
4
4
  Summary: Configure GitLab groups and projects settings automatically
5
5
  Home-page: https://gitlab.com/RadianDevCore/tools/gitlab-projects-settings
6
6
  Author: Adrian DC
@@ -33,6 +33,18 @@ Requires-Dist: python-gitlab>=4.4.0
33
33
  Requires-Dist: questionary>=2.0.1
34
34
  Requires-Dist: setuptools>=45.1.0
35
35
  Requires-Dist: update_checker>=0.18.0
36
+ Dynamic: author
37
+ Dynamic: author-email
38
+ Dynamic: classifier
39
+ Dynamic: description
40
+ Dynamic: description-content-type
41
+ Dynamic: home-page
42
+ Dynamic: keywords
43
+ Dynamic: license
44
+ Dynamic: project-url
45
+ Dynamic: requires-dist
46
+ Dynamic: requires-python
47
+ Dynamic: summary
36
48
 
37
49
  # gitlab-projects-settings
38
50
 
@@ -16,3 +16,6 @@ sonar.sources=src
16
16
 
17
17
  # Python versions
18
18
  sonar.python.version=3.8, 3.9, 3.10, 3.11, 3.12
19
+
20
+ # Patterns used to exclude some files from coverage report.
21
+ sonar.coverage.exclusions=setup.py
@@ -93,6 +93,7 @@ class Entrypoint:
93
93
  )
94
94
  print(f'{Colors.BOLD} - GitLab host: '
95
95
  f'{Colors.GREEN}{gitlab.url}'
96
+ f'{Colors.CYAN} ({gitlab.username})'
96
97
  f'{Colors.RESET}')
97
98
  Platform.flush()
98
99
 
@@ -189,6 +190,7 @@ class Entrypoint:
189
190
  for group_project in sorted(
190
191
  group.projects.list(
191
192
  get_all=True,
193
+ with_shared=False,
192
194
  include_subgroups=not options.exclude_subgroups,
193
195
  order_by='path',
194
196
  sort='asc',
@@ -279,6 +281,9 @@ class Entrypoint:
279
281
  subgroup: bool = False,
280
282
  ) -> Result:
281
283
 
284
+ # Variables
285
+ changed: bool
286
+
282
287
  # Acquire group
283
288
  group = gitlab.group(criteria)
284
289
 
@@ -325,9 +330,12 @@ class Entrypoint:
325
330
 
326
331
  # Set group description
327
332
  if options.set_description:
328
- gitlab.group_set_description(criteria, options.set_description)
333
+ changed = gitlab.group_set_description(
334
+ criteria,
335
+ options.set_description,
336
+ )
329
337
  print(f'{Colors.BOLD} - Set description: '
330
- f'{Colors.CYAN}{options.set_description}'
338
+ f'{Colors.CYAN if changed else Colors.GREEN}{options.set_description}'
331
339
  f'{Colors.RESET}')
332
340
  Platform.flush()
333
341
 
@@ -345,9 +353,12 @@ class Entrypoint:
345
353
  ):
346
354
  description = f'{Namespaces.describe(name=group.name)}' \
347
355
  f'{parent_description_text}'
348
- gitlab.group_set_description(criteria, description)
356
+ changed = gitlab.group_set_description(
357
+ criteria,
358
+ description,
359
+ )
349
360
  print(f'{Colors.BOLD} - Updated description: '
350
- f'{Colors.CYAN}{description}'
361
+ f'{Colors.CYAN if changed else Colors.GREEN}{description}'
351
362
  f'{Colors.RESET}')
352
363
  Platform.flush()
353
364
  else:
@@ -366,7 +377,10 @@ class Entrypoint:
366
377
 
367
378
  # Set group avatar
368
379
  if options.set_avatar:
369
- gitlab.group_set_avatar(criteria, options.set_avatar)
380
+ gitlab.group_set_avatar(
381
+ criteria,
382
+ options.set_avatar,
383
+ )
370
384
  print(f'{Colors.BOLD} - Set avatar: '
371
385
  f'{Colors.CYAN}{options.set_avatar}'
372
386
  f'{Colors.RESET}')
@@ -374,20 +388,26 @@ class Entrypoint:
374
388
 
375
389
  # Set group roles create projects
376
390
  if options.set_roles_create_projects:
377
- gitlab.group_set_roles_create_projects(criteria,
378
- options.set_roles_create_projects)
379
- print(f'{Colors.BOLD} - Set roles allowed to create projects: '
380
- f'{Colors.CYAN}{options.set_roles_create_projects}'
381
- f'{Colors.RESET}')
391
+ changed = gitlab.group_set_roles_create_projects(
392
+ criteria,
393
+ options.set_roles_create_projects,
394
+ )
395
+ print(
396
+ f'{Colors.BOLD} - Set roles allowed to create projects: '
397
+ f'{Colors.CYAN if changed else Colors.GREEN}{options.set_roles_create_projects}'
398
+ f'{Colors.RESET}')
382
399
  Platform.flush()
383
400
 
384
401
  # Set group roles create subgroups
385
402
  if options.set_roles_create_subgroups:
386
- gitlab.group_set_roles_create_subgroups(criteria,
387
- options.set_roles_create_subgroups)
388
- print(f'{Colors.BOLD} - Set roles allowed to create subgroups: '
389
- f'{Colors.CYAN}{options.set_roles_create_subgroups}'
390
- f'{Colors.RESET}')
403
+ changed = gitlab.group_set_roles_create_subgroups(
404
+ criteria,
405
+ options.set_roles_create_subgroups,
406
+ )
407
+ print(
408
+ f'{Colors.BOLD} - Set roles allowed to create subgroups: '
409
+ f'{Colors.CYAN if changed else Colors.GREEN}{options.set_roles_create_subgroups}'
410
+ f'{Colors.RESET}')
391
411
  Platform.flush()
392
412
 
393
413
  # Get group labels
@@ -446,6 +466,9 @@ class Entrypoint:
446
466
  criteria: str,
447
467
  ) -> Result:
448
468
 
469
+ # Variables
470
+ changed: bool
471
+
449
472
  # Acquire project
450
473
  project = gitlab.project(criteria)
451
474
 
@@ -479,9 +502,12 @@ class Entrypoint:
479
502
 
480
503
  # Set project description
481
504
  if options.set_description:
482
- gitlab.project_set_description(criteria, options.set_description)
505
+ changed = gitlab.project_set_description(
506
+ criteria,
507
+ options.set_description,
508
+ )
483
509
  print(f'{Colors.BOLD} - Set description: '
484
- f'{Colors.CYAN}{options.set_description}'
510
+ f'{Colors.CYAN if changed else Colors.GREEN}{options.set_description}'
485
511
  f'{Colors.RESET}')
486
512
  Platform.flush()
487
513
 
@@ -501,9 +527,12 @@ class Entrypoint:
501
527
  not project.description.endswith(f' - {namespace_description}'):
502
528
  description = f'{Namespaces.describe(name=project.name)}' \
503
529
  f' - {namespace_description}'
504
- gitlab.project_set_description(criteria, description)
530
+ changed = gitlab.project_set_description(
531
+ criteria,
532
+ description,
533
+ )
505
534
  print(f'{Colors.BOLD} - Updated description: '
506
- f'{Colors.CYAN}{description}'
535
+ f'{Colors.CYAN if changed else Colors.GREEN}{description}'
507
536
  f'{Colors.RESET}')
508
537
  Platform.flush()
509
538
  else:
@@ -576,7 +605,10 @@ class Entrypoint:
576
605
 
577
606
  # Set project avatar
578
607
  if options.set_avatar:
579
- gitlab.project_set_avatar(criteria, options.set_avatar)
608
+ gitlab.project_set_avatar(
609
+ criteria,
610
+ options.set_avatar,
611
+ )
580
612
  print(f'{Colors.BOLD} - Set avatar: '
581
613
  f'{Colors.CYAN}{options.set_avatar}'
582
614
  f'{Colors.RESET}')
@@ -600,17 +632,25 @@ class Entrypoint:
600
632
 
601
633
  # Archive project
602
634
  if options.archive_project:
603
- gitlab.project_set_archive(criteria, True)
635
+ changed = gitlab.project_set_archive(
636
+ criteria,
637
+ True,
638
+ )
604
639
  print(f'{Colors.BOLD} - Archive project: '
605
- f'{Colors.GREEN}Success'
640
+ f'{Colors.CYAN if changed else Colors.GREEN}'
641
+ f'{"Success" if changed else "Already done"}'
606
642
  f'{Colors.RESET}')
607
643
  Platform.flush()
608
644
 
609
645
  # Unarchive project
610
646
  elif options.unarchive_project:
611
- gitlab.project_set_archive(criteria, False)
647
+ changed = gitlab.project_set_archive(
648
+ criteria,
649
+ False,
650
+ )
612
651
  print(f'{Colors.BOLD} - Unarchive project: '
613
- f'{Colors.GREEN}Success'
652
+ f'{Colors.CYAN if changed else Colors.GREEN}'
653
+ f'{"Success" if changed else "Already done"}'
614
654
  f'{Colors.RESET}')
615
655
  Platform.flush()
616
656
 
@@ -645,61 +685,64 @@ class Entrypoint:
645
685
 
646
686
  # Set project merge method
647
687
  if options.set_merge_method is not None:
648
- gitlab.project_set_attribute(
688
+ changed = gitlab.project_set_attribute(
649
689
  criteria,
650
690
  MergeRequestsMethod.ATTRIBUTE,
651
691
  MergeRequestsMethod.VALUES[options.set_merge_method],
652
692
  )
653
693
  print(f'{Colors.BOLD} - Set merge method: '
654
- f'{Colors.CYAN}{options.set_merge_method}'
694
+ f'{Colors.CYAN if changed else Colors.GREEN}{options.set_merge_method}'
655
695
  f'{Colors.RESET}')
656
696
  Platform.flush()
657
697
 
658
698
  # Set project merge squash
659
699
  if options.set_merge_squash is not None:
660
- gitlab.project_set_attribute(
700
+ changed = gitlab.project_set_attribute(
661
701
  criteria,
662
702
  MergeRequestsSquash.ATTRIBUTE,
663
703
  MergeRequestsSquash.VALUES[options.set_merge_squash],
664
704
  )
665
705
  print(f'{Colors.BOLD} - Set merge squash: '
666
- f'{Colors.CYAN}{options.set_merge_squash}'
706
+ f'{Colors.CYAN if changed else Colors.GREEN}{options.set_merge_squash}'
667
707
  f'{Colors.RESET}')
668
708
  Platform.flush()
669
709
 
670
710
  # Set project merge pipelines
671
711
  if options.set_merge_pipelines is not None:
672
- gitlab.project_set_attribute(
712
+ changed = gitlab.project_set_attribute(
673
713
  criteria,
674
714
  MergeRequestsPipelines.ATTRIBUTE,
675
715
  options.set_merge_pipelines,
676
716
  )
677
717
  print(f'{Colors.BOLD} - Set merge pipelines: '
678
- f'{Colors.CYAN}{str(options.set_merge_pipelines).lower()}'
718
+ f'{Colors.CYAN if changed else Colors.GREEN}'
719
+ f'{str(options.set_merge_pipelines).lower()}'
679
720
  f'{Colors.RESET}')
680
721
  Platform.flush()
681
722
 
682
723
  # Set project merge skipped
683
724
  if options.set_merge_skipped is not None:
684
- gitlab.project_set_attribute(
725
+ changed = gitlab.project_set_attribute(
685
726
  criteria,
686
727
  MergeRequestsSkipped.ATTRIBUTE,
687
728
  options.set_merge_skipped,
688
729
  )
689
730
  print(f'{Colors.BOLD} - Set merge skipped: '
690
- f'{Colors.CYAN}{str(options.set_merge_skipped).lower()}'
731
+ f'{Colors.CYAN if changed else Colors.GREEN}'
732
+ f'{str(options.set_merge_skipped).lower()}'
691
733
  f'{Colors.RESET}')
692
734
  Platform.flush()
693
735
 
694
736
  # Set project merge resolved
695
737
  if options.set_merge_resolved is not None:
696
- gitlab.project_set_attribute(
738
+ changed = gitlab.project_set_attribute(
697
739
  criteria,
698
740
  MergeRequestsResolved.ATTRIBUTE,
699
741
  options.set_merge_resolved,
700
742
  )
701
743
  print(f'{Colors.BOLD} - Set merge method: '
702
- f'{Colors.CYAN}{str(options.set_merge_resolved).lower()}'
744
+ f'{Colors.CYAN if changed else Colors.GREEN}'
745
+ f'{str(options.set_merge_resolved).lower()}'
703
746
  f'{Colors.RESET}')
704
747
  Platform.flush()
705
748
 
@@ -80,11 +80,17 @@ class GitLabFeature:
80
80
  self.__gitlab.auth()
81
81
 
82
82
  # Group
83
- def group(self, criteria: str) -> Group:
83
+ def group(
84
+ self,
85
+ criteria: str,
86
+ ) -> Group:
84
87
  return self.__gitlab.groups.get(criteria)
85
88
 
86
89
  # Group delete
87
- def group_delete(self, criteria: str) -> None:
90
+ def group_delete(
91
+ self,
92
+ criteria: str,
93
+ ) -> None:
88
94
 
89
95
  # Delete group
90
96
  group = self.group(criteria)
@@ -126,7 +132,10 @@ class GitLabFeature:
126
132
  return group.labels.list(get_all=True)
127
133
 
128
134
  # Group reset members
129
- def group_reset_members(self, criteria: str) -> None:
135
+ def group_reset_members(
136
+ self,
137
+ criteria: str,
138
+ ) -> None:
130
139
 
131
140
  # Remove group members
132
141
  group = self.group(criteria)
@@ -139,7 +148,11 @@ class GitLabFeature:
139
148
  group.save()
140
149
 
141
150
  # Group set avatar
142
- def group_set_avatar(self, criteria: str, file: str) -> None:
151
+ def group_set_avatar(
152
+ self,
153
+ criteria: str,
154
+ file: str,
155
+ ) -> None:
143
156
 
144
157
  # Set group avatar
145
158
  group = self.group(criteria)
@@ -151,16 +164,27 @@ class GitLabFeature:
151
164
  group.save()
152
165
 
153
166
  # Group set description
154
- def group_set_description(self, criteria: str, description: str) -> None:
167
+ def group_set_description(
168
+ self,
169
+ criteria: str,
170
+ description: str,
171
+ ) -> bool:
172
+
173
+ # Variables
174
+ changed: bool = False
155
175
 
156
176
  # Set group description
157
177
  group = self.group(criteria)
158
- if not self.__dry_run:
178
+ if not self.__dry_run and group.description != description:
159
179
  group.description = description
180
+ changed = True
160
181
 
161
182
  # Save group
162
183
  group.save()
163
184
 
185
+ # Result
186
+ return changed
187
+
164
188
  # Group set label, pylint: disable=too-many-arguments,too-many-positional-arguments
165
189
  def group_set_label(
166
190
  self,
@@ -195,7 +219,14 @@ class GitLabFeature:
195
219
  return label
196
220
 
197
221
  # Group set roles create projects
198
- def group_set_roles_create_projects(self, criteria: str, level: str) -> None:
222
+ def group_set_roles_create_projects(
223
+ self,
224
+ criteria: str,
225
+ level: str,
226
+ ) -> bool:
227
+
228
+ # Variables
229
+ changed: bool = False
199
230
 
200
231
  # Validate level
201
232
  if level not in RolesCreateProjects.names():
@@ -204,14 +235,25 @@ class GitLabFeature:
204
235
 
205
236
  # Set roles allowed to create projects
206
237
  group = self.group(criteria)
207
- if not self.__dry_run:
238
+ if not self.__dry_run and group.project_creation_level != level:
208
239
  group.project_creation_level = level
240
+ changed = True
209
241
 
210
242
  # Save group
211
243
  group.save()
212
244
 
245
+ # Result
246
+ return changed
247
+
213
248
  # Group set roles create subgroups
214
- def group_set_roles_create_subgroups(self, criteria: str, level: str) -> None:
249
+ def group_set_roles_create_subgroups(
250
+ self,
251
+ criteria: str,
252
+ level: str,
253
+ ) -> bool:
254
+
255
+ # Variables
256
+ changed: bool = False
215
257
 
216
258
  # Validate level
217
259
  if level not in RolesCreateSubgroups.names():
@@ -220,22 +262,35 @@ class GitLabFeature:
220
262
 
221
263
  # Set roles allowed to create subgroups
222
264
  group = self.group(criteria)
223
- if not self.__dry_run:
265
+ if not self.__dry_run and group.subgroup_creation_level != level:
224
266
  group.subgroup_creation_level = level
267
+ changed = True
225
268
 
226
269
  # Save group
227
270
  group.save()
228
271
 
272
+ # Result
273
+ return changed
274
+
229
275
  # Namespace
230
- def namespace(self, criteria: str) -> Namespace:
276
+ def namespace(
277
+ self,
278
+ criteria: str,
279
+ ) -> Namespace:
231
280
  return self.__gitlab.namespaces.get(criteria)
232
281
 
233
282
  # Project
234
- def project(self, criteria: str) -> Project:
283
+ def project(
284
+ self,
285
+ criteria: str,
286
+ ) -> Project:
235
287
  return self.__gitlab.projects.get(criteria)
236
288
 
237
289
  # Project delete
238
- def project_delete(self, criteria: str) -> None:
290
+ def project_delete(
291
+ self,
292
+ criteria: str,
293
+ ) -> None:
239
294
 
240
295
  # Delete project
241
296
  project = self.project(criteria)
@@ -267,7 +322,10 @@ class GitLabFeature:
267
322
  sleep(3)
268
323
 
269
324
  # Project erase jobs artifacts
270
- def project_erase_jobs_artifacts(self, criteria: str) -> None:
325
+ def project_erase_jobs_artifacts(
326
+ self,
327
+ criteria: str,
328
+ ) -> None:
271
329
 
272
330
  # Erase project jobs artifacts
273
331
  project = self.project(criteria)
@@ -277,7 +335,10 @@ class GitLabFeature:
277
335
  job.delete_artifacts()
278
336
 
279
337
  # Project erase jobs artifacts and traces
280
- def project_erase_jobs_contents(self, criteria: str) -> None:
338
+ def project_erase_jobs_contents(
339
+ self,
340
+ criteria: str,
341
+ ) -> None:
281
342
 
282
343
  # Erase project jobs artifacts and traces
283
344
  project = self.project(criteria)
@@ -338,7 +399,10 @@ class GitLabFeature:
338
399
  project.job_token_scope.get().groups_allowlist.delete(path_group.id)
339
400
 
340
401
  # Project protect branches
341
- def project_protect_branches(self, criteria: str) -> List[str]:
402
+ def project_protect_branches(
403
+ self,
404
+ criteria: str,
405
+ ) -> List[str]:
342
406
 
343
407
  # Validate project feature
344
408
  result: List[str] = []
@@ -422,13 +486,14 @@ class GitLabFeature:
422
486
  ) -> List[str]:
423
487
 
424
488
  # Variables
489
+ changed: bool
425
490
  result: List[str] = []
426
491
  project = self.__gitlab.projects.get(criteria, statistics=True)
427
492
 
428
493
  # Iterate through features
429
494
  for key in features:
430
495
  if key in ProjectFeatures.keys():
431
- changed: bool = False
496
+ changed = False
432
497
  feature = ProjectFeatures.get(key)
433
498
 
434
499
  # Disable 'access_level' feature
@@ -472,13 +537,14 @@ class GitLabFeature:
472
537
  ) -> List[str]:
473
538
 
474
539
  # Variables
540
+ changed: bool
475
541
  result: List[str] = []
476
542
  project = self.__gitlab.projects.get(criteria, statistics=True)
477
543
 
478
544
  # Iterate through features
479
545
  for key in features:
480
546
  if key in ProjectFeatures.keys():
481
- changed: bool = False
547
+ changed = False
482
548
  feature = ProjectFeatures.get(key)
483
549
 
484
550
  # Enable 'access_level' feature
@@ -522,13 +588,14 @@ class GitLabFeature:
522
588
  ) -> List[str]:
523
589
 
524
590
  # Variables
591
+ changed: bool
525
592
  result: List[str] = []
526
593
  project = self.__gitlab.projects.get(criteria, statistics=True)
527
594
 
528
595
  # Iterate through features
529
596
  for key in ProjectFeatures.keys():
530
597
  if key not in keep_features:
531
- changed: bool = False
598
+ changed = False
532
599
  feature = ProjectFeatures.get(key)
533
600
 
534
601
  # Disable 'access_level' feature
@@ -589,7 +656,11 @@ class GitLabFeature:
589
656
  ]
590
657
 
591
658
  # Project protect tags, pylint: disable=too-many-branches
592
- def project_protect_tags(self, criteria: str, protect_level: str) -> List[str]:
659
+ def project_protect_tags(
660
+ self,
661
+ criteria: str,
662
+ protect_level: str,
663
+ ) -> List[str]:
593
664
 
594
665
  # Validate project feature
595
666
  result: List[str] = []
@@ -650,7 +721,10 @@ class GitLabFeature:
650
721
  return result
651
722
 
652
723
  # Project prune unreachable objects
653
- def project_prune_unreachable_objects(self, criteria: str) -> None:
724
+ def project_prune_unreachable_objects(
725
+ self,
726
+ criteria: str,
727
+ ) -> None:
654
728
 
655
729
  # Prune project unreachable objects
656
730
  project = self.project(criteria)
@@ -658,7 +732,10 @@ class GitLabFeature:
658
732
  project.housekeeping(post_data={'task': 'prune'})
659
733
 
660
734
  # Project reset members
661
- def project_reset_members(self, criteria: str) -> None:
735
+ def project_reset_members(
736
+ self,
737
+ criteria: str,
738
+ ) -> None:
662
739
 
663
740
  # Remove project members
664
741
  project = self.project(criteria)
@@ -673,7 +750,10 @@ class GitLabFeature:
673
750
  project.save()
674
751
 
675
752
  # Project run housekeeping
676
- def project_run_housekeeping(self, criteria: str) -> None:
753
+ def project_run_housekeeping(
754
+ self,
755
+ criteria: str,
756
+ ) -> None:
677
757
 
678
758
  # Run project housekeeping
679
759
  project = self.project(criteria)
@@ -681,16 +761,30 @@ class GitLabFeature:
681
761
  project.housekeeping()
682
762
 
683
763
  # Project set archive
684
- def project_set_archive(self, criteria: str, enabled: bool) -> None:
764
+ def project_set_archive(
765
+ self,
766
+ criteria: str,
767
+ enabled: bool,
768
+ ) -> bool:
769
+
770
+ # Variables
771
+ changed: bool = False
685
772
 
686
773
  # Archive project
687
774
  project = self.project(criteria)
688
775
  if not self.__dry_run and enabled:
689
- project.archive()
776
+ if not project.archived:
777
+ project.archive()
778
+ changed = True
690
779
 
691
780
  # Unarchive project
692
781
  elif not self.__dry_run:
693
- project.unarchive()
782
+ if project.archived:
783
+ project.unarchive()
784
+ changed = True
785
+
786
+ # Result
787
+ return changed
694
788
 
695
789
  # Project set attribute
696
790
  def project_set_attribute(
@@ -698,18 +792,29 @@ class GitLabFeature:
698
792
  criteria: str,
699
793
  name: str,
700
794
  value: Union[bool, str],
701
- ) -> None:
795
+ ) -> bool:
796
+
797
+ # Variables
798
+ changed: bool = False
702
799
 
703
800
  # Set project attribute
704
801
  project = self.project(criteria)
705
- if not self.__dry_run:
802
+ if not self.__dry_run and getattr(project, name) != value:
706
803
  setattr(project, name, value)
804
+ changed = True
707
805
 
708
806
  # Save project
709
807
  project.save()
710
808
 
809
+ # Result
810
+ return changed
811
+
711
812
  # Project set avatar
712
- def project_set_avatar(self, criteria: str, file: str) -> None:
813
+ def project_set_avatar(
814
+ self,
815
+ criteria: str,
816
+ file: str,
817
+ ) -> None:
713
818
 
714
819
  # Set project avatar
715
820
  project = self.project(criteria)
@@ -721,16 +826,27 @@ class GitLabFeature:
721
826
  project.save()
722
827
 
723
828
  # Project set description
724
- def project_set_description(self, criteria: str, description: str) -> None:
829
+ def project_set_description(
830
+ self,
831
+ criteria: str,
832
+ description: str,
833
+ ) -> bool:
834
+
835
+ # Variables
836
+ changed: bool = False
725
837
 
726
838
  # Set project description
727
839
  project = self.project(criteria)
728
- if not self.__dry_run:
840
+ if not self.__dry_run and project.description != description:
729
841
  project.description = description
842
+ changed = True
730
843
 
731
844
  # Save project
732
845
  project.save()
733
846
 
847
+ # Result
848
+ return changed
849
+
734
850
  # Project set issues_board, pylint: disable=too-many-arguments,too-many-positional-arguments
735
851
  def project_set_issues_board(
736
852
  self,
@@ -747,7 +863,7 @@ class GitLabFeature:
747
863
  try:
748
864
  issues_board = next(board for board in project.boards.list(get_all=True)
749
865
  if board.name == name and isinstance(board, ProjectBoard))
750
- except GitlabGetError:
866
+ except (GitlabGetError, StopIteration):
751
867
  project.boards.create({
752
868
  'name': name,
753
869
  })
@@ -769,7 +885,7 @@ class GitLabFeature:
769
885
  for board_list in issues_board.lists.list(get_all=True)
770
886
  if board_list.label['name'] == list_json['label']
771
887
  and isinstance(board_list, ProjectBoardList))
772
- except (GitlabGetError, IndexError):
888
+ except (GitlabGetError, IndexError, StopIteration):
773
889
  label = project.labels.get(list_json['label'],
774
890
  include_ancestor_groups=True)
775
891
  issues_board.lists.create({
@@ -832,14 +948,24 @@ class GitLabFeature:
832
948
  # Result
833
949
  return label
834
950
 
951
+ # URL
952
+ @property
953
+ def url(self) -> str:
954
+ return str(self.__gitlab.api_url)
955
+
835
956
  # User
836
- def user(self, criteria: str) -> User:
957
+ def user(
958
+ self,
959
+ criteria: str,
960
+ ) -> User:
837
961
  users = self.__gitlab.users.list(all=True, iterator=True, username=criteria)
838
962
  for user in users:
839
963
  return cast(User, user)
840
- raise RuntimeError()
964
+ raise RuntimeError(f'Could not find user {criteria}')
841
965
 
842
- # URL
966
+ # User name
843
967
  @property
844
- def url(self) -> str:
845
- return str(self.__gitlab.api_url)
968
+ def username(self) -> str:
969
+ if self.__gitlab.user:
970
+ return str(self.__gitlab.user.username)
971
+ return '/'
@@ -8,7 +8,7 @@ try:
8
8
  try: # colored>=2.0.0
9
9
  from colored import Colored
10
10
  except ImportError: # colored<2.0.0 # pragma: no cover
11
- from colored import colored as Colored
11
+ from colored import colored as Colored # type: ignore[assignment]
12
12
  except ModuleNotFoundError: # pragma: no cover
13
13
  pass
14
14