dycw-actions 0.8.5__py3-none-any.whl → 0.11.3__py3-none-any.whl

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 (38) hide show
  1. actions/__init__.py +1 -1
  2. actions/clean_dir/lib.py +5 -12
  3. actions/cli.py +18 -2
  4. actions/constants.py +2 -4
  5. actions/git_clone_with/__init__.py +1 -0
  6. actions/git_clone_with/cli.py +41 -0
  7. actions/git_clone_with/constants.py +7 -0
  8. actions/git_clone_with/lib.py +78 -0
  9. actions/git_clone_with/settings.py +20 -0
  10. actions/pre_commit/conformalize_repo/action_dicts.py +40 -41
  11. actions/pre_commit/conformalize_repo/cli.py +16 -3
  12. actions/pre_commit/conformalize_repo/constants.py +7 -3
  13. actions/pre_commit/conformalize_repo/lib.py +243 -163
  14. actions/pre_commit/conformalize_repo/settings.py +43 -11
  15. actions/pre_commit/constants.py +4 -1
  16. actions/pre_commit/format_requirements/lib.py +5 -10
  17. actions/pre_commit/replace_sequence_strs/lib.py +5 -10
  18. actions/pre_commit/touch_empty_py/lib.py +8 -14
  19. actions/pre_commit/touch_py_typed/lib.py +8 -13
  20. actions/pre_commit/update_requirements/lib.py +5 -11
  21. actions/pre_commit/utilities.py +83 -72
  22. actions/publish_package/lib.py +12 -16
  23. actions/random_sleep/cli.py +2 -2
  24. actions/random_sleep/lib.py +9 -18
  25. actions/register_gitea_runner/configs/entrypoint.sh +8 -8
  26. actions/register_gitea_runner/lib.py +23 -30
  27. actions/run_hooks/lib.py +11 -15
  28. actions/setup_cronjob/lib.py +16 -24
  29. actions/setup_ssh_config/__init__.py +1 -0
  30. actions/setup_ssh_config/cli.py +17 -0
  31. actions/setup_ssh_config/constants.py +7 -0
  32. actions/setup_ssh_config/lib.py +30 -0
  33. actions/tag_commit/lib.py +12 -16
  34. actions/utilities.py +7 -0
  35. {dycw_actions-0.8.5.dist-info → dycw_actions-0.11.3.dist-info}/METADATA +4 -3
  36. {dycw_actions-0.8.5.dist-info → dycw_actions-0.11.3.dist-info}/RECORD +38 -29
  37. {dycw_actions-0.8.5.dist-info → dycw_actions-0.11.3.dist-info}/WHEEL +1 -1
  38. {dycw_actions-0.8.5.dist-info → dycw_actions-0.11.3.dist-info}/entry_points.txt +0 -0
@@ -14,13 +14,14 @@ from typing import TYPE_CHECKING, Literal, assert_never
14
14
  import tomlkit
15
15
  from tomlkit import TOMLDocument, table
16
16
  from tomlkit.exceptions import NonExistentKey
17
+ from utilities.functions import get_func_name
17
18
  from utilities.inflect import counted_noun
18
19
  from utilities.re import extract_groups
19
20
  from utilities.subprocess import ripgrep
21
+ from utilities.tabulate import func_param_desc
20
22
  from utilities.text import repr_str, strip_and_dedent
21
23
  from utilities.throttle import throttle
22
24
  from utilities.version import ParseVersionError, Version, parse_version
23
- from utilities.whenever import HOUR
24
25
 
25
26
  from actions import __version__
