sentry-devenv 1.19.0__py3-none-any.whl → 1.21.0__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.
- devenv/checks/{credsStore.py → dockerConfig.py} +11 -1
- devenv/lib/archive.py +53 -44
- devenv/lib/colima.py +1 -1
- devenv/lib/docker.py +2 -2
- devenv/lib/gcloud.py +1 -1
- devenv/lib/limactl.py +1 -1
- devenv/lib/node.py +2 -2
- devenv/lib/tenv.py +1 -1
- devenv/lib/venv.py +1 -1
- devenv/main.py +1 -1
- {sentry_devenv-1.19.0.dist-info → sentry_devenv-1.21.0.dist-info}/METADATA +15 -6
- {sentry_devenv-1.19.0.dist-info → sentry_devenv-1.21.0.dist-info}/RECORD +17 -17
- {sentry_devenv-1.19.0.dist-info → sentry_devenv-1.21.0.dist-info}/WHEEL +1 -1
- tests/checks/{test_credStore.py → test_dockerConfig.py} +12 -6
- tests/lib/test_archive.py +59 -2
- {sentry_devenv-1.19.0.dist-info → sentry_devenv-1.21.0.dist-info}/entry_points.txt +0 -0
- {sentry_devenv-1.19.0.dist-info → sentry_devenv-1.21.0.dist-info}/top_level.txt +0 -0
|
@@ -8,7 +8,7 @@ from devenv.lib_check.types import checker
|
|
|
8
8
|
from devenv.lib_check.types import fixer
|
|
9
9
|
|
|
10
10
|
tags: set[str] = {"builtin"}
|
|
11
|
-
name = "
|
|
11
|
+
name = "correct docker configuration"
|
|
12
12
|
|
|
13
13
|
|
|
14
14
|
@checker
|
|
@@ -23,6 +23,15 @@ def check() -> tuple[bool, str]:
|
|
|
23
23
|
if store and not shutil.which(f"docker-credential-{store}"):
|
|
24
24
|
return False, "credsStore requires nonexistent binary"
|
|
25
25
|
|
|
26
|
+
# When docker-buildx is installed via brew, brew adds cliPluginsExtraDirs
|
|
27
|
+
# which takes precedence over the default plugin path we rely on.
|
|
28
|
+
# This ensures the devenv-managed global docker cli uses the default plugin path.
|
|
29
|
+
if config.get("cliPluginsExtraDirs"):
|
|
30
|
+
return (
|
|
31
|
+
False,
|
|
32
|
+
"cliPluginsExtraDirs exists, which overshadows the default plugin path",
|
|
33
|
+
)
|
|
34
|
+
|
|
26
35
|
return True, ""
|
|
27
36
|
|
|
28
37
|
|
|
@@ -33,6 +42,7 @@ def fix() -> tuple[bool, str]:
|
|
|
33
42
|
config = json.load(f)
|
|
34
43
|
|
|
35
44
|
config.pop("credsStore", None)
|
|
45
|
+
config.pop("cliPluginsExtraDirs", None)
|
|
36
46
|
|
|
37
47
|
with open(os.path.expanduser("~/.docker/config.json"), "w") as f:
|
|
38
48
|
json.dump(config, f)
|
devenv/lib/archive.py
CHANGED
|
@@ -38,51 +38,60 @@ def download(
|
|
|
38
38
|
dest = f"{cache_root}/{sha256}"
|
|
39
39
|
os.makedirs(cache_root, exist_ok=True)
|
|
40
40
|
|
|
41
|
-
if
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
41
|
+
if os.path.islink(dest):
|
|
42
|
+
# there are cases where dest can be an existing symlink
|
|
43
|
+
# (docker desktop starts and puts symlinks into ~/.docker/cli-plugins)
|
|
44
|
+
# such symlinks should be removed otherwise callers to download
|
|
45
|
+
# usually try to chmod after and end up with PermissionError
|
|
46
|
+
os.remove(dest)
|
|
47
|
+
|
|
48
|
+
if os.path.exists(dest):
|
|
49
|
+
return dest
|
|
50
|
+
|
|
51
|
+
headers = {}
|
|
52
|
+
if url.startswith("https://ghcr.io/v2/homebrew"):
|
|
53
|
+
# downloading homebrew blobs requires auth
|
|
54
|
+
# you can get an anonymous token from https://ghcr.io/token?service=ghcr.io&scope=repository%3Ahomebrew/core/go%3Apull
|
|
55
|
+
# but there's also a special shortcut token QQ==
|
|
56
|
+
# https://github.com/Homebrew/brew/blob/2184406bd8444e4de2626f5b0c749d4d08cb1aed/Library/Homebrew/brew.sh#L993
|
|
57
|
+
headers["Authorization"] = "bearer QQ=="
|
|
58
|
+
|
|
59
|
+
req = urllib.request.Request(url, headers=headers)
|
|
60
|
+
|
|
61
|
+
retry_sleep = 1.0
|
|
62
|
+
while retries >= 0:
|
|
63
|
+
try:
|
|
64
|
+
resp = urllib.request.urlopen(req)
|
|
65
|
+
break
|
|
66
|
+
except HTTPError as e:
|
|
67
|
+
if retries == 0:
|
|
68
|
+
raise RuntimeError(f"Error getting {url}: {e}")
|
|
69
|
+
print(f"Error getting {url} ({retries} retries left): {e}")
|
|
70
|
+
|
|
71
|
+
time.sleep(retry_sleep)
|
|
72
|
+
retries -= 1
|
|
73
|
+
retry_sleep *= retry_exp
|
|
74
|
+
|
|
75
|
+
dest_dir = os.path.dirname(dest)
|
|
76
|
+
os.makedirs(dest_dir, exist_ok=True)
|
|
77
|
+
|
|
78
|
+
with tempfile.NamedTemporaryFile(delete=False, dir=dest_dir) as tmpf:
|
|
79
|
+
shutil.copyfileobj(resp, tmpf)
|
|
80
|
+
tmpf.seek(0)
|
|
81
|
+
checksum = hashlib.sha256()
|
|
82
|
+
buf = tmpf.read(4096)
|
|
83
|
+
while buf:
|
|
84
|
+
checksum.update(buf)
|
|
73
85
|
buf = tmpf.read(4096)
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
)
|
|
84
|
-
|
|
85
|
-
atomic_replace(tmpf.name, dest)
|
|
86
|
+
|
|
87
|
+
if not secrets.compare_digest(checksum.hexdigest(), sha256):
|
|
88
|
+
raise RuntimeError(
|
|
89
|
+
f"checksum mismatch for {url}:\n"
|
|
90
|
+
f"- got: {checksum.hexdigest()}\n"
|
|
91
|
+
f"- expected: {sha256}\n"
|
|
92
|
+
)
|
|
93
|
+
|
|
94
|
+
atomic_replace(tmpf.name, dest)
|
|
86
95
|
|
|
87
96
|
return dest
|
|
88
97
|
|
devenv/lib/colima.py
CHANGED
|
@@ -78,7 +78,7 @@ def install_global() -> None:
|
|
|
78
78
|
installed_version = stdout.strip().split()[-1]
|
|
79
79
|
if version == installed_version:
|
|
80
80
|
return
|
|
81
|
-
print(f"installed colima {installed_version} is
|
|
81
|
+
print(f"installed colima {installed_version} is unexpected!")
|
|
82
82
|
|
|
83
83
|
print(f"installing colima {version}...")
|
|
84
84
|
uninstall(binroot)
|
devenv/lib/docker.py
CHANGED
|
@@ -101,7 +101,7 @@ def _check_buildx(binroot: str, expected_version: str) -> bool:
|
|
|
101
101
|
return True
|
|
102
102
|
|
|
103
103
|
print(
|
|
104
|
-
f"installed docker-buildx {installed_version} is
|
|
104
|
+
f"installed docker-buildx {installed_version} is unexpected! expected: {expected_version}"
|
|
105
105
|
)
|
|
106
106
|
return False
|
|
107
107
|
|
|
@@ -133,7 +133,7 @@ def install_global() -> None:
|
|
|
133
133
|
stdout = proc.run((f"{binroot}/docker", "--version"), stdout=True)
|
|
134
134
|
installed_version = stdout.strip().split()[2][:-1]
|
|
135
135
|
if version != installed_version:
|
|
136
|
-
print(f"installed docker {installed_version} is
|
|
136
|
+
print(f"installed docker {installed_version} is unexpected!")
|
|
137
137
|
print(f"installing docker (cli, not desktop) {version}...")
|
|
138
138
|
uninstall(binroot)
|
|
139
139
|
_install(
|
devenv/lib/gcloud.py
CHANGED
|
@@ -82,7 +82,7 @@ def install(version: str, url: str, sha256: str, reporoot: str) -> None:
|
|
|
82
82
|
installed_version = f.read().strip()
|
|
83
83
|
if version == installed_version:
|
|
84
84
|
return
|
|
85
|
-
print(f"installed gcloud {installed_version} is
|
|
85
|
+
print(f"installed gcloud {installed_version} is unexpected!")
|
|
86
86
|
|
|
87
87
|
print(f"installing gcloud {version}...")
|
|
88
88
|
uninstall(binroot)
|
devenv/lib/limactl.py
CHANGED
|
@@ -91,7 +91,7 @@ def install_global() -> None:
|
|
|
91
91
|
installed_version = stdout.strip().split()[-1]
|
|
92
92
|
if version == installed_version:
|
|
93
93
|
return
|
|
94
|
-
print(f"installed limactl {installed_version} is
|
|
94
|
+
print(f"installed limactl {installed_version} is unexpected!")
|
|
95
95
|
|
|
96
96
|
uninstall(binroot)
|
|
97
97
|
_install(cfg[SYSTEM_MACHINE], cfg[f"{SYSTEM_MACHINE}_sha256"], binroot)
|
devenv/lib/node.py
CHANGED
|
@@ -67,7 +67,7 @@ def installed(version: str, binroot: str) -> bool:
|
|
|
67
67
|
if version == installed_version:
|
|
68
68
|
return True
|
|
69
69
|
|
|
70
|
-
print(f"installed node {installed_version} is
|
|
70
|
+
print(f"installed node {installed_version} is unexpected!")
|
|
71
71
|
return False
|
|
72
72
|
|
|
73
73
|
|
|
@@ -118,7 +118,7 @@ def installed_yarn(version: str, binroot: str) -> bool:
|
|
|
118
118
|
if version == installed_version:
|
|
119
119
|
return True
|
|
120
120
|
|
|
121
|
-
print(f"installed yarn {installed_version} is
|
|
121
|
+
print(f"installed yarn {installed_version} is unexpected!")
|
|
122
122
|
return False
|
|
123
123
|
|
|
124
124
|
|
devenv/lib/tenv.py
CHANGED
|
@@ -88,7 +88,7 @@ def install(version: str, url: str, sha256: str, reporoot: str) -> None:
|
|
|
88
88
|
installed_version = _version(binpath)
|
|
89
89
|
if version == installed_version:
|
|
90
90
|
return
|
|
91
|
-
print(f"installed tenv {installed_version} is
|
|
91
|
+
print(f"installed tenv {installed_version} is unexpected!")
|
|
92
92
|
|
|
93
93
|
print(f"installing tenv {version}...")
|
|
94
94
|
uninstall(binroot)
|
devenv/lib/venv.py
CHANGED
|
@@ -106,7 +106,7 @@ def ensure(venv: str, python_version: str, url: str, sha256: str) -> None:
|
|
|
106
106
|
return
|
|
107
107
|
|
|
108
108
|
print(
|
|
109
|
-
f"virtualenv doesn't exist or is using an
|
|
109
|
+
f"virtualenv doesn't exist or is using an unexpected python, recreating at {venv}..."
|
|
110
110
|
)
|
|
111
111
|
if os.path.exists(venv):
|
|
112
112
|
shutil.rmtree(venv)
|
devenv/main.py
CHANGED
|
@@ -103,7 +103,7 @@ def main() -> ExitCode:
|
|
|
103
103
|
# https://sentry.sentry.io/settings/projects/sentry-dev-env/keys/
|
|
104
104
|
dsn="https://9bdb053cb8274ea69231834d1edeec4c@o1.ingest.sentry.io/5723503",
|
|
105
105
|
# enable performance monitoring
|
|
106
|
-
|
|
106
|
+
traces_sample_rate=1.0,
|
|
107
107
|
)
|
|
108
108
|
|
|
109
109
|
return devenv(sys.argv, f"{home}/.config/sentry-devenv/config.ini")
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: sentry_devenv
|
|
3
|
-
Version: 1.
|
|
3
|
+
Version: 1.21.0
|
|
4
4
|
Summary: Utilities for setting up a Sentry development environment
|
|
5
5
|
Author-email: Joshua Li <joshua.li@sentry.io>, Ian Woodard <ian.woodard@sentry.io>, Buck Evan <buck.evan@sentry.io>
|
|
6
6
|
Classifier: Programming Language :: Python :: 3
|
|
@@ -47,7 +47,6 @@ To update this installation, run `devenv update`.
|
|
|
47
47
|
|
|
48
48
|
This is intended for initial setup of a new machine.
|
|
49
49
|
|
|
50
|
-
|
|
51
50
|
`devenv fetch [repository name]`
|
|
52
51
|
|
|
53
52
|
Any repository on github in the form of `[org]/[reponame]`
|
|
@@ -71,7 +70,6 @@ In general, our library is designed to isolate, as much as possible, a repo's de
|
|
|
71
70
|
For example, [gcloud](#gcloud) is installed to `[reporoot]/.devenv/bin/gcloud` (with the gcloud sdk at `[reporoot]/.devenv/bin/google-cloud-sdk`).
|
|
72
71
|
An exception to this would be python virtualenvs, which was implemented before the idea of `[reporoot]/.devenv`.
|
|
73
72
|
|
|
74
|
-
|
|
75
73
|
`devenv doctor`
|
|
76
74
|
|
|
77
75
|
Use this to diagnose and fix common issues.
|
|
@@ -79,14 +77,25 @@ Use this to diagnose and fix common issues.
|
|
|
79
77
|
Repo-specific checks and fixes can be defined in `[reporoot]/devenv/checks`.
|
|
80
78
|
Otherwise we have "builtin" checks and fixes in `devenv.checks`.
|
|
81
79
|
|
|
80
|
+
`devenv update`
|
|
81
|
+
|
|
82
|
+
This updates the global devenv installation, and global tools.
|
|
83
|
+
|
|
84
|
+
If you're upgrading from a particularly old devenv, it won't have `update` so you need to:
|
|
85
|
+
`~/.local/share/sentry-devenv/venv/bin/pip install -U sentry-devenv`
|
|
86
|
+
|
|
82
87
|
|
|
83
88
|
## technical overview
|
|
84
89
|
|
|
85
90
|
Everything devenv needs is in `~/.local/share/sentry-devenv`.
|
|
86
91
|
|
|
87
|
-
- `~/.local/share/sentry-devenv/bin` contains
|
|
88
|
-
-
|
|
89
|
-
-
|
|
92
|
+
- `~/.local/share/sentry-devenv/bin` contains:
|
|
93
|
+
- `devenv` itself
|
|
94
|
+
- `direnv`
|
|
95
|
+
- we currently rely on direnv and a minimal [`[reporoot]/.envrc`](#direnv) to add `[reporoot]/.devenv/bin` to PATH
|
|
96
|
+
- see [examples](#examples) for .envrc suggestions
|
|
97
|
+
- global tools: `docker` (cli), `colima`
|
|
98
|
+
|
|
90
99
|
|
|
91
100
|
### runtime
|
|
92
101
|
|
|
@@ -6,36 +6,36 @@ devenv/colima.py,sha256=Dk9t6eu2DEoqqkY8xLmgiB96r-6zi3aXcvON3P8h1JQ,1537
|
|
|
6
6
|
devenv/constants.py,sha256=wl0sRfkNeJL-sML6MG5nS0zU-dwRo1mDPrhUSHHY1YQ,1498
|
|
7
7
|
devenv/doctor.py,sha256=tcwXrE2Y7Ued2gAXCXtfFkyXbG9DOi6jVobbq6DnuZs,8663
|
|
8
8
|
devenv/fetch.py,sha256=MbztGFOzBR4KDPG0TVWcQsA4pGXk61zrQXvh-C9xHuk,3904
|
|
9
|
-
devenv/main.py,sha256=
|
|
9
|
+
devenv/main.py,sha256=grOHjy0kUJjeGW8STg-WMneVYlkTRVMoFjNdIgt7sjg,3267
|
|
10
10
|
devenv/pin_gha.py,sha256=t7A5CV1bnYRa4SAikuoJeodHuwV6moIePvhQ1Zdc1eE,2187
|
|
11
11
|
devenv/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
12
12
|
devenv/pythons.py,sha256=ZcjBrkfmQEkiMP217VyTG48cyteJdYG_hoQ6oFKx_CU,1252
|
|
13
13
|
devenv/sync.py,sha256=B9bvAuI7K-4SqcfHD4_zwKpozAnHWCNOL-IhVOcc3Zg,1254
|
|
14
14
|
devenv/update.py,sha256=CkshQUvmVVblXdjARgWQKXSe7pwMjSMrPR3gDEesX5c,2402
|
|
15
15
|
devenv/checks/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
16
|
-
devenv/checks/
|
|
16
|
+
devenv/checks/dockerConfig.py,sha256=5VExtcarjizPhR7OSdyWhkvzS6zY-6qiefxlwkexQuk,1623
|
|
17
17
|
devenv/checks/dockerDesktop.py,sha256=ynt8nNQ2DDT2rJDGZ-g7xxc4HErHJV_iqBqYHQtvA7Q,1343
|
|
18
18
|
devenv/checks/limaDns.py,sha256=cHef2czdYYLvQqiM4bxiYtzYw4UVTIXJPwrGW2Kjpxo,1885
|
|
19
19
|
devenv/checks/test.py,sha256=AvxoA2W5qTO2ZpoXmjScLiJxXD3Y_limYp5yTjGSZ9U,701
|
|
20
20
|
devenv/lib/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
21
|
-
devenv/lib/archive.py,sha256=
|
|
21
|
+
devenv/lib/archive.py,sha256=75MjlDuwHVaazbNUr8vJmqTyl4Jz6KRd_fUcpwvPwec,4710
|
|
22
22
|
devenv/lib/brew.py,sha256=_7recvYh-LnUJC0eKnYK7F8AzGRL5bi_Khv0f_mgrlM,1795
|
|
23
|
-
devenv/lib/colima.py,sha256=
|
|
23
|
+
devenv/lib/colima.py,sha256=fVzM8jCN06HAkJd3dTz3CXXlpGoykkAe-Ln8RgYb2QU,7383
|
|
24
24
|
devenv/lib/config.py,sha256=5eXYwM44AJ3w2VfVbCDqchYOL1zAjazNcirtM6kxxGw,3344
|
|
25
25
|
devenv/lib/context.py,sha256=4EDImK9pvTp3FqeNigevC9lbJsgdDO9D1t2_Y4NyPlc,207
|
|
26
26
|
devenv/lib/direnv.py,sha256=HDRUaIR0PMAQYiiTaw3gEQuh6Tdb7BUJmV7dBZdPztM,1325
|
|
27
|
-
devenv/lib/docker.py,sha256=
|
|
27
|
+
devenv/lib/docker.py,sha256=d-jGdagfvxGpZtfoEG_m6IMcm8YvUEjJoHx0ACKNWKk,5688
|
|
28
28
|
devenv/lib/fs.py,sha256=IBahQ9fB-o9cK9HipK_L0gso2OVinIDTxFWoeMte9ww,2764
|
|
29
|
-
devenv/lib/gcloud.py,sha256=
|
|
29
|
+
devenv/lib/gcloud.py,sha256=pJ28_L0gUS1lZna-gIHeJPo9bEfSHVXh63CoRQGyAw8,3552
|
|
30
30
|
devenv/lib/github.py,sha256=AMtcz6gTVKy7qvCP1zTUdHQlnSM32TVaji0aOXJ_F9A,3463
|
|
31
|
-
devenv/lib/limactl.py,sha256=
|
|
31
|
+
devenv/lib/limactl.py,sha256=wMA_Q4DRPjmBPe0JSj1xPwYesFa9MT_vVSdaBAAKn5w,4256
|
|
32
32
|
devenv/lib/modules.py,sha256=shoqgja0b-xzXr601Ryz0JOy3Vxbw53I3cRYezVt77g,859
|
|
33
|
-
devenv/lib/node.py,sha256=
|
|
33
|
+
devenv/lib/node.py,sha256=sp5QbExF0H03UnfLUmFown42_NhyPWKw0H776W7987U,4160
|
|
34
34
|
devenv/lib/proc.py,sha256=eU7DHIk_66wgkHRmdtKbBKZTa6q4tl9QJbrlnQOQCls,2743
|
|
35
35
|
devenv/lib/repository.py,sha256=cDCgcZ6lw0bcWC6DrcDp3tz_MWObmgAyFq39TeU7YHY,1966
|
|
36
36
|
devenv/lib/rosetta.py,sha256=Lm-tDFut86o6l-Y55d5kTacRHTwrv5MFEymQpy7Qihc,1170
|
|
37
|
-
devenv/lib/tenv.py,sha256=
|
|
38
|
-
devenv/lib/venv.py,sha256=
|
|
37
|
+
devenv/lib/tenv.py,sha256=EulO1xYh8wu6-QoDvQd3TVbaLvmztXqCV6ya5sBWZiw,3030
|
|
38
|
+
devenv/lib/venv.py,sha256=1HWY1uFXLP1YCGVX7Ik5R3tNilRCKrVXOZN42-k_5eQ,3188
|
|
39
39
|
devenv/lib_check/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
40
40
|
devenv/lib_check/brew.py,sha256=tId1IgItju-fulbmTXmmI2Oo_-q332rd1tUN5RSkTrs,544
|
|
41
41
|
devenv/lib_check/types.py,sha256=HIvuU3q27Izgm77jH6QX6gKMvgfunx05X4OEsJoqjP8,271
|
|
@@ -46,7 +46,7 @@ tests/test_pythons.py,sha256=Nepff11shv18irF3EYzf3U6zsRMrpLeS8QfrGJ3bTME,723
|
|
|
46
46
|
tests/test_sync.py,sha256=ihCYFxscPwbVY_cnFyq2fvYUBc_SyB6gsElz334fmaw,871
|
|
47
47
|
tests/utils.py,sha256=Qr2RM5Vo-14mF8tPSJITiYuhGc6fU9rk-fChxW-lokk,291
|
|
48
48
|
tests/checks/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
49
|
-
tests/checks/
|
|
49
|
+
tests/checks/test_dockerConfig.py,sha256=wJQ1ADdG4HJCQyiTirUk5VsEAUfhlSDWCJfW_ylH5po,1702
|
|
50
50
|
tests/doctor/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
51
51
|
tests/doctor/test_attempt_fix.py,sha256=cGUv7-xRKWCizC9cNNqiCp7aa95k3nHUXvRFFuLfJ34,1075
|
|
52
52
|
tests/doctor/test_filter_failing_checks.py,sha256=5L5XdBSyeySwZtJeAR71lbktt3NxkJdUfncKBJPYdAc,1270
|
|
@@ -63,7 +63,7 @@ tests/doctor/devenv/checks/no_check.py,sha256=hcX2CNzB07U7r6KHbW71IvsW7UG-JsHcji
|
|
|
63
63
|
tests/doctor/devenv/checks/no_name.py,sha256=txJhaXiJjY4CUPONTX9G6J6RttTCJ-BupDmZT1sKoAc,167
|
|
64
64
|
tests/doctor/devenv/checks/no_tags.py,sha256=ATwlSsn5fe-OwNfgEDDa0HiBoOgkOGwkqIbQuDaghpk,161
|
|
65
65
|
tests/doctor/devenv/checks/passing_check.py,sha256=F-gW4ZEqXVBL5akMaR3Hcf3yuihm3jfxTY80-EqsbOg,307
|
|
66
|
-
tests/lib/test_archive.py,sha256=
|
|
66
|
+
tests/lib/test_archive.py,sha256=4yWoB0ZBpGLQByutPAOEVjUYSBlWdZppvRofYqX3pjk,9370
|
|
67
67
|
tests/lib/test_brew.py,sha256=g2Sz-yg4-212qlsKg0vfHf604bQyRjUElsf3khvXrTQ,5711
|
|
68
68
|
tests/lib/test_direnv.py,sha256=GKpEbsHgaRZWevYrsa0oOGQFCsyllCLX1vGdg3igvAc,1551
|
|
69
69
|
tests/lib/test_fs.py,sha256=qhX9CQTTSht1f6ZJfmpsSFICTwPs--h_mLlS_1jnZQg,1670
|
|
@@ -71,8 +71,8 @@ tests/lib/test_github.py,sha256=IMEG2cmRaK_PMJprFE_ZMqPnZ0StwWqgznhhT_zVk3U,4526
|
|
|
71
71
|
tests/lib/test_proc.py,sha256=XH6OnxKPSSm3HvDjYHApputMKwgOE8lYqDuK2vK0Z0U,2626
|
|
72
72
|
tests/lib/test_repository.py,sha256=gUi1lkY7bha5WwZ5xcnENOlFYboVV8TFW1lCESvS0VA,787
|
|
73
73
|
tests/lib/test_venv.py,sha256=wscU7Enp8fK6o_2HgIT4WwDnvHbKwaKvJhNyJUrDNqk,3262
|
|
74
|
-
sentry_devenv-1.
|
|
75
|
-
sentry_devenv-1.
|
|
76
|
-
sentry_devenv-1.
|
|
77
|
-
sentry_devenv-1.
|
|
78
|
-
sentry_devenv-1.
|
|
74
|
+
sentry_devenv-1.21.0.dist-info/METADATA,sha256=HoKXEUwfiAL2U9Gfqz2BmOHWiPmz11r3h_4y2PRmz-4,13939
|
|
75
|
+
sentry_devenv-1.21.0.dist-info/WHEEL,sha256=zaaOINJESkSfm_4HQVc5ssNzHCPXhJm0kEUakpsEHaU,91
|
|
76
|
+
sentry_devenv-1.21.0.dist-info/entry_points.txt,sha256=StsIuNugcoEU8jsPy6H9ECjzoDzOVKXl1vUaYTIGbzM,44
|
|
77
|
+
sentry_devenv-1.21.0.dist-info/top_level.txt,sha256=dOQExvIA0fj_EQjCrMTS7CCHNH7WZFHxEU0M7LlNcKQ,16
|
|
78
|
+
sentry_devenv-1.21.0.dist-info/RECORD,,
|
|
@@ -8,7 +8,7 @@ from unittest import mock
|
|
|
8
8
|
|
|
9
9
|
import pytest
|
|
10
10
|
|
|
11
|
-
from devenv.checks import
|
|
11
|
+
from devenv.checks import dockerConfig
|
|
12
12
|
|
|
13
13
|
|
|
14
14
|
@pytest.fixture
|
|
@@ -25,26 +25,32 @@ def fake_config(tmp_path: pathlib.Path) -> Generator[pathlib.Path]:
|
|
|
25
25
|
|
|
26
26
|
def test_no_credsStore_ok(fake_config: pathlib.Path) -> None:
|
|
27
27
|
fake_config.write_text("{}")
|
|
28
|
-
assert
|
|
28
|
+
assert dockerConfig.check() == (True, "")
|
|
29
29
|
|
|
30
30
|
|
|
31
31
|
def test_binary_ok(fake_config: pathlib.Path) -> None:
|
|
32
32
|
fake_config.write_text('{"credsStore": "example"}')
|
|
33
33
|
with mock.patch.object(shutil, "which", return_value="/fake/exe"):
|
|
34
|
-
assert
|
|
34
|
+
assert dockerConfig.check() == (True, "")
|
|
35
35
|
|
|
36
36
|
|
|
37
37
|
@pytest.mark.parametrize("name", ("desktop", "osxkeychain"))
|
|
38
38
|
def test_binary_missing(fake_config: pathlib.Path, name: str) -> None:
|
|
39
39
|
fake_config.write_text(f'{{"credsStore": "{name}"}}')
|
|
40
40
|
with mock.patch.object(shutil, "which", return_value=None):
|
|
41
|
-
assert
|
|
41
|
+
assert dockerConfig.check() == (
|
|
42
42
|
False,
|
|
43
43
|
"credsStore requires nonexistent binary",
|
|
44
44
|
)
|
|
45
45
|
|
|
46
46
|
|
|
47
|
-
def
|
|
47
|
+
def test_fix_credsStore(fake_config: pathlib.Path) -> None:
|
|
48
48
|
fake_config.write_text('{"credsStore": "bad"}')
|
|
49
|
-
assert
|
|
49
|
+
assert dockerConfig.fix() == (True, "")
|
|
50
|
+
assert fake_config.read_text() == "{}"
|
|
51
|
+
|
|
52
|
+
|
|
53
|
+
def test_fix_cliPluginsExtraDirs(fake_config: pathlib.Path) -> None:
|
|
54
|
+
fake_config.write_text('{"cliPluginsExtraDirs": ["foo/"]}')
|
|
55
|
+
assert dockerConfig.fix() == (True, "")
|
|
50
56
|
assert fake_config.read_text() == "{}"
|
tests/lib/test_archive.py
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
from __future__ import annotations
|
|
2
2
|
|
|
3
3
|
import io
|
|
4
|
+
import os
|
|
4
5
|
import pathlib
|
|
5
6
|
import tarfile
|
|
6
7
|
import time
|
|
@@ -169,6 +170,12 @@ def test_download(tmp_path: pathlib.Path, mock_sleep: mock.MagicMock) -> None:
|
|
|
169
170
|
)
|
|
170
171
|
|
|
171
172
|
dest = f"{tmp_path}/a"
|
|
173
|
+
|
|
174
|
+
# if dest is already a valid symlink it should be paved over
|
|
175
|
+
with open(f"{tmp_path}/hi", "wb"):
|
|
176
|
+
pass
|
|
177
|
+
os.symlink(f"{tmp_path}/hi", dest)
|
|
178
|
+
|
|
172
179
|
with mock.patch.object(
|
|
173
180
|
urllib.request,
|
|
174
181
|
"urlopen",
|
|
@@ -186,7 +193,22 @@ def test_download(tmp_path: pathlib.Path, mock_sleep: mock.MagicMock) -> None:
|
|
|
186
193
|
with open(dest, "rb") as f:
|
|
187
194
|
assert f.read() == data
|
|
188
195
|
|
|
189
|
-
|
|
196
|
+
|
|
197
|
+
def test_download_exceeded_retries(
|
|
198
|
+
tmp_path: pathlib.Path, mock_sleep: mock.MagicMock
|
|
199
|
+
) -> None:
|
|
200
|
+
data_sha256 = (
|
|
201
|
+
"b5bb9d8014a0f9b1d61e21e796d78dccdf1352f23cd32812f4850b878ae4944c"
|
|
202
|
+
)
|
|
203
|
+
|
|
204
|
+
err = urllib.error.HTTPError(
|
|
205
|
+
"https://example.com/foo",
|
|
206
|
+
503,
|
|
207
|
+
"Service Unavailable",
|
|
208
|
+
"", # type: ignore
|
|
209
|
+
io.BytesIO(b""),
|
|
210
|
+
)
|
|
211
|
+
dest = f"{tmp_path}/a"
|
|
190
212
|
with pytest.raises(RuntimeError) as excinfo:
|
|
191
213
|
with mock.patch.object(
|
|
192
214
|
urllib.request,
|
|
@@ -202,7 +224,42 @@ def test_download(tmp_path: pathlib.Path, mock_sleep: mock.MagicMock) -> None:
|
|
|
202
224
|
== "Error getting https://example.com/foo: HTTP Error 503: Service Unavailable"
|
|
203
225
|
)
|
|
204
226
|
|
|
205
|
-
|
|
227
|
+
|
|
228
|
+
def test_download_dest_is_broken_symlink(
|
|
229
|
+
tmp_path: pathlib.Path, mock_sleep: mock.MagicMock
|
|
230
|
+
) -> None:
|
|
231
|
+
data = b"foo\n"
|
|
232
|
+
data_sha256 = (
|
|
233
|
+
"b5bb9d8014a0f9b1d61e21e796d78dccdf1352f23cd32812f4850b878ae4944c"
|
|
234
|
+
)
|
|
235
|
+
|
|
236
|
+
dest = f"{tmp_path}/a"
|
|
237
|
+
|
|
238
|
+
# if dest is already a dead symlink it should be paved over as well
|
|
239
|
+
os.symlink(f"{tmp_path}/does-not-exist", dest)
|
|
240
|
+
|
|
241
|
+
with mock.patch.object(
|
|
242
|
+
urllib.request,
|
|
243
|
+
"urlopen",
|
|
244
|
+
autospec=True,
|
|
245
|
+
side_effect=(io.BytesIO(data),),
|
|
246
|
+
):
|
|
247
|
+
archive.download("https://example.com/foo", data_sha256, dest)
|
|
248
|
+
|
|
249
|
+
with open(dest, "rb") as f:
|
|
250
|
+
assert f.read() == data
|
|
251
|
+
|
|
252
|
+
|
|
253
|
+
def test_download_wrong_sha(
|
|
254
|
+
tmp_path: pathlib.Path, mock_sleep: mock.MagicMock
|
|
255
|
+
) -> None:
|
|
256
|
+
data = b"foo\n"
|
|
257
|
+
data_sha256 = (
|
|
258
|
+
"b5bb9d8014a0f9b1d61e21e796d78dccdf1352f23cd32812f4850b878ae4944c"
|
|
259
|
+
)
|
|
260
|
+
|
|
261
|
+
dest = f"{tmp_path}/a"
|
|
262
|
+
|
|
206
263
|
with pytest.raises(RuntimeError) as excinfo:
|
|
207
264
|
with mock.patch.object(
|
|
208
265
|
urllib.request,
|
|
File without changes
|
|
File without changes
|