dycw-actions 0.7.1__py3-none-any.whl → 0.7.7__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 +1 -1
- actions/clean_dir/lib.py +1 -0
- actions/cli.py +10 -0
- actions/constants.py +5 -1
- actions/pre_commit/conformalize_repo/lib.py +31 -18
- actions/pre_commit/touch_empty_py/lib.py +9 -1
- actions/pre_commit/touch_py_typed/lib.py +9 -1
- actions/pre_commit/update_requirements/classes.py +16 -3
- actions/pre_commit/update_requirements/lib.py +15 -3
- actions/register_gitea_runner/__init__.py +1 -0
- actions/register_gitea_runner/cli.py +32 -0
- actions/register_gitea_runner/configs/config.yml +110 -0
- actions/register_gitea_runner/configs/entrypoint.sh +23 -0
- actions/register_gitea_runner/constants.py +23 -0
- actions/register_gitea_runner/lib.py +289 -0
- actions/register_gitea_runner/settings.py +33 -0
- {dycw_actions-0.7.1.dist-info → dycw_actions-0.7.7.dist-info}/METADATA +4 -3
- {dycw_actions-0.7.1.dist-info → dycw_actions-0.7.7.dist-info}/RECORD +20 -13
- {dycw_actions-0.7.1.dist-info → dycw_actions-0.7.7.dist-info}/WHEEL +0 -0
- {dycw_actions-0.7.1.dist-info → dycw_actions-0.7.7.dist-info}/entry_points.txt +0 -0
actions/__init__.py
CHANGED
actions/clean_dir/lib.py
CHANGED
actions/cli.py
CHANGED
|
@@ -42,6 +42,11 @@ from actions.publish_package.constants import (
|
|
|
42
42
|
)
|
|
43
43
|
from actions.random_sleep.cli import random_sleep_sub_cmd
|
|
44
44
|
from actions.random_sleep.constants import RANDOM_SLEEP_DOCSTRING, RANDOM_SLEEP_SUB_CMD
|
|
45
|
+
from actions.register_gitea_runner.cli import register_gitea_runner_sub_cmd
|
|
46
|
+
from actions.register_gitea_runner.constants import (
|
|
47
|
+
REGISTER_GITEA_RUNNER_DOCSTRING,
|
|
48
|
+
REGISTER_GITEA_RUNNER_SUB_CMD,
|
|
49
|
+
)
|
|
45
50
|
from actions.run_hooks.cli import run_hooks_sub_cmd
|
|
46
51
|
from actions.run_hooks.constants import RUN_HOOKS_DOCSTRING, RUN_HOOKS_SUB_CMD
|
|
47
52
|
from actions.setup_cronjob.cli import setup_cronjob_sub_cmd
|
|
@@ -69,6 +74,11 @@ _ = _main.command(name=RUN_HOOKS_SUB_CMD, help=RUN_HOOKS_DOCSTRING, **CONTEXT_SE
|
|
|
69
74
|
_ = _main.command(
|
|
70
75
|
name=RANDOM_SLEEP_SUB_CMD, help=RANDOM_SLEEP_DOCSTRING, **CONTEXT_SETTINGS
|
|
71
76
|
)(random_sleep_sub_cmd)
|
|
77
|
+
_ = _main.command(
|
|
78
|
+
name=REGISTER_GITEA_RUNNER_SUB_CMD,
|
|
79
|
+
help=REGISTER_GITEA_RUNNER_DOCSTRING,
|
|
80
|
+
**CONTEXT_SETTINGS,
|
|
81
|
+
)(register_gitea_runner_sub_cmd)
|
|
72
82
|
_ = _main.command(
|
|
73
83
|
name=SETUP_CRONJOB_SUB_CMD, help=SETUP_CRONJOB_DOCSTRING, **CONTEXT_SETTINGS
|
|
74
84
|
)(setup_cronjob_sub_cmd)
|
actions/constants.py
CHANGED
|
@@ -2,9 +2,13 @@ from __future__ import annotations
|
|
|
2
2
|
|
|
3
3
|
from ruamel.yaml import YAML
|
|
4
4
|
from utilities.importlib import files
|
|
5
|
+
from utilities.pathlib import get_repo_root
|
|
6
|
+
from xdg_base_dirs import xdg_cache_home
|
|
5
7
|
|
|
6
8
|
PATH_ACTIONS = files(anchor="actions")
|
|
9
|
+
PATH_CACHE = xdg_cache_home() / "actions"
|
|
10
|
+
PATH_THROTTLE_CACHE = PATH_CACHE / "throttle" / get_repo_root().name
|
|
7
11
|
YAML_INSTANCE = YAML()
|
|
8
12
|
|
|
9
13
|
|
|
10
|
-
__all__ = ["PATH_ACTIONS", "YAML_INSTANCE"]
|
|
14
|
+
__all__ = ["PATH_ACTIONS", "PATH_CACHE", "PATH_THROTTLE_CACHE", "YAML_INSTANCE"]
|
|
@@ -2,6 +2,7 @@ from __future__ import annotations
|
|
|
2
2
|
|
|
3
3
|
import sys
|
|
4
4
|
from contextlib import contextmanager, suppress
|
|
5
|
+
from hashlib import blake2b
|
|
5
6
|
from itertools import product
|
|
6
7
|
from pathlib import Path
|
|
7
8
|
from re import MULTILINE, escape, search, sub
|
|
@@ -15,14 +16,12 @@ from ruamel.yaml.scalarstring import LiteralScalarString
|
|
|
15
16
|
from tomlkit import TOMLDocument, table
|
|
16
17
|
from tomlkit.exceptions import NonExistentKey
|
|
17
18
|
from utilities.inflect import counted_noun
|
|
18
|
-
from utilities.pathlib import get_repo_root
|
|
19
19
|
from utilities.re import extract_groups
|
|
20
20
|
from utilities.subprocess import ripgrep
|
|
21
21
|
from utilities.text import repr_str, strip_and_dedent
|
|
22
|
+
from utilities.throttle import throttle
|
|
22
23
|
from utilities.version import ParseVersionError, Version, parse_version
|
|
23
|
-
from utilities.whenever import HOUR
|
|
24
|
-
from whenever import ZonedDateTime
|
|
25
|
-
from xdg_base_dirs import xdg_cache_home
|
|
24
|
+
from utilities.whenever import HOUR
|
|
26
25
|
|
|
27
26
|
from actions import __version__
|
|
28
27
|
from actions.action_dicts.lib import (
|
|
@@ -33,7 +32,7 @@ from actions.action_dicts.lib import (
|
|
|
33
32
|
run_action_ruff_dict,
|
|
34
33
|
run_action_tag_dict,
|
|
35
34
|
)
|
|
36
|
-
from actions.constants import YAML_INSTANCE
|
|
35
|
+
from actions.constants import PATH_THROTTLE_CACHE, YAML_INSTANCE
|
|
37
36
|
from actions.logging import LOGGER
|
|
38
37
|
from actions.pre_commit.conformalize_repo.constants import (
|
|
39
38
|
ACTIONS_URL,
|
|
@@ -67,6 +66,7 @@ from actions.pre_commit.replace_sequence_strs.constants import (
|
|
|
67
66
|
)
|
|
68
67
|
from actions.pre_commit.touch_empty_py.constants import TOUCH_EMPTY_PY_SUB_CMD
|
|
69
68
|
from actions.pre_commit.touch_py_typed.constants import TOUCH_PY_TYPED_SUB_CMD
|
|
69
|
+
from actions.pre_commit.update_requirements.constants import UPDATE_REQUIREMENTS_SUB_CMD
|
|
70
70
|
from actions.pre_commit.utilities import (
|
|
71
71
|
ensure_aot_contains,
|
|
72
72
|
ensure_contains,
|
|
@@ -83,7 +83,7 @@ from actions.pre_commit.utilities import (
|
|
|
83
83
|
yield_toml_doc,
|
|
84
84
|
yield_yaml_dict,
|
|
85
85
|
)
|
|
86
|
-
from actions.utilities import logged_run
|
|
86
|
+
from actions.utilities import logged_run
|
|
87
87
|
|
|
88
88
|
if TYPE_CHECKING:
|
|
89
89
|
from collections.abc import Iterator, MutableSet
|
|
@@ -284,6 +284,7 @@ def conformalize_repo(
|
|
|
284
284
|
pytest__ubuntu=github__pull_request__pytest__ubuntu,
|
|
285
285
|
pytest__timeout=pytest__timeout,
|
|
286
286
|
python_version=python_version,
|
|
287
|
+
repo_name=repo_name,
|
|
287
288
|
ruff=ruff,
|
|
288
289
|
script=script,
|
|
289
290
|
)
|
|
@@ -504,6 +505,7 @@ def add_github_pull_request_yaml(
|
|
|
504
505
|
pytest__windows: bool = SETTINGS.github__pull_request__pytest__windows,
|
|
505
506
|
pytest__timeout: int | None = SETTINGS.pytest__timeout,
|
|
506
507
|
python_version: str = SETTINGS.python_version,
|
|
508
|
+
repo_name: str | None = SETTINGS.repo_name,
|
|
507
509
|
ruff: bool = SETTINGS.github__pull_request__ruff,
|
|
508
510
|
script: str | None = SETTINGS.script,
|
|
509
511
|
) -> None:
|
|
@@ -516,7 +518,7 @@ def add_github_pull_request_yaml(
|
|
|
516
518
|
branches = get_list(pull_request, "branches")
|
|
517
519
|
ensure_contains(branches, "master")
|
|
518
520
|
schedule = get_list(on, "schedule")
|
|
519
|
-
ensure_contains(schedule, {"cron":
|
|
521
|
+
ensure_contains(schedule, {"cron": get_cron_job(repo_name=repo_name)})
|
|
520
522
|
jobs = get_dict(dict_, "jobs")
|
|
521
523
|
if pre_commit:
|
|
522
524
|
pre_commit_dict = get_dict(jobs, "pre-commit")
|
|
@@ -695,6 +697,7 @@ def add_pre_commit_config_yaml(
|
|
|
695
697
|
)
|
|
696
698
|
_add_pre_commit_config_repo(dict_, ACTIONS_URL, TOUCH_EMPTY_PY_SUB_CMD)
|
|
697
699
|
_add_pre_commit_config_repo(dict_, ACTIONS_URL, TOUCH_PY_TYPED_SUB_CMD)
|
|
700
|
+
_add_pre_commit_config_repo(dict_, ACTIONS_URL, UPDATE_REQUIREMENTS_SUB_CMD)
|
|
698
701
|
if ruff:
|
|
699
702
|
_add_pre_commit_config_repo(
|
|
700
703
|
dict_, RUFF_URL, "ruff-check", args=("add", ["--fix"])
|
|
@@ -1050,6 +1053,20 @@ def check_versions() -> None:
|
|
|
1050
1053
|
##
|
|
1051
1054
|
|
|
1052
1055
|
|
|
1056
|
+
def get_cron_job(*, repo_name: str | None = SETTINGS.repo_name) -> str:
|
|
1057
|
+
if repo_name is None:
|
|
1058
|
+
hour = minute = 0
|
|
1059
|
+
else:
|
|
1060
|
+
digest = blake2b(repo_name.encode(), digest_size=8).digest()
|
|
1061
|
+
value = int.from_bytes(digest, "big")
|
|
1062
|
+
minute = value % 60
|
|
1063
|
+
hour = (value // 60) % 24
|
|
1064
|
+
return f"{hour} {minute} * * *"
|
|
1065
|
+
|
|
1066
|
+
|
|
1067
|
+
##
|
|
1068
|
+
|
|
1069
|
+
|
|
1053
1070
|
def get_python_package_name(
|
|
1054
1071
|
*,
|
|
1055
1072
|
package_name: str | None = SETTINGS.package_name,
|
|
@@ -1123,23 +1140,18 @@ def run_bump_my_version(*, modifications: MutableSet[Path] | None = None) -> Non
|
|
|
1123
1140
|
##
|
|
1124
1141
|
|
|
1125
1142
|
|
|
1126
|
-
def
|
|
1127
|
-
cache = xdg_cache_home() / "conformalize" / get_repo_root().name
|
|
1128
|
-
try:
|
|
1129
|
-
text = cache.read_text()
|
|
1130
|
-
except FileNotFoundError:
|
|
1131
|
-
...
|
|
1132
|
-
else:
|
|
1133
|
-
prev = ZonedDateTime.parse_iso(text.rstrip("\n"))
|
|
1134
|
-
if prev >= (get_now() - 12 * HOUR):
|
|
1135
|
-
return
|
|
1136
|
-
write_text(cache, get_now().format_iso())
|
|
1143
|
+
def _run_pre_commit_update(*, modifications: MutableSet[Path] | None = None) -> None:
|
|
1137
1144
|
current = PRE_COMMIT_CONFIG_YAML.read_text()
|
|
1138
1145
|
logged_run("pre-commit", "autoupdate", print=True)
|
|
1139
1146
|
if (modifications is not None) and (PRE_COMMIT_CONFIG_YAML.read_text() != current):
|
|
1140
1147
|
modifications.add(PRE_COMMIT_CONFIG_YAML)
|
|
1141
1148
|
|
|
1142
1149
|
|
|
1150
|
+
run_pre_commit_update = throttle(
|
|
1151
|
+
delta=12 * HOUR, path=PATH_THROTTLE_CACHE / _run_pre_commit_update.__name__
|
|
1152
|
+
)(_run_pre_commit_update)
|
|
1153
|
+
|
|
1154
|
+
|
|
1143
1155
|
##
|
|
1144
1156
|
|
|
1145
1157
|
|
|
@@ -1278,6 +1290,7 @@ __all__ = [
|
|
|
1278
1290
|
"add_readme_md",
|
|
1279
1291
|
"add_ruff_toml",
|
|
1280
1292
|
"check_versions",
|
|
1293
|
+
"get_cron_job",
|
|
1281
1294
|
"get_python_package_name",
|
|
1282
1295
|
"get_version_from_bumpversion_toml",
|
|
1283
1296
|
"get_version_from_git_show",
|
|
@@ -5,8 +5,11 @@ from typing import TYPE_CHECKING
|
|
|
5
5
|
|
|
6
6
|
from libcst import parse_statement
|
|
7
7
|
from utilities.text import repr_str, strip_and_dedent
|
|
8
|
+
from utilities.throttle import throttle
|
|
9
|
+
from utilities.whenever import HOUR
|
|
8
10
|
|
|
9
11
|
from actions import __version__
|
|
12
|
+
from actions.constants import PATH_THROTTLE_CACHE
|
|
10
13
|
from actions.logging import LOGGER
|
|
11
14
|
from actions.pre_commit.utilities import yield_python_file
|
|
12
15
|
|
|
@@ -17,7 +20,7 @@ if TYPE_CHECKING:
|
|
|
17
20
|
from utilities.types import PathLike
|
|
18
21
|
|
|
19
22
|
|
|
20
|
-
def
|
|
23
|
+
def _touch_empty_py(*paths: PathLike) -> None:
|
|
21
24
|
LOGGER.info(
|
|
22
25
|
strip_and_dedent("""
|
|
23
26
|
Running '%s' (version %s) with settings:
|
|
@@ -38,6 +41,11 @@ def touch_empty_py(*paths: PathLike) -> None:
|
|
|
38
41
|
sys.exit(1)
|
|
39
42
|
|
|
40
43
|
|
|
44
|
+
touch_empty_py = throttle(
|
|
45
|
+
delta=12 * HOUR, path=PATH_THROTTLE_CACHE / _touch_empty_py.__name__
|
|
46
|
+
)(_touch_empty_py)
|
|
47
|
+
|
|
48
|
+
|
|
41
49
|
def _format_path(
|
|
42
50
|
path: PathLike, /, *, modifications: MutableSet[Path] | None = None
|
|
43
51
|
) -> None:
|
|
@@ -6,8 +6,11 @@ from typing import TYPE_CHECKING
|
|
|
6
6
|
|
|
7
7
|
from utilities.iterables import one
|
|
8
8
|
from utilities.text import repr_str, strip_and_dedent
|
|
9
|
+
from utilities.throttle import throttle
|
|
10
|
+
from utilities.whenever import HOUR
|
|
9
11
|
|
|
10
12
|
from actions import __version__
|
|
13
|
+
from actions.constants import PATH_THROTTLE_CACHE
|
|
11
14
|
from actions.logging import LOGGER
|
|
12
15
|
|
|
13
16
|
if TYPE_CHECKING:
|
|
@@ -16,7 +19,7 @@ if TYPE_CHECKING:
|
|
|
16
19
|
from utilities.types import PathLike
|
|
17
20
|
|
|
18
21
|
|
|
19
|
-
def
|
|
22
|
+
def _touch_py_typed(*paths: PathLike) -> None:
|
|
20
23
|
LOGGER.info(
|
|
21
24
|
strip_and_dedent("""
|
|
22
25
|
Running '%s' (version %s) with settings:
|
|
@@ -37,6 +40,11 @@ def touch_py_typed(*paths: PathLike) -> None:
|
|
|
37
40
|
sys.exit(1)
|
|
38
41
|
|
|
39
42
|
|
|
43
|
+
touch_py_typed = throttle(
|
|
44
|
+
delta=12 * HOUR, path=PATH_THROTTLE_CACHE / _touch_py_typed.__name__
|
|
45
|
+
)(_touch_py_typed)
|
|
46
|
+
|
|
47
|
+
|
|
40
48
|
def _format_path(
|
|
41
49
|
path: PathLike, /, *, modifications: MutableSet[Path] | None = None
|
|
42
50
|
) -> None:
|
|
@@ -1,8 +1,10 @@
|
|
|
1
|
+
# ruff: noqa: TC003
|
|
1
2
|
from __future__ import annotations
|
|
2
3
|
|
|
3
4
|
import re
|
|
4
5
|
from dataclasses import dataclass, field, replace
|
|
5
6
|
from functools import total_ordering
|
|
7
|
+
from pathlib import Path
|
|
6
8
|
from typing import Any, Self, override
|
|
7
9
|
|
|
8
10
|
from pydantic import BaseModel
|
|
@@ -22,6 +24,15 @@ type Version2or3 = Version2 | Version3
|
|
|
22
24
|
type VersionSet = dict[str, Version2or3]
|
|
23
25
|
|
|
24
26
|
|
|
27
|
+
##
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
class PipListOutput(BaseModel):
|
|
31
|
+
name: str
|
|
32
|
+
version: str
|
|
33
|
+
editable_project_location: Path | None = None
|
|
34
|
+
|
|
35
|
+
|
|
25
36
|
class PipListOutdatedOutput(BaseModel):
|
|
26
37
|
name: str
|
|
27
38
|
version: str
|
|
@@ -29,6 +40,10 @@ class PipListOutdatedOutput(BaseModel):
|
|
|
29
40
|
latest_filetype: str
|
|
30
41
|
|
|
31
42
|
|
|
43
|
+
_ = PipListOutput.model_rebuild()
|
|
44
|
+
_ = PipListOutdatedOutput.model_rebuild()
|
|
45
|
+
|
|
46
|
+
|
|
32
47
|
##
|
|
33
48
|
|
|
34
49
|
|
|
@@ -100,11 +115,9 @@ def parse_version2(version: str, /) -> Version2:
|
|
|
100
115
|
_PARSE_VERSION2_PATTERN = re.compile(r"^(\d+)\.(\d+)(?:-(\w+))?")
|
|
101
116
|
|
|
102
117
|
|
|
103
|
-
_ = PipListOutdatedOutput.model_rebuild()
|
|
104
|
-
|
|
105
|
-
|
|
106
118
|
__all__ = [
|
|
107
119
|
"PipListOutdatedOutput",
|
|
120
|
+
"PipListOutput",
|
|
108
121
|
"TwoSidedVersions",
|
|
109
122
|
"Version1or2",
|
|
110
123
|
"Version2",
|
|
@@ -5,12 +5,14 @@ from functools import partial
|
|
|
5
5
|
from typing import TYPE_CHECKING
|
|
6
6
|
|
|
7
7
|
from pydantic import TypeAdapter
|
|
8
|
+
from utilities.functions import max_nullable
|
|
8
9
|
from utilities.text import repr_str, strip_and_dedent
|
|
9
10
|
|
|
10
11
|
from actions import __version__
|
|
11
12
|
from actions.logging import LOGGER
|
|
12
13
|
from actions.pre_commit.update_requirements.classes import (
|
|
13
14
|
PipListOutdatedOutput,
|
|
15
|
+
PipListOutput,
|
|
14
16
|
Version1or2,
|
|
15
17
|
Version2,
|
|
16
18
|
Version3,
|
|
@@ -28,6 +30,7 @@ if TYPE_CHECKING:
|
|
|
28
30
|
from utilities.types import PathLike
|
|
29
31
|
|
|
30
32
|
from actions.pre_commit.update_requirements.classes import Version2or3, VersionSet
|
|
33
|
+
from actions.types import StrDict
|
|
31
34
|
|
|
32
35
|
|
|
33
36
|
def update_requirements(*paths: PathLike) -> None:
|
|
@@ -66,11 +69,20 @@ def _format_path(
|
|
|
66
69
|
|
|
67
70
|
|
|
68
71
|
def _get_versions() -> VersionSet:
|
|
69
|
-
|
|
72
|
+
json1 = logged_run(
|
|
73
|
+
"uv", "pip", "list", "--format", "json", "--strict", return_=True
|
|
74
|
+
)
|
|
75
|
+
models1 = TypeAdapter(list[PipListOutput]).validate_json(json1)
|
|
76
|
+
versions1 = {p.name: parse_version2_or_3(p.version) for p in models1}
|
|
77
|
+
json2 = logged_run(
|
|
70
78
|
"uv", "pip", "list", "--format", "json", "--outdated", "--strict", return_=True
|
|
71
79
|
)
|
|
72
|
-
|
|
73
|
-
|
|
80
|
+
models2 = TypeAdapter(list[PipListOutdatedOutput]).validate_json(json2)
|
|
81
|
+
versions2 = {p.name: parse_version2_or_3(p.latest_version) for p in models2}
|
|
82
|
+
out: StrDict = {}
|
|
83
|
+
for key in set(versions1) | set(versions2):
|
|
84
|
+
out[key] = max_nullable([versions1.get(key), versions2.get(key)])
|
|
85
|
+
return out
|
|
74
86
|
|
|
75
87
|
|
|
76
88
|
def _format_req(requirement: Requirement, /, *, versions: VersionSet) -> Requirement:
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
from typed_settings import click_options
|
|
4
|
+
from utilities.logging import basic_config
|
|
5
|
+
from utilities.os import is_pytest
|
|
6
|
+
|
|
7
|
+
from actions.logging import LOGGER
|
|
8
|
+
from actions.register_gitea_runner.lib import register_gitea_runner
|
|
9
|
+
from actions.register_gitea_runner.settings import Settings
|
|
10
|
+
from actions.utilities import LOADER
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
@click_options(Settings, [LOADER], show_envvars_in_help=True)
|
|
14
|
+
def register_gitea_runner_sub_cmd(settings: Settings, /) -> None:
|
|
15
|
+
if is_pytest():
|
|
16
|
+
return
|
|
17
|
+
basic_config(obj=LOGGER)
|
|
18
|
+
register_gitea_runner(
|
|
19
|
+
ssh_user=settings.ssh_user,
|
|
20
|
+
ssh_host=settings.ssh_host,
|
|
21
|
+
gitea_container_user=settings.gitea_container_user,
|
|
22
|
+
gitea_container_name=settings.gitea_container_name,
|
|
23
|
+
runner_certificate=settings.runner_certificate,
|
|
24
|
+
runner_capacity=settings.runner_capacity,
|
|
25
|
+
runner_container_name=settings.runner_container_name,
|
|
26
|
+
gitea_host=settings.gitea_host,
|
|
27
|
+
gitea_port=settings.gitea_port,
|
|
28
|
+
runner_instance_name=settings.runner_instance_name,
|
|
29
|
+
)
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
__all__ = ["register_gitea_runner_sub_cmd"]
|
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
# Example configuration file, it's safe to copy this as the default config file without any modification.
|
|
2
|
+
|
|
3
|
+
# You don't have to copy this file to your instance,
|
|
4
|
+
# just run `./act_runner generate-config > config.yaml` to generate a config file.
|
|
5
|
+
|
|
6
|
+
log:
|
|
7
|
+
# The level of logging, can be trace, debug, info, warn, error, fatal
|
|
8
|
+
level: info
|
|
9
|
+
|
|
10
|
+
runner:
|
|
11
|
+
# Where to store the registration result.
|
|
12
|
+
file: .runner
|
|
13
|
+
# Execute how many tasks concurrently at the same time.
|
|
14
|
+
capacity: ${CAPACITY}
|
|
15
|
+
# Extra environment variables to run jobs.
|
|
16
|
+
envs:
|
|
17
|
+
A_TEST_ENV_NAME_1: a_test_env_value_1
|
|
18
|
+
A_TEST_ENV_NAME_2: a_test_env_value_2
|
|
19
|
+
# Extra environment variables to run jobs from a file.
|
|
20
|
+
# It will be ignored if it's empty or the file doesn't exist.
|
|
21
|
+
env_file: .env
|
|
22
|
+
# The timeout for a job to be finished.
|
|
23
|
+
# Please note that the Gitea instance also has a timeout (3h by default) for the job.
|
|
24
|
+
# So the job could be stopped by the Gitea instance if it's timeout is shorter than this.
|
|
25
|
+
timeout: 3h
|
|
26
|
+
# The timeout for the runner to wait for running jobs to finish when shutting down.
|
|
27
|
+
# Any running jobs that haven't finished after this timeout will be cancelled.
|
|
28
|
+
shutdown_timeout: 0s
|
|
29
|
+
# Whether skip verifying the TLS certificate of the Gitea instance.
|
|
30
|
+
insecure: false
|
|
31
|
+
# The timeout for fetching the job from the Gitea instance.
|
|
32
|
+
fetch_timeout: 5s
|
|
33
|
+
# The interval for fetching the job from the Gitea instance.
|
|
34
|
+
fetch_interval: 2s
|
|
35
|
+
# The github_mirror of a runner is used to specify the mirror address of the github that pulls the action repository.
|
|
36
|
+
# It works when something like `uses: actions/checkout@v4` is used and DEFAULT_ACTIONS_URL is set to github,
|
|
37
|
+
# and github_mirror is not empty. In this case,
|
|
38
|
+
# it replaces https://github.com with the value here, which is useful for some special network environments.
|
|
39
|
+
github_mirror: ""
|
|
40
|
+
# The labels of a runner are used to determine which jobs the runner can run, and how to run them.
|
|
41
|
+
# Like: "macos-arm64:host" or "ubuntu-latest:docker://docker.gitea.com/runner-images:ubuntu-latest"
|
|
42
|
+
# Find more images provided by Gitea at https://gitea.com/docker.gitea.com/runner-images .
|
|
43
|
+
# If it's empty when registering, it will ask for inputting labels.
|
|
44
|
+
# If it's empty when execute `daemon`, will use labels in `.runner` file.
|
|
45
|
+
labels:
|
|
46
|
+
- "ubuntu-latest:docker://docker.gitea.com/runner-images:ubuntu-latest"
|
|
47
|
+
- "ubuntu-22.04:docker://docker.gitea.com/runner-images:ubuntu-22.04"
|
|
48
|
+
- "ubuntu-20.04:docker://docker.gitea.com/runner-images:ubuntu-20.04"
|
|
49
|
+
|
|
50
|
+
cache:
|
|
51
|
+
# Enable cache server to use actions/cache.
|
|
52
|
+
enabled: true
|
|
53
|
+
# The directory to store the cache data.
|
|
54
|
+
# If it's empty, the cache data will be stored in ${HOME}/.cache/actcache.
|
|
55
|
+
dir: ""
|
|
56
|
+
# The host of the cache server.
|
|
57
|
+
# It's not for the address to listen, but the address to connect from job containers.
|
|
58
|
+
# So 0.0.0.0 is a bad choice, leave it empty to detect automatically.
|
|
59
|
+
host: ""
|
|
60
|
+
# The port of the cache server.
|
|
61
|
+
# 0 means to use a random available port.
|
|
62
|
+
port: 0
|
|
63
|
+
# The external cache server URL. Valid only when enable is true.
|
|
64
|
+
# If it's specified, act_runner will use this URL as the ACTIONS_CACHE_URL rather than start a server by itself.
|
|
65
|
+
# The URL should generally end with "/".
|
|
66
|
+
external_server: ""
|
|
67
|
+
|
|
68
|
+
container:
|
|
69
|
+
# Specifies the network to which the container will connect.
|
|
70
|
+
# Could be host, bridge or the name of a custom network.
|
|
71
|
+
# If it's empty, act_runner will create a network automatically.
|
|
72
|
+
network: ""
|
|
73
|
+
# Whether to use privileged mode or not when launching task containers (privileged mode is required for Docker-in-Docker).
|
|
74
|
+
privileged: false
|
|
75
|
+
# And other options to be used when the container is started (eg, --add-host=my.gitea.url:host-gateway).
|
|
76
|
+
options: "-v ${CERTIFICATE}:/usr/local/share/ca-certificates/root.crt:ro"
|
|
77
|
+
# The parent directory of a job's working directory.
|
|
78
|
+
# NOTE: There is no need to add the first '/' of the path as act_runner will add it automatically.
|
|
79
|
+
# If the path starts with '/', the '/' will be trimmed.
|
|
80
|
+
# For example, if the parent directory is /path/to/my/dir, workdir_parent should be path/to/my/dir
|
|
81
|
+
# If it's empty, /workspace will be used.
|
|
82
|
+
workdir_parent:
|
|
83
|
+
# Volumes (including bind mounts) can be mounted to containers. Glob syntax is supported, see https://github.com/gobwas/glob
|
|
84
|
+
# You can specify multiple volumes. If the sequence is empty, no volumes can be mounted.
|
|
85
|
+
# For example, if you only allow containers to mount the `data` volume and all the json files in `/src`, you should change the config to:
|
|
86
|
+
# valid_volumes:
|
|
87
|
+
# - data
|
|
88
|
+
# - /src/*.json
|
|
89
|
+
# If you want to allow any volume, please use the following configuration:
|
|
90
|
+
# valid_volumes:
|
|
91
|
+
# - '**'
|
|
92
|
+
valid_volumes: ["**"]
|
|
93
|
+
# overrides the docker client host with the specified one.
|
|
94
|
+
# If it's empty, act_runner will find an available docker host automatically.
|
|
95
|
+
# If it's "-", act_runner will find an available docker host automatically, but the docker host won't be mounted to the job containers and service containers.
|
|
96
|
+
# If it's not empty or "-", the specified docker host will be used. An error will be returned if it doesn't work.
|
|
97
|
+
docker_host: ""
|
|
98
|
+
# Pull docker image(s) even if already present
|
|
99
|
+
force_pull: true
|
|
100
|
+
# Rebuild docker image(s) even if already present
|
|
101
|
+
force_rebuild: false
|
|
102
|
+
# Always require a reachable docker daemon, even if not required by act_runner
|
|
103
|
+
require_docker: false
|
|
104
|
+
# Timeout to wait for the docker daemon to be reachable, if docker is required by require_docker or act_runner
|
|
105
|
+
docker_timeout: 0s
|
|
106
|
+
|
|
107
|
+
host:
|
|
108
|
+
# The parent directory of a job's working directory.
|
|
109
|
+
# If it's empty, ${HOME}/.cache/act/ will be used.
|
|
110
|
+
workdir_parent:
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
#!/usr/bin/env sh
|
|
2
|
+
set -euxo
|
|
3
|
+
|
|
4
|
+
# echo
|
|
5
|
+
echo_date() { echo "[$(date +'%Y-%m-%d %H:%M:%S')] $*" >&2; }
|
|
6
|
+
|
|
7
|
+
# main
|
|
8
|
+
wait-for-it.sh \
|
|
9
|
+
--host="${GITEA_HOST}" \
|
|
10
|
+
--port="${GITEA_PORT}" \
|
|
11
|
+
--strict \
|
|
12
|
+
-- \
|
|
13
|
+
echo "${GITEA_HOST}:${GITEA_PORT} is up"
|
|
14
|
+
|
|
15
|
+
if ! command -v update-ca-certificates >/dev/null 2>&1; then
|
|
16
|
+
echo_date "Installing 'ca-certificates'..."
|
|
17
|
+
apk update
|
|
18
|
+
apk add --no-cache ca-certificates
|
|
19
|
+
fi
|
|
20
|
+
|
|
21
|
+
update-ca-certificates || true
|
|
22
|
+
|
|
23
|
+
exec /sbin/tini -- run.sh
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
import actions.constants
|
|
4
|
+
from actions.constants import PATH_ACTIONS
|
|
5
|
+
|
|
6
|
+
REGISTER_GITEA_RUNNER_SUB_CMD = "register-gitea-runner"
|
|
7
|
+
REGISTER_GITEA_RUNNER_DOCSTRING = "Register a Gitea runner"
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
PATH_CACHE = actions.constants.PATH_CACHE / REGISTER_GITEA_RUNNER_SUB_CMD
|
|
11
|
+
PATH_CONFIGS = PATH_ACTIONS / "register_gitea_runner/configs"
|
|
12
|
+
PATH_WAIT_FOR_IT = PATH_CACHE / "wait-for-it.sh"
|
|
13
|
+
URL_WAIT_FOR_IT = "https://raw.githubusercontent.com/vishnubob/wait-for-it/refs/heads/master/wait-for-it.sh"
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
__all__ = [
|
|
17
|
+
"PATH_CACHE",
|
|
18
|
+
"PATH_CONFIGS",
|
|
19
|
+
"PATH_WAIT_FOR_IT",
|
|
20
|
+
"REGISTER_GITEA_RUNNER_DOCSTRING",
|
|
21
|
+
"REGISTER_GITEA_RUNNER_SUB_CMD",
|
|
22
|
+
"URL_WAIT_FOR_IT",
|
|
23
|
+
]
|
|
@@ -0,0 +1,289 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
from pathlib import Path
|
|
4
|
+
from re import search
|
|
5
|
+
from string import Template
|
|
6
|
+
from typing import TYPE_CHECKING
|
|
7
|
+
|
|
8
|
+
from requests import get
|
|
9
|
+
from utilities.atomicwrites import writer
|
|
10
|
+
from utilities.subprocess import chmod, run, ssh
|
|
11
|
+
from utilities.text import strip_and_dedent
|
|
12
|
+
|
|
13
|
+
from actions import __version__
|
|
14
|
+
from actions.logging import LOGGER
|
|
15
|
+
from actions.register_gitea_runner.constants import (
|
|
16
|
+
PATH_CACHE,
|
|
17
|
+
PATH_CONFIGS,
|
|
18
|
+
PATH_WAIT_FOR_IT,
|
|
19
|
+
URL_WAIT_FOR_IT,
|
|
20
|
+
)
|
|
21
|
+
from actions.register_gitea_runner.settings import SETTINGS
|
|
22
|
+
|
|
23
|
+
if TYPE_CHECKING:
|
|
24
|
+
from utilities.types import PathLike
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
def register_gitea_runner(
|
|
28
|
+
*,
|
|
29
|
+
ssh_user: str = SETTINGS.ssh_user,
|
|
30
|
+
ssh_host: str = SETTINGS.ssh_host,
|
|
31
|
+
gitea_container_user: str = SETTINGS.gitea_container_user,
|
|
32
|
+
gitea_container_name: str = SETTINGS.gitea_container_name,
|
|
33
|
+
runner_certificate: PathLike = SETTINGS.runner_certificate,
|
|
34
|
+
runner_capacity: int = SETTINGS.runner_capacity,
|
|
35
|
+
runner_container_name: str = SETTINGS.runner_container_name,
|
|
36
|
+
gitea_host: str = SETTINGS.gitea_host,
|
|
37
|
+
gitea_port: int = SETTINGS.gitea_port,
|
|
38
|
+
runner_instance_name: str = SETTINGS.runner_instance_name,
|
|
39
|
+
) -> None:
|
|
40
|
+
"""Register against a remote instance of Gitea."""
|
|
41
|
+
LOGGER.info(
|
|
42
|
+
strip_and_dedent("""
|
|
43
|
+
Running '%s' (version %s) with settings:
|
|
44
|
+
- ssh_user = %s
|
|
45
|
+
- ssh_host = %s
|
|
46
|
+
- gitea_container_user = %s
|
|
47
|
+
- gitea_container_name = %s
|
|
48
|
+
- runner_certificate = %s
|
|
49
|
+
- runner_capacity = %d
|
|
50
|
+
- runner_container_name = %s
|
|
51
|
+
- gitea_host = %s
|
|
52
|
+
- gitea_port = %d
|
|
53
|
+
- runner_instance_name = %s
|
|
54
|
+
"""),
|
|
55
|
+
register_gitea_runner.__name__,
|
|
56
|
+
__version__,
|
|
57
|
+
ssh_user,
|
|
58
|
+
ssh_host,
|
|
59
|
+
gitea_container_user,
|
|
60
|
+
gitea_container_name,
|
|
61
|
+
runner_certificate,
|
|
62
|
+
runner_capacity,
|
|
63
|
+
runner_container_name,
|
|
64
|
+
gitea_host,
|
|
65
|
+
gitea_port,
|
|
66
|
+
runner_instance_name,
|
|
67
|
+
)
|
|
68
|
+
token = ssh(
|
|
69
|
+
ssh_user,
|
|
70
|
+
ssh_host,
|
|
71
|
+
*_docker_exec_generate(user=gitea_container_user, name=gitea_container_name),
|
|
72
|
+
return_=True,
|
|
73
|
+
)
|
|
74
|
+
_start_runner(
|
|
75
|
+
token,
|
|
76
|
+
runner_certificate=runner_certificate,
|
|
77
|
+
runner_capacity=runner_capacity,
|
|
78
|
+
runner_container_name=runner_container_name,
|
|
79
|
+
gitea_host=gitea_host,
|
|
80
|
+
gitea_port=gitea_port,
|
|
81
|
+
runner_instance_name=runner_instance_name,
|
|
82
|
+
)
|
|
83
|
+
|
|
84
|
+
|
|
85
|
+
def register_against_local(
|
|
86
|
+
*,
|
|
87
|
+
gitea_container_user: str = SETTINGS.gitea_container_user,
|
|
88
|
+
gitea_container_name: str = SETTINGS.gitea_container_name,
|
|
89
|
+
runner_certificate: PathLike = SETTINGS.runner_certificate,
|
|
90
|
+
runner_capacity: int = SETTINGS.runner_capacity,
|
|
91
|
+
runner_container_name: str = SETTINGS.runner_container_name,
|
|
92
|
+
gitea_host: str = SETTINGS.gitea_host,
|
|
93
|
+
gitea_port: int = SETTINGS.gitea_port,
|
|
94
|
+
runner_instance_name: str = SETTINGS.runner_instance_name,
|
|
95
|
+
) -> None:
|
|
96
|
+
"""Register against a local instance of Gitea."""
|
|
97
|
+
LOGGER.info("Registering against %s:%d...", gitea_host, gitea_port)
|
|
98
|
+
token = run(
|
|
99
|
+
*_docker_exec_generate(user=gitea_container_user, name=gitea_container_name),
|
|
100
|
+
return_=True,
|
|
101
|
+
logger=LOGGER,
|
|
102
|
+
)
|
|
103
|
+
_start_runner(
|
|
104
|
+
token,
|
|
105
|
+
runner_certificate=runner_certificate,
|
|
106
|
+
runner_capacity=runner_capacity,
|
|
107
|
+
runner_container_name=runner_container_name,
|
|
108
|
+
gitea_host=gitea_host,
|
|
109
|
+
gitea_port=gitea_port,
|
|
110
|
+
runner_instance_name=runner_instance_name,
|
|
111
|
+
)
|
|
112
|
+
|
|
113
|
+
|
|
114
|
+
def _check_certificate(*, certificate: PathLike = SETTINGS.runner_certificate) -> None:
|
|
115
|
+
if not Path(certificate).is_file():
|
|
116
|
+
msg = f"Missing certificate {certificate!r}"
|
|
117
|
+
raise FileNotFoundError(msg)
|
|
118
|
+
|
|
119
|
+
|
|
120
|
+
def _check_token(text: str, /) -> None:
|
|
121
|
+
if not search(r"^[A-Za-z0-9]{40}$", text):
|
|
122
|
+
msg = f"Invalid token; got {text!r}"
|
|
123
|
+
raise ValueError(msg)
|
|
124
|
+
|
|
125
|
+
|
|
126
|
+
def _docker_exec_generate(
|
|
127
|
+
*,
|
|
128
|
+
user: str = SETTINGS.gitea_container_user,
|
|
129
|
+
name: str = SETTINGS.gitea_container_name,
|
|
130
|
+
) -> list[str]:
|
|
131
|
+
return [
|
|
132
|
+
"docker",
|
|
133
|
+
"exec",
|
|
134
|
+
"--user",
|
|
135
|
+
user,
|
|
136
|
+
name,
|
|
137
|
+
"gitea",
|
|
138
|
+
"actions",
|
|
139
|
+
"generate-runner-token",
|
|
140
|
+
]
|
|
141
|
+
|
|
142
|
+
|
|
143
|
+
def _docker_run_act_runner_args(
|
|
144
|
+
token: str,
|
|
145
|
+
/,
|
|
146
|
+
*,
|
|
147
|
+
host: str = SETTINGS.gitea_host,
|
|
148
|
+
port: int = SETTINGS.gitea_port,
|
|
149
|
+
runner_certificate: PathLike = SETTINGS.runner_certificate,
|
|
150
|
+
instance_name: str = SETTINGS.runner_instance_name,
|
|
151
|
+
container_name: str = SETTINGS.runner_container_name,
|
|
152
|
+
) -> list[str]:
|
|
153
|
+
config_host = _get_config_path(token)
|
|
154
|
+
config_cont = "/config.yml"
|
|
155
|
+
entrypoint_host = _get_entrypoint_path(host=host, port=port)
|
|
156
|
+
entrypoint_cont = Path("/usr/local/bin/entrypoint.sh")
|
|
157
|
+
return [
|
|
158
|
+
"docker",
|
|
159
|
+
"run",
|
|
160
|
+
"--detach",
|
|
161
|
+
"--entrypoint",
|
|
162
|
+
str(entrypoint_cont),
|
|
163
|
+
"--env",
|
|
164
|
+
f"CONFIG_FILE={config_cont}",
|
|
165
|
+
"--env",
|
|
166
|
+
f"GITEA_INSTANCE_URL=https://{host}:{port}",
|
|
167
|
+
"--env",
|
|
168
|
+
f"GITEA_RUNNER_NAME={instance_name}",
|
|
169
|
+
"--env",
|
|
170
|
+
f"GITEA_RUNNER_REGISTRATION_TOKEN={token}",
|
|
171
|
+
"--name",
|
|
172
|
+
container_name,
|
|
173
|
+
"--volume",
|
|
174
|
+
"/var/run/docker.sock:/var/run/docker.sock",
|
|
175
|
+
"--volume",
|
|
176
|
+
f"{PATH_WAIT_FOR_IT}:/usr/local/bin/wait-for-it.sh:ro",
|
|
177
|
+
"--volume",
|
|
178
|
+
f"{Path.cwd()}/data:/data",
|
|
179
|
+
"--volume",
|
|
180
|
+
f"{config_host}:{config_cont}:ro",
|
|
181
|
+
"--volume",
|
|
182
|
+
f"{entrypoint_host}:{entrypoint_cont}:ro",
|
|
183
|
+
"--volume",
|
|
184
|
+
f"{runner_certificate}:/etc/ssl/certs/runner-certificate.pem:ro",
|
|
185
|
+
"gitea/act_runner",
|
|
186
|
+
]
|
|
187
|
+
|
|
188
|
+
|
|
189
|
+
def _docker_stop_runner_args(
|
|
190
|
+
*, name: str = SETTINGS.runner_container_name
|
|
191
|
+
) -> list[str]:
|
|
192
|
+
return ["docker", "rm", "--force", name]
|
|
193
|
+
|
|
194
|
+
|
|
195
|
+
def _get_config_contents(
|
|
196
|
+
*,
|
|
197
|
+
capacity: int = SETTINGS.runner_capacity,
|
|
198
|
+
certificate: PathLike = SETTINGS.runner_certificate,
|
|
199
|
+
) -> str:
|
|
200
|
+
src = PATH_CONFIGS / "config.yml"
|
|
201
|
+
return Template(src.read_text()).safe_substitute(
|
|
202
|
+
CAPACITY=capacity, CERTIFICATE=certificate
|
|
203
|
+
)
|
|
204
|
+
|
|
205
|
+
|
|
206
|
+
def _get_config_path(token: str, /) -> Path:
|
|
207
|
+
return PATH_CACHE / f"configs/{token}.yml"
|
|
208
|
+
|
|
209
|
+
|
|
210
|
+
def _get_entrypoint_contents(
|
|
211
|
+
*, host: str = SETTINGS.gitea_host, port: int = SETTINGS.gitea_port
|
|
212
|
+
) -> str:
|
|
213
|
+
src = PATH_CONFIGS / "entrypoint.sh"
|
|
214
|
+
return Template(src.read_text()).safe_substitute(GITEA_HOST=host, GITEA_PORT=port)
|
|
215
|
+
|
|
216
|
+
|
|
217
|
+
def _get_entrypoint_path(
|
|
218
|
+
*, host: str = SETTINGS.gitea_host, port: int = SETTINGS.gitea_port
|
|
219
|
+
) -> Path:
|
|
220
|
+
return PATH_CACHE / f"entrypoints/{host}-{port}"
|
|
221
|
+
|
|
222
|
+
|
|
223
|
+
def _start_runner(
|
|
224
|
+
token: str,
|
|
225
|
+
/,
|
|
226
|
+
*,
|
|
227
|
+
runner_certificate: PathLike = SETTINGS.runner_certificate,
|
|
228
|
+
runner_capacity: int = SETTINGS.runner_capacity,
|
|
229
|
+
runner_container_name: str = SETTINGS.runner_container_name,
|
|
230
|
+
gitea_host: str = SETTINGS.gitea_host,
|
|
231
|
+
gitea_port: int = SETTINGS.gitea_port,
|
|
232
|
+
runner_instance_name: str = SETTINGS.runner_instance_name,
|
|
233
|
+
) -> None:
|
|
234
|
+
_check_certificate(certificate=runner_certificate)
|
|
235
|
+
_check_token(token)
|
|
236
|
+
_write_config(token, capacity=runner_capacity, certificate=runner_certificate)
|
|
237
|
+
_write_entrypoint(host=gitea_host, port=gitea_port)
|
|
238
|
+
_write_wait_for_it()
|
|
239
|
+
run(
|
|
240
|
+
*_docker_stop_runner_args(name=runner_container_name), print=True, logger=LOGGER
|
|
241
|
+
)
|
|
242
|
+
run(
|
|
243
|
+
*_docker_run_act_runner_args(
|
|
244
|
+
token,
|
|
245
|
+
host=gitea_host,
|
|
246
|
+
port=gitea_port,
|
|
247
|
+
runner_certificate=runner_certificate,
|
|
248
|
+
instance_name=runner_instance_name,
|
|
249
|
+
container_name=runner_container_name,
|
|
250
|
+
),
|
|
251
|
+
print=True,
|
|
252
|
+
logger=LOGGER,
|
|
253
|
+
)
|
|
254
|
+
|
|
255
|
+
|
|
256
|
+
def _write_config(
|
|
257
|
+
token: str,
|
|
258
|
+
/,
|
|
259
|
+
*,
|
|
260
|
+
capacity: int = SETTINGS.runner_capacity,
|
|
261
|
+
certificate: PathLike = SETTINGS.runner_certificate,
|
|
262
|
+
) -> None:
|
|
263
|
+
dest = _get_config_path(token)
|
|
264
|
+
text = _get_config_contents(capacity=capacity, certificate=certificate)
|
|
265
|
+
with writer(dest, overwrite=True) as temp:
|
|
266
|
+
_ = temp.write_text(text)
|
|
267
|
+
|
|
268
|
+
|
|
269
|
+
def _write_entrypoint(
|
|
270
|
+
*, host: str = SETTINGS.gitea_host, port: int = SETTINGS.gitea_port
|
|
271
|
+
) -> None:
|
|
272
|
+
dest = _get_entrypoint_path(host=host, port=port)
|
|
273
|
+
text = _get_entrypoint_contents(host=host, port=port)
|
|
274
|
+
with writer(dest, overwrite=True) as temp:
|
|
275
|
+
_ = temp.write_text(text)
|
|
276
|
+
chmod(temp, "u=rwx,g=rx,o=rx")
|
|
277
|
+
|
|
278
|
+
|
|
279
|
+
def _write_wait_for_it() -> None:
|
|
280
|
+
if PATH_WAIT_FOR_IT.is_file():
|
|
281
|
+
return
|
|
282
|
+
with writer(PATH_WAIT_FOR_IT, overwrite=True) as temp:
|
|
283
|
+
resp = get(URL_WAIT_FOR_IT, timeout=60)
|
|
284
|
+
resp.raise_for_status()
|
|
285
|
+
_ = temp.write_bytes(resp.content)
|
|
286
|
+
chmod(temp, "u=rwx,g=rx,o=rx")
|
|
287
|
+
|
|
288
|
+
|
|
289
|
+
__all__ = ["register_against_local"]
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
from pathlib import Path
|
|
4
|
+
|
|
5
|
+
from typed_settings import load_settings, option, settings
|
|
6
|
+
from utilities.getpass import USER
|
|
7
|
+
from utilities.socket import HOSTNAME
|
|
8
|
+
|
|
9
|
+
from actions.utilities import LOADER
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
@settings
|
|
13
|
+
class Settings:
|
|
14
|
+
ssh_user: str = option(default="user", help="SSH username")
|
|
15
|
+
ssh_host: str = option(default="gitea", help="SSH host")
|
|
16
|
+
gitea_container_user: str = option(default="git", help="Gitea container user name")
|
|
17
|
+
gitea_container_name: str = option(default="gitea", help="Gitea container name")
|
|
18
|
+
gitea_host: str = option(default="gitea", help="Gitea host")
|
|
19
|
+
gitea_port: int = option(default=3000, help="Gitea port")
|
|
20
|
+
runner_capacity: int = option(default=1, help="Runner capacity")
|
|
21
|
+
runner_instance_name: str = option(
|
|
22
|
+
default=f"{USER}--{HOSTNAME}", help="Runner instance name"
|
|
23
|
+
)
|
|
24
|
+
runner_certificate: Path = option(
|
|
25
|
+
default=Path("root.pem"), help="Runner root certificate"
|
|
26
|
+
)
|
|
27
|
+
runner_container_name: str = option(default="runner", help="Runner container name")
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
SETTINGS = load_settings(Settings, [LOADER])
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
__all__ = ["SETTINGS", "Settings"]
|
|
@@ -1,16 +1,17 @@
|
|
|
1
1
|
Metadata-Version: 2.3
|
|
2
2
|
Name: dycw-actions
|
|
3
|
-
Version: 0.7.
|
|
3
|
+
Version: 0.7.7
|
|
4
4
|
Summary: Library of actions
|
|
5
5
|
Requires-Dist: click>=8.3.1,<9
|
|
6
|
-
Requires-Dist: dycw-utilities>=0.
|
|
6
|
+
Requires-Dist: dycw-utilities>=0.178.0,<1
|
|
7
7
|
Requires-Dist: inflect>=7.5.0,<8
|
|
8
8
|
Requires-Dist: libcst>=1.8.6,<2
|
|
9
9
|
Requires-Dist: packaging>=25.0,<26
|
|
10
10
|
Requires-Dist: pydantic>=2.12.5,<3
|
|
11
11
|
Requires-Dist: pyyaml>=6.0.3,<7
|
|
12
|
+
Requires-Dist: requests>=2.32.5,<3
|
|
12
13
|
Requires-Dist: rich>=14.2.0,<15
|
|
13
|
-
Requires-Dist: ruamel-yaml>=0.19.
|
|
14
|
+
Requires-Dist: ruamel-yaml>=0.19.1,<1
|
|
14
15
|
Requires-Dist: tomlkit>=0.13.3,<1
|
|
15
16
|
Requires-Dist: typed-settings[attrs,click]>=25.3.0,<26
|
|
16
17
|
Requires-Dist: xdg-base-dirs>=6.0.2,<7
|
|
@@ -1,14 +1,14 @@
|
|
|
1
|
-
actions/__init__.py,sha256=
|
|
1
|
+
actions/__init__.py,sha256=trsIPKwrk3xNHIWvYXX9uhHoJTOvGbfIIBQNFcFa_Js,58
|
|
2
2
|
actions/action_dicts/__init__.py,sha256=U4S_2y3zgLZVfMenHRaJFBW8yqh2mUBuI291LGQVOJ8,35
|
|
3
3
|
actions/action_dicts/constants.py,sha256=tYYLr3aRRRvnR6NSADOJMN-B6gtqg2A9gBuheEPyGy4,189
|
|
4
4
|
actions/action_dicts/lib.py,sha256=MpK_y5Jao0-3p6bWeYX5QQy3-JjMxwyzXRU5LjO25Iw,5547
|
|
5
5
|
actions/clean_dir/__init__.py,sha256=U4S_2y3zgLZVfMenHRaJFBW8yqh2mUBuI291LGQVOJ8,35
|
|
6
6
|
actions/clean_dir/cli.py,sha256=OrFA2nEN2LyGF22mhTNEBr7KSuKgX54sGy9RyE73qUc,569
|
|
7
7
|
actions/clean_dir/constants.py,sha256=aDNaYtemEv3lcMXo96Oh4pw_HASMby1GZC1D_gbjPAc,167
|
|
8
|
-
actions/clean_dir/lib.py,sha256=
|
|
8
|
+
actions/clean_dir/lib.py,sha256=7_-QbvB9Bq2veEl4eYWkBBWN0jSNrjGVlx1gLWS1PwU,1606
|
|
9
9
|
actions/clean_dir/settings.py,sha256=mqM0Oq-yz4dXKcUi3JmOCvDhoeBNQm_Qe70cGmhdcQE,345
|
|
10
|
-
actions/cli.py,sha256=
|
|
11
|
-
actions/constants.py,sha256=
|
|
10
|
+
actions/cli.py,sha256=J9k7_BQzgDHdgzkTqwXVzncRMHm0eAT0WW_c_gAUFlE,4441
|
|
11
|
+
actions/constants.py,sha256=DgcgYPL3l2lAMIVRi7LzB_YsD0H8WDhaMphh5ztRD54,445
|
|
12
12
|
actions/logging.py,sha256=rMTcQMGndUHTCaXXtyOHt_VXUMhQGRHoN7okpoX0y5I,120
|
|
13
13
|
actions/pre_commit/__init__.py,sha256=U4S_2y3zgLZVfMenHRaJFBW8yqh2mUBuI291LGQVOJ8,35
|
|
14
14
|
actions/pre_commit/click.py,sha256=BLHjkO0gIW7rgLabuWnszwXmI4yb8Li5D8gt81GR-FQ,270
|
|
@@ -16,7 +16,7 @@ actions/pre_commit/conformalize_repo/__init__.py,sha256=U4S_2y3zgLZVfMenHRaJFBW8
|
|
|
16
16
|
actions/pre_commit/conformalize_repo/cli.py,sha256=rPrxobdo4sKnq0de_UWDtrHqlhF6GTAabRhw_1XBeZY,3063
|
|
17
17
|
actions/pre_commit/conformalize_repo/configs/gitignore,sha256=8YCRPwysCD8-67yFXaTg6O8TTl4xeNIh7_DVmaU5Ix0,5063
|
|
18
18
|
actions/pre_commit/conformalize_repo/constants.py,sha256=7WMbc1BwkVPJIf3eh3MaCoWj5A7pSPvNic28nrFTcoA,2148
|
|
19
|
-
actions/pre_commit/conformalize_repo/lib.py,sha256=
|
|
19
|
+
actions/pre_commit/conformalize_repo/lib.py,sha256=cdEggEXiDTt2QHbzP0rIViFriPoaApf3XcGeAo-hiHY,48020
|
|
20
20
|
actions/pre_commit/conformalize_repo/settings.py,sha256=Oz2AeStS64DFzT1HKJ888_7tiU1TdJIGBarvyKYfp4E,4985
|
|
21
21
|
actions/pre_commit/constants.py,sha256=NBJ5GBMg5qhMAhAfxx1FKw0CdPwW_wG2cUJJ0dkF5HE,158
|
|
22
22
|
actions/pre_commit/format_requirements/__init__.py,sha256=U4S_2y3zgLZVfMenHRaJFBW8yqh2mUBuI291LGQVOJ8,35
|
|
@@ -30,16 +30,16 @@ actions/pre_commit/replace_sequence_strs/lib.py,sha256=FzfwYeL3bhTCYbb1T-Yk1NtdH
|
|
|
30
30
|
actions/pre_commit/touch_empty_py/__init__.py,sha256=U4S_2y3zgLZVfMenHRaJFBW8yqh2mUBuI291LGQVOJ8,35
|
|
31
31
|
actions/pre_commit/touch_empty_py/cli.py,sha256=s2S5OfAGcSLtd2aGm1ooa1k20oNK-LQ1PZWz6T30vO8,559
|
|
32
32
|
actions/pre_commit/touch_empty_py/constants.py,sha256=zSwH60zfn9RhIAbBFnXjHrm2s1nFpPUskX3CZuJpQLk,198
|
|
33
|
-
actions/pre_commit/touch_empty_py/lib.py,sha256=
|
|
33
|
+
actions/pre_commit/touch_empty_py/lib.py,sha256=jxT6CRZ3rrBatk3o-D0xDXon3a-G02sCvdMSNuRvCv0,1706
|
|
34
34
|
actions/pre_commit/touch_py_typed/__init__.py,sha256=U4S_2y3zgLZVfMenHRaJFBW8yqh2mUBuI291LGQVOJ8,35
|
|
35
35
|
actions/pre_commit/touch_py_typed/cli.py,sha256=CDJV4NuUHJlSdJ84dY0XvdwYHMdqygZ7C6x07B-iN3E,559
|
|
36
36
|
actions/pre_commit/touch_py_typed/constants.py,sha256=kLZOm_wgypp7MaXRYq-6AZqVE4OttOMKmUqt11V2zn0,191
|
|
37
|
-
actions/pre_commit/touch_py_typed/lib.py,sha256=
|
|
37
|
+
actions/pre_commit/touch_py_typed/lib.py,sha256=8crPXxI6CwudW13RIJrn3YtrFcZsspyJnTmNRHz4TaU,2020
|
|
38
38
|
actions/pre_commit/update_requirements/__init__.py,sha256=U4S_2y3zgLZVfMenHRaJFBW8yqh2mUBuI291LGQVOJ8,35
|
|
39
|
-
actions/pre_commit/update_requirements/classes.py,sha256=
|
|
39
|
+
actions/pre_commit/update_requirements/classes.py,sha256=ERC70c1CxQ3rOsQaEtp6FGbK_VaJ4K0jAV5XTB5-L30,3486
|
|
40
40
|
actions/pre_commit/update_requirements/cli.py,sha256=CBfm8M7hwSRw8KS6ttiNE86IFHJ52V42AxlfakqTDN0,584
|
|
41
41
|
actions/pre_commit/update_requirements/constants.py,sha256=ve44_RYed_41ckgQNPkb08u7Y1cpLpzutGSL9FdGBF8,228
|
|
42
|
-
actions/pre_commit/update_requirements/lib.py,sha256=
|
|
42
|
+
actions/pre_commit/update_requirements/lib.py,sha256=akSmdqFpDS8ETsdGs4-8lfoKOp_8bBlKyKUXhUlrzpg,4619
|
|
43
43
|
actions/pre_commit/utilities.py,sha256=L1HCi3l778REPfomMuYbxrrnCn0FDRFaWAfmFR0lsTY,11422
|
|
44
44
|
actions/publish_package/__init__.py,sha256=U4S_2y3zgLZVfMenHRaJFBW8yqh2mUBuI291LGQVOJ8,35
|
|
45
45
|
actions/publish_package/cli.py,sha256=nAPHCq67mxUb3yHepVGcoQ69qgaQahM1-cxdbHfxQg0,803
|
|
@@ -52,6 +52,13 @@ actions/random_sleep/cli.py,sha256=-d9y63oWgvQtNp9j_8v3zt5gKl-GrUq8-b3Ky52R42c,6
|
|
|
52
52
|
actions/random_sleep/constants.py,sha256=5GMqCD1f12uyKDVTZBbnDDn6TQa99mUYZb9p-crg5BA,190
|
|
53
53
|
actions/random_sleep/lib.py,sha256=JzgpeEONdKXSBeNc3ex9goVyJR3bsa76lB_tkH1Ggc0,1762
|
|
54
54
|
actions/random_sleep/settings.py,sha256=F8gO2j2EEX8moemwhWWCPdRuOpZ_qLtqzSfWhjIy3P8,529
|
|
55
|
+
actions/register_gitea_runner/__init__.py,sha256=U4S_2y3zgLZVfMenHRaJFBW8yqh2mUBuI291LGQVOJ8,35
|
|
56
|
+
actions/register_gitea_runner/cli.py,sha256=70RUyzKCZHxyDRMFwCAwDC0LDsUZxBi2T6ctzbFlpc8,1129
|
|
57
|
+
actions/register_gitea_runner/configs/config.yml,sha256=0kpaqAjMRDqdSxkSK8ydOk2IsrlkB4cUkYmbkHAurrg,5683
|
|
58
|
+
actions/register_gitea_runner/configs/entrypoint.sh,sha256=IN40hAu8ufyyFWPIgsX_hWp0ZZZ0c36czCaqmECjBrw,476
|
|
59
|
+
actions/register_gitea_runner/constants.py,sha256=wX1f5qvhIXngBVWbIQRoIaXIdPaUByvG8HS8P0WcCGM,694
|
|
60
|
+
actions/register_gitea_runner/lib.py,sha256=V_K6UHmZOD9V-DF6ZNA2QakNyuyuyjgJZ6AJQFf37lQ,8832
|
|
61
|
+
actions/register_gitea_runner/settings.py,sha256=0UQm8M3qDiBE3jiE333M4FdLjikNAzpc9gk_VlzI0s8,1149
|
|
55
62
|
actions/run_hooks/__init__.py,sha256=U4S_2y3zgLZVfMenHRaJFBW8yqh2mUBuI291LGQVOJ8,35
|
|
56
63
|
actions/run_hooks/cli.py,sha256=xKBw6iIlHpUlHl6-QWQLSL6KKVjnsihBeJ7h58Rl8P4,616
|
|
57
64
|
actions/run_hooks/constants.py,sha256=JRhDk08qbzo5C-zwHdXZV5ajvNSKh4GcOcBvOIY6IGU,172
|
|
@@ -71,7 +78,7 @@ actions/tag_commit/lib.py,sha256=rq1SqAkNp98cPsNOsFY4F1D6nNi7N3wqVbFPno8lsuI,184
|
|
|
71
78
|
actions/tag_commit/settings.py,sha256=TOeKG_GODP--2lBSyGzH_M32jDIfh4vk_Ts06R3_ak4,629
|
|
72
79
|
actions/types.py,sha256=GRXLoJtYWmRjgfatDDRMcXKZkN9ZtK1Fi2MEyAZ84uk,591
|
|
73
80
|
actions/utilities.py,sha256=VpFLBiAezgSRlm9dvnyPyQohreaV2Lv7cJ9HAxqZ4WI,4086
|
|
74
|
-
dycw_actions-0.7.
|
|
75
|
-
dycw_actions-0.7.
|
|
76
|
-
dycw_actions-0.7.
|
|
77
|
-
dycw_actions-0.7.
|
|
81
|
+
dycw_actions-0.7.7.dist-info/WHEEL,sha256=KSLUh82mDPEPk0Bx0ScXlWL64bc8KmzIPNcpQZFV-6E,79
|
|
82
|
+
dycw_actions-0.7.7.dist-info/entry_points.txt,sha256=2Uu7wAZOm0mmcsGBEsGB370HAWgVWECRFJ9rKgfC3-I,46
|
|
83
|
+
dycw_actions-0.7.7.dist-info/METADATA,sha256=CORF-XquPdSrUKd4Doo9mV0OA8RmDHzyWwZUMXgtC8E,654
|
|
84
|
+
dycw_actions-0.7.7.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|