pygitpub 0.0.64__tar.gz → 0.0.65__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.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.5
2
2
  Name: pygitpub
3
- Version: 0.0.64
3
+ Version: 0.0.65
4
4
  Summary: Pygitpub will help you work with github
5
5
  Project-URL: Homepage, https://github.com/veltzer/pygitpub
6
6
  Project-URL: Bug Tracker, https://github.com/veltzer/pygitpub/issues
@@ -41,7 +41,7 @@ project website: https://veltzer.github.io/pygitpub
41
41
 
42
42
  author: Mark Veltzer
43
43
 
44
- version: 0.0.64
44
+ version: 0.0.65
45
45
 
46
46
  ## github
47
47
 
@@ -9,7 +9,7 @@ project website: https://veltzer.github.io/pygitpub
9
9
 
10
10
  author: Mark Veltzer
11
11
 
12
- version: 0.0.64
12
+ version: 0.0.65
13
13
 
14
14
  ## github
15
15
 
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
4
4
 
5
5
  [project]
6
6
  name = "pygitpub"
7
- version = "0.0.64"
7
+ version = "0.0.65"
8
8
  requires-python = ">=3.14"
9
9
  authors = [
10
10
  { name = "Mark Veltzer", email = "mark.veltzer@gmail.com" }
@@ -90,7 +90,6 @@ preset = "legacy"
90
90
  python-version = "3.14"
91
91
  search-path = [
92
92
  "src",
93
- "scripts",
94
93
  ".",
95
94
  ]
96
95
  # Third-party libraries without type information.
@@ -14,11 +14,8 @@ AFFILIATIONS = [
14
14
 
15
15
  class ConfigGithub(Config):
16
16
  """
17
- Paramters for your github account
17
+ Parameters for your github account
18
18
  """
19
- username = ParamCreator.create_str(
20
- help_string="What is your github username?",
21
- )
22
19
  apikey = ParamCreator.create_str(
23
20
  help_string="What is the name of your apikey (see pyapikey)?",
24
21
  )
@@ -44,9 +44,13 @@ def get_affiliation() -> str:
44
44
  return ",".join(values)
45
45
 
46
46
 
47
- def yield_repos():
47
+ def get_github(**kwargs: Any) -> github.Github:
48
48
  apikey = pyapikey.get_key(ConfigGithub.apikey)
49
- g = github.Github(login_or_token=apikey)
49
+ return github.Github(auth=github.Auth.Token(apikey), **kwargs)
50
+
51
+
52
+ def yield_repos():
53
+ g = get_github()
50
54
  # github filters by affiliation server side, so repos we are not interested
51
55
  # in (org repos, by default) are never fetched in the first place
52
56
  affiliation = get_affiliation()
@@ -95,7 +99,8 @@ def fix_metadata() -> None:
95
99
  print(f"in {folder}...")
96
100
  print(f"description_short is [{description_short}]")
97
101
  print(f"repo.description is [{repo.description}]")
98
- repo.edit(description=description_short)
102
+ if not ConfigAlgo.dryrun:
103
+ repo.edit(description=description_short)
99
104
  if "KEYWORDS" not in project:
100
105
  print(f"{folder} no keywords")
101
106
  continue
@@ -104,32 +109,36 @@ def fix_metadata() -> None:
104
109
  print(f"in {folder}...")
105
110
  print(f"keywords is [{keywords}]")
106
111
  print(f"repo.get_topics() is [{repo.get_topics()}]")
107
- repo.replace_topics(keywords)
112
+ if not ConfigAlgo.dryrun:
113
+ repo.replace_topics(keywords)
108
114
 
109
115
 
110
116
  @register_endpoint(
111
117
  description="Set the correct website for the project on all repos where it is not correct",
112
118
  configs=[
113
119
  ConfigGithub,
120
+ ConfigOutput,
114
121
  ConfigAlgo,
115
122
  ],
116
123
  )
117
124
  def homepage_fix() -> None:
118
125
  for repo in yield_repos():
126
+ owner = repo.owner.login
127
+ # the user site repo is served at the root of the site, usually under
128
+ # a custom domain, so the pattern below does not apply to it
129
+ if repo.name.lower() == f"{owner.lower()}.github.io":
130
+ if ConfigOutput.verbose:
131
+ print(f"skipping [{repo.name}] because it is the user site")
132
+ continue
119
133
  if repo.has_pages:
120
- right_homepage = f"https://{ConfigGithub.username}.github.io/{repo.name}/"
121
- if repo.homepage != right_homepage:
122
- print(f"{repo.name} is wrong!")
123
- print(f"homepage: {repo.homepage}")
124
- print(f"right_homepage: {right_homepage}")
125
- print(f"patching [{repo.name}]...")
126
- repo.edit(repo.name, homepage=right_homepage)
134
+ right_homepage = f"https://{owner}.github.io/{repo.name}/"
127
135
  else:
128
- right_homepage = f"https://github.com/{ConfigGithub.username}/{repo.name}/"
129
- if repo.homepage != right_homepage:
130
- print(f"{repo.name} is wrong!")
131
- print(f"homepage: {repo.homepage}")
132
- print(f"right_homepage: {right_homepage}")
136
+ right_homepage = f"https://github.com/{owner}/{repo.name}/"
137
+ if repo.homepage != right_homepage:
138
+ print(f"{repo.name} is wrong!")
139
+ print(f"homepage: {repo.homepage}")
140
+ print(f"right_homepage: {right_homepage}")
141
+ if not ConfigAlgo.dryrun:
133
142
  print(f"patching [{repo.name}]...")
134
143
  repo.edit(repo.name, homepage=right_homepage)
135
144
 
@@ -198,20 +207,23 @@ def repos_list() -> None:
198
207
  ],
199
208
  )
