dycw-actions 0.2.2__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.
actions/__init__.py ADDED
@@ -0,0 +1,3 @@
1
+ from __future__ import annotations
2
+
3
+ __version__ = "0.2.2"
actions/cli.py ADDED
@@ -0,0 +1,21 @@
1
+ from __future__ import annotations
2
+
3
+ from click import group
4
+ from utilities.click import CONTEXT_SETTINGS
5
+
6
+ from actions.publish.cli import publish_sub_cmd
7
+ from actions.sleep.cli import sleep_sub_cmd
8
+ from actions.tag.cli import tag_sub_cmd
9
+
10
+
11
+ @group(**CONTEXT_SETTINGS)
12
+ def _main() -> None: ...
13
+
14
+
15
+ _ = _main.command(name="publish", **CONTEXT_SETTINGS)(publish_sub_cmd)
16
+ _ = _main.command(name="sleep", **CONTEXT_SETTINGS)(sleep_sub_cmd)
17
+ _ = _main.command(name="tag", **CONTEXT_SETTINGS)(tag_sub_cmd)
18
+
19
+
20
+ if __name__ == "__main__":
21
+ _main()
actions/logging.py ADDED
@@ -0,0 +1,8 @@
1
+ from __future__ import annotations
2
+
3
+ from logging import getLogger
4
+
5
+ LOGGER = getLogger("actions")
6
+
7
+
8
+ __all__ = ["LOGGER"]
@@ -0,0 +1 @@
1
+ from __future__ import annotations
actions/publish/cli.py ADDED
@@ -0,0 +1,45 @@
1
+ from __future__ import annotations
2
+
3
+ from rich.pretty import pretty_repr
4
+ from typed_settings import click_options
5
+ from utilities.logging import basic_config
6
+
7
+ from actions import __version__
8
+ from actions.logging import LOGGER
9
+ from actions.publish.lib import publish_package
10
+ from actions.publish.settings import PublishSettings
11
+ from actions.settings import CommonSettings
12
+ from actions.utilities import ENV_LOADER
13
+
14
+
15
+ @click_options(
16
+ CommonSettings, [ENV_LOADER], show_envvars_in_help=True, argname="common"
17
+ )
18
+ @click_options(
19
+ PublishSettings, [ENV_LOADER], show_envvars_in_help=True, argname="publish"
20
+ )
21
+ def publish_sub_cmd(*, common: CommonSettings, publish: PublishSettings) -> None:
22
+ basic_config(obj=LOGGER)
23
+ LOGGER.info(
24
+ """\
25
+ Running '%r' (version %s) with settings:
26
+ %s
27
+ %s""",
28
+ publish_package.__name__,
29
+ __version__,
30
+ pretty_repr(common),
31
+ pretty_repr(publish),
32
+ )
33
+ if common.dry_run:
34
+ LOGGER.info("Dry run; exiting...")
35
+ return
36
+ publish_package(
37
+ username=publish.username,
38
+ password=publish.password,
39
+ publish_url=publish.publish_url,
40
+ trusted_publishing=publish.trusted_publishing,
41
+ native_tls=publish.native_tls,
42
+ )
43
+
44
+
45
+ __all__ = ["publish_sub_cmd"]
actions/publish/lib.py ADDED
@@ -0,0 +1,55 @@
1
+ from __future__ import annotations
2
+
3
+ from typing import TYPE_CHECKING
4
+
5
+ from utilities.tempfile import TemporaryDirectory
6
+
7
+ from actions import __version__
8
+ from actions.logging import LOGGER
9
+ from actions.publish.settings import PUBLISH_SETTINGS
10
+ from actions.utilities import log_run
11
+
12
+ if TYPE_CHECKING:
13
+ from typed_settings import Secret
14
+
15
+
16
+ def publish_package(
17
+ *,
18
+ username: str | None = PUBLISH_SETTINGS.username,
19
+ password: Secret[str] | None = PUBLISH_SETTINGS.password,
20
+ publish_url: str | None = PUBLISH_SETTINGS.publish_url,
21
+ trusted_publishing: bool = PUBLISH_SETTINGS.trusted_publishing,
22
+ native_tls: bool = PUBLISH_SETTINGS.native_tls,
23
+ ) -> None:
24
+ LOGGER.info(
25
+ """\
26
+ Running %r (version %s) with settings:
27
+ - username = %s
28
+ - password = %s
29
+ - publish_url = %s
30
+ - trusted_publishing = %s
31
+ - native_tls = %s
32
+ """,
33
+ publish_package.__name__,
34
+ __version__,
35
+ username,
36
+ password,
37
+ publish_url,
38
+ trusted_publishing,
39
+ native_tls,
40
+ )
41
+ with TemporaryDirectory() as temp:
42
+ _ = log_run("uv", "build", "--out-dir", str(temp), "--wheel", "--clear")
43
+ _ = log_run(
44
+ "uv",
45
+ "publish",
46
+ *([] if username is None else ["--username", username]),
47
+ *([] if password is None else ["--password", password]),
48
+ *([] if publish_url is None else ["--publish-url", publish_url]),
49
+ *(["--trusted-publishing", "always"] if trusted_publishing else []),
50
+ *(["--native-tls"] if native_tls else []),
51
+ f"{temp}/*",
52
+ )
53
+
54
+
55
+ __all__ = ["publish_package"]
@@ -0,0 +1,35 @@
1
+ from __future__ import annotations
2
+
3
+ from typed_settings import Secret, load_settings, option, secret, settings
4
+
5
+ from actions.utilities import ENV_LOADER, empty_str_to_none
6
+
7
+
8
+ @settings
9
+ class PublishSettings:
10
+ token: Secret[str] | None = secret(
11
+ default=None, converter=empty_str_to_none, help="GitHub token"
12
+ )
13
+ username: str | None = option(
14
+ default=None, converter=empty_str_to_none, help="The username of the upload"
15
+ )
16
+ password: Secret[str] | None = secret(
17
+ default=None, converter=empty_str_to_none, help="The password for the upload"
18
+ )
19
+ publish_url: str | None = option(
20
+ default=None, converter=empty_str_to_none, help="The URL of the upload endpoint"
21
+ )
22
+ trusted_publishing: bool = option(
23
+ default=False, help="Configure trusted publishing"
24
+ )
25
+ native_tls: bool = option(
26
+ default=False,
27
+ help="Whether to load TLS certificates from the platform's native certificate store",
28
+ )
29
+ dry_run: bool = option(default=False, help="Dry run the CLI")
30
+
31
+
32
+ PUBLISH_SETTINGS = load_settings(PublishSettings, [ENV_LOADER])
33
+
34
+
35
+ __all__ = ["PUBLISH_SETTINGS", "PublishSettings"]
actions/settings.py ADDED
@@ -0,0 +1,19 @@
1
+ from __future__ import annotations
2
+
3
+ from typed_settings import Secret, load_settings, option, secret, settings
4
+
5
+ from actions.utilities import ENV_LOADER, empty_str_to_none
6
+
7
+
8
+ @settings
9
+ class CommonSettings:
10
+ token: Secret[str] | None = secret(
11
+ default=None, converter=empty_str_to_none, help="GitHub token"
12
+ )
13
+ dry_run: bool = option(default=False, help="Dry run the CLI")
14
+
15
+
16
+ COMMON_SETTINGS = load_settings(CommonSettings, [ENV_LOADER])
17
+
18
+
19
+ __all__ = ["COMMON_SETTINGS", "CommonSettings"]
@@ -0,0 +1 @@
1
+ from __future__ import annotations
actions/sleep/cli.py ADDED
@@ -0,0 +1,39 @@
1
+ from __future__ import annotations
2
+
3
+ from rich.pretty import pretty_repr
4
+ from typed_settings import click_options
5
+ from utilities.logging import basic_config
6
+
7
+ from actions import __version__
8
+ from actions.logging import LOGGER
9
+ from actions.settings import CommonSettings
10
+ from actions.sleep.lib import random_sleep
11
+ from actions.sleep.settings import SleepSettings
12
+ from actions.utilities import ENV_LOADER
13
+
14
+
15
+ @click_options(
16
+ CommonSettings, [ENV_LOADER], show_envvars_in_help=True, argname="common"
17
+ )
18
+ @click_options(SleepSettings, [ENV_LOADER], show_envvars_in_help=True, argname="sleep")
19
+ def sleep_sub_cmd(*, common: CommonSettings, sleep: SleepSettings) -> None:
20
+ basic_config(obj=LOGGER)
21
+ LOGGER.info(
22
+ """\
23
+ Running '%r' (version %s) with settings:
24
+ %s
25
+ %s""",
26
+ random_sleep.__name__,
27
+ __version__,
28
+ pretty_repr(common),
29
+ pretty_repr(sleep),
30
+ )
31
+ if common.dry_run:
32
+ LOGGER.info("Dry run; exiting...")
33
+ return
34
+ random_sleep(
35
+ min_=sleep.min, max_=sleep.max, step=sleep.step, log_freq=sleep.log_freq
36
+ )
37
+
38
+
39
+ __all__ = ["sleep_sub_cmd"]
actions/sleep/lib.py ADDED
@@ -0,0 +1,66 @@
1
+ from __future__ import annotations
2
+
3
+ from math import ceil, floor
4
+ from random import choice
5
+ from time import sleep
6
+
7
+ from utilities.whenever import get_now
8
+ from whenever import TimeDelta, ZonedDateTime
9
+
10
+ from actions import __version__
11
+ from actions.logging import LOGGER
12
+ from actions.sleep.settings import SLEEP_SETTINGS
13
+
14
+
15
+ def random_sleep(
16
+ *,
17
+ min_: int = SLEEP_SETTINGS.min,
18
+ max_: int = SLEEP_SETTINGS.max,
19
+ step: int = SLEEP_SETTINGS.step,
20
+ log_freq: int = SLEEP_SETTINGS.log_freq,
21
+ ) -> None:
22
+ LOGGER.info(
23
+ """\
24
+ Running %r (version %s) with settings:
25
+ - min_ = %s
26
+ - max_ = %s
27
+ - step = %s
28
+ - log_freq = %s
29
+ """,
30
+ random_sleep.__name__,
31
+ __version__,
32
+ min_,
33
+ max_,
34
+ step,
35
+ log_freq,
36
+ )
37
+ start = get_now()
38
+ delta = TimeDelta(seconds=choice(range(min_, max_, step)))
39
+ LOGGER.info("Sleeping for %s...", delta)
40
+ end = (start + delta).round(mode="ceil")
41
+ while (now := get_now()) < end:
42
+ _intermediate(start, now, end, log_freq=log_freq)
43
+ LOGGER.info("Finished sleeping for %s", delta)
44
+
45
+
46
+ def _intermediate(
47
+ start: ZonedDateTime,
48
+ now: ZonedDateTime,
49
+ end: ZonedDateTime,
50
+ /,
51
+ *,
52
+ log_freq: int = SLEEP_SETTINGS.log_freq,
53
+ ) -> None:
54
+ elapsed = TimeDelta(seconds=floor((now - start).in_seconds()))
55
+ remaining = TimeDelta(seconds=ceil((end - now).in_seconds()))
56
+ this_sleep = min(remaining, TimeDelta(seconds=log_freq))
57
+ LOGGER.info(
58
+ "Sleeping for %s... (elapsed = %s, remaining = %s)",
59
+ this_sleep,
60
+ elapsed,
61
+ remaining,
62
+ )
63
+ sleep(round(this_sleep.in_seconds()))
64
+
65
+
66
+ __all__ = ["random_sleep"]
@@ -0,0 +1,19 @@
1
+ from __future__ import annotations
2
+
3
+ from typed_settings import load_settings, option, settings
4
+
5
+ from actions.utilities import ENV_LOADER
6
+
7
+
8
+ @settings
9
+ class SleepSettings:
10
+ min: int = option(default=0, help="Minimum duration, in seconds")
11
+ max: int = option(default=3600, help="Maximum duration, in seconds")
12
+ step: int = option(default=1, help="Step duration, in seconds")
13
+ log_freq: int = option(default=60, help="Log frequency, in seconds")
14
+
15
+
16
+ SLEEP_SETTINGS = load_settings(SleepSettings, [ENV_LOADER])
17
+
18
+
19
+ __all__ = ["SLEEP_SETTINGS", "SleepSettings"]
@@ -0,0 +1 @@
1
+ from __future__ import annotations
actions/tag/cli.py ADDED
@@ -0,0 +1,43 @@
1
+ from __future__ import annotations
2
+
3
+ from rich.pretty import pretty_repr
4
+ from typed_settings import click_options
5
+ from utilities.logging import basic_config
6
+
7
+ from actions import __version__
8
+ from actions.logging import LOGGER
9
+ from actions.settings import CommonSettings
10
+ from actions.tag.lib import tag_commit
11
+ from actions.tag.settings import TagSettings
12
+ from actions.utilities import ENV_LOADER
13
+
14
+
15
+ @click_options(
16
+ CommonSettings, [ENV_LOADER], show_envvars_in_help=True, argname="common"
17
+ )
18
+ @click_options(TagSettings, [ENV_LOADER], show_envvars_in_help=True, argname="tag")
19
+ def tag_sub_cmd(*, common: CommonSettings, tag: TagSettings) -> None:
20
+ basic_config(obj=LOGGER)
21
+ LOGGER.info(
22
+ """\
23
+ Running '%r' (version %s) with settings:
24
+ %s
25
+ %s""",
26
+ tag_commit.__name__,
27
+ __version__,
28
+ pretty_repr(common),
29
+ pretty_repr(tag),
30
+ )
31
+ if common.dry_run:
32
+ LOGGER.info("Dry run; exiting...")
33
+ return
34
+ tag_commit(
35
+ user_name=tag.user_name,
36
+ user_email=tag.user_email,
37
+ major_minor=tag.major_minor,
38
+ major=tag.major,
39
+ latest=tag.latest,
40
+ )
41
+
42
+
43
+ __all__ = ["tag_sub_cmd"]
actions/tag/lib.py ADDED
@@ -0,0 +1,60 @@
1
+ from __future__ import annotations
2
+
3
+ from contextlib import suppress
4
+ from subprocess import CalledProcessError
5
+
6
+ from utilities.version import parse_version
7
+
8
+ from actions import __version__
9
+ from actions.logging import LOGGER
10
+ from actions.tag.settings import TAG_SETTINGS
11
+ from actions.utilities import log_run
12
+
13
+
14
+ def tag_commit(
15
+ *,
16
+ user_name: str = TAG_SETTINGS.user_name,
17
+ user_email: str = TAG_SETTINGS.user_email,
18
+ major_minor: bool = TAG_SETTINGS.major_minor,
19
+ major: bool = TAG_SETTINGS.major,
20
+ latest: bool = TAG_SETTINGS.latest,
21
+ ) -> None:
22
+ LOGGER.info(
23
+ """\
24
+ Running %r (version %s) with settings:
25
+ - user_name = %s
26
+ - user_email = %s
27
+ - major_minor = %s
28
+ - major = %s
29
+ - latest = %s
30
+ """,
31
+ tag_commit.__name__,
32
+ __version__,
33
+ user_name,
34
+ user_email,
35
+ major_minor,
36
+ major,
37
+ latest,
38
+ )
39
+ _ = log_run("git", "config", "--global", "user.name", user_name)
40
+ _ = log_run("git", "config", "--global", "user.email", user_email)
41
+ version = parse_version(log_run("bump-my-version", "show", "current_version"))
42
+ _tag(str(version))
43
+ if major_minor:
44
+ _tag(f"{version.major}.{version.minor}")
45
+ if major:
46
+ _tag(str(version.major))
47
+ if latest:
48
+ _tag("latest")
49
+
50
+
51
+ def _tag(version: str, /) -> None:
52
+ with suppress(CalledProcessError):
53
+ _ = log_run("git", "tag", "--delete", version)
54
+ with suppress(CalledProcessError):
55
+ _ = log_run("git", "push", "--delete", "origin", version)
56
+ _ = log_run("git", "tag", "-a", version, "HEAD", "-m", version)
57
+ _ = log_run("git", "push", "--tags", "--force", "--set-upstream", "origin")
58
+
59
+
60
+ __all__ = ["tag_commit"]
@@ -0,0 +1,20 @@
1
+ from __future__ import annotations
2
+
3
+ from typed_settings import load_settings, option, settings
4
+
5
+ from actions.utilities import ENV_LOADER
6
+
7
+
8
+ @settings
9
+ class TagSettings:
10
+ user_name: str = option(default="github-actions-bot", help="'git' user name")
11
+ user_email: str = option(default="noreply@github.com", help="'git' user email")
12
+ major_minor: bool = option(default=False, help="Add the 'major.minor' tag")
13
+ major: bool = option(default=False, help="Add the 'major' tag")
14
+ latest: bool = option(default=False, help="Add the 'latest' tag")
15
+
16
+
17
+ TAG_SETTINGS = load_settings(TagSettings, [ENV_LOADER])
18
+
19
+
20
+ __all__ = ["TAG_SETTINGS", "TagSettings"]
actions/utilities.py ADDED
@@ -0,0 +1,23 @@
1
+ from __future__ import annotations
2
+
3
+ from subprocess import check_output
4
+
5
+ from typed_settings import EnvLoader, Secret
6
+
7
+ from actions.logging import LOGGER
8
+
9
+ ENV_LOADER = EnvLoader("")
10
+
11
+
12
+ def empty_str_to_none(text: str, /) -> str | None:
13
+ return None if text == "" else text
14
+
15
+
16
+ def log_run(*cmds: str | Secret[str]) -> str:
17
+ LOGGER.info("Running '%s'...", " ".join(map(str, cmds)))
18
+ return check_output(
19
+ [c if isinstance(c, str) else c.get_secret_value() for c in cmds], text=True
20
+ ).rstrip("\n")
21
+
22
+
23
+ __all__ = ["ENV_LOADER", "empty_str_to_none", "log_run"]
@@ -0,0 +1,14 @@
1
+ Metadata-Version: 2.3
2
+ Name: dycw-actions
3
+ Version: 0.2.2
4
+ Summary: GitHub actions
5
+ Requires-Dist: click>=8.3.1,<8.4
6
+ Requires-Dist: dycw-utilities>=0.170.0,<0.171
7
+ Requires-Dist: rich>=14.2.0,<14.3
8
+ Requires-Dist: typed-settings[attrs,click]>=25.3.0,<25.4
9
+ Requires-Python: >=3.13
10
+ Description-Content-Type: text/markdown
11
+
12
+ # `actions`
13
+
14
+ GitHub actions
@@ -0,0 +1,21 @@
1
+ actions/__init__.py,sha256=p-v1DNzSSlMZQrSYK8zcIuyQfiDyhSSgIRE1gXXYcJ0,58
2
+ actions/cli.py,sha256=S2q5iRqZ-AsB-IF0GxExRBBnguPcKRH_97o-kxg-RLU,536
3
+ actions/logging.py,sha256=rMTcQMGndUHTCaXXtyOHt_VXUMhQGRHoN7okpoX0y5I,120
4
+ actions/publish/__init__.py,sha256=U4S_2y3zgLZVfMenHRaJFBW8yqh2mUBuI291LGQVOJ8,35
5
+ actions/publish/cli.py,sha256=QN9I8jdZVeRLG0DuYFigV-3uTrAkBfa9XHkpzfpJgJk,1263
6
+ actions/publish/lib.py,sha256=4efV3RnJNrPPebCHS_a6FzSRM9ifFJtBXZXXc5ORNFw,1651
7
+ actions/publish/settings.py,sha256=LPuU3PMDByuxukaDsEVLnZQVRX9Fzwm11ashvn1Gm8g,1160
8
+ actions/settings.py,sha256=__Lu6E960DTvP05C0C0NCauOazn6SS5-fu6y3ENWz7Y,503
9
+ actions/sleep/__init__.py,sha256=U4S_2y3zgLZVfMenHRaJFBW8yqh2mUBuI291LGQVOJ8,35
10
+ actions/sleep/cli.py,sha256=3AGGpovn1pdVYn6TOmB_TOusGnjUDMjstemVTvJ3Ci8,1104
11
+ actions/sleep/lib.py,sha256=uMre9J4A4ZEOfDntxn-PZmi7glaHI_QaXuZmmvpq0go,1660
12
+ actions/sleep/settings.py,sha256=M3nn8r9P5lYWz_I-lBNX_dhpWPvtprC48bW55uSgwIA,564
13
+ actions/tag/__init__.py,sha256=U4S_2y3zgLZVfMenHRaJFBW8yqh2mUBuI291LGQVOJ8,35
14
+ actions/tag/cli.py,sha256=txW0XDc71eVrQuyKpfk8rrbK2UWU4LuwbuFk03KQkAY,1154
15
+ actions/tag/lib.py,sha256=BHRedlrgk-JpECcPc7yxj7JnAQIScwecoGTFNWwkzUY,1695
16
+ actions/tag/settings.py,sha256=Lg5rE08dSl9rQ_EuqJ5CoW9D_6pxcxiNZEJwQOfcW5w,654
17
+ actions/utilities.py,sha256=F1p07eXZt0m0Ho92_70u-85E-CBWGYfzhiwFJUzdKwo,572
18
+ dycw_actions-0.2.2.dist-info/WHEEL,sha256=ZyFSCYkV2BrxH6-HRVRg3R9Fo7MALzer9KiPYqNxSbo,79
19
+ dycw_actions-0.2.2.dist-info/entry_points.txt,sha256=2Uu7wAZOm0mmcsGBEsGB370HAWgVWECRFJ9rKgfC3-I,46
20
+ dycw_actions-0.2.2.dist-info/METADATA,sha256=uqq2NqHNuqX4k69OOd00Gave-paWkRiDhFs0uBDpuBg,343
21
+ dycw_actions-0.2.2.dist-info/RECORD,,
@@ -0,0 +1,4 @@
1
+ Wheel-Version: 1.0
2
+ Generator: uv 0.9.18
3
+ Root-Is-Purelib: true
4
+ Tag: py3-none-any
@@ -0,0 +1,3 @@
1
+ [console_scripts]
2
+ action = actions.cli:_main
3
+