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.
@@ -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 = "credsStore fix"
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 not os.path.exists(dest):
42
- headers = {}
43
- if url.startswith("https://ghcr.io/v2/homebrew"):
44
- # downloading homebrew blobs requires auth
45
- # you can get an anonymous token from https://ghcr.io/token?service=ghcr.io&scope=repository%3Ahomebrew/core/go%3Apull
46
- # but there's also a special shortcut token QQ==
47
- # https://github.com/Homebrew/brew/blob/2184406bd8444e4de2626f5b0c749d4d08cb1aed/Library/Homebrew/brew.sh#L993
48
- headers["Authorization"] = "bearer QQ=="
49
-
50
- req = urllib.request.Request(url, headers=headers)
51
-
52
- retry_sleep = 1.0
53
- while retries >= 0:
54
- try:
55
- resp = urllib.request.urlopen(req)
56
- break
57
- except HTTPError as e:
58
- if retries == 0:
59
- raise RuntimeError(f"Error getting {url}: {e}")
60
- print(f"Error getting {url} ({retries} retries left): {e}")
61
-
62
- time.sleep(retry_sleep)
63
- retries -= 1
64
- retry_sleep *= retry_exp
65
-
66
- dest_dir = os.path.dirname(dest)
67
- os.makedirs(dest_dir, exist_ok=True)
68
-
69
- with tempfile.NamedTemporaryFile(delete=False, dir=dest_dir) as tmpf:
70
- shutil.copyfileobj(resp, tmpf)
71
- tmpf.seek(0)
72
- checksum = hashlib.sha256()
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
- while buf:
75
- checksum.update(buf)
76
- buf = tmpf.read(4096)
77
-
78
- if not secrets.compare_digest(checksum.hexdigest(), sha256):
79
- raise RuntimeError(
80
- f"checksum mismatch for {url}:\n"
81
- f"- got: {checksum.hexdigest()}\n"
82
- f"- expected: {sha256}\n"
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 outdated!")
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 outdated! expected: {expected_version}"
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 outdated!")
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 outdated!")
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 outdated!")
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 outdated!")
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 outdated!")
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 outdated!")
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 outdated python, recreating at {venv}..."
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
- enable_tracing=True,
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.19.0
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 `devenv` and `direnv`
88
- - we currently rely on a minimal [`[reporoot]/.envrc`](#direnv) to add `[reporoot]/.devenv/bin` to PATH
89
- - see [examples](#examples) for .envrc suggestions
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=JYV1GflML2DOrIhbZq_Vn89dFd0hqOKXxDVSd2GQRgY,3264
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/credsStore.py,sha256=G0mqzH62w4_3Tc4VG6tssGHFOUiVgp4RSPlYj86zsUc,1153
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=LlVETRsf3J53yY_8sjL4P8plLNEMKoS9G48kfoVoseA,4503
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=8JSAGC2pXthY_h7-AOsW0xgN-kyZq7_fh63-hhYFCIE,7381
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=cOBe9TRzoVkJbYv0g8yqkuyDYyntTasagwBGSiAgijs,5684
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=G8rhKC89TqWcFzIVsFd64d4ouD6M6s-TaMX5ZxtKypw,3550
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=uGcRkXQACDvbwKWhgEqgoUSVZjX6vEUGOutJDEw3kNM,4254
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=0LobIBWRQMzBiTKgv-WCva0Q1ZK3sR2NXNmnSa0Pcow,4156
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=9-I-7wvJNqanaMEs39bheOfikVz3wgTKtArkeCsOz8I,3028
38
- devenv/lib/venv.py,sha256=VbV2IA3HTk5WABBpMQJvlizdknEQVz1SsLxlEBDOLkc,3186
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/test_credStore.py,sha256=fvvKBx2vqbHDAfwxz77GPHO_gc8jawkqOpaDOob1dEs,1459
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=5FdCF8t64FewevL4P9PFojWS-a15z2I11TX0G1L_A-g,7944
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.19.0.dist-info/METADATA,sha256=I9mqOnTg4iM8ffcjIKb-grNlcw2KrQCQph6WUzMK5fI,13622
75
- sentry_devenv-1.19.0.dist-info/WHEEL,sha256=ck4Vq1_RXyvS4Jt6SI0Vz6fyVs4GWg7AINwpsaGEgPE,91
76
- sentry_devenv-1.19.0.dist-info/entry_points.txt,sha256=StsIuNugcoEU8jsPy6H9ECjzoDzOVKXl1vUaYTIGbzM,44
77
- sentry_devenv-1.19.0.dist-info/top_level.txt,sha256=dOQExvIA0fj_EQjCrMTS7CCHNH7WZFHxEU0M7LlNcKQ,16
78
- sentry_devenv-1.19.0.dist-info/RECORD,,
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,,
@@ -1,5 +1,5 @@
1
1
  Wheel-Version: 1.0
2
- Generator: setuptools (80.0.0)
2
+ Generator: setuptools (80.8.0)
3
3
  Root-Is-Purelib: true
4
4
  Tag: py3-none-any
5
5
 
@@ -8,7 +8,7 @@ from unittest import mock
8
8
 
9
9
  import pytest
10
10
 
11
- from devenv.checks import credsStore
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 credsStore.check() == (True, "")
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 credsStore.check() == (True, "")
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 credsStore.check() == (
41
+ assert dockerConfig.check() == (
42
42
  False,
43
43
  "credsStore requires nonexistent binary",
44
44
  )
45
45
 
46
46
 
47
- def test_fix(fake_config: pathlib.Path) -> None:
47
+ def test_fix_credsStore(fake_config: pathlib.Path) -> None:
48
48
  fake_config.write_text('{"credsStore": "bad"}')
49
- assert credsStore.fix() == (True, "")
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
- dest = f"{tmp_path}/b"
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
- dest = f"{tmp_path}/b"
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,