make-cloudflare 0.3.0__tar.gz → 0.4.0__tar.gz
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.
- {make_cloudflare-0.3.0 → make_cloudflare-0.4.0}/PKG-INFO +9 -2
- {make_cloudflare-0.3.0 → make_cloudflare-0.4.0}/README.md +8 -1
- {make_cloudflare-0.3.0 → make_cloudflare-0.4.0}/pyproject.toml +1 -1
- {make_cloudflare-0.3.0 → make_cloudflare-0.4.0}/src/make_cloudflare/__init__.py +1 -1
- {make_cloudflare-0.3.0 → make_cloudflare-0.4.0}/src/make_cloudflare/pages.py +48 -0
- {make_cloudflare-0.3.0 → make_cloudflare-0.4.0}/tests/test_pages.py +34 -0
- {make_cloudflare-0.3.0 → make_cloudflare-0.4.0}/.gitignore +0 -0
- {make_cloudflare-0.3.0 → make_cloudflare-0.4.0}/src/make_cloudflare/cloudflare.py +0 -0
- {make_cloudflare-0.3.0 → make_cloudflare-0.4.0}/tests/conftest.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.5
|
|
2
2
|
Name: make-cloudflare
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.4.0
|
|
4
4
|
Summary: Cloudflare Pages direct upload for mkrun -- deploy a built site with no Node and no wrangler.
|
|
5
5
|
Project-URL: Homepage, https://make.optersoft.com
|
|
6
6
|
Author-email: "Optersoft, S.L." <david@optersoft.com>
|
|
@@ -21,7 +21,7 @@ in the pipeline.
|
|
|
21
21
|
# Makefile.py in a consuming repo
|
|
22
22
|
# /// script
|
|
23
23
|
# requires-python = ">=3.11"
|
|
24
|
-
# dependencies = ["mkrun>=0.4", "make-cloudflare>=0.
|
|
24
|
+
# dependencies = ["mkrun>=0.4.1", "make-cloudflare>=0.3"]
|
|
25
25
|
# ///
|
|
26
26
|
from make_cloudflare import cloudflare # importing is what registers the group
|
|
27
27
|
```
|
|
@@ -62,6 +62,13 @@ site's own `_routes.json` wins. Everything else is still the four calls below.
|
|
|
62
62
|
Bindings (D1, KV) and secrets are settings on the Pages project, never part of
|
|
63
63
|
the upload.
|
|
64
64
|
|
|
65
|
+
**Those settings are one call.** `pages.configure(project, d1={"DB": "<id>"},
|
|
66
|
+
vars={...}, compatibility_date="2026-10-01")` PATCHes the project's
|
|
67
|
+
`production` (or `preview`) configuration. Only what you pass is sent, and
|
|
68
|
+
Cloudflare merges it in. It takes effect on the **next** deployment. Secrets
|
|
69
|
+
are not set this way: a plain variable is shown in the dashboard, so a secret
|
|
70
|
+
goes through `wrangler pages secret put`.
|
|
71
|
+
|
|
65
72
|
## Why this exists
|
|
66
73
|
|
|
67
74
|
`wrangler pages deploy` is four HTTPS calls and a hash. Reaching them through
|
|
@@ -8,7 +8,7 @@ in the pipeline.
|
|
|
8
8
|
# Makefile.py in a consuming repo
|
|
9
9
|
# /// script
|
|
10
10
|
# requires-python = ">=3.11"
|
|
11
|
-
# dependencies = ["mkrun>=0.4", "make-cloudflare>=0.
|
|
11
|
+
# dependencies = ["mkrun>=0.4.1", "make-cloudflare>=0.3"]
|
|
12
12
|
# ///
|
|
13
13
|
from make_cloudflare import cloudflare # importing is what registers the group
|
|
14
14
|
```
|
|
@@ -49,6 +49,13 @@ site's own `_routes.json` wins. Everything else is still the four calls below.
|
|
|
49
49
|
Bindings (D1, KV) and secrets are settings on the Pages project, never part of
|
|
50
50
|
the upload.
|
|
51
51
|
|
|
52
|
+
**Those settings are one call.** `pages.configure(project, d1={"DB": "<id>"},
|
|
53
|
+
vars={...}, compatibility_date="2026-10-01")` PATCHes the project's
|
|
54
|
+
`production` (or `preview`) configuration. Only what you pass is sent, and
|
|
55
|
+
Cloudflare merges it in. It takes effect on the **next** deployment. Secrets
|
|
56
|
+
are not set this way: a plain variable is shown in the dashboard, so a secret
|
|
57
|
+
goes through `wrangler pages secret put`.
|
|
58
|
+
|
|
52
59
|
## Why this exists
|
|
53
60
|
|
|
54
61
|
`wrangler pages deploy` is four HTTPS calls and a hash. Reaching them through
|
|
@@ -61,6 +61,7 @@ from make.errors import ConfigError, MakeError
|
|
|
61
61
|
__all__ = [
|
|
62
62
|
"Asset",
|
|
63
63
|
"build_functions",
|
|
64
|
+
"configure",
|
|
64
65
|
"collect",
|
|
65
66
|
"deploy",
|
|
66
67
|
"deployments",
|
|
@@ -494,6 +495,53 @@ def create_project(
|
|
|
494
495
|
return created if isinstance(created, dict) else {"name": project}
|
|
495
496
|
|
|
496
497
|
|
|
498
|
+
def configure(
|
|
499
|
+
project: str,
|
|
500
|
+
*,
|
|
501
|
+
d1: Mapping[str, str] | None = None,
|
|
502
|
+
vars: Mapping[str, str] | None = None,
|
|
503
|
+
compatibility_date: str | None = None,
|
|
504
|
+
compatibility_flags: Iterable[str] | None = None,
|
|
505
|
+
environment: str = "production",
|
|
506
|
+
account: str | None = None,
|
|
507
|
+
token: str | None = None,
|
|
508
|
+
) -> dict:
|
|
509
|
+
"""Set what a project's Functions run with; return the project as Cloudflare now has it.
|
|
510
|
+
|
|
511
|
+
`d1` maps a binding name to a D1 database id (`{"DB": "<uuid>"}`), `vars` sets plain
|
|
512
|
+
environment variables, and the compatibility date and flags pick the runtime.
|
|
513
|
+
`environment` is `production` or `preview`. Only what is passed is sent, and
|
|
514
|
+
Cloudflare merges it into what the project already has -- nothing unnamed is removed.
|
|
515
|
+
|
|
516
|
+
⚠ Settings take effect on the **next deployment**, never on the live one. Secrets are
|
|
517
|
+
not set here: a value sent this way is stored in plain text and shown in the dashboard,
|
|
518
|
+
so a secret goes through `wrangler pages secret put`.
|
|
519
|
+
"""
|
|
520
|
+
if environment not in ("production", "preview"):
|
|
521
|
+
raise MakeError(f"no Pages environment {environment!r}", hint="production or preview")
|
|
522
|
+
settings: dict[str, Any] = {}
|
|
523
|
+
if d1:
|
|
524
|
+
settings["d1_databases"] = {name: {"id": ident} for name, ident in d1.items()}
|
|
525
|
+
if vars:
|
|
526
|
+
settings["env_vars"] = {name: {"type": "plain_text", "value": value} for name, value in vars.items()}
|
|
527
|
+
if compatibility_date:
|
|
528
|
+
settings["compatibility_date"] = compatibility_date
|
|
529
|
+
if compatibility_flags is not None:
|
|
530
|
+
settings["compatibility_flags"] = list(compatibility_flags)
|
|
531
|
+
if not settings:
|
|
532
|
+
raise MakeError(f"nothing to set on {project}", hint="pass d1=, vars= or a compatibility date")
|
|
533
|
+
|
|
534
|
+
account, token = _credentials(account, token)
|
|
535
|
+
step(f"{project} ({environment}): " + ", ".join(sorted(settings)))
|
|
536
|
+
result = _json_call(
|
|
537
|
+
"PATCH",
|
|
538
|
+
f"{API}/accounts/{account}/pages/projects/{project}",
|
|
539
|
+
auth=token,
|
|
540
|
+
payload={"deployment_configs": {environment: settings}},
|
|
541
|
+
)
|
|
542
|
+
return result if isinstance(result, dict) else {"name": project}
|
|
543
|
+
|
|
544
|
+
|
|
497
545
|
def deployments(project: str, *, account: str | None = None, token: str | None = None) -> list[dict]:
|
|
498
546
|
"""A project's deployments, newest first -- every page of them.
|
|
499
547
|
|
|
@@ -423,3 +423,37 @@ def test_a_missing_functions_tree_is_named(monkeypatch, tmp_path):
|
|
|
423
423
|
site = build(tmp_path / "dist", {"index.html": "x"})
|
|
424
424
|
with pytest.raises(MakeError, match="not a directory"):
|
|
425
425
|
deploy(monkeypatch, site, FakeHTTP(), functions=tmp_path / "nope")
|
|
426
|
+
|
|
427
|
+
|
|
428
|
+
# -- project settings --------------------------------------------------------
|
|
429
|
+
|
|
430
|
+
|
|
431
|
+
def test_configure_patches_only_what_it_is_given(monkeypatch):
|
|
432
|
+
fake = FakeHTTP()
|
|
433
|
+
monkeypatch.setattr(pages.http, "request", fake)
|
|
434
|
+
pages.configure(
|
|
435
|
+
"demo",
|
|
436
|
+
d1={"DB": "uuid-1"},
|
|
437
|
+
vars={"ZONE": "example.dev"},
|
|
438
|
+
compatibility_date="2026-10-01",
|
|
439
|
+
account="acct",
|
|
440
|
+
token="tok",
|
|
441
|
+
)
|
|
442
|
+
method, url, call = fake.calls[0]
|
|
443
|
+
assert (method, url) == ("PATCH", f"{pages.API}/accounts/acct/pages/projects/demo")
|
|
444
|
+
assert json.loads(call["data"]) == {
|
|
445
|
+
"deployment_configs": {
|
|
446
|
+
"production": {
|
|
447
|
+
"d1_databases": {"DB": {"id": "uuid-1"}},
|
|
448
|
+
"env_vars": {"ZONE": {"type": "plain_text", "value": "example.dev"}},
|
|
449
|
+
"compatibility_date": "2026-10-01",
|
|
450
|
+
}
|
|
451
|
+
}
|
|
452
|
+
}
|
|
453
|
+
|
|
454
|
+
|
|
455
|
+
def test_configure_refuses_an_empty_or_unknown_request():
|
|
456
|
+
with pytest.raises(MakeError, match="nothing to set"):
|
|
457
|
+
pages.configure("demo", account="acct", token="tok")
|
|
458
|
+
with pytest.raises(MakeError, match="no Pages environment"):
|
|
459
|
+
pages.configure("demo", vars={"A": "1"}, environment="staging", account="acct", token="tok")
|
|
File without changes
|
|
File without changes
|
|
File without changes
|