proj-flow 0.9.3__py3-none-any.whl → 0.10.0__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.
- proj_flow/__init__.py +6 -1
- proj_flow/api/arg.py +47 -24
- proj_flow/api/ctx.py +43 -23
- proj_flow/api/env.py +7 -2
- proj_flow/api/makefile.py +1 -1
- proj_flow/api/step.py +3 -5
- proj_flow/base/name_list.py +19 -0
- proj_flow/base/plugins.py +1 -36
- proj_flow/base/registry.py +19 -4
- proj_flow/cli/__init__.py +2 -4
- proj_flow/cli/argument.py +3 -3
- proj_flow/{flow/dependency.py → dependency.py} +1 -1
- proj_flow/ext/cplusplus/__init__.py +10 -0
- proj_flow/ext/cplusplus/cmake/__init__.py +12 -0
- proj_flow/{plugins → ext/cplusplus}/cmake/__version__.py +5 -0
- proj_flow/{plugins → ext/cplusplus}/cmake/context.py +10 -8
- proj_flow/{plugins → ext/cplusplus}/cmake/parser.py +6 -28
- proj_flow/ext/cplusplus/cmake/steps.py +142 -0
- proj_flow/ext/cplusplus/cmake/version.py +35 -0
- proj_flow/{plugins → ext/cplusplus}/conan/__init__.py +7 -3
- proj_flow/{plugins → ext/cplusplus}/conan/_conan.py +8 -3
- proj_flow/ext/github/__init__.py +2 -2
- proj_flow/ext/github/cli.py +2 -11
- proj_flow/{plugins/github.py → ext/github/switches.py} +3 -3
- proj_flow/ext/{markdown_changelist.py → markdown_changelog.py} +2 -1
- proj_flow/ext/python/rtdocs.py +1 -1
- proj_flow/ext/python/version.py +1 -2
- proj_flow/ext/{re_structured_changelist.py → re_structured_changelog.py} +3 -1
- proj_flow/{plugins → ext}/sign/__init__.py +64 -44
- proj_flow/ext/sign/api.py +83 -0
- proj_flow/ext/sign/win32.py +152 -0
- proj_flow/{plugins/store/store_packages.py → ext/store.py} +51 -9
- proj_flow/flow/__init__.py +2 -2
- proj_flow/log/release.py +1 -1
- proj_flow/log/rich_text/markdown.py +1 -1
- proj_flow/log/rich_text/re_structured_text.py +1 -1
- proj_flow/minimal/__init__.py +2 -2
- proj_flow/{plugins → minimal}/base.py +3 -2
- proj_flow/{plugins/commands → minimal}/init.py +44 -11
- proj_flow/minimal/run.py +1 -2
- proj_flow/project/__init__.py +11 -0
- proj_flow/project/api.py +51 -0
- proj_flow/project/cplusplus.py +17 -0
- proj_flow/project/data.py +14 -0
- proj_flow/{flow → project}/interact.py +114 -13
- {proj_flow-0.9.3.dist-info → proj_flow-0.10.0.dist-info}/METADATA +3 -2
- {proj_flow-0.9.3.dist-info → proj_flow-0.10.0.dist-info}/RECORD +50 -55
- proj_flow/flow/init.py +0 -65
- proj_flow/plugins/__init__.py +0 -8
- proj_flow/plugins/cmake/__init__.py +0 -11
- proj_flow/plugins/cmake/build.py +0 -29
- proj_flow/plugins/cmake/config.py +0 -59
- proj_flow/plugins/cmake/pack.py +0 -37
- proj_flow/plugins/cmake/test.py +0 -29
- proj_flow/plugins/commands/__init__.py +0 -12
- proj_flow/plugins/commands/ci/__init__.py +0 -17
- proj_flow/plugins/commands/ci/changelog.py +0 -47
- proj_flow/plugins/commands/ci/matrix.py +0 -46
- proj_flow/plugins/commands/ci/release.py +0 -116
- proj_flow/plugins/sign/win32.py +0 -191
- proj_flow/plugins/store/__init__.py +0 -11
- proj_flow/plugins/store/store_both.py +0 -22
- proj_flow/plugins/store/store_tests.py +0 -21
- {proj_flow-0.9.3.dist-info → proj_flow-0.10.0.dist-info}/WHEEL +0 -0
- {proj_flow-0.9.3.dist-info → proj_flow-0.10.0.dist-info}/entry_points.txt +0 -0
- {proj_flow-0.9.3.dist-info → proj_flow-0.10.0.dist-info}/licenses/LICENSE +0 -0
|
@@ -1,46 +0,0 @@
|
|
|
1
|
-
# Copyright (c) 2025 Marcin Zdun
|
|
2
|
-
# This code is licensed under MIT license (see LICENSE for details)
|
|
3
|
-
|
|
4
|
-
"""
|
|
5
|
-
The **proj_flow.plugins.commands.ci.matrix** implements ``./flow ci matrix`` command.
|
|
6
|
-
"""
|
|
7
|
-
|
|
8
|
-
import argparse
|
|
9
|
-
import json
|
|
10
|
-
import os
|
|
11
|
-
import sys
|
|
12
|
-
from typing import Annotated, Optional
|
|
13
|
-
|
|
14
|
-
from proj_flow.api import arg, env
|
|
15
|
-
from proj_flow.flow.configs import Configs
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
@arg.command("ci", "matrix")
|
|
19
|
-
def matrix(
|
|
20
|
-
official: Annotated[
|
|
21
|
-
bool, arg.FlagArgument(help="Cut matrix to release builds only")
|
|
22
|
-
],
|
|
23
|
-
rt: env.Runtime,
|
|
24
|
-
):
|
|
25
|
-
"""Supply data for github actions"""
|
|
26
|
-
|
|
27
|
-
configs = Configs(
|
|
28
|
-
rt, argparse.Namespace(configs=[], matrix=True, official=official)
|
|
29
|
-
)
|
|
30
|
-
|
|
31
|
-
usable = [usable.items for usable in configs.usable]
|
|
32
|
-
for config in usable:
|
|
33
|
-
if "--orig-compiler" in config:
|
|
34
|
-
orig_compiler = config["--orig-compiler"]
|
|
35
|
-
del config["--orig-compiler"]
|
|
36
|
-
config["compiler"] = orig_compiler
|
|
37
|
-
if "GITHUB_ACTIONS" in os.environ:
|
|
38
|
-
var = json.dumps({"include": usable})
|
|
39
|
-
GITHUB_OUTPUT = os.environ.get("GITHUB_OUTPUT")
|
|
40
|
-
if GITHUB_OUTPUT is not None:
|
|
41
|
-
with open(GITHUB_OUTPUT, "a", encoding="UTF-8") as github_output:
|
|
42
|
-
print(f"matrix={var}", file=github_output)
|
|
43
|
-
else:
|
|
44
|
-
print(f"matrix={var}")
|
|
45
|
-
else:
|
|
46
|
-
json.dump(usable, sys.stdout)
|
|
@@ -1,116 +0,0 @@
|
|
|
1
|
-
# Copyright (c) 2025 Marcin Zdun
|
|
2
|
-
# This code is licensed under MIT license (see LICENSE for details)
|
|
3
|
-
|
|
4
|
-
"""
|
|
5
|
-
The **proj_flow.plugins.commands.ci.release** implements
|
|
6
|
-
``./flow ci release`` command.
|
|
7
|
-
"""
|
|
8
|
-
|
|
9
|
-
import typing
|
|
10
|
-
|
|
11
|
-
from proj_flow.api import arg, env
|
|
12
|
-
from proj_flow.log import commit, fmt, hosting, release, rich_text
|
|
13
|
-
from proj_flow.plugins import cmake
|
|
14
|
-
|
|
15
|
-
FORCED_LEVEL_CHOICES = list(commit.FORCED_LEVEL.keys())
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
def _name_list(names: typing.List[str]) -> str:
|
|
19
|
-
if len(names) == 0:
|
|
20
|
-
return ""
|
|
21
|
-
|
|
22
|
-
prefix = ", ".join(names[:-1])
|
|
23
|
-
if prefix:
|
|
24
|
-
prefix += " and "
|
|
25
|
-
return f"{prefix}{names[-1]}"
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
def _bump_version(ver: str, level: commit.Level):
|
|
29
|
-
split = ver.split("-", 1)
|
|
30
|
-
if len(split) == 2:
|
|
31
|
-
stability = f"-{split[1]}"
|
|
32
|
-
else:
|
|
33
|
-
stability = ""
|
|
34
|
-
|
|
35
|
-
semver = [int(s) for s in split[0].split(".")]
|
|
36
|
-
while len(semver) < 3:
|
|
37
|
-
semver.append(0)
|
|
38
|
-
semver = semver[:3]
|
|
39
|
-
|
|
40
|
-
if level.value > commit.Level.BENIGN.value:
|
|
41
|
-
# This turns [1, 2, 3] through 4 - x into [3, 2, 1]
|
|
42
|
-
lvl = commit.Level.BREAKING.value - level.value
|
|
43
|
-
semver[lvl] += 1
|
|
44
|
-
for index in range(lvl + 1, len(semver)):
|
|
45
|
-
semver[index] = 0
|
|
46
|
-
|
|
47
|
-
return ".".join(str(v) for v in semver) + stability
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
@arg.command("ci", "release")
|
|
51
|
-
def main(
|
|
52
|
-
rt: env.Runtime,
|
|
53
|
-
all: typing.Annotated[
|
|
54
|
-
bool, arg.FlagArgument(help="Take all Conventional Commits.")
|
|
55
|
-
],
|
|
56
|
-
force: typing.Annotated[
|
|
57
|
-
typing.Optional[str],
|
|
58
|
-
arg.Argument(
|
|
59
|
-
help="Ignore the version change from changelog and instead use this value. "
|
|
60
|
-
f"Allowed values are: {_name_list(FORCED_LEVEL_CHOICES)}",
|
|
61
|
-
meta="level",
|
|
62
|
-
choices=FORCED_LEVEL_CHOICES,
|
|
63
|
-
),
|
|
64
|
-
],
|
|
65
|
-
stability: typing.Annotated[
|
|
66
|
-
typing.Optional[str],
|
|
67
|
-
arg.Argument(help="Change the stability of the version.", meta="value"),
|
|
68
|
-
],
|
|
69
|
-
):
|
|
70
|
-
"""
|
|
71
|
-
Bumps the project version based on current git logs, in a "chore" commit,
|
|
72
|
-
attaches an annotated tag with the version number and pushes it all to , if GitHub CLI
|
|
73
|
-
"""
|
|
74
|
-
generator = rich_text.markdown.ChangelogGenerator()
|
|
75
|
-
|
|
76
|
-
forced_level = commit.FORCED_LEVEL.get(force) if force else None
|
|
77
|
-
|
|
78
|
-
project = cmake.parser.get_project(rt.root)
|
|
79
|
-
if not project:
|
|
80
|
-
rt.fatal("No CMakeLists.txt with project() found.")
|
|
81
|
-
|
|
82
|
-
git = commit.Git(rt)
|
|
83
|
-
tags = git.tag_list(silent=True)
|
|
84
|
-
gh_links = hosting.github.GitHub.from_repo(git)
|
|
85
|
-
|
|
86
|
-
prev_tag = tags[-1] if len(tags) > 0 else None
|
|
87
|
-
|
|
88
|
-
setup = commit.LogSetup(gh_links, prev_tag, None, take_all=all)
|
|
89
|
-
log, log_level = git.get_log(setup)
|
|
90
|
-
|
|
91
|
-
project_version = f"{project.version.value}{project.stability.value}"
|
|
92
|
-
next_version = _bump_version(project_version, forced_level or log_level)
|
|
93
|
-
setup.curr_tag = f"v{next_version}"
|
|
94
|
-
|
|
95
|
-
if setup.curr_tag in tags:
|
|
96
|
-
rt.fatal(f"Tag {setup.curr_tag} already exists.")
|
|
97
|
-
|
|
98
|
-
files_to_commit: typing.List[str] = []
|
|
99
|
-
if not rt.dry_run and project_version != next_version:
|
|
100
|
-
files_to_commit.extend(generator.update_changelog(log, setup, rt))
|
|
101
|
-
files_to_commit.extend(project.set_version(rt.root, next_version))
|
|
102
|
-
# TODO: plugins for other places a version would need to be updated
|
|
103
|
-
|
|
104
|
-
commit_message = f"release {next_version}"
|
|
105
|
-
git.add_files(*files_to_commit)
|
|
106
|
-
git.commit(f"chore: {commit_message}{fmt.format_commit_message(log)}")
|
|
107
|
-
git.annotated_tag(setup.curr_tag, commit_message)
|
|
108
|
-
|
|
109
|
-
if gh_links.is_active:
|
|
110
|
-
draft_url = gh_links.draft_a_release(log, setup, git).draft_url
|
|
111
|
-
if draft_url:
|
|
112
|
-
rt.message("-- Visit draft at", draft_url, level=env.Msg.ALWAYS)
|
|
113
|
-
|
|
114
|
-
print()
|
|
115
|
-
|
|
116
|
-
print(project_version, "->", next_version)
|
proj_flow/plugins/sign/win32.py
DELETED
|
@@ -1,191 +0,0 @@
|
|
|
1
|
-
# Copyright (c) 2025 Marcin Zdun
|
|
2
|
-
# This code is licensed under MIT license (see LICENSE for details)
|
|
3
|
-
|
|
4
|
-
"""
|
|
5
|
-
The **proj_flow.plugins.sign.win32** provides code signing with SignTool
|
|
6
|
-
from Windows SDKs.
|
|
7
|
-
"""
|
|
8
|
-
|
|
9
|
-
import base64
|
|
10
|
-
import json
|
|
11
|
-
import os
|
|
12
|
-
import platform
|
|
13
|
-
import struct
|
|
14
|
-
import subprocess
|
|
15
|
-
import sys
|
|
16
|
-
import winreg
|
|
17
|
-
from typing import Iterable, List, NamedTuple, Optional, Tuple
|
|
18
|
-
|
|
19
|
-
from proj_flow.api.env import Runtime
|
|
20
|
-
|
|
21
|
-
ENV_KEY = "SIGN_TOKEN"
|
|
22
|
-
|
|
23
|
-
Version = Tuple[int, int, int]
|
|
24
|
-
|
|
25
|
-
machine = {"ARM64": "arm64", "AMD64": "x64", "X86": "x86"}.get(
|
|
26
|
-
platform.machine(), "x86"
|
|
27
|
-
)
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
def find_sign_tool(rt: Runtime) -> Optional[str]:
|
|
31
|
-
with winreg.OpenKeyEx(
|
|
32
|
-
winreg.HKEY_LOCAL_MACHINE, r"SOFTWARE\Microsoft\Windows Kits\Installed Roots"
|
|
33
|
-
) as kits:
|
|
34
|
-
try:
|
|
35
|
-
kits_root = winreg.QueryValueEx(kits, "KitsRoot10")[0]
|
|
36
|
-
except FileNotFoundError:
|
|
37
|
-
rt.message("sign/win32: No KitsRoot10 value")
|
|
38
|
-
return None
|
|
39
|
-
|
|
40
|
-
versions: List[Tuple[Version, str]] = []
|
|
41
|
-
try:
|
|
42
|
-
index = 0
|
|
43
|
-
while True:
|
|
44
|
-
ver_str = winreg.EnumKey(kits, index)
|
|
45
|
-
ver = tuple(int(chunk) for chunk in ver_str.split("."))
|
|
46
|
-
index += 1
|
|
47
|
-
versions.append((ver, ver_str))
|
|
48
|
-
except OSError:
|
|
49
|
-
pass
|
|
50
|
-
versions.sort()
|
|
51
|
-
versions.reverse()
|
|
52
|
-
rt.message(
|
|
53
|
-
"sign/win32: Regarding versions:", ", ".join(version[1] for version in versions)
|
|
54
|
-
)
|
|
55
|
-
for _, version in versions:
|
|
56
|
-
# C:\Program Files (x86)\Windows Kits\10\bin\10.0.22621.0\x64\signtool.exe
|
|
57
|
-
sign_tool = os.path.join(kits_root, "bin", version, machine, "signtool.exe")
|
|
58
|
-
if os.path.isfile(sign_tool):
|
|
59
|
-
rt.message("sign/win32: using:", sign_tool)
|
|
60
|
-
return sign_tool
|
|
61
|
-
return None
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
class Key(NamedTuple):
|
|
65
|
-
token: str
|
|
66
|
-
secret: bytes
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
def _get_key_from_contents(key: str, rt: Runtime):
|
|
70
|
-
try:
|
|
71
|
-
obj = json.loads(key)
|
|
72
|
-
except json.decoder.JSONDecodeError:
|
|
73
|
-
rt.message("sign/win32: the signature is not a valid JSON document")
|
|
74
|
-
return None
|
|
75
|
-
|
|
76
|
-
if not isinstance(obj, dict):
|
|
77
|
-
rt.message("sign/win32: the signature is missing required fields")
|
|
78
|
-
return None
|
|
79
|
-
|
|
80
|
-
token = obj.get("token")
|
|
81
|
-
secret = obj.get("secret")
|
|
82
|
-
if not isinstance(token, str) or not isinstance(secret, str):
|
|
83
|
-
rt.message("sign/win32: the signature is missing required fields")
|
|
84
|
-
return None
|
|
85
|
-
|
|
86
|
-
return Key(
|
|
87
|
-
base64.b64decode(token).decode("UTF-8"),
|
|
88
|
-
base64.b64decode(secret),
|
|
89
|
-
)
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
def get_key(rt: Runtime) -> Optional[Key]:
|
|
93
|
-
rt.message(f"sign/win32: trying ${ENV_KEY}")
|
|
94
|
-
env = os.environ.get(ENV_KEY)
|
|
95
|
-
if env:
|
|
96
|
-
key = _get_key_from_contents(env, rt)
|
|
97
|
-
if key is not None:
|
|
98
|
-
return key
|
|
99
|
-
local_signature = os.path.join(".", "signature.key")
|
|
100
|
-
home_signature = os.path.join(os.path.expanduser("~"), "signature.key")
|
|
101
|
-
for filename in [local_signature, home_signature]:
|
|
102
|
-
rt.message(f"sign/win32: trying {filename}")
|
|
103
|
-
if os.path.isfile(filename):
|
|
104
|
-
with open(filename, encoding="UTF-8") as file:
|
|
105
|
-
result = file.read().strip()
|
|
106
|
-
key = _get_key_from_contents(result, rt)
|
|
107
|
-
if key is not None:
|
|
108
|
-
return key
|
|
109
|
-
|
|
110
|
-
rt.message("sign/win32: no key set up")
|
|
111
|
-
|
|
112
|
-
return None
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
def is_active(os_name: str, rt: Runtime):
|
|
116
|
-
if os_name != "windows":
|
|
117
|
-
return False
|
|
118
|
-
key = get_key(rt)
|
|
119
|
-
return (
|
|
120
|
-
key is not None
|
|
121
|
-
and key.token is not None
|
|
122
|
-
and key.secret is not None
|
|
123
|
-
and find_sign_tool(rt) is not None
|
|
124
|
-
)
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
_IMAGE_DOS_HEADER = "HHHHHHHHHHHHHH8sHH20sI"
|
|
128
|
-
_IMAGE_NT_HEADERS_Signature = "H"
|
|
129
|
-
_IMAGE_DOS_HEADER_size = struct.calcsize(_IMAGE_DOS_HEADER)
|
|
130
|
-
_IMAGE_NT_HEADERS_Signature_size = struct.calcsize(_IMAGE_NT_HEADERS_Signature)
|
|
131
|
-
_MZ = 23117
|
|
132
|
-
_PE = 17744
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
def is_pe_exec(path: str):
|
|
136
|
-
with open(path, "rb") as exe:
|
|
137
|
-
mz_header = exe.read(_IMAGE_DOS_HEADER_size)
|
|
138
|
-
dos_header = struct.unpack(_IMAGE_DOS_HEADER, mz_header)
|
|
139
|
-
if dos_header[0] != _MZ:
|
|
140
|
-
return False
|
|
141
|
-
|
|
142
|
-
PE_offset = dos_header[-1]
|
|
143
|
-
if PE_offset < _IMAGE_DOS_HEADER_size:
|
|
144
|
-
return False
|
|
145
|
-
|
|
146
|
-
if PE_offset > _IMAGE_DOS_HEADER_size:
|
|
147
|
-
exe.read(PE_offset - _IMAGE_DOS_HEADER_size)
|
|
148
|
-
|
|
149
|
-
pe_header = exe.read(_IMAGE_NT_HEADERS_Signature_size)
|
|
150
|
-
signature = struct.unpack(_IMAGE_NT_HEADERS_Signature, pe_header)[0]
|
|
151
|
-
return signature == _PE
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
def sign(files: Iterable[str], rt: Runtime):
|
|
155
|
-
key = get_key(rt)
|
|
156
|
-
|
|
157
|
-
if key is None or key.token is None or key.secret is None:
|
|
158
|
-
print("proj-flow: sign: the key is missing", file=sys.stderr)
|
|
159
|
-
return 1
|
|
160
|
-
|
|
161
|
-
sign_tool = find_sign_tool(rt)
|
|
162
|
-
if sign_tool is None:
|
|
163
|
-
print("proj-flow: sign: signtool.exe not found", file=sys.stderr)
|
|
164
|
-
sys.exit(0)
|
|
165
|
-
|
|
166
|
-
with open("temp.pfx", "wb") as pfx:
|
|
167
|
-
pfx.write(key.secret)
|
|
168
|
-
|
|
169
|
-
args = [
|
|
170
|
-
sign_tool,
|
|
171
|
-
"sign",
|
|
172
|
-
"/f",
|
|
173
|
-
"temp.pfx",
|
|
174
|
-
"/p",
|
|
175
|
-
key.token,
|
|
176
|
-
"/tr",
|
|
177
|
-
"http://timestamp.digicert.com",
|
|
178
|
-
"/fd",
|
|
179
|
-
"sha256",
|
|
180
|
-
"/td",
|
|
181
|
-
"sha256",
|
|
182
|
-
*files,
|
|
183
|
-
]
|
|
184
|
-
|
|
185
|
-
result = 1
|
|
186
|
-
try:
|
|
187
|
-
result = subprocess.run(args, shell=False).returncode
|
|
188
|
-
finally:
|
|
189
|
-
os.remove("temp.pfx")
|
|
190
|
-
|
|
191
|
-
return result
|
|
@@ -1,11 +0,0 @@
|
|
|
1
|
-
# Copyright (c) 2025 Marcin Zdun
|
|
2
|
-
# This code is licensed under MIT license (see LICENSE for details)
|
|
3
|
-
|
|
4
|
-
"""
|
|
5
|
-
The **proj_flow.plugins.store** provides ``"Store"``, ``"StoreTests"`` and
|
|
6
|
-
``"StorePackages"`` steps.
|
|
7
|
-
"""
|
|
8
|
-
|
|
9
|
-
from . import store_both, store_packages, store_tests
|
|
10
|
-
|
|
11
|
-
__all__ = ["store_both", "store_tests", "store_packages"]
|
|
@@ -1,22 +0,0 @@
|
|
|
1
|
-
# Copyright (c) 2025 Marcin Zdun
|
|
2
|
-
# This code is licensed under MIT license (see LICENSE for details)
|
|
3
|
-
|
|
4
|
-
"""
|
|
5
|
-
The **proj_flow.plugins.store** provides ``"Store"`` step.
|
|
6
|
-
"""
|
|
7
|
-
|
|
8
|
-
from proj_flow.api import step
|
|
9
|
-
|
|
10
|
-
from .store_packages import StorePackages
|
|
11
|
-
from .store_tests import StoreTests
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
@step.register
|
|
15
|
-
class StoreBoth(step.SerialStep):
|
|
16
|
-
"""Stores all artifacts created for ``preset`` config value."""
|
|
17
|
-
|
|
18
|
-
name = "Store"
|
|
19
|
-
|
|
20
|
-
def __init__(self):
|
|
21
|
-
super().__init__()
|
|
22
|
-
self.children = [StoreTests(), StorePackages()]
|
|
@@ -1,21 +0,0 @@
|
|
|
1
|
-
# Copyright (c) 2025 Marcin Zdun
|
|
2
|
-
# This code is licensed under MIT license (see LICENSE for details)
|
|
3
|
-
|
|
4
|
-
"""
|
|
5
|
-
The **proj_flow.plugins.store** provides ``"StoreTests"`` step.
|
|
6
|
-
"""
|
|
7
|
-
|
|
8
|
-
from proj_flow.api import env, step
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
@step.register
|
|
12
|
-
class StoreTests(step.Step):
|
|
13
|
-
"""Stores test results gathered during tests for ``preset`` config value."""
|
|
14
|
-
|
|
15
|
-
name = "StoreTests"
|
|
16
|
-
runs_after = ["Test"]
|
|
17
|
-
|
|
18
|
-
def run(self, config: env.Config, rt: env.Runtime) -> int:
|
|
19
|
-
return rt.cp(
|
|
20
|
-
f"build/{config.preset}/test-results", "build/artifacts/test-results"
|
|
21
|
-
)
|
|
File without changes
|
|
File without changes
|
|
File without changes
|