envrcctl 0.2.4__tar.gz → 0.2.6__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.
- {envrcctl-0.2.4 → envrcctl-0.2.6}/PKG-INFO +1 -1
- {envrcctl-0.2.4 → envrcctl-0.2.6}/pyproject.toml +1 -1
- {envrcctl-0.2.4 → envrcctl-0.2.6}/scripts/release_artifacts.py +103 -1
- {envrcctl-0.2.4 → envrcctl-0.2.6}/.gitignore +0 -0
- {envrcctl-0.2.4 → envrcctl-0.2.6}/LICENSE +0 -0
- {envrcctl-0.2.4 → envrcctl-0.2.6}/README.md +0 -0
- {envrcctl-0.2.4 → envrcctl-0.2.6}/completions/envrcctl.bash +0 -0
- {envrcctl-0.2.4 → envrcctl-0.2.6}/completions/envrcctl.fish +0 -0
- {envrcctl-0.2.4 → envrcctl-0.2.6}/completions/envrcctl.zsh +0 -0
- {envrcctl-0.2.4 → envrcctl-0.2.6}/scripts/build_macos_auth_helper.sh +0 -0
- {envrcctl-0.2.4 → envrcctl-0.2.6}/scripts/generate_completions.py +0 -0
- {envrcctl-0.2.4 → envrcctl-0.2.6}/scripts/macos/envrcctl-macos-auth.swift +0 -0
- {envrcctl-0.2.4 → envrcctl-0.2.6}/scripts/package_for_ship.sh +0 -0
- {envrcctl-0.2.4 → envrcctl-0.2.6}/src/envrcctl/__init__.py +0 -0
- {envrcctl-0.2.4 → envrcctl-0.2.6}/src/envrcctl/audit.py +0 -0
- {envrcctl-0.2.4 → envrcctl-0.2.6}/src/envrcctl/auth.py +0 -0
- {envrcctl-0.2.4 → envrcctl-0.2.6}/src/envrcctl/cli.py +0 -0
- {envrcctl-0.2.4 → envrcctl-0.2.6}/src/envrcctl/command_runner.py +0 -0
- {envrcctl-0.2.4 → envrcctl-0.2.6}/src/envrcctl/envrc.py +0 -0
- {envrcctl-0.2.4 → envrcctl-0.2.6}/src/envrcctl/envrcctl-macos-auth.bak +0 -0
- {envrcctl-0.2.4 → envrcctl-0.2.6}/src/envrcctl/errors.py +0 -0
- {envrcctl-0.2.4 → envrcctl-0.2.6}/src/envrcctl/keychain.py +0 -0
- {envrcctl-0.2.4 → envrcctl-0.2.6}/src/envrcctl/main.py +0 -0
- {envrcctl-0.2.4 → envrcctl-0.2.6}/src/envrcctl/managed_block.py +0 -0
- {envrcctl-0.2.4 → envrcctl-0.2.6}/src/envrcctl/secrets.py +0 -0
- {envrcctl-0.2.4 → envrcctl-0.2.6}/src/envrcctl/secretservice.py +0 -0
- {envrcctl-0.2.4 → envrcctl-0.2.6}/tests/__init__.py +0 -0
- {envrcctl-0.2.4 → envrcctl-0.2.6}/tests/conftest.py +0 -0
- {envrcctl-0.2.4 → envrcctl-0.2.6}/tests/helpers/__init__.py +0 -0
- {envrcctl-0.2.4 → envrcctl-0.2.6}/tests/helpers/cli_support.py +0 -0
- {envrcctl-0.2.4 → envrcctl-0.2.6}/tests/test_audit.py +0 -0
- {envrcctl-0.2.4 → envrcctl-0.2.6}/tests/test_audit_cli.py +0 -0
- {envrcctl-0.2.4 → envrcctl-0.2.6}/tests/test_auth.py +0 -0
- {envrcctl-0.2.4 → envrcctl-0.2.6}/tests/test_cli.py +0 -0
- {envrcctl-0.2.4 → envrcctl-0.2.6}/tests/test_cli_doctor.py +0 -0
- {envrcctl-0.2.4 → envrcctl-0.2.6}/tests/test_cli_errors.py +0 -0
- {envrcctl-0.2.4 → envrcctl-0.2.6}/tests/test_cli_eval.py +0 -0
- {envrcctl-0.2.4 → envrcctl-0.2.6}/tests/test_cli_exec.py +0 -0
- {envrcctl-0.2.4 → envrcctl-0.2.6}/tests/test_cli_helpers.py +0 -0
- {envrcctl-0.2.4 → envrcctl-0.2.6}/tests/test_cli_inject.py +0 -0
- {envrcctl-0.2.4 → envrcctl-0.2.6}/tests/test_cli_migrate.py +0 -0
- {envrcctl-0.2.4 → envrcctl-0.2.6}/tests/test_cli_secret_get.py +0 -0
- {envrcctl-0.2.4 → envrcctl-0.2.6}/tests/test_cli_secret_list.py +0 -0
- {envrcctl-0.2.4 → envrcctl-0.2.6}/tests/test_cli_secret_set_unset.py +0 -0
- {envrcctl-0.2.4 → envrcctl-0.2.6}/tests/test_command_runner.py +0 -0
- {envrcctl-0.2.4 → envrcctl-0.2.6}/tests/test_envrc.py +0 -0
- {envrcctl-0.2.4 → envrcctl-0.2.6}/tests/test_keychain.py +0 -0
- {envrcctl-0.2.4 → envrcctl-0.2.6}/tests/test_main.py +0 -0
- {envrcctl-0.2.4 → envrcctl-0.2.6}/tests/test_managed_block.py +0 -0
- {envrcctl-0.2.4 → envrcctl-0.2.6}/tests/test_secrets.py +0 -0
- {envrcctl-0.2.4 → envrcctl-0.2.6}/tests/test_secretservice.py +0 -0
- {envrcctl-0.2.4 → envrcctl-0.2.6}/tests/test_smoke.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: envrcctl
|
|
3
|
-
Version: 0.2.
|
|
3
|
+
Version: 0.2.6
|
|
4
4
|
Summary: Manage .envrc with managed blocks and OS-backed secrets.
|
|
5
5
|
Project-URL: Homepage, https://github.com/rioriost/envrcctl
|
|
6
6
|
Project-URL: Issues, https://github.com/rioriost/envrcctl/issues
|
|
@@ -3,6 +3,7 @@ from __future__ import annotations
|
|
|
3
3
|
|
|
4
4
|
import argparse
|
|
5
5
|
import hashlib
|
|
6
|
+
import re
|
|
6
7
|
import shutil
|
|
7
8
|
import subprocess
|
|
8
9
|
import sys
|
|
@@ -40,6 +41,87 @@ def project_version(pyproject_path: Path) -> str:
|
|
|
40
41
|
raise RuntimeError(f"Could not find project version in {pyproject_path}")
|
|
41
42
|
|
|
42
43
|
|
|
44
|
+
def project_dependencies(pyproject_path: Path) -> list[str]:
|
|
45
|
+
text = pyproject_path.read_text(encoding="utf-8")
|
|
46
|
+
match = re.search(r"(?ms)^\[project\]\n.*?^dependencies\s*=\s*\[(.*?)\]", text)
|
|
47
|
+
if not match:
|
|
48
|
+
return []
|
|
49
|
+
|
|
50
|
+
dependencies: list[str] = []
|
|
51
|
+
for raw_line in match.group(1).splitlines():
|
|
52
|
+
stripped = raw_line.strip().rstrip(",")
|
|
53
|
+
if not stripped:
|
|
54
|
+
continue
|
|
55
|
+
if stripped.startswith('"') and stripped.endswith('"'):
|
|
56
|
+
dependencies.append(stripped[1:-1])
|
|
57
|
+
elif stripped.startswith("'") and stripped.endswith("'"):
|
|
58
|
+
dependencies.append(stripped[1:-1])
|
|
59
|
+
return dependencies
|
|
60
|
+
|
|
61
|
+
|
|
62
|
+
def normalize_package_name(name: str) -> str:
|
|
63
|
+
return re.sub(r"[-_.]+", "-", name).lower()
|
|
64
|
+
|
|
65
|
+
|
|
66
|
+
def dependency_name(requirement: str) -> str:
|
|
67
|
+
base = re.split(r"[<>=!~;\[\]\s]", requirement, maxsplit=1)[0]
|
|
68
|
+
if not base:
|
|
69
|
+
raise RuntimeError(f"Could not parse dependency requirement: {requirement}")
|
|
70
|
+
return normalize_package_name(base)
|
|
71
|
+
|
|
72
|
+
|
|
73
|
+
def uv_lock_package_block(lock_text: str, package_name: str) -> str:
|
|
74
|
+
normalized = normalize_package_name(package_name)
|
|
75
|
+
current: list[str] = []
|
|
76
|
+
in_package = False
|
|
77
|
+
|
|
78
|
+
for line in lock_text.splitlines():
|
|
79
|
+
if line == "[[package]]":
|
|
80
|
+
if in_package:
|
|
81
|
+
block = "\n".join(current)
|
|
82
|
+
name_match = re.search(r'^name = "([^"]+)"$', block, re.MULTILINE)
|
|
83
|
+
if name_match and normalize_package_name(name_match.group(1)) == normalized:
|
|
84
|
+
return block
|
|
85
|
+
current = [line]
|
|
86
|
+
in_package = True
|
|
87
|
+
continue
|
|
88
|
+
|
|
89
|
+
if in_package:
|
|
90
|
+
current.append(line)
|
|
91
|
+
|
|
92
|
+
if in_package:
|
|
93
|
+
block = "\n".join(current)
|
|
94
|
+
name_match = re.search(r'^name = "([^"]+)"$', block, re.MULTILINE)
|
|
95
|
+
if name_match and normalize_package_name(name_match.group(1)) == normalized:
|
|
96
|
+
return block
|
|
97
|
+
|
|
98
|
+
raise RuntimeError(f"Package {package_name!r} not found in uv.lock")
|
|
99
|
+
|
|
100
|
+
|
|
101
|
+
def extract_sdist_url_and_sha(block: str, package_name: str) -> tuple[str, str]:
|
|
102
|
+
sdist_match = re.search(
|
|
103
|
+
r'sdist = \{ url = "([^"]+\.tar\.gz)", hash = "sha256:([0-9a-f]+)"',
|
|
104
|
+
block,
|
|
105
|
+
)
|
|
106
|
+
if sdist_match:
|
|
107
|
+
return sdist_match.group(1), sdist_match.group(2)
|
|
108
|
+
|
|
109
|
+
raise RuntimeError(f"Could not find sdist URL and sha256 for {package_name!r} in uv.lock")
|
|
110
|
+
|
|
111
|
+
|
|
112
|
+
def dependency_resource_specs(repo_root: Path) -> list[tuple[str, str, str]]:
|
|
113
|
+
lock_text = (repo_root / "uv.lock").read_text(encoding="utf-8")
|
|
114
|
+
specs: list[tuple[str, str, str]] = []
|
|
115
|
+
|
|
116
|
+
for requirement in project_dependencies(repo_root / "pyproject.toml"):
|
|
117
|
+
package_name = dependency_name(requirement)
|
|
118
|
+
block = uv_lock_package_block(lock_text, package_name)
|
|
119
|
+
url, sha256 = extract_sdist_url_and_sha(block, package_name)
|
|
120
|
+
specs.append((package_name, url, sha256))
|
|
121
|
+
|
|
122
|
+
return specs
|
|
123
|
+
|
|
124
|
+
|
|
43
125
|
def require_command(name: str) -> None:
|
|
44
126
|
if shutil.which(name) is None:
|
|
45
127
|
raise RuntimeError(f"Required command not found in PATH: {name}")
|
|
@@ -141,11 +223,26 @@ def formula_content(
|
|
|
141
223
|
helper_sha256: str,
|
|
142
224
|
homepage: str,
|
|
143
225
|
license_name: str,
|
|
226
|
+
dependency_resources: list[tuple[str, str, str]],
|
|
144
227
|
) -> str:
|
|
145
228
|
release_base = f"{homepage}/releases/download/{version}"
|
|
146
229
|
source_url = f"{release_base}/envrcctl-{version}.tar.gz"
|
|
147
230
|
helper_url = f"{release_base}/envrcctl-macos-auth-{version}-arm64.tar.gz"
|
|
148
231
|
|
|
232
|
+
resource_blocks = []
|
|
233
|
+
install_lines = []
|
|
234
|
+
for package_name, package_url, package_sha256 in dependency_resources:
|
|
235
|
+
resource_blocks.append(
|
|
236
|
+
f""" resource "{package_name}" do
|
|
237
|
+
url "{package_url}"
|
|
238
|
+
sha256 "{package_sha256}"
|
|
239
|
+
end"""
|
|
240
|
+
)
|
|
241
|
+
install_lines.append(f' venv.pip_install resource("{package_name}")')
|
|
242
|
+
|
|
243
|
+
resources_section = "\n\n".join(resource_blocks)
|
|
244
|
+
install_resources = "\n".join(install_lines)
|
|
245
|
+
|
|
149
246
|
return f"""class Envrcctl < Formula
|
|
150
247
|
include Language::Python::Virtualenv
|
|
151
248
|
|
|
@@ -157,6 +254,8 @@ def formula_content(
|
|
|
157
254
|
|
|
158
255
|
depends_on "python@3.12"
|
|
159
256
|
|
|
257
|
+
{resources_section}
|
|
258
|
+
|
|
160
259
|
on_macos do
|
|
161
260
|
on_arm do
|
|
162
261
|
resource "envrcctl-macos-auth-arm64" do
|
|
@@ -168,6 +267,7 @@ def formula_content(
|
|
|
168
267
|
|
|
169
268
|
def install
|
|
170
269
|
venv = virtualenv_create(libexec, "python3.12")
|
|
270
|
+
{install_resources}
|
|
171
271
|
venv.pip_install buildpath
|
|
172
272
|
|
|
173
273
|
bin.install_symlink libexec/"bin/envrcctl"
|
|
@@ -185,7 +285,7 @@ def formula_content(
|
|
|
185
285
|
|
|
186
286
|
test do
|
|
187
287
|
assert_predicate bin/"envrcctl", :exist?
|
|
188
|
-
assert_match version.to_s, shell_output("#{bin}/envrcctl --version")
|
|
288
|
+
assert_match version.to_s, shell_output("#{{bin}}/envrcctl --version")
|
|
189
289
|
if OS.mac? && Hardware::CPU.arm?
|
|
190
290
|
assert_predicate bin/"envrcctl-macos-auth", :exist?
|
|
191
291
|
end
|
|
@@ -255,6 +355,7 @@ def main() -> int:
|
|
|
255
355
|
|
|
256
356
|
source_sha256 = sha256_file(sdist_path)
|
|
257
357
|
helper_sha256 = sha256_file(helper_archive)
|
|
358
|
+
dependency_resources = dependency_resource_specs(repo_root)
|
|
258
359
|
|
|
259
360
|
formula_path = write_formula(
|
|
260
361
|
repo_root,
|
|
@@ -264,6 +365,7 @@ def main() -> int:
|
|
|
264
365
|
helper_sha256=helper_sha256,
|
|
265
366
|
homepage=args.homepage,
|
|
266
367
|
license_name=args.license_name,
|
|
368
|
+
dependency_resources=dependency_resources,
|
|
267
369
|
),
|
|
268
370
|
args.formula_dir,
|
|
269
371
|
)
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|