wasm-action 0.0.2__py3-none-any.whl → 0.0.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.
- warg_openapi/models/package_record.py +181 -57
- warg_openapi/models/processing_record.py +11 -2
- warg_openapi/models/prove_inclusion422_response.py +35 -0
- warg_openapi/models/published_record.py +11 -2
- warg_openapi/models/rejected_record.py +11 -2
- warg_openapi/models/sourcing_record.py +11 -2
- wasm_action/__init__.py +2 -0
- wasm_action/cli.py +58 -0
- wasm_action/lib.py +170 -0
- wasm_action/registry.py +48 -0
- wasm_action/util.py +9 -36
- wasm_action/warg/__init__.py +0 -0
- wasm_action/{warg_pull.py → warg/actions.py} +80 -6
- wasm_action/warg/client.py +201 -0
- wasm_action/{warg_crypto.py → warg/crypto.py} +5 -1
- {wasm_action-0.0.2.dist-info → wasm_action-0.0.3.dist-info}/METADATA +20 -4
- {wasm_action-0.0.2.dist-info → wasm_action-0.0.3.dist-info}/RECORD +20 -18
- {wasm_action-0.0.2.dist-info → wasm_action-0.0.3.dist-info}/WHEEL +1 -1
- wasm_action-0.0.3.dist-info/entry_points.txt +3 -0
- wasm_action/action.py +0 -123
- wasm_action/model.py +0 -28
- wasm_action/warg_client.py +0 -78
- wasm_action-0.0.2.dist-info/entry_points.txt +0 -3
- /wasm_action/{warg_proto.py → warg/proto.py} +0 -0
|
@@ -13,81 +13,205 @@
|
|
|
13
13
|
|
|
14
14
|
|
|
15
15
|
from __future__ import annotations
|
|
16
|
+
from inspect import getfullargspec
|
|
17
|
+
import json
|
|
16
18
|
import pprint
|
|
17
19
|
import re # noqa: F401
|
|
18
|
-
import json
|
|
19
20
|
|
|
21
|
+
from typing import Any, List, Optional
|
|
22
|
+
from pydantic import BaseModel, Field, StrictStr, ValidationError, validator
|
|
23
|
+
from warg_openapi.models.processing_record import ProcessingRecord
|
|
24
|
+
from warg_openapi.models.published_record import PublishedRecord
|
|
25
|
+
from warg_openapi.models.rejected_record import RejectedRecord
|
|
26
|
+
from warg_openapi.models.sourcing_record import SourcingRecord
|
|
27
|
+
from typing import Union, Any, List, TYPE_CHECKING
|
|
28
|
+
from pydantic import StrictStr, Field
|
|
20
29
|
|
|
21
|
-
|
|
22
|
-
from pydantic import BaseModel, Field, StrictInt, StrictStr, constr, validator
|
|
30
|
+
PACKAGERECORD_ONE_OF_SCHEMAS = ["ProcessingRecord", "PublishedRecord", "RejectedRecord", "SourcingRecord"]
|
|
23
31
|
|
|
24
32
|
class PackageRecord(BaseModel):
|
|
25
33
|
"""
|
|
26
|
-
A package log record.
|
|
34
|
+
A package log record.
|
|
27
35
|
"""
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
@validator('state')
|
|
43
|
-
def state_validate_enum(cls, value):
|
|
44
|
-
"""Validates the enum"""
|
|
45
|
-
if value not in ('published',):
|
|
46
|
-
raise ValueError("must be one of enum values ('published')")
|
|
47
|
-
return value
|
|
36
|
+
# data type: SourcingRecord
|
|
37
|
+
oneof_schema_1_validator: Optional[SourcingRecord] = None
|
|
38
|
+
# data type: ProcessingRecord
|
|
39
|
+
oneof_schema_2_validator: Optional[ProcessingRecord] = None
|
|
40
|
+
# data type: RejectedRecord
|
|
41
|
+
oneof_schema_3_validator: Optional[RejectedRecord] = None
|
|
42
|
+
# data type: PublishedRecord
|
|
43
|
+
oneof_schema_4_validator: Optional[PublishedRecord] = None
|
|
44
|
+
if TYPE_CHECKING:
|
|
45
|
+
actual_instance: Union[ProcessingRecord, PublishedRecord, RejectedRecord, SourcingRecord]
|
|
46
|
+
else:
|
|
47
|
+
actual_instance: Any
|
|
48
|
+
one_of_schemas: List[str] = Field(PACKAGERECORD_ONE_OF_SCHEMAS, const=True)
|
|
48
49
|
|
|
49
50
|
class Config:
|
|
50
|
-
"""Pydantic configuration"""
|
|
51
|
-
allow_population_by_field_name = True
|
|
52
51
|
validate_assignment = True
|
|
53
52
|
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
53
|
+
discriminator_value_class_map = {
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
def __init__(self, *args, **kwargs) -> None:
|
|
57
|
+
if args:
|
|
58
|
+
if len(args) > 1:
|
|
59
|
+
raise ValueError("If a position argument is used, only 1 is allowed to set `actual_instance`")
|
|
60
|
+
if kwargs:
|
|
61
|
+
raise ValueError("If a position argument is used, keyword arguments cannot be used.")
|
|
62
|
+
super().__init__(actual_instance=args[0])
|
|
63
|
+
else:
|
|
64
|
+
super().__init__(**kwargs)
|
|
65
|
+
|
|
66
|
+
@validator('actual_instance')
|
|
67
|
+
def actual_instance_must_validate_oneof(cls, v):
|
|
68
|
+
instance = PackageRecord.construct()
|
|
69
|
+
error_messages = []
|
|
70
|
+
match = 0
|
|
71
|
+
# validate data type: SourcingRecord
|
|
72
|
+
if not isinstance(v, SourcingRecord):
|
|
73
|
+
error_messages.append(f"Error! Input type `{type(v)}` is not `SourcingRecord`")
|
|
74
|
+
else:
|
|
75
|
+
match += 1
|
|
76
|
+
# validate data type: ProcessingRecord
|
|
77
|
+
if not isinstance(v, ProcessingRecord):
|
|
78
|
+
error_messages.append(f"Error! Input type `{type(v)}` is not `ProcessingRecord`")
|
|
79
|
+
else:
|
|
80
|
+
match += 1
|
|
81
|
+
# validate data type: RejectedRecord
|
|
82
|
+
if not isinstance(v, RejectedRecord):
|
|
83
|
+
error_messages.append(f"Error! Input type `{type(v)}` is not `RejectedRecord`")
|
|
84
|
+
else:
|
|
85
|
+
match += 1
|
|
86
|
+
# validate data type: PublishedRecord
|
|
87
|
+
if not isinstance(v, PublishedRecord):
|
|
88
|
+
error_messages.append(f"Error! Input type `{type(v)}` is not `PublishedRecord`")
|
|
89
|
+
else:
|
|
90
|
+
match += 1
|
|
91
|
+
if match > 1:
|
|
92
|
+
# more than 1 match
|
|
93
|
+
raise ValueError("Multiple matches found when setting `actual_instance` in PackageRecord with oneOf schemas: ProcessingRecord, PublishedRecord, RejectedRecord, SourcingRecord. Details: " + ", ".join(error_messages))
|
|
94
|
+
elif match == 0:
|
|
95
|
+
# no match
|
|
96
|
+
raise ValueError("No match found when setting `actual_instance` in PackageRecord with oneOf schemas: ProcessingRecord, PublishedRecord, RejectedRecord, SourcingRecord. Details: " + ", ".join(error_messages))
|
|
97
|
+
else:
|
|
98
|
+
return v
|
|
57
99
|
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
return json.dumps(
|
|
100
|
+
@classmethod
|
|
101
|
+
def from_dict(cls, obj: dict) -> PackageRecord:
|
|
102
|
+
return cls.from_json(json.dumps(obj))
|
|
61
103
|
|
|
62
104
|
@classmethod
|
|
63
105
|
def from_json(cls, json_str: str) -> PackageRecord:
|
|
64
|
-
"""
|
|
65
|
-
|
|
106
|
+
"""Returns the object represented by the json string"""
|
|
107
|
+
instance = PackageRecord.construct()
|
|
108
|
+
error_messages = []
|
|
109
|
+
match = 0
|
|
110
|
+
|
|
111
|
+
# use oneOf discriminator to lookup the data type
|
|
112
|
+
_data_type = json.loads(json_str).get("state")
|
|
113
|
+
if not _data_type:
|
|
114
|
+
raise ValueError("Failed to lookup data type from the field `state` in the input.")
|
|
115
|
+
|
|
116
|
+
# check if data type is `ProcessingRecord`
|
|
117
|
+
if _data_type == "processing":
|
|
118
|
+
instance.actual_instance = ProcessingRecord.from_json(json_str)
|
|
119
|
+
return instance
|
|
120
|
+
|
|
121
|
+
# check if data type is `PublishedRecord`
|
|
122
|
+
if _data_type == "published":
|
|
123
|
+
instance.actual_instance = PublishedRecord.from_json(json_str)
|
|
124
|
+
return instance
|
|
125
|
+
|
|
126
|
+
# check if data type is `RejectedRecord`
|
|
127
|
+
if _data_type == "rejected":
|
|
128
|
+
instance.actual_instance = RejectedRecord.from_json(json_str)
|
|
129
|
+
return instance
|
|
130
|
+
|
|
131
|
+
# check if data type is `SourcingRecord`
|
|
132
|
+
if _data_type == "sourcing":
|
|
133
|
+
instance.actual_instance = SourcingRecord.from_json(json_str)
|
|
134
|
+
return instance
|
|
135
|
+
|
|
136
|
+
# check if data type is `ProcessingRecord`
|
|
137
|
+
if _data_type == "ProcessingRecord":
|
|
138
|
+
instance.actual_instance = ProcessingRecord.from_json(json_str)
|
|
139
|
+
return instance
|
|
140
|
+
|
|
141
|
+
# check if data type is `PublishedRecord`
|
|
142
|
+
if _data_type == "PublishedRecord":
|
|
143
|
+
instance.actual_instance = PublishedRecord.from_json(json_str)
|
|
144
|
+
return instance
|
|
145
|
+
|
|
146
|
+
# check if data type is `RejectedRecord`
|
|
147
|
+
if _data_type == "RejectedRecord":
|
|
148
|
+
instance.actual_instance = RejectedRecord.from_json(json_str)
|
|
149
|
+
return instance
|
|
150
|
+
|
|
151
|
+
# check if data type is `SourcingRecord`
|
|
152
|
+
if _data_type == "SourcingRecord":
|
|
153
|
+
instance.actual_instance = SourcingRecord.from_json(json_str)
|
|
154
|
+
return instance
|
|
155
|
+
|
|
156
|
+
# deserialize data into SourcingRecord
|
|
157
|
+
try:
|
|
158
|
+
instance.actual_instance = SourcingRecord.from_json(json_str)
|
|
159
|
+
match += 1
|
|
160
|
+
except (ValidationError, ValueError) as e:
|
|
161
|
+
error_messages.append(str(e))
|
|
162
|
+
# deserialize data into ProcessingRecord
|
|
163
|
+
try:
|
|
164
|
+
instance.actual_instance = ProcessingRecord.from_json(json_str)
|
|
165
|
+
match += 1
|
|
166
|
+
except (ValidationError, ValueError) as e:
|
|
167
|
+
error_messages.append(str(e))
|
|
168
|
+
# deserialize data into RejectedRecord
|
|
169
|
+
try:
|
|
170
|
+
instance.actual_instance = RejectedRecord.from_json(json_str)
|
|
171
|
+
match += 1
|
|
172
|
+
except (ValidationError, ValueError) as e:
|
|
173
|
+
error_messages.append(str(e))
|
|
174
|
+
# deserialize data into PublishedRecord
|
|
175
|
+
try:
|
|
176
|
+
instance.actual_instance = PublishedRecord.from_json(json_str)
|
|
177
|
+
match += 1
|
|
178
|
+
except (ValidationError, ValueError) as e:
|
|
179
|
+
error_messages.append(str(e))
|
|
180
|
+
|
|
181
|
+
if match > 1:
|
|
182
|
+
# more than 1 match
|
|
183
|
+
raise ValueError("Multiple matches found when deserializing the JSON string into PackageRecord with oneOf schemas: ProcessingRecord, PublishedRecord, RejectedRecord, SourcingRecord. Details: " + ", ".join(error_messages))
|
|
184
|
+
elif match == 0:
|
|
185
|
+
# no match
|
|
186
|
+
raise ValueError("No match found when deserializing the JSON string into PackageRecord with oneOf schemas: ProcessingRecord, PublishedRecord, RejectedRecord, SourcingRecord. Details: " + ", ".join(error_messages))
|
|
187
|
+
else:
|
|
188
|
+
return instance
|
|
66
189
|
|
|
67
|
-
def
|
|
68
|
-
"""Returns the
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
190
|
+
def to_json(self) -> str:
|
|
191
|
+
"""Returns the JSON representation of the actual instance"""
|
|
192
|
+
if self.actual_instance is None:
|
|
193
|
+
return "null"
|
|
194
|
+
|
|
195
|
+
to_json = getattr(self.actual_instance, "to_json", None)
|
|
196
|
+
if callable(to_json):
|
|
197
|
+
return self.actual_instance.to_json()
|
|
198
|
+
else:
|
|
199
|
+
return json.dumps(self.actual_instance)
|
|
200
|
+
|
|
201
|
+
def to_dict(self) -> dict:
|
|
202
|
+
"""Returns the dict representation of the actual instance"""
|
|
203
|
+
if self.actual_instance is None:
|
|
79
204
|
return None
|
|
80
205
|
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
return _obj
|
|
206
|
+
to_dict = getattr(self.actual_instance, "to_dict", None)
|
|
207
|
+
if callable(to_dict):
|
|
208
|
+
return self.actual_instance.to_dict()
|
|
209
|
+
else:
|
|
210
|
+
# primitive type
|
|
211
|
+
return self.actual_instance
|
|
212
|
+
|
|
213
|
+
def to_str(self) -> str:
|
|
214
|
+
"""Returns the string representation of the actual instance"""
|
|
215
|
+
return pprint.pformat(self.dict())
|
|
92
216
|
|
|
93
217
|
|
|
@@ -19,14 +19,22 @@ import json
|
|
|
19
19
|
|
|
20
20
|
|
|
21
21
|
|
|
22
|
-
from pydantic import BaseModel, Field, StrictStr, validator
|
|
22
|
+
from pydantic import BaseModel, Field, StrictStr, constr, validator
|
|
23
23
|
|
|
24
24
|
class ProcessingRecord(BaseModel):
|
|
25
25
|
"""
|
|
26
26
|
A record that is being processed. # noqa: E501
|
|
27
27
|
"""
|
|
28
|
+
record_id: constr(strict=True) = Field(default=..., alias="recordId", description="Represents a supported hash.")
|
|
28
29
|
state: StrictStr = Field(default=..., description="The state of the package record.")
|
|
29
|
-
__properties = ["state"]
|
|
30
|
+
__properties = ["recordId", "state"]
|
|
31
|
+
|
|
32
|
+
@validator('record_id')
|
|
33
|
+
def record_id_validate_regular_expression(cls, value):
|
|
34
|
+
"""Validates the regular expression"""
|
|
35
|
+
if not re.match(r"^[a-z0-9-]+:[a-f0-9]+$", value):
|
|
36
|
+
raise ValueError(r"must validate the regular expression /^[a-z0-9-]+:[a-f0-9]+$/")
|
|
37
|
+
return value
|
|
30
38
|
|
|
31
39
|
@validator('state')
|
|
32
40
|
def state_validate_enum(cls, value):
|
|
@@ -71,6 +79,7 @@ class ProcessingRecord(BaseModel):
|
|
|
71
79
|
return ProcessingRecord.parse_obj(obj)
|
|
72
80
|
|
|
73
81
|
_obj = ProcessingRecord.parse_obj({
|
|
82
|
+
"record_id": obj.get("recordId"),
|
|
74
83
|
"state": obj.get("state")
|
|
75
84
|
})
|
|
76
85
|
return _obj
|
|
@@ -100,6 +100,41 @@ class ProveInclusion422Response(BaseModel):
|
|
|
100
100
|
error_messages = []
|
|
101
101
|
match = 0
|
|
102
102
|
|
|
103
|
+
# use oneOf discriminator to lookup the data type
|
|
104
|
+
_data_type = json.loads(json_str).get("reason")
|
|
105
|
+
if not _data_type:
|
|
106
|
+
raise ValueError("Failed to lookup data type from the field `reason` in the input.")
|
|
107
|
+
|
|
108
|
+
# check if data type is `BundleFailureError`
|
|
109
|
+
if _data_type == "failure":
|
|
110
|
+
instance.actual_instance = BundleFailureError.from_json(json_str)
|
|
111
|
+
return instance
|
|
112
|
+
|
|
113
|
+
# check if data type is `IncorrectProofError`
|
|
114
|
+
if _data_type == "incorrectProof":
|
|
115
|
+
instance.actual_instance = IncorrectProofError.from_json(json_str)
|
|
116
|
+
return instance
|
|
117
|
+
|
|
118
|
+
# check if data type is `PackageNotIncludedError`
|
|
119
|
+
if _data_type == "packageNotIncluded":
|
|
120
|
+
instance.actual_instance = PackageNotIncludedError.from_json(json_str)
|
|
121
|
+
return instance
|
|
122
|
+
|
|
123
|
+
# check if data type is `BundleFailureError`
|
|
124
|
+
if _data_type == "BundleFailureError":
|
|
125
|
+
instance.actual_instance = BundleFailureError.from_json(json_str)
|
|
126
|
+
return instance
|
|
127
|
+
|
|
128
|
+
# check if data type is `IncorrectProofError`
|
|
129
|
+
if _data_type == "IncorrectProofError":
|
|
130
|
+
instance.actual_instance = IncorrectProofError.from_json(json_str)
|
|
131
|
+
return instance
|
|
132
|
+
|
|
133
|
+
# check if data type is `PackageNotIncludedError`
|
|
134
|
+
if _data_type == "PackageNotIncludedError":
|
|
135
|
+
instance.actual_instance = PackageNotIncludedError.from_json(json_str)
|
|
136
|
+
return instance
|
|
137
|
+
|
|
103
138
|
# deserialize data into PackageNotIncludedError
|
|
104
139
|
try:
|
|
105
140
|
instance.actual_instance = PackageNotIncludedError.from_json(json_str)
|
|
@@ -19,15 +19,23 @@ import json
|
|
|
19
19
|
|
|
20
20
|
|
|
21
21
|
|
|
22
|
-
from pydantic import BaseModel, Field, StrictInt, StrictStr, validator
|
|
22
|
+
from pydantic import BaseModel, Field, StrictInt, StrictStr, constr, validator
|
|
23
23
|
|
|
24
24
|
class PublishedRecord(BaseModel):
|
|
25
25
|
"""
|
|
26
26
|
A record that has been published to the log. # noqa: E501
|
|
27
27
|
"""
|
|
28
|
+
record_id: constr(strict=True) = Field(default=..., alias="recordId", description="Represents a supported hash.")
|
|
28
29
|
state: StrictStr = Field(default=..., description="The state of the package record.")
|
|
29
30
|
registry_index: StrictInt = Field(default=..., alias="registryIndex", description="The index of the record in the registry log.")
|
|
30
|
-
__properties = ["state", "registryIndex"]
|
|
31
|
+
__properties = ["recordId", "state", "registryIndex"]
|
|
32
|
+
|
|
33
|
+
@validator('record_id')
|
|
34
|
+
def record_id_validate_regular_expression(cls, value):
|
|
35
|
+
"""Validates the regular expression"""
|
|
36
|
+
if not re.match(r"^[a-z0-9-]+:[a-f0-9]+$", value):
|
|
37
|
+
raise ValueError(r"must validate the regular expression /^[a-z0-9-]+:[a-f0-9]+$/")
|
|
38
|
+
return value
|
|
31
39
|
|
|
32
40
|
@validator('state')
|
|
33
41
|
def state_validate_enum(cls, value):
|
|
@@ -72,6 +80,7 @@ class PublishedRecord(BaseModel):
|
|
|
72
80
|
return PublishedRecord.parse_obj(obj)
|
|
73
81
|
|
|
74
82
|
_obj = PublishedRecord.parse_obj({
|
|
83
|
+
"record_id": obj.get("recordId"),
|
|
75
84
|
"state": obj.get("state"),
|
|
76
85
|
"registry_index": obj.get("registryIndex")
|
|
77
86
|
})
|
|
@@ -19,15 +19,23 @@ import json
|
|
|
19
19
|
|
|
20
20
|
|
|
21
21
|
|
|
22
|
-
from pydantic import BaseModel, Field, StrictStr, validator
|
|
22
|
+
from pydantic import BaseModel, Field, StrictStr, constr, validator
|
|
23
23
|
|
|
24
24
|
class RejectedRecord(BaseModel):
|
|
25
25
|
"""
|
|
26
26
|
A rejected package record. # noqa: E501
|
|
27
27
|
"""
|
|
28
|
+
record_id: constr(strict=True) = Field(default=..., alias="recordId", description="Represents a supported hash.")
|
|
28
29
|
state: StrictStr = Field(default=..., description="The state of the package record.")
|
|
29
30
|
reason: StrictStr = Field(default=..., description="The reason the package record was rejected.")
|
|
30
|
-
__properties = ["state", "reason"]
|
|
31
|
+
__properties = ["recordId", "state", "reason"]
|
|
32
|
+
|
|
33
|
+
@validator('record_id')
|
|
34
|
+
def record_id_validate_regular_expression(cls, value):
|
|
35
|
+
"""Validates the regular expression"""
|
|
36
|
+
if not re.match(r"^[a-z0-9-]+:[a-f0-9]+$", value):
|
|
37
|
+
raise ValueError(r"must validate the regular expression /^[a-z0-9-]+:[a-f0-9]+$/")
|
|
38
|
+
return value
|
|
31
39
|
|
|
32
40
|
@validator('state')
|
|
33
41
|
def state_validate_enum(cls, value):
|
|
@@ -72,6 +80,7 @@ class RejectedRecord(BaseModel):
|
|
|
72
80
|
return RejectedRecord.parse_obj(obj)
|
|
73
81
|
|
|
74
82
|
_obj = RejectedRecord.parse_obj({
|
|
83
|
+
"record_id": obj.get("recordId"),
|
|
75
84
|
"state": obj.get("state"),
|
|
76
85
|
"reason": obj.get("reason")
|
|
77
86
|
})
|
|
@@ -19,15 +19,23 @@ import json
|
|
|
19
19
|
|
|
20
20
|
|
|
21
21
|
from typing import Any, Dict
|
|
22
|
-
from pydantic import BaseModel, Field, StrictStr, validator
|
|
22
|
+
from pydantic import BaseModel, Field, StrictStr, constr, validator
|
|
23
23
|
|
|
24
24
|
class SourcingRecord(BaseModel):
|
|
25
25
|
"""
|
|
26
26
|
The package record is sourcing content. # noqa: E501
|
|
27
27
|
"""
|
|
28
|
+
record_id: constr(strict=True) = Field(default=..., alias="recordId", description="Represents a supported hash.")
|
|
28
29
|
state: StrictStr = Field(default=..., description="The state of the package record.")
|
|
29
30
|
missing_content: Dict[str, Any] = Field(default=..., alias="missingContent", description="The map of content digest to missing content info.")
|
|
30
|
-
__properties = ["state", "missingContent"]
|
|
31
|
+
__properties = ["recordId", "state", "missingContent"]
|
|
32
|
+
|
|
33
|
+
@validator('record_id')
|
|
34
|
+
def record_id_validate_regular_expression(cls, value):
|
|
35
|
+
"""Validates the regular expression"""
|
|
36
|
+
if not re.match(r"^[a-z0-9-]+:[a-f0-9]+$", value):
|
|
37
|
+
raise ValueError(r"must validate the regular expression /^[a-z0-9-]+:[a-f0-9]+$/")
|
|
38
|
+
return value
|
|
31
39
|
|
|
32
40
|
@validator('state')
|
|
33
41
|
def state_validate_enum(cls, value):
|
|
@@ -72,6 +80,7 @@ class SourcingRecord(BaseModel):
|
|
|
72
80
|
return SourcingRecord.parse_obj(obj)
|
|
73
81
|
|
|
74
82
|
_obj = SourcingRecord.parse_obj({
|
|
83
|
+
"record_id": obj.get("recordId"),
|
|
75
84
|
"state": obj.get("state"),
|
|
76
85
|
"missing_content": obj.get("missingContent")
|
|
77
86
|
})
|
wasm_action/__init__.py
CHANGED
wasm_action/cli.py
ADDED
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import sys
|
|
2
|
+
import click
|
|
3
|
+
|
|
4
|
+
from . import lib
|
|
5
|
+
|
|
6
|
+
@click.group()
|
|
7
|
+
def cli():
|
|
8
|
+
pass
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
@cli.command(help="Push to registry")
|
|
12
|
+
@click.option('--registry', required=True, help="registry domain name")
|
|
13
|
+
@click.option('--package', required=True, help="package spec")
|
|
14
|
+
@click.option('--path', required=True, help="filename")
|
|
15
|
+
@click.option('--warg-token', required=False, envvar='WARG_TOKEN', help="warg token")
|
|
16
|
+
@click.option('--warg-private-key', required=False, envvar='WARG_PRIVATE_KEY', help="warg private key")
|
|
17
|
+
def push(registry, package, path, warg_token, warg_private_key):
|
|
18
|
+
|
|
19
|
+
try:
|
|
20
|
+
|
|
21
|
+
lib.push_file(
|
|
22
|
+
registry=registry,
|
|
23
|
+
package=package,
|
|
24
|
+
path=path,
|
|
25
|
+
warg_token=warg_token,
|
|
26
|
+
warg_private_key=warg_private_key,
|
|
27
|
+
cli=True,
|
|
28
|
+
)
|
|
29
|
+
|
|
30
|
+
except Exception as e:
|
|
31
|
+
print(e)
|
|
32
|
+
sys.exit(1)
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
@cli.command(help="Pull from registry")
|
|
36
|
+
@click.option('--registry', required=True, help="registry domain name")
|
|
37
|
+
@click.option('--package', required=True, help="package spec")
|
|
38
|
+
@click.option('--path', required=False, help="filename")
|
|
39
|
+
@click.option('--warg-token', required=False, envvar='WARG_TOKEN', help="warg token")
|
|
40
|
+
def pull(registry, package, path=None, warg_token=None):
|
|
41
|
+
|
|
42
|
+
try:
|
|
43
|
+
|
|
44
|
+
lib.pull_file(
|
|
45
|
+
registry=registry,
|
|
46
|
+
package=package,
|
|
47
|
+
path=path,
|
|
48
|
+
warg_token=warg_token,
|
|
49
|
+
cli=True,
|
|
50
|
+
)
|
|
51
|
+
|
|
52
|
+
except Exception as e:
|
|
53
|
+
print(e)
|
|
54
|
+
sys.exit(1)
|
|
55
|
+
|
|
56
|
+
|
|
57
|
+
if __name__ == "__main__":
|
|
58
|
+
cli()
|
wasm_action/lib.py
ADDED
|
@@ -0,0 +1,170 @@
|
|
|
1
|
+
import sys
|
|
2
|
+
import enum
|
|
3
|
+
import glob
|
|
4
|
+
import os
|
|
5
|
+
import hashlib
|
|
6
|
+
import base64
|
|
7
|
+
import json
|
|
8
|
+
|
|
9
|
+
import click
|
|
10
|
+
import semver
|
|
11
|
+
import validators
|
|
12
|
+
import requests
|
|
13
|
+
|
|
14
|
+
from .registry import RegistryType, detect_registry_settings
|
|
15
|
+
from .util import add_github_output, format_package, parse_package, extract_version
|
|
16
|
+
from .warg.crypto import PrivateKey
|
|
17
|
+
from .warg.client import WargClient
|
|
18
|
+
from .warg.actions import warg_pull, warg_push
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
def error(text):
|
|
22
|
+
return ValueError(text)
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
def push_file(registry, package, path, warg_token, warg_private_key, cli=False):
|
|
26
|
+
"""Push file to registry"""
|
|
27
|
+
|
|
28
|
+
# path
|
|
29
|
+
if not path:
|
|
30
|
+
raise error('path is required')
|
|
31
|
+
|
|
32
|
+
# glob pattern support: (ex.: package-*.wasm)
|
|
33
|
+
# expand path pattern into filename, ensure only a single file
|
|
34
|
+
files = glob.glob(path)
|
|
35
|
+
if not files:
|
|
36
|
+
raise error('file not found: {}'.format(path))
|
|
37
|
+
if len(files) > 1:
|
|
38
|
+
raise error('more than one file found: {}'.format(path))
|
|
39
|
+
filename = files[0]
|
|
40
|
+
|
|
41
|
+
# extract version from filename if not provided
|
|
42
|
+
namespace, name, version = parse_package(package)
|
|
43
|
+
if not version:
|
|
44
|
+
version = extract_version(filename)
|
|
45
|
+
package = format_package(namespace, name, version)
|
|
46
|
+
|
|
47
|
+
with open(filename, 'rb') as f:
|
|
48
|
+
content_bytes = f.read()
|
|
49
|
+
|
|
50
|
+
return push(registry, package, content_bytes, warg_token, warg_private_key, cli=cli)
|
|
51
|
+
|
|
52
|
+
|
|
53
|
+
def push(registry, package, content_bytes, warg_token, warg_private_key, cli=False):
|
|
54
|
+
"""Push to registry"""
|
|
55
|
+
|
|
56
|
+
# package
|
|
57
|
+
if not package:
|
|
58
|
+
raise error("package is required")
|
|
59
|
+
|
|
60
|
+
namespace, name, version = parse_package(package)
|
|
61
|
+
if not version:
|
|
62
|
+
raise error("version is required")
|
|
63
|
+
|
|
64
|
+
# validate version as semver
|
|
65
|
+
semver.Version.parse(version)
|
|
66
|
+
|
|
67
|
+
settings = validate_registry(registry, cli=cli)
|
|
68
|
+
if settings.get('registry-type') != RegistryType.WARG:
|
|
69
|
+
raise error("Registry type not supported: {}".format(settings.get('registry-type')))
|
|
70
|
+
|
|
71
|
+
# validate private key
|
|
72
|
+
if not warg_private_key:
|
|
73
|
+
raise error('no private key provided')
|
|
74
|
+
|
|
75
|
+
try:
|
|
76
|
+
private_key = PrivateKey.load(warg_private_key)
|
|
77
|
+
except:
|
|
78
|
+
raise error("Error loading private key")
|
|
79
|
+
else:
|
|
80
|
+
if cli:
|
|
81
|
+
add_github_output('key-id', private_key.public_key().fingerprint())
|
|
82
|
+
add_github_output('public-key', private_key.public_key().canonical())
|
|
83
|
+
|
|
84
|
+
if warg_token and '/' in warg_token:
|
|
85
|
+
v = warg_token.split('/', 1)[1]
|
|
86
|
+
if cli:
|
|
87
|
+
add_github_output('token-id', "sha256:{}".format(hashlib.sha256(v.encode('utf8')).hexdigest()))
|
|
88
|
+
|
|
89
|
+
# push
|
|
90
|
+
try:
|
|
91
|
+
|
|
92
|
+
record = warg_push(
|
|
93
|
+
registry, settings['warg-url'],
|
|
94
|
+
namespace, name, version, content_bytes,
|
|
95
|
+
warg_token, warg_private_key)
|
|
96
|
+
|
|
97
|
+
except Exception as e:
|
|
98
|
+
message = str(e)
|
|
99
|
+
if hasattr(e, 'body'):
|
|
100
|
+
message = str(e.body)
|
|
101
|
+
try:
|
|
102
|
+
message = json.loads(e.body)['message']
|
|
103
|
+
except:
|
|
104
|
+
pass
|
|
105
|
+
if cli:
|
|
106
|
+
add_github_output('error', message)
|
|
107
|
+
raise
|
|
108
|
+
|
|
109
|
+
if cli:
|
|
110
|
+
add_github_output('state', record['state'])
|
|
111
|
+
add_github_output('package', format_package(namespace=record['namespace'], name=record['name'], version=record['version']))
|
|
112
|
+
add_github_output('package-namespace', record['namespace'])
|
|
113
|
+
add_github_output('package-name', record['name'])
|
|
114
|
+
add_github_output('package-version', record['version'])
|
|
115
|
+
add_github_output('package-record-id', record['record_id'])
|
|
116
|
+
|
|
117
|
+
return record
|
|
118
|
+
|
|
119
|
+
|
|
120
|
+
def pull(registry, package, warg_token=None, cli=False):
|
|
121
|
+
"""Pull from registry"""
|
|
122
|
+
|
|
123
|
+
if not package:
|
|
124
|
+
raise error("package is required")
|
|
125
|
+
|
|
126
|
+
namespace, name, version = parse_package(package)
|
|
127
|
+
|
|
128
|
+
settings = validate_registry(registry, cli=cli)
|
|
129
|
+
|
|
130
|
+
if settings.get('registry-type') != RegistryType.WARG:
|
|
131
|
+
raise error("Registry type not supported: {}".format(settings.get('registry-type')))
|
|
132
|
+
|
|
133
|
+
download = warg_pull(registry, settings['warg-url'], namespace, name, version, warg_token=warg_token)
|
|
134
|
+
|
|
135
|
+
return download
|
|
136
|
+
|
|
137
|
+
|
|
138
|
+
def pull_file(registry, package, path=None, warg_token=None, cli=False):
|
|
139
|
+
"""Pull from registry, write to file"""
|
|
140
|
+
|
|
141
|
+
download = pull(registry, package, warg_token, cli=cli)
|
|
142
|
+
|
|
143
|
+
filename = path or "{}:{}@{}.wasm".format(download.namespace, download.name, download.version)
|
|
144
|
+
with open(filename, 'wb') as f:
|
|
145
|
+
f.write(download.content)
|
|
146
|
+
|
|
147
|
+
if cli:
|
|
148
|
+
add_github_output('package', format_package(
|
|
149
|
+
namespace=download.namespace, name=download.name, version=download.version))
|
|
150
|
+
add_github_output('package-namespace', download.namespace)
|
|
151
|
+
add_github_output('package-name', download.name)
|
|
152
|
+
add_github_output('package-version', download.version)
|
|
153
|
+
add_github_output('digest', download.digest)
|
|
154
|
+
add_github_output('filename', filename)
|
|
155
|
+
|
|
156
|
+
|
|
157
|
+
def validate_registry(registry, cli=False):
|
|
158
|
+
if not registry:
|
|
159
|
+
raise error('registry is required')
|
|
160
|
+
|
|
161
|
+
if not validators.domain(registry, consider_tld=True):
|
|
162
|
+
raise error('registry is not a valid domain name: "{}"'.format(registry))
|
|
163
|
+
|
|
164
|
+
if cli:
|
|
165
|
+
add_github_output('registry', registry)
|
|
166
|
+
settings = detect_registry_settings(registry)
|
|
167
|
+
if cli:
|
|
168
|
+
for key, value in settings.items():
|
|
169
|
+
add_github_output(key, str(value))
|
|
170
|
+
return settings
|