ominfra 0.0.0.dev176__py3-none-any.whl → 0.0.0.dev178__py3-none-any.whl
Sign up to get free protection for your applications and to get access to all the features.
- ominfra/manage/deploy/apps.py +7 -8
- ominfra/manage/deploy/commands.py +4 -3
- ominfra/manage/deploy/conf.py +0 -12
- ominfra/manage/deploy/config.py +1 -2
- ominfra/manage/deploy/deploy.py +1 -38
- ominfra/manage/deploy/driver.py +71 -0
- ominfra/manage/deploy/git.py +24 -9
- ominfra/manage/deploy/inject.py +36 -8
- ominfra/manage/deploy/paths/manager.py +0 -3
- ominfra/manage/deploy/paths/owners.py +4 -10
- ominfra/manage/deploy/specs.py +5 -0
- ominfra/manage/deploy/tmp.py +9 -28
- ominfra/manage/deploy/venvs.py +2 -10
- ominfra/manage/main.py +1 -7
- ominfra/scripts/manage.py +452 -233
- ominfra/scripts/supervisor.py +205 -11
- {ominfra-0.0.0.dev176.dist-info → ominfra-0.0.0.dev178.dist-info}/METADATA +3 -3
- {ominfra-0.0.0.dev176.dist-info → ominfra-0.0.0.dev178.dist-info}/RECORD +22 -21
- {ominfra-0.0.0.dev176.dist-info → ominfra-0.0.0.dev178.dist-info}/LICENSE +0 -0
- {ominfra-0.0.0.dev176.dist-info → ominfra-0.0.0.dev178.dist-info}/WHEEL +0 -0
- {ominfra-0.0.0.dev176.dist-info → ominfra-0.0.0.dev178.dist-info}/entry_points.txt +0 -0
- {ominfra-0.0.0.dev176.dist-info → ominfra-0.0.0.dev178.dist-info}/top_level.txt +0 -0
ominfra/scripts/manage.py
CHANGED
@@ -17,6 +17,7 @@ import base64
|
|
17
17
|
import collections
|
18
18
|
import collections.abc
|
19
19
|
import contextlib
|
20
|
+
import contextvars
|
20
21
|
import ctypes as ct
|
21
22
|
import dataclasses as dc
|
22
23
|
import datetime
|
@@ -1384,7 +1385,7 @@ class MainConfig:
|
|
1384
1385
|
|
1385
1386
|
@dc.dataclass(frozen=True)
|
1386
1387
|
class DeployConfig:
|
1387
|
-
|
1388
|
+
pass
|
1388
1389
|
|
1389
1390
|
|
1390
1391
|
########################################
|
@@ -4905,6 +4906,10 @@ class InjectorBinding:
|
|
4905
4906
|
key: InjectorKey
|
4906
4907
|
provider: InjectorProvider
|
4907
4908
|
|
4909
|
+
def __post_init__(self) -> None:
|
4910
|
+
check.isinstance(self.key, InjectorKey)
|
4911
|
+
check.isinstance(self.provider, InjectorProvider)
|
4912
|
+
|
4908
4913
|
|
4909
4914
|
class InjectorBindings(abc.ABC):
|
4910
4915
|
@abc.abstractmethod
|
@@ -5168,6 +5173,164 @@ def build_injector_provider_map(bs: InjectorBindings) -> ta.Mapping[InjectorKey,
|
|
5168
5173
|
return pm
|
5169
5174
|
|
5170
5175
|
|
5176
|
+
###
|
5177
|
+
# scopes
|
5178
|
+
|
5179
|
+
|
5180
|
+
class InjectorScope(abc.ABC): # noqa
|
5181
|
+
def __init__(
|
5182
|
+
self,
|
5183
|
+
*,
|
5184
|
+
_i: Injector,
|
5185
|
+
) -> None:
|
5186
|
+
check.not_in(abc.ABC, type(self).__bases__)
|
5187
|
+
|
5188
|
+
super().__init__()
|
5189
|
+
|
5190
|
+
self._i = _i
|
5191
|
+
|
5192
|
+
all_seeds: ta.Iterable[_InjectorScopeSeed] = self._i.provide(InjectorKey(_InjectorScopeSeed, array=True))
|
5193
|
+
self._sks = {s.k for s in all_seeds if s.sc is type(self)}
|
5194
|
+
|
5195
|
+
#
|
5196
|
+
|
5197
|
+
@dc.dataclass(frozen=True)
|
5198
|
+
class State:
|
5199
|
+
seeds: ta.Dict[InjectorKey, ta.Any]
|
5200
|
+
prvs: ta.Dict[InjectorKey, ta.Any] = dc.field(default_factory=dict)
|
5201
|
+
|
5202
|
+
def new_state(self, vs: ta.Mapping[InjectorKey, ta.Any]) -> State:
|
5203
|
+
vs = dict(vs)
|
5204
|
+
check.equal(set(vs.keys()), self._sks)
|
5205
|
+
return InjectorScope.State(vs)
|
5206
|
+
|
5207
|
+
#
|
5208
|
+
|
5209
|
+
@abc.abstractmethod
|
5210
|
+
def state(self) -> State:
|
5211
|
+
raise NotImplementedError
|
5212
|
+
|
5213
|
+
@abc.abstractmethod
|
5214
|
+
def enter(self, vs: ta.Mapping[InjectorKey, ta.Any]) -> ta.ContextManager[None]:
|
5215
|
+
raise NotImplementedError
|
5216
|
+
|
5217
|
+
|
5218
|
+
class ExclusiveInjectorScope(InjectorScope, abc.ABC):
|
5219
|
+
_st: ta.Optional[InjectorScope.State] = None
|
5220
|
+
|
5221
|
+
def state(self) -> InjectorScope.State:
|
5222
|
+
return check.not_none(self._st)
|
5223
|
+
|
5224
|
+
@contextlib.contextmanager
|
5225
|
+
def enter(self, vs: ta.Mapping[InjectorKey, ta.Any]) -> ta.Iterator[None]:
|
5226
|
+
check.none(self._st)
|
5227
|
+
self._st = self.new_state(vs)
|
5228
|
+
try:
|
5229
|
+
yield
|
5230
|
+
finally:
|
5231
|
+
self._st = None
|
5232
|
+
|
5233
|
+
|
5234
|
+
class ContextvarInjectorScope(InjectorScope, abc.ABC):
|
5235
|
+
_cv: contextvars.ContextVar
|
5236
|
+
|
5237
|
+
def __init_subclass__(cls, **kwargs: ta.Any) -> None:
|
5238
|
+
super().__init_subclass__(**kwargs)
|
5239
|
+
check.not_in(abc.ABC, cls.__bases__)
|
5240
|
+
check.state(not hasattr(cls, '_cv'))
|
5241
|
+
cls._cv = contextvars.ContextVar(f'{cls.__name__}_cv')
|
5242
|
+
|
5243
|
+
def state(self) -> InjectorScope.State:
|
5244
|
+
return self._cv.get()
|
5245
|
+
|
5246
|
+
@contextlib.contextmanager
|
5247
|
+
def enter(self, vs: ta.Mapping[InjectorKey, ta.Any]) -> ta.Iterator[None]:
|
5248
|
+
try:
|
5249
|
+
self._cv.get()
|
5250
|
+
except LookupError:
|
5251
|
+
pass
|
5252
|
+
else:
|
5253
|
+
raise RuntimeError(f'Scope already entered: {self}')
|
5254
|
+
st = self.new_state(vs)
|
5255
|
+
tok = self._cv.set(st)
|
5256
|
+
try:
|
5257
|
+
yield
|
5258
|
+
finally:
|
5259
|
+
self._cv.reset(tok)
|
5260
|
+
|
5261
|
+
|
5262
|
+
#
|
5263
|
+
|
5264
|
+
|
5265
|
+
@dc.dataclass(frozen=True)
|
5266
|
+
class ScopedInjectorProvider(InjectorProvider):
|
5267
|
+
p: InjectorProvider
|
5268
|
+
k: InjectorKey
|
5269
|
+
sc: ta.Type[InjectorScope]
|
5270
|
+
|
5271
|
+
def __post_init__(self) -> None:
|
5272
|
+
check.isinstance(self.p, InjectorProvider)
|
5273
|
+
check.isinstance(self.k, InjectorKey)
|
5274
|
+
check.issubclass(self.sc, InjectorScope)
|
5275
|
+
|
5276
|
+
def provider_fn(self) -> InjectorProviderFn:
|
5277
|
+
def pfn(i: Injector) -> ta.Any:
|
5278
|
+
st = i[self.sc].state()
|
5279
|
+
try:
|
5280
|
+
return st.prvs[self.k]
|
5281
|
+
except KeyError:
|
5282
|
+
pass
|
5283
|
+
v = ufn(i)
|
5284
|
+
st.prvs[self.k] = v
|
5285
|
+
return v
|
5286
|
+
|
5287
|
+
ufn = self.p.provider_fn()
|
5288
|
+
return pfn
|
5289
|
+
|
5290
|
+
|
5291
|
+
@dc.dataclass(frozen=True)
|
5292
|
+
class _ScopeSeedInjectorProvider(InjectorProvider):
|
5293
|
+
k: InjectorKey
|
5294
|
+
sc: ta.Type[InjectorScope]
|
5295
|
+
|
5296
|
+
def __post_init__(self) -> None:
|
5297
|
+
check.isinstance(self.k, InjectorKey)
|
5298
|
+
check.issubclass(self.sc, InjectorScope)
|
5299
|
+
|
5300
|
+
def provider_fn(self) -> InjectorProviderFn:
|
5301
|
+
def pfn(i: Injector) -> ta.Any:
|
5302
|
+
st = i[self.sc].state()
|
5303
|
+
return st.seeds[self.k]
|
5304
|
+
return pfn
|
5305
|
+
|
5306
|
+
|
5307
|
+
def bind_injector_scope(sc: ta.Type[InjectorScope]) -> InjectorBindingOrBindings:
|
5308
|
+
return as_injector_bindings(
|
5309
|
+
InjectorBinder.bind(sc, singleton=True),
|
5310
|
+
)
|
5311
|
+
|
5312
|
+
|
5313
|
+
#
|
5314
|
+
|
5315
|
+
|
5316
|
+
@dc.dataclass(frozen=True)
|
5317
|
+
class _InjectorScopeSeed:
|
5318
|
+
sc: ta.Type['InjectorScope']
|
5319
|
+
k: InjectorKey
|
5320
|
+
|
5321
|
+
def __post_init__(self) -> None:
|
5322
|
+
check.issubclass(self.sc, InjectorScope)
|
5323
|
+
check.isinstance(self.k, InjectorKey)
|
5324
|
+
|
5325
|
+
|
5326
|
+
def bind_injector_scope_seed(k: ta.Any, sc: ta.Type[InjectorScope]) -> InjectorBindingOrBindings:
|
5327
|
+
kk = as_injector_key(k)
|
5328
|
+
return as_injector_bindings(
|
5329
|
+
InjectorBinding(kk, _ScopeSeedInjectorProvider(kk, sc)),
|
5330
|
+
InjectorBinder.bind(_InjectorScopeSeed(sc, kk), array=True),
|
5331
|
+
)
|
5332
|
+
|
5333
|
+
|
5171
5334
|
###
|
5172
5335
|
# inspection
|
5173
5336
|
|
@@ -5312,13 +5475,21 @@ _INJECTOR_EAGER_ARRAY_KEY: InjectorKey[_InjectorEager] = InjectorKey(_InjectorEa
|
|
5312
5475
|
|
5313
5476
|
|
5314
5477
|
class _Injector(Injector):
|
5478
|
+
_DEFAULT_BINDINGS: ta.ClassVar[ta.List[InjectorBinding]] = []
|
5479
|
+
|
5315
5480
|
def __init__(self, bs: InjectorBindings, p: ta.Optional[Injector] = None) -> None:
|
5316
5481
|
super().__init__()
|
5317
5482
|
|
5318
5483
|
self._bs = check.isinstance(bs, InjectorBindings)
|
5319
5484
|
self._p: ta.Optional[Injector] = check.isinstance(p, (Injector, type(None)))
|
5320
5485
|
|
5321
|
-
self._pfm = {
|
5486
|
+
self._pfm = {
|
5487
|
+
k: v.provider_fn()
|
5488
|
+
for k, v in build_injector_provider_map(as_injector_bindings(
|
5489
|
+
*self._DEFAULT_BINDINGS,
|
5490
|
+
bs,
|
5491
|
+
)).items()
|
5492
|
+
}
|
5322
5493
|
|
5323
5494
|
if _INJECTOR_INJECTOR_KEY in self._pfm:
|
5324
5495
|
raise DuplicateInjectorKeyError(_INJECTOR_INJECTOR_KEY)
|
@@ -5485,6 +5656,7 @@ class InjectorBinder:
|
|
5485
5656
|
to_const: ta.Any = None,
|
5486
5657
|
to_key: ta.Any = None,
|
5487
5658
|
|
5659
|
+
in_: ta.Optional[ta.Type[InjectorScope]] = None,
|
5488
5660
|
singleton: bool = False,
|
5489
5661
|
|
5490
5662
|
eager: bool = False,
|
@@ -5494,12 +5666,12 @@ class InjectorBinder:
|
|
5494
5666
|
if isinstance(obj, cls._BANNED_BIND_TYPES):
|
5495
5667
|
raise TypeError(obj)
|
5496
5668
|
|
5497
|
-
|
5669
|
+
#
|
5498
5670
|
|
5499
5671
|
if key is not None:
|
5500
5672
|
key = as_injector_key(key)
|
5501
5673
|
|
5502
|
-
|
5674
|
+
#
|
5503
5675
|
|
5504
5676
|
has_to = (
|
5505
5677
|
to_fn is not None or
|
@@ -5529,7 +5701,7 @@ class InjectorBinder:
|
|
5529
5701
|
key = InjectorKey(type(obj))
|
5530
5702
|
del has_to
|
5531
5703
|
|
5532
|
-
|
5704
|
+
#
|
5533
5705
|
|
5534
5706
|
if tag is not None:
|
5535
5707
|
if key.tag is not None:
|
@@ -5539,7 +5711,7 @@ class InjectorBinder:
|
|
5539
5711
|
if array is not None:
|
5540
5712
|
key = dc.replace(key, array=array)
|
5541
5713
|
|
5542
|
-
|
5714
|
+
#
|
5543
5715
|
|
5544
5716
|
providers: ta.List[InjectorProvider] = []
|
5545
5717
|
if to_fn is not None:
|
@@ -5554,23 +5726,34 @@ class InjectorBinder:
|
|
5554
5726
|
raise TypeError('Must specify provider')
|
5555
5727
|
if len(providers) > 1:
|
5556
5728
|
raise TypeError('May not specify multiple providers')
|
5557
|
-
provider
|
5729
|
+
provider = check.single(providers)
|
5558
5730
|
|
5559
|
-
|
5731
|
+
#
|
5560
5732
|
|
5733
|
+
pws: ta.List[ta.Any] = []
|
5734
|
+
if in_ is not None:
|
5735
|
+
check.issubclass(in_, InjectorScope)
|
5736
|
+
check.not_in(abc.ABC, in_.__bases__)
|
5737
|
+
pws.append(functools.partial(ScopedInjectorProvider, k=key, sc=in_))
|
5561
5738
|
if singleton:
|
5562
|
-
|
5739
|
+
pws.append(SingletonInjectorProvider)
|
5740
|
+
if len(pws) > 1:
|
5741
|
+
raise TypeError('May not specify multiple provider wrappers')
|
5742
|
+
elif pws:
|
5743
|
+
provider = check.single(pws)(provider)
|
5744
|
+
|
5745
|
+
#
|
5563
5746
|
|
5564
5747
|
binding = InjectorBinding(key, provider)
|
5565
5748
|
|
5566
|
-
|
5749
|
+
#
|
5567
5750
|
|
5568
5751
|
extras: ta.List[InjectorBinding] = []
|
5569
5752
|
|
5570
5753
|
if eager:
|
5571
5754
|
extras.append(bind_injector_eager_key(key))
|
5572
5755
|
|
5573
|
-
|
5756
|
+
#
|
5574
5757
|
|
5575
5758
|
if extras:
|
5576
5759
|
return as_injector_bindings(binding, *extras)
|
@@ -5643,7 +5826,8 @@ def bind_injector_eager_key(key: ta.Any) -> InjectorBinding:
|
|
5643
5826
|
return InjectorBinding(_INJECTOR_EAGER_ARRAY_KEY, ConstInjectorProvider(_InjectorEager(as_injector_key(key))))
|
5644
5827
|
|
5645
5828
|
|
5646
|
-
|
5829
|
+
###
|
5830
|
+
# api
|
5647
5831
|
|
5648
5832
|
|
5649
5833
|
class InjectionApi:
|
@@ -5666,6 +5850,14 @@ class InjectionApi:
|
|
5666
5850
|
def override(self, p: InjectorBindings, *args: InjectorBindingOrBindings) -> InjectorBindings:
|
5667
5851
|
return injector_override(p, *args)
|
5668
5852
|
|
5853
|
+
# scopes
|
5854
|
+
|
5855
|
+
def bind_scope(self, sc: ta.Type[InjectorScope]) -> InjectorBindingOrBindings:
|
5856
|
+
return bind_injector_scope(sc)
|
5857
|
+
|
5858
|
+
def bind_scope_seed(self, k: ta.Any, sc: ta.Type[InjectorScope]) -> InjectorBindingOrBindings:
|
5859
|
+
return bind_injector_scope_seed(k, sc)
|
5860
|
+
|
5669
5861
|
# injector
|
5670
5862
|
|
5671
5863
|
def create_injector(self, *args: InjectorBindingOrBindings, parent: ta.Optional[Injector] = None) -> Injector:
|
@@ -5686,6 +5878,7 @@ class InjectionApi:
|
|
5686
5878
|
to_const: ta.Any = None,
|
5687
5879
|
to_key: ta.Any = None,
|
5688
5880
|
|
5881
|
+
in_: ta.Optional[ta.Type[InjectorScope]] = None,
|
5689
5882
|
singleton: bool = False,
|
5690
5883
|
|
5691
5884
|
eager: bool = False,
|
@@ -5702,6 +5895,7 @@ class InjectionApi:
|
|
5702
5895
|
to_const=to_const,
|
5703
5896
|
to_key=to_key,
|
5704
5897
|
|
5898
|
+
in_=in_,
|
5705
5899
|
singleton=singleton,
|
5706
5900
|
|
5707
5901
|
eager=eager,
|
@@ -7547,6 +7741,37 @@ class LocalCommandExecutor(CommandExecutor):
|
|
7547
7741
|
return await ce.execute(cmd)
|
7548
7742
|
|
7549
7743
|
|
7744
|
+
########################################
|
7745
|
+
# ../deploy/deploy.py
|
7746
|
+
|
7747
|
+
|
7748
|
+
DEPLOY_TAG_DATETIME_FMT = '%Y%m%dT%H%M%SZ'
|
7749
|
+
|
7750
|
+
|
7751
|
+
DeployManagerUtcClock = ta.NewType('DeployManagerUtcClock', Func0[datetime.datetime])
|
7752
|
+
|
7753
|
+
|
7754
|
+
class DeployManager:
|
7755
|
+
def __init__(
|
7756
|
+
self,
|
7757
|
+
*,
|
7758
|
+
|
7759
|
+
utc_clock: ta.Optional[DeployManagerUtcClock] = None,
|
7760
|
+
):
|
7761
|
+
super().__init__()
|
7762
|
+
|
7763
|
+
self._utc_clock = utc_clock
|
7764
|
+
|
7765
|
+
def _utc_now(self) -> datetime.datetime:
|
7766
|
+
if self._utc_clock is not None:
|
7767
|
+
return self._utc_clock() # noqa
|
7768
|
+
else:
|
7769
|
+
return datetime.datetime.now(tz=datetime.timezone.utc) # noqa
|
7770
|
+
|
7771
|
+
def make_deploy_time(self) -> DeployTime:
|
7772
|
+
return DeployTime(self._utc_now().strftime(DEPLOY_TAG_DATETIME_FMT))
|
7773
|
+
|
7774
|
+
|
7550
7775
|
########################################
|
7551
7776
|
# ../deploy/paths/paths.py
|
7552
7777
|
"""
|
@@ -7885,9 +8110,13 @@ class DeployAppSpec(DeploySpecKeyed[DeployAppKey]):
|
|
7885
8110
|
|
7886
8111
|
@dc.dataclass(frozen=True)
|
7887
8112
|
class DeploySpec(DeploySpecKeyed[DeployKey]):
|
8113
|
+
home: DeployHome
|
8114
|
+
|
7888
8115
|
apps: ta.Sequence[DeployAppSpec]
|
7889
8116
|
|
7890
8117
|
def __post_init__(self) -> None:
|
8118
|
+
check.non_empty_str(self.home)
|
8119
|
+
|
7891
8120
|
seen: ta.Set[DeployApp] = set()
|
7892
8121
|
for a in self.apps:
|
7893
8122
|
if a.app in seen:
|
@@ -8707,17 +8936,6 @@ TODO:
|
|
8707
8936
|
|
8708
8937
|
|
8709
8938
|
class DeployConfManager:
|
8710
|
-
def __init__(
|
8711
|
-
self,
|
8712
|
-
*,
|
8713
|
-
deploy_home: ta.Optional[DeployHome] = None,
|
8714
|
-
) -> None:
|
8715
|
-
super().__init__()
|
8716
|
-
|
8717
|
-
self._deploy_home = deploy_home
|
8718
|
-
|
8719
|
-
#
|
8720
|
-
|
8721
8939
|
async def _write_app_conf_file(
|
8722
8940
|
self,
|
8723
8941
|
acf: DeployAppConfFile,
|
@@ -8884,7 +9102,6 @@ class SingleDirDeployPathOwner(DeployPathOwner, abc.ABC):
|
|
8884
9102
|
self,
|
8885
9103
|
*args: ta.Any,
|
8886
9104
|
owned_dir: str,
|
8887
|
-
deploy_home: ta.Optional[DeployHome],
|
8888
9105
|
**kwargs: ta.Any,
|
8889
9106
|
) -> None:
|
8890
9107
|
super().__init__(*args, **kwargs)
|
@@ -8892,17 +9109,13 @@ class SingleDirDeployPathOwner(DeployPathOwner, abc.ABC):
|
|
8892
9109
|
check.not_in('/', owned_dir)
|
8893
9110
|
self._owned_dir: str = check.non_empty_str(owned_dir)
|
8894
9111
|
|
8895
|
-
self._deploy_home = deploy_home
|
8896
|
-
|
8897
9112
|
self._owned_deploy_paths = frozenset([DeployPath.parse(self._owned_dir + '/')])
|
8898
9113
|
|
8899
|
-
|
8900
|
-
|
8901
|
-
return os.path.join(check.non_empty_str(self._deploy_home), self._owned_dir)
|
9114
|
+
def _dir(self, home: DeployHome) -> str:
|
9115
|
+
return os.path.join(check.non_empty_str(home), self._owned_dir)
|
8902
9116
|
|
8903
|
-
|
8904
|
-
|
8905
|
-
if not os.path.isdir(d := self._dir()):
|
9117
|
+
def _make_dir(self, home: DeployHome) -> str:
|
9118
|
+
if not os.path.isdir(d := self._dir(home)):
|
8906
9119
|
os.makedirs(d, exist_ok=True)
|
8907
9120
|
return d
|
8908
9121
|
|
@@ -9442,122 +9655,6 @@ def bind_commands(
|
|
9442
9655
|
return inj.as_bindings(*lst)
|
9443
9656
|
|
9444
9657
|
|
9445
|
-
########################################
|
9446
|
-
# ../deploy/git.py
|
9447
|
-
"""
|
9448
|
-
TODO:
|
9449
|
-
- 'repos'?
|
9450
|
-
|
9451
|
-
git/github.com/wrmsr/omlish <- bootstrap repo
|
9452
|
-
- shallow clone off bootstrap into /apps
|
9453
|
-
|
9454
|
-
github.com/wrmsr/omlish@rev
|
9455
|
-
"""
|
9456
|
-
|
9457
|
-
|
9458
|
-
##
|
9459
|
-
|
9460
|
-
|
9461
|
-
class DeployGitManager(SingleDirDeployPathOwner):
|
9462
|
-
def __init__(
|
9463
|
-
self,
|
9464
|
-
*,
|
9465
|
-
deploy_home: ta.Optional[DeployHome] = None,
|
9466
|
-
atomics: AtomicPathSwapping,
|
9467
|
-
) -> None:
|
9468
|
-
super().__init__(
|
9469
|
-
owned_dir='git',
|
9470
|
-
deploy_home=deploy_home,
|
9471
|
-
)
|
9472
|
-
|
9473
|
-
self._atomics = atomics
|
9474
|
-
|
9475
|
-
self._repo_dirs: ta.Dict[DeployGitRepo, DeployGitManager.RepoDir] = {}
|
9476
|
-
|
9477
|
-
class RepoDir:
|
9478
|
-
def __init__(
|
9479
|
-
self,
|
9480
|
-
git: 'DeployGitManager',
|
9481
|
-
repo: DeployGitRepo,
|
9482
|
-
) -> None:
|
9483
|
-
super().__init__()
|
9484
|
-
|
9485
|
-
self._git = git
|
9486
|
-
self._repo = repo
|
9487
|
-
self._dir = os.path.join(
|
9488
|
-
self._git._make_dir(), # noqa
|
9489
|
-
check.non_empty_str(repo.host),
|
9490
|
-
check.non_empty_str(repo.path),
|
9491
|
-
)
|
9492
|
-
|
9493
|
-
@property
|
9494
|
-
def repo(self) -> DeployGitRepo:
|
9495
|
-
return self._repo
|
9496
|
-
|
9497
|
-
@property
|
9498
|
-
def url(self) -> str:
|
9499
|
-
if self._repo.username is not None:
|
9500
|
-
return f'{self._repo.username}@{self._repo.host}:{self._repo.path}'
|
9501
|
-
else:
|
9502
|
-
return f'https://{self._repo.host}/{self._repo.path}'
|
9503
|
-
|
9504
|
-
#
|
9505
|
-
|
9506
|
-
async def _call(self, *cmd: str) -> None:
|
9507
|
-
await asyncio_subprocesses.check_call(
|
9508
|
-
*cmd,
|
9509
|
-
cwd=self._dir,
|
9510
|
-
)
|
9511
|
-
|
9512
|
-
#
|
9513
|
-
|
9514
|
-
@async_cached_nullary
|
9515
|
-
async def init(self) -> None:
|
9516
|
-
os.makedirs(self._dir, exist_ok=True)
|
9517
|
-
if os.path.exists(os.path.join(self._dir, '.git')):
|
9518
|
-
return
|
9519
|
-
|
9520
|
-
await self._call('git', 'init')
|
9521
|
-
await self._call('git', 'remote', 'add', 'origin', self.url)
|
9522
|
-
|
9523
|
-
async def fetch(self, rev: DeployRev) -> None:
|
9524
|
-
await self.init()
|
9525
|
-
await self._call('git', 'fetch', '--depth=1', 'origin', rev)
|
9526
|
-
|
9527
|
-
#
|
9528
|
-
|
9529
|
-
async def checkout(self, spec: DeployGitSpec, dst_dir: str) -> None:
|
9530
|
-
check.state(not os.path.exists(dst_dir))
|
9531
|
-
with self._git._atomics.begin_atomic_path_swap( # noqa
|
9532
|
-
'dir',
|
9533
|
-
dst_dir,
|
9534
|
-
auto_commit=True,
|
9535
|
-
make_dirs=True,
|
9536
|
-
) as dst_swap:
|
9537
|
-
await self.fetch(spec.rev)
|
9538
|
-
|
9539
|
-
dst_call = functools.partial(asyncio_subprocesses.check_call, cwd=dst_swap.tmp_path)
|
9540
|
-
await dst_call('git', 'init')
|
9541
|
-
|
9542
|
-
await dst_call('git', 'remote', 'add', 'local', self._dir)
|
9543
|
-
await dst_call('git', 'fetch', '--depth=1', 'local', spec.rev)
|
9544
|
-
await dst_call('git', 'checkout', spec.rev, *(spec.subtrees or []))
|
9545
|
-
|
9546
|
-
def get_repo_dir(self, repo: DeployGitRepo) -> RepoDir:
|
9547
|
-
try:
|
9548
|
-
return self._repo_dirs[repo]
|
9549
|
-
except KeyError:
|
9550
|
-
repo_dir = self._repo_dirs[repo] = DeployGitManager.RepoDir(self, repo)
|
9551
|
-
return repo_dir
|
9552
|
-
|
9553
|
-
async def checkout(
|
9554
|
-
self,
|
9555
|
-
spec: DeployGitSpec,
|
9556
|
-
dst_dir: str,
|
9557
|
-
) -> None:
|
9558
|
-
await self.get_repo_dir(spec.repo).checkout(spec, dst_dir)
|
9559
|
-
|
9560
|
-
|
9561
9658
|
########################################
|
9562
9659
|
# ../deploy/paths/manager.py
|
9563
9660
|
|
@@ -9566,12 +9663,10 @@ class DeployPathsManager:
|
|
9566
9663
|
def __init__(
|
9567
9664
|
self,
|
9568
9665
|
*,
|
9569
|
-
deploy_home: ta.Optional[DeployHome],
|
9570
9666
|
deploy_path_owners: DeployPathOwners,
|
9571
9667
|
) -> None:
|
9572
9668
|
super().__init__()
|
9573
9669
|
|
9574
|
-
self._deploy_home = deploy_home
|
9575
9670
|
self._deploy_path_owners = deploy_path_owners
|
9576
9671
|
|
9577
9672
|
@cached_nullary
|
@@ -9592,37 +9687,22 @@ class DeployPathsManager:
|
|
9592
9687
|
# ../deploy/tmp.py
|
9593
9688
|
|
9594
9689
|
|
9690
|
+
class DeployHomeAtomics(Func1[DeployHome, AtomicPathSwapping]):
|
9691
|
+
pass
|
9692
|
+
|
9693
|
+
|
9595
9694
|
class DeployTmpManager(
|
9596
9695
|
SingleDirDeployPathOwner,
|
9597
|
-
AtomicPathSwapping,
|
9598
9696
|
):
|
9599
|
-
def __init__(
|
9600
|
-
self,
|
9601
|
-
*,
|
9602
|
-
deploy_home: ta.Optional[DeployHome] = None,
|
9603
|
-
) -> None:
|
9697
|
+
def __init__(self) -> None:
|
9604
9698
|
super().__init__(
|
9605
9699
|
owned_dir='tmp',
|
9606
|
-
deploy_home=deploy_home,
|
9607
9700
|
)
|
9608
9701
|
|
9609
|
-
|
9610
|
-
def _swapping(self) -> AtomicPathSwapping:
|
9702
|
+
def get_swapping(self, home: DeployHome) -> AtomicPathSwapping:
|
9611
9703
|
return TempDirAtomicPathSwapping(
|
9612
|
-
temp_dir=self._make_dir(),
|
9613
|
-
root_dir=check.non_empty_str(
|
9614
|
-
)
|
9615
|
-
|
9616
|
-
def begin_atomic_path_swap(
|
9617
|
-
self,
|
9618
|
-
kind: AtomicPathSwapKind,
|
9619
|
-
dst_path: str,
|
9620
|
-
**kwargs: ta.Any,
|
9621
|
-
) -> AtomicPathSwap:
|
9622
|
-
return self._swapping().begin_atomic_path_swap(
|
9623
|
-
kind,
|
9624
|
-
dst_path,
|
9625
|
-
**kwargs,
|
9704
|
+
temp_dir=self._make_dir(home),
|
9705
|
+
root_dir=check.non_empty_str(home),
|
9626
9706
|
)
|
9627
9707
|
|
9628
9708
|
|
@@ -10081,11 +10161,11 @@ class PyenvVersionInstaller:
|
|
10081
10161
|
full_args = [
|
10082
10162
|
os.path.join(check.not_none(await self._pyenv.root()), 'plugins', 'python-build', 'bin', 'python-build'), # noqa
|
10083
10163
|
*conf_args,
|
10084
|
-
self.install_dir(),
|
10164
|
+
await self.install_dir(),
|
10085
10165
|
]
|
10086
10166
|
else:
|
10087
10167
|
full_args = [
|
10088
|
-
self._pyenv.exe(),
|
10168
|
+
await self._pyenv.exe(),
|
10089
10169
|
'install',
|
10090
10170
|
*conf_args,
|
10091
10171
|
]
|
@@ -10340,6 +10420,137 @@ class SystemInterpProvider(InterpProvider):
|
|
10340
10420
|
raise KeyError(version)
|
10341
10421
|
|
10342
10422
|
|
10423
|
+
########################################
|
10424
|
+
# ../deploy/git.py
|
10425
|
+
"""
|
10426
|
+
TODO:
|
10427
|
+
- 'repos'?
|
10428
|
+
|
10429
|
+
git/github.com/wrmsr/omlish <- bootstrap repo
|
10430
|
+
- shallow clone off bootstrap into /apps
|
10431
|
+
|
10432
|
+
github.com/wrmsr/omlish@rev
|
10433
|
+
"""
|
10434
|
+
|
10435
|
+
|
10436
|
+
##
|
10437
|
+
|
10438
|
+
|
10439
|
+
class DeployGitManager(SingleDirDeployPathOwner):
|
10440
|
+
def __init__(
|
10441
|
+
self,
|
10442
|
+
*,
|
10443
|
+
atomics: DeployHomeAtomics,
|
10444
|
+
) -> None:
|
10445
|
+
super().__init__(
|
10446
|
+
owned_dir='git',
|
10447
|
+
)
|
10448
|
+
|
10449
|
+
self._atomics = atomics
|
10450
|
+
|
10451
|
+
self._repo_dirs: ta.Dict[DeployGitRepo, DeployGitManager.RepoDir] = {}
|
10452
|
+
|
10453
|
+
class RepoDir:
|
10454
|
+
def __init__(
|
10455
|
+
self,
|
10456
|
+
git: 'DeployGitManager',
|
10457
|
+
repo: DeployGitRepo,
|
10458
|
+
home: DeployHome,
|
10459
|
+
) -> None:
|
10460
|
+
super().__init__()
|
10461
|
+
|
10462
|
+
self._git = git
|
10463
|
+
self._repo = repo
|
10464
|
+
self._home = home
|
10465
|
+
self._dir = os.path.join(
|
10466
|
+
self._git._make_dir(home), # noqa
|
10467
|
+
check.non_empty_str(repo.host),
|
10468
|
+
check.non_empty_str(repo.path),
|
10469
|
+
)
|
10470
|
+
|
10471
|
+
@property
|
10472
|
+
def repo(self) -> DeployGitRepo:
|
10473
|
+
return self._repo
|
10474
|
+
|
10475
|
+
@property
|
10476
|
+
def url(self) -> str:
|
10477
|
+
if self._repo.username is not None:
|
10478
|
+
return f'{self._repo.username}@{self._repo.host}:{self._repo.path}'
|
10479
|
+
else:
|
10480
|
+
return f'https://{self._repo.host}/{self._repo.path}'
|
10481
|
+
|
10482
|
+
#
|
10483
|
+
|
10484
|
+
async def _call(self, *cmd: str) -> None:
|
10485
|
+
await asyncio_subprocesses.check_call(
|
10486
|
+
*cmd,
|
10487
|
+
cwd=self._dir,
|
10488
|
+
)
|
10489
|
+
|
10490
|
+
#
|
10491
|
+
|
10492
|
+
@async_cached_nullary
|
10493
|
+
async def init(self) -> None:
|
10494
|
+
os.makedirs(self._dir, exist_ok=True)
|
10495
|
+
if os.path.exists(os.path.join(self._dir, '.git')):
|
10496
|
+
return
|
10497
|
+
|
10498
|
+
await self._call('git', 'init')
|
10499
|
+
await self._call('git', 'remote', 'add', 'origin', self.url)
|
10500
|
+
|
10501
|
+
async def fetch(self, rev: DeployRev) -> None:
|
10502
|
+
await self.init()
|
10503
|
+
await self._call('git', 'fetch', '--depth=1', 'origin', rev)
|
10504
|
+
|
10505
|
+
#
|
10506
|
+
|
10507
|
+
async def checkout(self, spec: DeployGitSpec, dst_dir: str) -> None:
|
10508
|
+
check.state(not os.path.exists(dst_dir))
|
10509
|
+
with self._git._atomics(self._home).begin_atomic_path_swap( # noqa
|
10510
|
+
'dir',
|
10511
|
+
dst_dir,
|
10512
|
+
auto_commit=True,
|
10513
|
+
make_dirs=True,
|
10514
|
+
) as dst_swap:
|
10515
|
+
await self.fetch(spec.rev)
|
10516
|
+
|
10517
|
+
dst_call = functools.partial(asyncio_subprocesses.check_call, cwd=dst_swap.tmp_path)
|
10518
|
+
await dst_call('git', 'init')
|
10519
|
+
|
10520
|
+
await dst_call('git', 'remote', 'add', 'local', self._dir)
|
10521
|
+
await dst_call('git', 'fetch', '--depth=1', 'local', spec.rev)
|
10522
|
+
await dst_call('git', 'checkout', spec.rev, *(spec.subtrees or []))
|
10523
|
+
|
10524
|
+
def get_repo_dir(
|
10525
|
+
self,
|
10526
|
+
repo: DeployGitRepo,
|
10527
|
+
home: DeployHome,
|
10528
|
+
) -> RepoDir:
|
10529
|
+
try:
|
10530
|
+
return self._repo_dirs[repo]
|
10531
|
+
except KeyError:
|
10532
|
+
repo_dir = self._repo_dirs[repo] = DeployGitManager.RepoDir(
|
10533
|
+
self,
|
10534
|
+
repo,
|
10535
|
+
home,
|
10536
|
+
)
|
10537
|
+
return repo_dir
|
10538
|
+
|
10539
|
+
async def checkout(
|
10540
|
+
self,
|
10541
|
+
spec: DeployGitSpec,
|
10542
|
+
home: DeployHome,
|
10543
|
+
dst_dir: str,
|
10544
|
+
) -> None:
|
10545
|
+
await self.get_repo_dir(
|
10546
|
+
spec.repo,
|
10547
|
+
home,
|
10548
|
+
).checkout(
|
10549
|
+
spec,
|
10550
|
+
dst_dir,
|
10551
|
+
)
|
10552
|
+
|
10553
|
+
|
10343
10554
|
########################################
|
10344
10555
|
# ../deploy/paths/inject.py
|
10345
10556
|
|
@@ -10739,18 +10950,10 @@ TODO:
|
|
10739
10950
|
|
10740
10951
|
|
10741
10952
|
class DeployVenvManager:
|
10742
|
-
def __init__(
|
10743
|
-
self,
|
10744
|
-
*,
|
10745
|
-
atomics: AtomicPathSwapping,
|
10746
|
-
) -> None:
|
10747
|
-
super().__init__()
|
10748
|
-
|
10749
|
-
self._atomics = atomics
|
10750
|
-
|
10751
10953
|
async def setup_venv(
|
10752
10954
|
self,
|
10753
10955
|
spec: DeployVenvSpec,
|
10956
|
+
home: DeployHome,
|
10754
10957
|
git_dir: str,
|
10755
10958
|
venv_dir: str,
|
10756
10959
|
) -> None:
|
@@ -10793,16 +10996,12 @@ class DeployAppManager(DeployPathOwner):
|
|
10793
10996
|
def __init__(
|
10794
10997
|
self,
|
10795
10998
|
*,
|
10796
|
-
deploy_home: ta.Optional[DeployHome] = None,
|
10797
|
-
|
10798
10999
|
conf: DeployConfManager,
|
10799
11000
|
git: DeployGitManager,
|
10800
11001
|
venvs: DeployVenvManager,
|
10801
11002
|
) -> None:
|
10802
11003
|
super().__init__()
|
10803
11004
|
|
10804
|
-
self._deploy_home = deploy_home
|
10805
|
-
|
10806
11005
|
self._conf = conf
|
10807
11006
|
self._git = git
|
10808
11007
|
self._venvs = venvs
|
@@ -10843,12 +11042,13 @@ class DeployAppManager(DeployPathOwner):
|
|
10843
11042
|
async def prepare_app(
|
10844
11043
|
self,
|
10845
11044
|
spec: DeployAppSpec,
|
11045
|
+
home: DeployHome,
|
10846
11046
|
tags: DeployTagMap,
|
10847
11047
|
) -> None:
|
10848
|
-
|
11048
|
+
check.non_empty_str(home)
|
10849
11049
|
|
10850
11050
|
def build_path(pth: DeployPath) -> str:
|
10851
|
-
return os.path.join(
|
11051
|
+
return os.path.join(home, pth.render(tags))
|
10852
11052
|
|
10853
11053
|
app_dir = build_path(self._APP_DIR)
|
10854
11054
|
deploy_dir = build_path(self._DEPLOY_DIR)
|
@@ -10858,7 +11058,7 @@ class DeployAppManager(DeployPathOwner):
|
|
10858
11058
|
|
10859
11059
|
os.makedirs(deploy_dir, exist_ok=True)
|
10860
11060
|
|
10861
|
-
deploying_link = os.path.join(
|
11061
|
+
deploying_link = os.path.join(home, 'deploys/deploying')
|
10862
11062
|
if os.path.exists(deploying_link):
|
10863
11063
|
os.unlink(deploying_link)
|
10864
11064
|
relative_symlink(
|
@@ -10905,7 +11105,7 @@ class DeployAppManager(DeployPathOwner):
|
|
10905
11105
|
# else:
|
10906
11106
|
# os.makedirs(os.path.join(dst, os.path.relpath(dp2, src)))
|
10907
11107
|
|
10908
|
-
current_link = os.path.join(
|
11108
|
+
current_link = os.path.join(home, 'deploys/current')
|
10909
11109
|
|
10910
11110
|
# if os.path.exists(current_link):
|
10911
11111
|
# mirror_symlinks(
|
@@ -10922,6 +11122,7 @@ class DeployAppManager(DeployPathOwner):
|
|
10922
11122
|
app_git_dir = os.path.join(app_dir, 'git')
|
10923
11123
|
await self._git.checkout(
|
10924
11124
|
spec.git,
|
11125
|
+
home,
|
10925
11126
|
app_git_dir,
|
10926
11127
|
)
|
10927
11128
|
|
@@ -10931,6 +11132,7 @@ class DeployAppManager(DeployPathOwner):
|
|
10931
11132
|
app_venv_dir = os.path.join(app_dir, 'venv')
|
10932
11133
|
await self._venvs.setup_venv(
|
10933
11134
|
spec.venv,
|
11135
|
+
home,
|
10934
11136
|
app_git_dir,
|
10935
11137
|
app_venv_dir,
|
10936
11138
|
)
|
@@ -10952,56 +11154,53 @@ class DeployAppManager(DeployPathOwner):
|
|
10952
11154
|
|
10953
11155
|
|
10954
11156
|
########################################
|
10955
|
-
# ../deploy/
|
11157
|
+
# ../deploy/driver.py
|
10956
11158
|
|
10957
11159
|
|
10958
|
-
|
10959
|
-
|
10960
|
-
|
10961
|
-
DeployManagerUtcClock = ta.NewType('DeployManagerUtcClock', Func0[datetime.datetime])
|
11160
|
+
class DeployDriverFactory(Func1[DeploySpec, ta.ContextManager['DeployDriver']]):
|
11161
|
+
pass
|
10962
11162
|
|
10963
11163
|
|
10964
|
-
class
|
11164
|
+
class DeployDriver:
|
10965
11165
|
def __init__(
|
10966
11166
|
self,
|
10967
11167
|
*,
|
10968
|
-
|
10969
|
-
paths: DeployPathsManager,
|
11168
|
+
spec: DeploySpec,
|
10970
11169
|
|
10971
|
-
|
10972
|
-
|
11170
|
+
deploys: DeployManager,
|
11171
|
+
paths: DeployPathsManager,
|
11172
|
+
apps: DeployAppManager,
|
11173
|
+
) -> None:
|
10973
11174
|
super().__init__()
|
10974
11175
|
|
10975
|
-
self.
|
11176
|
+
self._spec = spec
|
11177
|
+
|
11178
|
+
self._deploys = deploys
|
10976
11179
|
self._paths = paths
|
11180
|
+
self._apps = apps
|
10977
11181
|
|
10978
|
-
|
11182
|
+
async def drive_deploy(self) -> None:
|
11183
|
+
self._paths.validate_deploy_paths()
|
10979
11184
|
|
10980
|
-
|
10981
|
-
if self._utc_clock is not None:
|
10982
|
-
return self._utc_clock() # noqa
|
10983
|
-
else:
|
10984
|
-
return datetime.datetime.now(tz=datetime.timezone.utc) # noqa
|
11185
|
+
#
|
10985
11186
|
|
10986
|
-
|
10987
|
-
|
11187
|
+
hs = check.non_empty_str(self._spec.home)
|
11188
|
+
hs = os.path.expanduser(hs)
|
11189
|
+
hs = os.path.realpath(hs)
|
11190
|
+
hs = os.path.abspath(hs)
|
10988
11191
|
|
10989
|
-
|
10990
|
-
self,
|
10991
|
-
spec: DeploySpec,
|
10992
|
-
) -> None:
|
10993
|
-
self._paths.validate_deploy_paths()
|
11192
|
+
home = DeployHome(hs)
|
10994
11193
|
|
10995
11194
|
#
|
10996
11195
|
|
10997
11196
|
deploy_tags = DeployTagMap(
|
10998
|
-
self.
|
10999
|
-
|
11197
|
+
self._deploys.make_deploy_time(),
|
11198
|
+
self._spec.key(),
|
11000
11199
|
)
|
11001
11200
|
|
11002
11201
|
#
|
11003
11202
|
|
11004
|
-
for app in
|
11203
|
+
for app in self._spec.apps:
|
11005
11204
|
app_tags = deploy_tags.add(
|
11006
11205
|
app.app,
|
11007
11206
|
app.key(),
|
@@ -11010,6 +11209,7 @@ class DeployManager:
|
|
11010
11209
|
|
11011
11210
|
await self._apps.prepare_app(
|
11012
11211
|
app,
|
11212
|
+
home,
|
11013
11213
|
app_tags,
|
11014
11214
|
)
|
11015
11215
|
|
@@ -11032,12 +11232,13 @@ class DeployCommand(Command['DeployCommand.Output']):
|
|
11032
11232
|
|
11033
11233
|
@dc.dataclass(frozen=True)
|
11034
11234
|
class DeployCommandExecutor(CommandExecutor[DeployCommand, DeployCommand.Output]):
|
11035
|
-
|
11235
|
+
_driver_factory: DeployDriverFactory
|
11036
11236
|
|
11037
11237
|
async def execute(self, cmd: DeployCommand) -> DeployCommand.Output:
|
11038
11238
|
log.info('Deploying! %r', cmd.spec)
|
11039
11239
|
|
11040
|
-
|
11240
|
+
with self._driver_factory(cmd.spec) as driver:
|
11241
|
+
await driver.drive_deploy()
|
11041
11242
|
|
11042
11243
|
return DeployCommand.Output()
|
11043
11244
|
|
@@ -11046,6 +11247,10 @@ class DeployCommandExecutor(CommandExecutor[DeployCommand, DeployCommand.Output]
|
|
11046
11247
|
# ../deploy/inject.py
|
11047
11248
|
|
11048
11249
|
|
11250
|
+
class DeployInjectorScope(ContextvarInjectorScope):
|
11251
|
+
pass
|
11252
|
+
|
11253
|
+
|
11049
11254
|
def bind_deploy(
|
11050
11255
|
*,
|
11051
11256
|
deploy_config: DeployConfig,
|
@@ -11077,13 +11282,37 @@ def bind_deploy(
|
|
11077
11282
|
bind_manager(DeployManager),
|
11078
11283
|
|
11079
11284
|
bind_manager(DeployTmpManager),
|
11080
|
-
inj.bind(AtomicPathSwapping, to_key=DeployTmpManager),
|
11081
11285
|
|
11082
11286
|
bind_manager(DeployVenvManager),
|
11083
11287
|
])
|
11084
11288
|
|
11085
11289
|
#
|
11086
11290
|
|
11291
|
+
def provide_deploy_home_atomics(tmp: DeployTmpManager) -> DeployHomeAtomics:
|
11292
|
+
return DeployHomeAtomics(tmp.get_swapping)
|
11293
|
+
lst.append(inj.bind(provide_deploy_home_atomics, singleton=True))
|
11294
|
+
|
11295
|
+
#
|
11296
|
+
|
11297
|
+
def provide_deploy_driver_factory(injector: Injector, sc: DeployInjectorScope) -> DeployDriverFactory:
|
11298
|
+
@contextlib.contextmanager
|
11299
|
+
def factory(spec: DeploySpec) -> ta.Iterator[DeployDriver]:
|
11300
|
+
with sc.enter({
|
11301
|
+
inj.as_key(DeploySpec): spec,
|
11302
|
+
}):
|
11303
|
+
yield injector[DeployDriver]
|
11304
|
+
return DeployDriverFactory(factory)
|
11305
|
+
lst.append(inj.bind(provide_deploy_driver_factory, singleton=True))
|
11306
|
+
|
11307
|
+
lst.extend([
|
11308
|
+
inj.bind_scope(DeployInjectorScope),
|
11309
|
+
inj.bind_scope_seed(DeploySpec, DeployInjectorScope),
|
11310
|
+
|
11311
|
+
inj.bind(DeployDriver, in_=DeployInjectorScope),
|
11312
|
+
])
|
11313
|
+
|
11314
|
+
#
|
11315
|
+
|
11087
11316
|
lst.extend([
|
11088
11317
|
bind_command(DeployCommand, DeployCommandExecutor),
|
11089
11318
|
bind_command(InterpCommand, InterpCommandExecutor),
|
@@ -11091,10 +11320,6 @@ def bind_deploy(
|
|
11091
11320
|
|
11092
11321
|
#
|
11093
11322
|
|
11094
|
-
if (dh := deploy_config.deploy_home) is not None:
|
11095
|
-
dh = os.path.abspath(os.path.expanduser(dh))
|
11096
|
-
lst.append(inj.bind(dh, key=DeployHome))
|
11097
|
-
|
11098
11323
|
return inj.as_bindings(*lst)
|
11099
11324
|
|
11100
11325
|
|
@@ -11190,8 +11415,6 @@ def main_bootstrap(bs: MainBootstrap) -> Injector:
|
|
11190
11415
|
|
11191
11416
|
@dc.dataclass(frozen=True)
|
11192
11417
|
class ManageConfig:
|
11193
|
-
deploy_home: ta.Optional[str] = None
|
11194
|
-
|
11195
11418
|
targets: ta.Optional[ta.Mapping[str, ManageTarget]] = None
|
11196
11419
|
|
11197
11420
|
|
@@ -11223,8 +11446,6 @@ class MainCli(ArgparseCli):
|
|
11223
11446
|
|
11224
11447
|
argparse_arg('--debug', action='store_true'),
|
11225
11448
|
|
11226
|
-
argparse_arg('--deploy-home'),
|
11227
|
-
|
11228
11449
|
argparse_arg('target'),
|
11229
11450
|
argparse_arg('-f', '--command-file', action='append'),
|
11230
11451
|
argparse_arg('command', nargs='*'),
|
@@ -11237,9 +11458,7 @@ class MainCli(ArgparseCli):
|
|
11237
11458
|
debug=bool(self.args.debug),
|
11238
11459
|
),
|
11239
11460
|
|
11240
|
-
deploy_config=DeployConfig(
|
11241
|
-
deploy_home=self.args.deploy_home or self.config().deploy_home,
|
11242
|
-
),
|
11461
|
+
deploy_config=DeployConfig(),
|
11243
11462
|
|
11244
11463
|
remote_config=RemoteConfig(
|
11245
11464
|
payload_file=self.args._payload_file, # noqa
|