200
209
  def cleanup() -> None:
201
- # pylint: disable=too-many-branches,too-many-statements
202
210
  for repo in yield_repos():
203
211
  # 1. Cleanup workflow runs
204
212
  for workflow in repo.get_workflows():
205
213
  existing = 0
206
214
  for run in workflow.get_runs():
207
215
  if ConfigOutput.verbose:
208
- print(f"inspecting [workflow run] {repo.name} {workflow.name} {run.conclusion}")
216
+ print(f"inspecting [workflow run] {repo.name} {workflow.name} {run.status} {run.conclusion}")
217
+ # github refuses to delete a run that is queued or still
218
+ # running, so leave those alone and don't count them
219
+ if run.status != "completed":
220
+ continue
209
221
  delete_it = False
210
- # if its a pages build delete it unless its in mid work (run.conclusion is None)
211
- if workflow.name == "pages-build-deployment" and run.conclusion is not None:
222
+ # if its a pages build delete it
223
+ if workflow.name == "pages-build-deployment":
212
224
  delete_it = True
213
- # if its not on the master branch, delete it
214
- if run.head_branch != "master":
225
+ # if its not on the default branch, delete it
226
+ if run.head_branch != repo.default_branch:
215
227
  delete_it = True
216
228
  # if its not a paged build and it failed then delete it
