Skip to content

Commit 267fc27

Browse files
committed
release
1 parent a300d79 commit 267fc27

File tree

10 files changed

+92
-54
lines changed

10 files changed

+92
-54
lines changed

Makefile

+1-1
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ lint: ## run linters
2727
.PHONY: test
2828
test: ## test with coverage
2929
@poetry run \
30-
pytest -v --cov --cov-report xml --cov-report html
30+
pytest -v --cov --cov-report xml --cov-report html -x
3131

3232
.PHONY: test-lint
3333
test-lint: ## run linters

metablock/__init__.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
from .spaces import Block, Service, Space, SpaceExtension
66
from .user import User
77

8-
__version__ = "1.0.1"
8+
__version__ = "1.0.2"
99

1010
__all__ = [
1111
"Metablock",

metablock/cli.py

+12-23
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,12 @@
11
import asyncio
22
import os
3-
import zipfile
43
from pathlib import Path
54

65
import click
76
import yaml
87

9-
from metablock import Metablock
8+
from metablock import Metablock, __version__
9+
from metablock.utils import temp_zipfile
1010

1111
METABLOCK_SPACE = os.environ.get("METABLOCK_SPACE", "")
1212
METABLOCK_ENV = os.environ.get("METABLOCK_ENV", "prod")
@@ -20,6 +20,7 @@ def manifest(file_path: Path) -> dict:
2020

2121

2222
@click.group()
23+
@click.version_option(version=__version__)
2324
def main() -> None:
2425
pass
2526

@@ -131,25 +132,13 @@ async def _ship(path: str, env: str, block_id: str, name: str, token: str) -> No
131132
click.echo("metablock block-id is required", err=True)
132133
raise click.Abort()
133134
p = Path(path)
134-
if not p.is_dir():
135-
click.echo(f"path {p} does not exist", err=True)
136-
raise click.Abort()
137-
138-
# Create a zip file from the directory
139-
zip_path = p.with_suffix(".zip")
140135
try:
141-
with zipfile.ZipFile(zip_path, "w", zipfile.ZIP_DEFLATED) as zipf:
142-
for file in p.rglob("*"): # Recursively add all files in the directory
143-
arcname = file.relative_to(p) # Preserve relative paths in the archive
144-
zipf.write(file, arcname)
145-
click.echo(f"Created zip file: {zip_path}")
146-
147-
async with Metablock(auth_key=token) as mb:
148-
block = await mb.blocks.get(block_id)
149-
await block.ship(zip_path, name=name, env=env)
150-
click.echo(f"shipped {zip_path} to {block.name} {env}")
151-
finally:
152-
# Clean up the zip file after shipping
153-
if zip_path.exists():
154-
zip_path.unlink()
155-
click.echo(f"Removed temporary zip file: {zip_path}")
136+
with temp_zipfile(p) as zip_path:
137+
click.echo(f"Created zip file: {zip_path}")
138+
async with Metablock(auth_key=token) as mb:
139+
block = await mb.blocks.get(block_id)
140+
await block.ship(zip_path, name=name, env=env, timeout=10)
141+
click.echo(f"shipped {zip_path} to {block.name} {env}")
142+
except ValueError as e:
143+
click.echo(str(e), err=True)
144+
raise click.Abort() from None

metablock/spaces.py

+4-5
Original file line numberDiff line numberDiff line change
@@ -46,15 +46,14 @@ async def ship(
4646
bundle_path: str | Path,
4747
name: str = "",
4848
env: str = "stage",
49-
*,
50-
callback: Any = None,
49+
**kwargs: Any,
5150
) -> dict:
52-
bundle = str(bundle_path)
51+
p = Path(bundle_path)
5352
return await self.cli.post(
5453
f"{self.url}/deployments",
5554
data=dict(name=name, env=env),
56-
files=dict(bundle=(bundle, open(bundle, "rb"))),
57-
callback=callback,
55+
files=dict(bundle=(p.name, p.read_bytes())),
56+
**kwargs,
5857
)
5958

6059
async def add_route(self, *, callback: Any = None, **kwargs: Any) -> dict:

metablock/utils.py

+25-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,7 @@
1-
from typing import Any
1+
import zipfile
2+
from contextlib import contextmanager
3+
from pathlib import Path
4+
from typing import Any, Iterator
25

36
from multidict import MultiDict
47

@@ -11,3 +14,24 @@ def as_params(*, params: dict | None = None, **kwargs: Any) -> MultiDict:
1114
d = MultiDict(params if params is not None else {})
1215
d.update(kwargs)
1316
return d
17+
18+
19+
@contextmanager
20+
def temp_zipfile(path: str | Path) -> Iterator[Path]:
21+
"""Create a temporary zip file."""
22+
p = Path(path)
23+
if not p.is_dir():
24+
raise ValueError(f"Path {p} is not a directory")
25+
26+
# Create a zip file from the directory
27+
zip_path = p.with_suffix(".zip")
28+
try:
29+
with zipfile.ZipFile(zip_path, "w", zipfile.ZIP_DEFLATED) as zipf:
30+
for file in p.rglob("*"): # Recursively add all files in the directory
31+
arcname = file.relative_to(p) # Preserve relative paths in the archive
32+
zipf.write(file, arcname)
33+
yield zip_path
34+
finally:
35+
# Clean up the zip file after shipping
36+
if zip_path.exists():
37+
zip_path.unlink()

poetry.lock

+22-22
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

pyproject.toml

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[tool.poetry]
22
name = "metablock"
3-
version = "1.0.1"
3+
version = "1.0.2"
44
description = "Metablock cloud python client"
55
authors = ["Luca <[email protected]>"]
66
license = "BSD"

readme.md

+9
Original file line numberDiff line numberDiff line change
@@ -34,3 +34,12 @@ alternatively, you can pass it to the client constructor:
3434
```python
3535
cli = Metablock(auth_key="your-token")
3636
```
37+
38+
39+
## Command line
40+
41+
You can also use the client from the command line
42+
43+
```bash
44+
metablock --help
45+
```

tests/conftest.py

+5
Original file line numberDiff line numberDiff line change
@@ -17,3 +17,8 @@ def invalid_headers(cli):
1717
@pytest.fixture
1818
async def org(cli: Metablock):
1919
return await cli.orgs.get("metablock")
20+
21+
22+
@pytest.fixture
23+
def ship_block_id():
24+
return "d90de3e3435d4c93b1d1c3a3c6888075"

tests/test_cli.py

+12
Original file line numberDiff line numberDiff line change
@@ -22,3 +22,15 @@ def test_cli_apply():
2222
result = runner.invoke(main, ["apply", "tests/blocks", "--space", "mblock"])
2323
assert result.exit_code == 0
2424
assert result.output.endswith("updated block test\n")
25+
26+
27+
def test_cli_ship(ship_block_id: str):
28+
runner = CliRunner()
29+
result = runner.invoke(
30+
main,
31+
["ship", "tests/blocks", "--block-id", ship_block_id, "--name", "just a test"],
32+
)
33+
assert result.exit_code == 0
34+
lines = result.output.splitlines()
35+
assert lines[0] == "Created zip file: tests/blocks.zip"
36+
assert lines[1] == "shipped tests/blocks.zip to test prod"

0 commit comments

Comments
 (0)