26
27
  from actions.constants import (
@@ -34,7 +35,6 @@ from actions.constants import (
34
35
  GITHUB_PUSH_YAML,
35
36
  GITIGNORE,
36
37
  MAX_PYTHON_VERSION,
37
- PATH_THROTTLE_CACHE,
38
38
  PRE_COMMIT_CONFIG_YAML,
39
39
  PYPROJECT_TOML,
40
40
  PYRIGHTCONFIG_JSON,
@@ -65,6 +65,7 @@ from actions.pre_commit.conformalize_repo.constants import (
65
65
  UV_URL,
66
66
  )
67
67
  from actions.pre_commit.conformalize_repo.settings import SETTINGS
68
+ from actions.pre_commit.constants import THROTTLE_DELTA
68
69
  from actions.pre_commit.format_requirements.constants import FORMAT_REQUIREMENTS_SUB_CMD
69
70
  from actions.pre_commit.replace_sequence_strs.constants import (
70
71
  REPLACE_SEQUENCE_STRS_SUB_CMD,
@@ -83,6 +84,7 @@ from actions.pre_commit.utilities import (
83
84
  get_dict,
84
85
  get_list,
85
86
  get_table,
87
+ path_throttle_cache,
86
88
  yield_json_dict,
87
89
  yield_text_file,
88
90
  yield_toml_doc,
@@ -100,23 +102,38 @@ if TYPE_CHECKING:
100
102
 
101
103
  def conformalize_repo(
102
104
  *,
103
- ci__ca_certificates: bool = SETTINGS.ci__ca_certificates,
105
+ ci__certificates: bool = SETTINGS.ci__certificates,
104
106
  ci__gitea: bool = SETTINGS.ci__gitea,
105
- ci__token: str | None = SETTINGS.ci__token,
107
+ ci__token_checkout: Secret[str] | None = SETTINGS.ci__token_checkout,
108
+ ci__token_github: Secret[str] | None = SETTINGS.ci__token_github,
106
109
  ci__pull_request__pre_commit: bool = SETTINGS.ci__pull_request__pre_commit,
110
+ ci__pull_request__pre_commit__submodules: str
111
+ | None = SETTINGS.ci__pull_request__pre_commit__submodules,
107
112
  ci__pull_request__pyright: bool = SETTINGS.ci__pull_request__pyright,
108
113
  ci__pull_request__pytest__macos: bool = SETTINGS.ci__pull_request__pytest__macos,
109
114
  ci__pull_request__pytest__ubuntu: bool = SETTINGS.ci__pull_request__pytest__ubuntu,
110
115
  ci__pull_request__pytest__windows: bool = SETTINGS.ci__pull_request__pytest__windows,
111
- ci__pull_request__pytest__sops_age_key: str
116
+ ci__pull_request__pytest__all_versions: bool = SETTINGS.ci__pull_request__pytest__all_versions,
117
+ ci__pull_request__pytest__sops_age_key: Secret[str]
112
118
  | None = SETTINGS.ci__pull_request__pytest__sops_age_key,
113
119
  ci__pull_request__ruff: bool = SETTINGS.ci__pull_request__ruff,
114
- ci__push__publish: bool = SETTINGS.ci__push__publish,
115
- ci__push__publish__username: str | None = SETTINGS.ci__push__publish__username,
116
- ci__push__publish__password: Secret[str]
117
- | None = SETTINGS.ci__push__publish__password,
118
- ci__push__publish__publish_url: Secret[str]
119
- | None = SETTINGS.ci__push__publish__publish_url,
120
+ ci__push__publish__github: bool = SETTINGS.ci__push__publish__github,
121
+ ci__push__publish__primary: bool = SETTINGS.ci__push__publish__primary,
122
+ ci__push__publish__primary__job_name: str = SETTINGS.ci__push__publish__primary__job_name,
123
+ ci__push__publish__primary__username: str
124
+ | None = SETTINGS.ci__push__publish__primary__username,
125
+ ci__push__publish__primary__password: Secret[str]
126
+ | None = SETTINGS.ci__push__publish__primary__password,
127
+ ci__push__publish__primary__publish_url: str
128
+ | None = SETTINGS.ci__push__publish__primary__publish_url,
129
+ ci__push__publish__secondary: bool = SETTINGS.ci__push__publish__secondary,
130
+ ci__push__publish__secondary__job_name: str = SETTINGS.ci__push__publish__secondary__job_name,
131
+ ci__push__publish__secondary__username: str
132
+ | None = SETTINGS.ci__push__publish__secondary__username,
133
+ ci__push__publish__secondary__password: Secret[str]
134
+ | None = SETTINGS.ci__push__publish__secondary__password,
135
+ ci__push__publish__secondary__publish_url: str
136
+ | None = SETTINGS.ci__push__publish__secondary__publish_url,
120
137
  ci__push__tag: bool = SETTINGS.ci__push__tag,
121
138
  ci__push__tag__all: bool = SETTINGS.ci__push__tag__all,
122
139
  coverage: bool = SETTINGS.coverage,
@@ -152,101 +169,65 @@ def conformalize_repo(
152
169
  uv__native_tls: bool = SETTINGS.uv__native_tls,
153
170
  ) -> None:
154
171
  LOGGER.info(
155
- strip_and_dedent("""
156
- Running '%s' (version %s) with settings:
157
- - ci__ca_certificates = %s
158
- - ci__gitea = %s
159
- - ci__token = %s
160
- - ci__pull_request__pre_commit = %s
161
- - ci__pull_request__pyright = %s
162
- - ci__pull_request__pytest__macos = %s
163
- - ci__pull_request__pytest__ubuntu = %s
164
- - ci__pull_request__pytest__windows = %s
165
- - ci__pull_request__pytest__sops_age_key = %s
166
- - ci__pull_request__ruff = %s
167
- - ci__push__publish = %s
168
- - ci__push__publish__username = %s
169
- - ci__push__publish__password = %s
170
- - ci__push__publish__publish_url = %s
171
- - ci__push__tag = %s
172
- - ci__push__tag__all = %s
173
- - coverage = %s
174
- - description = %s
175
- - envrc = %s
176
- - envrc__uv = %s
177
- - gitignore = %s
178
- - package_name = %s
179
- - pre_commit__dockerfmt = %s
180
- - pre_commit__prettier = %s
181
- - pre_commit__python = %s
182
- - pre_commit__ruff = %s
183
- - pre_commit__shell = %s
184
- - pre_commit__taplo = %s
185
- - pre_commit__uv = %s
186
- - pyproject = %s
187
- - pyproject__project__optional_dependencies__scripts = %s
188
- - pyproject__tool__uv__indexes = %s
189
- - pyright = %s
190
- - pytest = %s
191
- - pytest__asyncio = %s
192
- - pytest__ignore_warnings = %s
193
- - pytest__timeout = %s
194
- - python_package_name = %s
195
- - python_version = %s
196
- - readme = %s
197
- - repo_name = %s
198
- - ruff = %s
199
- - run_version_bump = %s
200
- - script = %s
201
- - uv__native__tls = %s
202
- """),
203
- conformalize_repo.__name__,
204
- __version__,
205
- ci__ca_certificates,
206
- ci__gitea,
207
- ci__token,
208
- ci__pull_request__pre_commit,
209
- ci__pull_request__pyright,
210
- ci__pull_request__pytest__macos,
211
- ci__pull_request__pytest__ubuntu,
212
- ci__pull_request__pytest__windows,
213
- ci__pull_request__pytest__sops_age_key,
214
- ci__pull_request__ruff,
215
- ci__push__publish,
216
- ci__push__publish__username,
217
- ci__push__publish__password,
218
- ci__push__publish__publish_url,
219
- ci__push__tag,
220
- ci__push__tag__all,
221
- coverage,
222
- description,
223
- envrc,
224
- envrc__uv,
225
- gitignore,
226
- package_name,
227
- pre_commit__dockerfmt,
228
- pre_commit__prettier,
229
- pre_commit__python,
230
- pre_commit__ruff,
231
- pre_commit__shell,
232
- pre_commit__taplo,
233
- pre_commit__uv,
234
- pyproject,
235
- pyproject__project__optional_dependencies__scripts,
236
- pyproject__tool__uv__indexes,
237
- pyright,
238
- pytest,
239
- pytest__asyncio,
240
- pytest__ignore_warnings,
241
- pytest__timeout,
242
- python_package_name,
243
- python_version,
244
- readme,
245
- repo_name,
246
- ruff,
247
- run_version_bump,
248
- script,
249
- uv__native_tls,
172
+ func_param_desc(
173
+ conformalize_repo,
174
+ __version__,
175
+ f"{ci__certificates=}",
176
+ f"{ci__gitea=}",
177
+ f"{ci__token_checkout=}",
178
+ f"{ci__token_github=}",
179
+ f"{ci__pull_request__pre_commit=}",
180
+ f"{ci__pull_request__pre_commit__submodules=}",
181
+ f"{ci__pull_request__pyright=}",
182
+ f"{ci__pull_request__pytest__macos=}",
183
+ f"{ci__pull_request__pytest__ubuntu=}",
184
+ f"{ci__pull_request__pytest__windows=}",
185
+ f"{ci__pull_request__pytest__all_versions=}",
186
+ f"{ci__pull_request__pytest__sops_age_key=}",
187
+ f"{ci__pull_request__ruff=}",
188
+ f"{ci__push__publish__github=}",
189
+ f"{ci__push__publish__primary=}",
190
+ f"{ci__push__publish__primary__job_name=}",
191
+ f"{ci__push__publish__primary__username=}",
192
+ f"{ci__push__publish__primary__password=}",
193
+ f"{ci__push__publish__primary__publish_url=}",
194
+ f"{ci__push__publish__secondary=}",
195
+ f"{ci__push__publish__secondary__job_name=}",
196
+ f"{ci__push__publish__secondary__username=}",
197
+ f"{ci__push__publish__secondary__password=}",
198
+ f"{ci__push__publish__secondary__publish_url=}",
199
+ f"{ci__push__tag=}",
200
+ f"{ci__push__tag__all=}",
201
+ f"{coverage=}",
202
+ f"{description=}",
203
+ f"{envrc=}",
204
+ f"{envrc__uv=}",
205
+ f"{gitignore=}",
206
+ f"{package_name=}",
207
+ f"{pre_commit__dockerfmt=}",
208
+ f"{pre_commit__prettier=}",
209
+ f"{pre_commit__python=}",
210
+ f"{pre_commit__ruff=}",
211
+ f"{pre_commit__shell=}",
212
+ f"{pre_commit__taplo=}",
213
+ f"{pre_commit__uv=}",
214
+ f"{pyproject=}",
215
+ f"{pyproject__project__optional_dependencies__scripts=}",
216
+ f"{pyproject__tool__uv__indexes=}",
217
+ f"{pyright=}",
218
+ f"{pytest=}",
219
+ f"{pytest__asyncio=}",
220
+ f"{pytest__ignore_warnings=}",
221
+ f"{pytest__timeout=}",
222
+ f"{python_package_name=}",
223
+ f"{python_version=}",
224
+ f"{readme=}",
225
+ f"{repo_name=}",
226
+ f"{ruff=}",
227
+ f"{run_version_bump=}",
228
+ f"{script=}",
229
+ f"{uv__native_tls=}",
230
+ )
250
231
  )
251
232
  modifications: set[Path] = set()
252
233
  add_bumpversion_toml(
@@ -273,50 +254,68 @@ def conformalize_repo(
273
254
  )
274
255
  if (
275
256
  ci__pull_request__pre_commit
257
+ or ci__pull_request__pre_commit__submodules
276
258
  or ci__pull_request__pyright
277
259
  or ci__pull_request__pytest__macos
278
260
  or ci__pull_request__pytest__ubuntu
279
261
  or ci__pull_request__pytest__windows
262
+ or ci__pull_request__pytest__all_versions
280
263
  or (ci__pull_request__pytest__sops_age_key is not None)
281
264
  or ci__pull_request__ruff
282
265
  ):
283
266
  add_ci_pull_request_yaml(
284
- certificates=ci__ca_certificates,
285
267
  gitea=ci__gitea,
286
- token=ci__token,
287
268
  modifications=modifications,
269
+ certificates=ci__certificates,
288
270
  pre_commit=ci__pull_request__pre_commit,
271
+ pre_commit__submodules=ci__pull_request__pre_commit__submodules,
289
272
  pyright=ci__pull_request__pyright,
290
273
  pytest__macos=ci__pull_request__pytest__macos,
291
274
  pytest__ubuntu=ci__pull_request__pytest__ubuntu,
292
275
  pytest__windows=ci__pull_request__pytest__windows,
276
+ pytest__all_versions=ci__pull_request__pytest__all_versions,
293
277
  pytest__sops_age_key=ci__pull_request__pytest__sops_age_key,
294
278
  pytest__timeout=pytest__timeout,
295
279
  python_version=python_version,
296
280
  repo_name=repo_name,
297
281
  ruff=ruff,
298
282
  script=script,
283
+ token_checkout=ci__token_checkout,
284
+ token_github=ci__token_github,
299
285
  uv__native_tls=uv__native_tls,
300
286
  )
301
287
  if (
302
- ci__push__publish
303
- or (ci__push__publish__username is not None)
304
- or (ci__push__publish__password is not None)
305
- or (ci__push__publish__publish_url is not None)
288
+ ci__push__publish__github
289
+ or ci__push__publish__primary
290
+ or (ci__push__publish__primary__username is not None)
291
+ or (ci__push__publish__primary__password is not None)
292
+ or (ci__push__publish__primary__publish_url is not None)
293
+ or ci__push__publish__secondary
294
+ or (ci__push__publish__secondary__username is not None)
295
+ or (ci__push__publish__secondary__password is not None)
296
+ or (ci__push__publish__secondary__publish_url is not None)
306
297
  or ci__push__tag
307
298
  or ci__push__tag__all
308
299
  ):
309
300
  add_ci_push_yaml(
310
- certificates=ci__ca_certificates,
311
301
  gitea=ci__gitea,
312
- token=ci__token,
313
302
  modifications=modifications,
314
- publish=ci__push__publish,
315
- publish__username=ci__push__publish__username,
316
- publish__password=ci__push__publish__password,
317
- publish__publish_url=ci__push__publish__publish_url,
303
+ certificates=ci__certificates,
304
+ publish__github=ci__push__publish__github,
305
+ publish__primary=ci__push__publish__primary,
306
+ publish__primary__job_name=ci__push__publish__primary__job_name,
307
+ publish__primary__username=ci__push__publish__primary__username,
308
+ publish__primary__password=ci__push__publish__primary__password,
309
+ publish__primary__publish_url=ci__push__publish__primary__publish_url,
310
+ publish__secondary=ci__push__publish__secondary,
311
+ publish__secondary__job_name=ci__push__publish__secondary__job_name,
312
+ publish__secondary__username=ci__push__publish__secondary__username,
313
+ publish__secondary__password=ci__push__publish__secondary__password,
314
+ publish__secondary__publish_url=ci__push__publish__secondary__publish_url,
318
315
  tag=ci__push__tag,
319
316
  tag__all=ci__push__tag__all,
317
+ token_checkout=ci__token_checkout,
318
+ token_github=ci__token_github,
320
319
  uv__native_tls=uv__native_tls,
321
320
  )
322
321
  if coverage:
@@ -381,6 +380,7 @@ def conformalize_repo(
381
380
  ", ".join(map(repr_str, sorted(modifications))),
382
381
  )
383
382
  sys.exit(1)
383
+ LOGGER.info("Finished running %r", get_func_name(conformalize_repo))
384
384
 
385
385
 
386
386
  ##
@@ -430,21 +430,26 @@ def _add_bumpversion_toml_file(path: PathLike, template: str, /) -> Table:
430
430
 
431
431
  def add_ci_pull_request_yaml(
432
432
  *,
433
- certificates: bool = SETTINGS.ci__ca_certificates,
434
433
  gitea: bool = SETTINGS.ci__gitea,
435
- token: str | None = SETTINGS.ci__token,
436
434
  modifications: MutableSet[Path] | None = None,
435
+ certificates: bool = SETTINGS.ci__certificates,
437
436
  pre_commit: bool = SETTINGS.ci__pull_request__pre_commit,
437
+ pre_commit__submodules: str
438
+ | None = SETTINGS.ci__pull_request__pre_commit__submodules,
438
439
  pyright: bool = SETTINGS.ci__pull_request__pyright,
439
440
  pytest__macos: bool = SETTINGS.ci__pull_request__pytest__macos,
440
441
  pytest__ubuntu: bool = SETTINGS.ci__pull_request__pytest__ubuntu,
441
442
  pytest__windows: bool = SETTINGS.ci__pull_request__pytest__windows,
442
- pytest__sops_age_key: str | None = SETTINGS.ci__pull_request__pytest__sops_age_key,
443
+ pytest__all_versions: bool = SETTINGS.ci__pull_request__pytest__all_versions,
444
+ pytest__sops_age_key: Secret[str]
445
+ | None = SETTINGS.ci__pull_request__pytest__sops_age_key,
443
446
  pytest__timeout: int | None = SETTINGS.pytest__timeout,
444
447
  python_version: str = SETTINGS.python_version,
445
448
  repo_name: str | None = SETTINGS.repo_name,
446
449
  ruff: bool = SETTINGS.ci__pull_request__ruff,
447
450
  script: str | None = SETTINGS.script,
451
+ token_checkout: Secret[str] | None = SETTINGS.ci__token_checkout,
452
+ token_github: Secret[str] | None = SETTINGS.ci__token_github,
448
453
  uv__native_tls: bool = SETTINGS.uv__native_tls,
449
454
  ) -> None:
450
455
  path = GITEA_PULL_REQUEST_YAML if gitea else GITHUB_PULL_REQUEST_YAML
@@ -466,7 +471,11 @@ def add_ci_pull_request_yaml(
466
471
  ensure_contains(
467
472
  steps,
468
473
  action_run_hooks_dict(
469
- token=token, repos=["pre-commit/pre-commit-hooks"], gitea=gitea
474
+ token_checkout=token_checkout,
475
+ token_github=token_github,
476
+ submodules=pre_commit__submodules,
477
+ repos=["dycw/actions", "pre-commit/pre-commit-hooks"],
478
+ gitea=gitea,
470
479
  ),
471
480
  )
472
481
  if pyright:
@@ -478,19 +487,14 @@ def add_ci_pull_request_yaml(
478
487
  ensure_contains(
479
488
  steps,
480
489
  action_pyright_dict(
481
- token=token,
490
+ token_checkout=token_checkout,
491
+ token_github=token_github,
482
492
  python_version=python_version,
483
493
  with_requirements=script,
484
494
  native_tls=uv__native_tls,
485
495
  ),
486
496
  )
487
- if (
488
- pytest__macos
489
- or pytest__ubuntu
490
- or pytest__windows
491
- or (pytest__sops_age_key is not None)
492
- or pytest__timeout
493
- ):
497
+ if pytest__macos or pytest__ubuntu or pytest__windows:
494
498
  pytest_dict = get_dict(jobs, "pytest")
495
499
  env = get_dict(pytest_dict, "env")
496
500
  env["CI"] = "1"
@@ -504,7 +508,8 @@ def add_ci_pull_request_yaml(
504
508
  ensure_contains(
505
509
  steps,
506
510
  action_pytest_dict(
507
- token=token,
511
+ token_checkout=token_checkout,
512
+ token_github=token_github,
508
513
  python_version="${{matrix.python-version}}",
509
514
  sops_age_key=pytest__sops_age_key,
510
515
  resolution="${{matrix.resolution}}",
@@ -523,7 +528,12 @@ def add_ci_pull_request_yaml(
523
528
  if pytest__windows:
524
529
  ensure_contains(os, "windows-latest")
525
530
  python_version_dict = get_list(matrix, "python-version")
526
- ensure_contains(python_version_dict, *yield_python_versions(python_version))
531
+ if pytest__all_versions:
532
+ ensure_contains(
533
+ python_version_dict, *yield_python_versions(python_version)
534
+ )
535
+ else:
536
+ ensure_contains(python_version_dict, python_version)
527
537
  resolution = get_list(matrix, "resolution")
528
538
  ensure_contains(resolution, "highest", "lowest-direct")
529
539
  if pytest__timeout is not None:
@@ -534,7 +544,12 @@ def add_ci_pull_request_yaml(
534
544
  steps = get_list(ruff_dict, "steps")
535
545
  if certificates:
536
546
  ensure_contains(steps, update_ca_certificates_dict("steps"))
537
- ensure_contains(steps, action_ruff_dict(token=token))
547
+ ensure_contains(
548
+ steps,
549
+ action_ruff_dict(
550
+ token_checkout=token_checkout, token_github=token_github
551
+ ),
552
+ )
538
553
 
539
554
 
540
555
  ##
@@ -542,16 +557,30 @@ def add_ci_pull_request_yaml(
542
557
 
543
558
  def add_ci_push_yaml(
544
559
  *,
545
- certificates: bool = SETTINGS.ci__ca_certificates,
546
560
  gitea: bool = SETTINGS.ci__gitea,
547
- token: str | None = SETTINGS.ci__token,
548
561
  modifications: MutableSet[Path] | None = None,
549
- publish: bool = SETTINGS.ci__push__publish,
550
- publish__username: str | None = SETTINGS.ci__push__publish__username,
551
- publish__password: Secret[str] | None = SETTINGS.ci__push__publish__password,
552
- publish__publish_url: Secret[str] | None = SETTINGS.ci__push__publish__publish_url,
562
+ certificates: bool = SETTINGS.ci__certificates,
563
+ publish__github: bool = SETTINGS.ci__push__publish__github,
564
+ publish__primary: bool = SETTINGS.ci__push__publish__primary,
565
+ publish__primary__job_name: str = SETTINGS.ci__push__publish__primary__job_name,
566
+ publish__primary__username: str
567
+ | None = SETTINGS.ci__push__publish__primary__username,
568
+ publish__primary__password: Secret[str]
569
+ | None = SETTINGS.ci__push__publish__primary__password,
570
+ publish__primary__publish_url: str
571
+ | None = SETTINGS.ci__push__publish__primary__publish_url,
572
+ publish__secondary: bool = SETTINGS.ci__push__publish__secondary,
573
+ publish__secondary__job_name: str = SETTINGS.ci__push__publish__secondary__job_name,
574
+ publish__secondary__username: str
575
+ | None = SETTINGS.ci__push__publish__secondary__username,
576
+ publish__secondary__password: Secret[str]
577
+ | None = SETTINGS.ci__push__publish__secondary__password,
578
+ publish__secondary__publish_url: str
579
+ | None = SETTINGS.ci__push__publish__secondary__publish_url,
553
580
  tag: bool = SETTINGS.ci__push__tag,
554
581
  tag__all: bool = SETTINGS.ci__push__tag__all,
582
+ token_checkout: Secret[str] | None = SETTINGS.ci__token_checkout,
583
+ token_github: Secret[str] | None = SETTINGS.ci__token_github,
555
584
  uv__native_tls: bool = SETTINGS.uv__native_tls,
556
585
  ) -> None:
557
586
  path = GITEA_PUSH_YAML if gitea else GITHUB_PUSH_YAML
@@ -562,25 +591,37 @@ def add_ci_push_yaml(
562
591
  branches = get_list(push, "branches")
563
592
  ensure_contains(branches, "master")
564
593
  jobs = get_dict(dict_, "jobs")
565
- if publish:
566
- publish_dict = get_dict(jobs, "publish")
567
- environment = get_dict(publish_dict, "environment")
568
- environment["name"] = "pypi"
569
- permissions = get_dict(publish_dict, "permissions")
570
- permissions["id-token"] = "write"
571
- publish_dict["runs-on"] = "ubuntu-latest"
572
- steps = get_list(publish_dict, "steps")
573
- if certificates:
574
- ensure_contains(steps, update_ca_certificates_dict("publish"))
575
- ensure_contains(
576
- steps,
577
- action_publish_package_dict(
578
- token=token,
579
- username=publish__username,
580
- password=publish__password,
581
- publish_url=publish__publish_url,
582
- native_tls=uv__native_tls,
583
- ),
594
+ if publish__github:
595
+ _add_ci_push_yaml_publish_dict(
596
+ jobs,
597
+ "github",
598
+ github=True,
599
+ token_checkout=token_checkout,
600
+ token_github=token_github,
601
+ )
602
+ if publish__primary:
603
+ _add_ci_push_yaml_publish_dict(
604
+ jobs,
605
+ publish__primary__job_name,
606
+ certificates=certificates,
607
+ token_checkout=token_checkout,
608
+ token_github=token_github,
609
+ username=publish__primary__username,
610
+ password=publish__primary__password,
611
+ publish_url=publish__primary__publish_url,
612
+ uv__native_tls=uv__native_tls,
613
+ )
614
+ if publish__secondary:
615
+ _add_ci_push_yaml_publish_dict(
616
+ jobs,
617
+ publish__secondary__job_name,
618
+ certificates=certificates,
619
+ token_checkout=token_checkout,
620
+ token_github=token_github,
621
+ username=publish__secondary__username,
622
+ password=publish__secondary__password,
623
+ publish_url=publish__secondary__publish_url,
624
+ uv__native_tls=uv__native_tls,
584
625
  )
585
626
  if tag:
586
627
  tag_dict = get_dict(jobs, "tag")
@@ -596,6 +637,44 @@ def add_ci_push_yaml(
596
637
  )
597
638
 
598
639
 
640
+ def _add_ci_push_yaml_publish_dict(
641
+ jobs: StrDict,
642
+ name: str,
643
+ /,
644
+ *,
645
+ github: bool = False,
646
+ certificates: bool = SETTINGS.ci__certificates,
647
+ token_checkout: Secret[str] | None = SETTINGS.ci__token_checkout,
648
+ token_github: Secret[str] | None = SETTINGS.ci__token_github,
649
+ username: str | None = None,
650
+ password: Secret[str] | None = None,
651
+ publish_url: str | None = None,
652
+ uv__native_tls: bool = SETTINGS.uv__native_tls,
653
+ ) -> None:
654
+ publish_name = f"publish-{name}"
655
+ publish_dict = get_dict(jobs, publish_name)
656
+ if github:
657
+ environment = get_dict(publish_dict, "environment")
658
+ environment["name"] = "pypi"
659
+ permissions = get_dict(publish_dict, "permissions")
660
+ permissions["id-token"] = "write"
661
+ publish_dict["runs-on"] = "ubuntu-latest"
662
+ steps = get_list(publish_dict, "steps")
663
+ if certificates:
664
+ ensure_contains(steps, update_ca_certificates_dict(publish_name))
665
+ ensure_contains(
666
+ steps,
667
+ action_publish_package_dict(
668
+ token_checkout=token_checkout,
669
+ token_github=token_github,
670
+ username=username,
671
+ password=password,
672
+ publish_url=publish_url,
673
+ native_tls=uv__native_tls,
674
+ ),
675
+ )
676
+
677
+
599
678
  ##
600
679
 
601
680
 
@@ -646,7 +725,7 @@ def add_envrc(
646
725
  native_tls=uv__native_tls, python_version=python_version, script=script
647
726
  )
648
727
  if search(escape(uv_text), context.output, flags=MULTILINE) is None:
649
- context.output += f"\n\n{echo}"
728
+ context.output += f"\n\n{uv_text}"
650
729
 
651
730
 
652
731
  def _add_envrc_uv_text(
@@ -667,14 +746,15 @@ def _add_envrc_uv_text(
667
746
  strip_and_dedent(f"""
668
747
  export UV_PRERELEASE='disallow'
669
748
  export UV_PYTHON='{python_version}'
749
+ export UV_VENV_CLEAR=1
670
750
  if ! command -v uv >/dev/null 2>&1; then
671
- echo_date "ERROR: 'uv' not found" && exit 1
751
+ \techo_date "ERROR: 'uv' not found" && exit 1
672
752
  fi
673
753
  activate='.venv/bin/activate'
674
754
  if [ -f $activate ]; then
675
- . $activate
755
+ \t. $activate
676
756
  else
677
- uv venv
757
+ \tuv venv
678
758
  fi
679
759
  """)
680
760
  )
@@ -1210,7 +1290,7 @@ def _run_pre_commit_update(*, modifications: MutableSet[Path] | None = None) ->
1210
1290
 
1211
1291
 
1212
1292
  run_pre_commit_update = throttle(
1213
- delta=12 * HOUR, path=PATH_THROTTLE_CACHE / _run_pre_commit_update.__name__
1293
+ delta=THROTTLE_DELTA, path=path_throttle_cache(_run_pre_commit_update)
1214
1294
  )(_run_pre_commit_update)
1215
1295
 
1216
1296