217
229
  if workflow.name != "pages-build-deployment" and run.conclusion in (
@@ -222,6 +234,8 @@ def cleanup() -> None:
222
234
  delete_it = True
223
235
  if delete_it:
224
236
  print(f"deleting [workflow run] {repo.name} {workflow.name} {run.head_branch} {run.conclusion} {run.url}")
237
+ if ConfigAlgo.dryrun:
238
+ continue
225
239
  try:
226
240
  run.delete()
227
241
  except github.GithubException as e:
@@ -245,12 +259,13 @@ def cleanup() -> None:
245
259
 
246
260
  if delete_it:
247
261
  print(f"deleting [deployment] {repo.name} {deployment.id}")
262
+ if ConfigAlgo.dryrun:
263
+ continue
248
264
  try:
249
265
  deployment.create_status("inactive")
250
266
  except github.GithubException as e:
251
267
  print(f"Failed to deactivate deployment: {e}")
252
268
  try:
253
- # pylint: disable=protected-access
254
269
  status, _, _ = deployment._requester.requestJson("DELETE", deployment.url)
255
270
  if status != 204:
256
271
  print(f"Failed to delete deployment: HTTP {status}")
@@ -262,6 +277,8 @@ def cleanup() -> None:
262
277
  for release in repo.get_releases():
263
278
  if existing_releases >= 4:
264
279
  print(f"deleting [release] {repo.name} {release.title}")
280
+ if ConfigAlgo.dryrun:
281
+ continue
265
282
  try:
266
283
  release.delete_release()
267
284
  except github.GithubException as e:
@@ -295,8 +312,8 @@ def runs_show_running() -> None:
295
312
  for repo in yield_repos():
296
313
  for workflow in repo.get_workflows():
297
314
  for run in workflow.get_runs():
298
- if run.conclusion is None:
299
- print(f"{repo.name}: {workflow.name} {run.conclusion}")
315
+ if run.status in ("in_progress", "queued"):
316
+ print(f"{repo.name}: {workflow.name} {run.status}")
300
317
 
301
318
 
302
319
  # repos per GraphQL query; measured fastest at around 10
@@ -344,11 +361,9 @@ def graphql_show_runs(bad_state: Callable[[str], bool], bad_conclusion: Callable
344
361
  Only the head commit of the default branch is looked at, so a failed run
345
362
  on another branch, or a scheduled run on an older commit, does not show.
346
363
  """
347
- apikey = pyapikey.get_key(ConfigGithub.apikey)
348
364
  # the default client sleeps a second between POSTs, and every GraphQL
349
365
  # query is a POST, which would serialize the parallel queries
350
- g = github.Github(
351
- login_or_token=apikey,
366
+ g = get_github(
352
367
  pool_size=GRAPHQL_WORKERS,
353
368
  seconds_between_requests=None,
354
369
  seconds_between_writes=None,
@@ -464,7 +479,6 @@ def pull_all() -> None:
464
479
  [
465
480
  "git",
466
481
  "pull",
467
- # "--tags",
468
482
  ],
469
483
  cwd=folder,
470
484
  )
@@ -484,7 +498,7 @@ def pull_all() -> None:
484
498
 
485
499
 
486
500
  @register_endpoint(
487
- description="Pull all projects from github",
501
+ description="Clone all projects from github",
488
502
  configs=[
489
503
  ConfigGithub,
490
504
  ConfigAlgo,
@@ -497,12 +511,9 @@ def clone_all() -> None:
497
511
  project = repo.name
498
512
  folder = get_repo_folder(repo)
499
513
  all_repo_folders.add(folder)
500
- # print(f"considering [{project}] from [{repo.ssh_url}]...")
501
514
  if os.path.isfile(folder):
502
- # print(f"skipping [{folder}] as it is not to be cloned...")
503
515
  continue
504
516
  if os.path.isdir(folder):
505
- # print(f"skipping [{folder}] as it is already cloned...")
506
517
  continue
507
518
  if ConfigAlgo.dryrun:
508
519
  continue
@@ -516,7 +527,6 @@ def clone_all() -> None:
516
527
  ],
517
528
  cwd=base_dir,
518
529
  stdout=subprocess.DEVNULL,
519
- stderr=subprocess.DEVNULL,
520
530
  )
521
531
  if ConfigAlgo.show_extra:
522
532
  disk_repos = get_all_git_repos(base_dir)
@@ -540,7 +550,7 @@ def workflows_run() -> None:
540
550
  for workflow in repo.get_workflows():
541
551
  print(f"{repo.name}: {workflow.name}...", end="")
542
552
  sys.stdout.flush()
543
- ret = workflow.create_dispatch(ref="master")
553
+ ret = workflow.create_dispatch(ref=repo.default_branch)
544
554
  print(f"{ret}")
545
555
 
546
556
 
@@ -1,5 +1,5 @@
1
1
  """ version which can be consumed from within the module """
2
- VERSION_STR = "0.0.64"
2
+ VERSION_STR = "0.0.65"
3
3
  DESCRIPTION = "Pygitpub will help you work with github"
4
4
  APP_NAME = "pygitpub"
5
5
  LOGGER_NAME = "pygitpub"
@@ -1,25 +1,8 @@
1
1
  """ misc.py """
2
2
 
3
3
  import glob
4
- import logging
5
- import os
6
4
  import os.path
7
5
 
8
- from pygitpub import LOGGER_NAME
9
-
10
-
11
- def get_logger():
12
- return logging.getLogger(LOGGER_NAME)
13
-
14
-
15
- def get_number_of_files(folder: str) -> int:
16
- count = 0
17
- for _root, _directories, files in os.walk(folder):
18
- count += len(files)
19
- return count
20
-
21
-
22
-
23
6
 
24
7
  def get_all_git_repos(base_dir: str) -> set[str]:
25
8
  """ we use */.git under base_dir with recursive=False (which is the default)
File without changes
File without changes