assertion-cli 0.5.18__tar.gz → 0.5.19__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.
Files changed (35) hide show
  1. {assertion_cli-0.5.18 → assertion_cli-0.5.19}/PKG-INFO +2 -3
  2. {assertion_cli-0.5.18 → assertion_cli-0.5.19}/README.md +1 -2
  3. {assertion_cli-0.5.18 → assertion_cli-0.5.19}/api.py +3 -3
  4. {assertion_cli-0.5.18 → assertion_cli-0.5.19}/assertion_cli.egg-info/PKG-INFO +2 -3
  5. {assertion_cli-0.5.18 → assertion_cli-0.5.19}/credentials.py +12 -51
  6. {assertion_cli-0.5.18 → assertion_cli-0.5.19}/main.py +2 -4
  7. {assertion_cli-0.5.18 → assertion_cli-0.5.19}/pyproject.toml +1 -1
  8. {assertion_cli-0.5.18 → assertion_cli-0.5.19}/tests/test_auth.py +3 -3
  9. {assertion_cli-0.5.18 → assertion_cli-0.5.19}/tests/test_credentials.py +26 -29
  10. {assertion_cli-0.5.18 → assertion_cli-0.5.19}/assertion_cli.egg-info/SOURCES.txt +0 -0
  11. {assertion_cli-0.5.18 → assertion_cli-0.5.19}/assertion_cli.egg-info/dependency_links.txt +0 -0
  12. {assertion_cli-0.5.18 → assertion_cli-0.5.19}/assertion_cli.egg-info/entry_points.txt +0 -0
  13. {assertion_cli-0.5.18 → assertion_cli-0.5.19}/assertion_cli.egg-info/requires.txt +0 -0
  14. {assertion_cli-0.5.18 → assertion_cli-0.5.19}/assertion_cli.egg-info/top_level.txt +0 -0
  15. {assertion_cli-0.5.18 → assertion_cli-0.5.19}/bundle.py +0 -0
  16. {assertion_cli-0.5.18 → assertion_cli-0.5.19}/git.py +0 -0
  17. {assertion_cli-0.5.18 → assertion_cli-0.5.19}/link.py +0 -0
  18. {assertion_cli-0.5.18 → assertion_cli-0.5.19}/models.py +0 -0
  19. {assertion_cli-0.5.18 → assertion_cli-0.5.19}/session.py +0 -0
  20. {assertion_cli-0.5.18 → assertion_cli-0.5.19}/setup.cfg +0 -0
  21. {assertion_cli-0.5.18 → assertion_cli-0.5.19}/templates/AGENTS.md +0 -0
  22. {assertion_cli-0.5.18 → assertion_cli-0.5.19}/templates/SKILL.md +0 -0
  23. {assertion_cli-0.5.18 → assertion_cli-0.5.19}/templates/__init__.py +0 -0
  24. {assertion_cli-0.5.18 → assertion_cli-0.5.19}/tests/test_api.py +0 -0
  25. {assertion_cli-0.5.18 → assertion_cli-0.5.19}/tests/test_bundle.py +0 -0
  26. {assertion_cli-0.5.18 → assertion_cli-0.5.19}/tests/test_decision.py +0 -0
  27. {assertion_cli-0.5.18 → assertion_cli-0.5.19}/tests/test_git.py +0 -0
  28. {assertion_cli-0.5.18 → assertion_cli-0.5.19}/tests/test_install.py +0 -0
  29. {assertion_cli-0.5.18 → assertion_cli-0.5.19}/tests/test_link.py +0 -0
  30. {assertion_cli-0.5.18 → assertion_cli-0.5.19}/tests/test_main.py +0 -0
  31. {assertion_cli-0.5.18 → assertion_cli-0.5.19}/tests/test_prompt.py +0 -0
  32. {assertion_cli-0.5.18 → assertion_cli-0.5.19}/tests/test_session.py +0 -0
  33. {assertion_cli-0.5.18 → assertion_cli-0.5.19}/tests/test_session_start.py +0 -0
  34. {assertion_cli-0.5.18 → assertion_cli-0.5.19}/tests/test_verify.py +0 -0
  35. {assertion_cli-0.5.18 → assertion_cli-0.5.19}/tests/test_verify_integration.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: assertion-cli
3
- Version: 0.5.18
3
+ Version: 0.5.19
4
4
  Summary: CLI for the Assertion API
5
5
  Requires-Python: >=3.13
6
6
  Description-Content-Type: text/markdown
@@ -74,8 +74,7 @@ shows which token is in effect.
74
74
  Token resolution at call time, in order:
75
75
 
76
76
  1. the token in `repo_index` for the current repo's GitHub `owner/repo`;
77
- 2. a legacy entry for the current repo path in `~/.assertion/credentials.json`;
78
- 3. the `ASSERTION_API_TOKEN` environment variable (a backup for CI, or repos
77
+ 2. the `ASSERTION_API_TOKEN` environment variable (a backup for CI, or repos
79
78
  with no remote that `asrt login` won't store);
80
79
 
81
80
  with a clear "run `asrt login`" error when neither is present. The API base URL
@@ -61,8 +61,7 @@ shows which token is in effect.
61
61
  Token resolution at call time, in order:
62
62
 
63
63
  1. the token in `repo_index` for the current repo's GitHub `owner/repo`;
64
- 2. a legacy entry for the current repo path in `~/.assertion/credentials.json`;
65
- 3. the `ASSERTION_API_TOKEN` environment variable (a backup for CI, or repos
64
+ 2. the `ASSERTION_API_TOKEN` environment variable (a backup for CI, or repos
66
65
  with no remote that `asrt login` won't store);
67
66
 
68
67
  with a clear "run `asrt login`" error when neither is present. The API base URL
@@ -35,9 +35,9 @@ def _base_url() -> str:
35
35
  def _resolve_token() -> str | None:
36
36
  """Token for the current repo, else the shell env-var backup, else None.
37
37
 
38
- Stored credentials are primarily keyed by the current repo's GitHub
39
- ``owner/repo`` identity, with the legacy exact git-root path as fallback. A
40
- real `export ASSERTION_API_TOKEN` only fills in when no stored entry matches.
38
+ Stored credentials are keyed by the current repo's GitHub ``owner/repo``
39
+ identity. A real `export ASSERTION_API_TOKEN` only fills in when no stored
40
+ entry matches.
41
41
  """
42
42
  repo_root = find_git_root_or_none(Path.cwd())
43
43
  repo_full_name = (
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: assertion-cli
3
- Version: 0.5.18
3
+ Version: 0.5.19
4
4
  Summary: CLI for the Assertion API
5
5
  Requires-Python: >=3.13
6
6
  Description-Content-Type: text/markdown
@@ -74,8 +74,7 @@ shows which token is in effect.
74
74
  Token resolution at call time, in order:
75
75
 
76
76
  1. the token in `repo_index` for the current repo's GitHub `owner/repo`;
77
- 2. a legacy entry for the current repo path in `~/.assertion/credentials.json`;
78
- 3. the `ASSERTION_API_TOKEN` environment variable (a backup for CI, or repos
77
+ 2. the `ASSERTION_API_TOKEN` environment variable (a backup for CI, or repos
79
78
  with no remote that `asrt login` won't store);
80
79
 
81
80
  with a clear "run `asrt login`" error when neither is present. The API base URL
@@ -10,14 +10,10 @@ points at a connected repo:
10
10
  "repo_index": {"acme/mvp": "alk_..."}
11
11
  }
12
12
 
13
- The legacy v1 ``repos`` path map is still read as a fallback:
14
-
15
- {"version": 1, "repos": {"/abs/path/to/repo": "alk_..."}}
16
-
17
13
  This module is deliberately git-free and pure stdlib — callers pass in the repo
18
- root / repo full name (resolved via ``git.py``) and handle their own error
19
- reporting. Token resolution precedence (repo entry first, then the env-var
20
- backup) lives in ``api.py``; this module only owns on-disk reads and writes.
14
+ full name (resolved via ``git.py``) and handle their own error reporting. Token
15
+ resolution precedence (repo entry first, then the env-var backup) lives in
16
+ ``api.py``; this module only owns on-disk reads and writes.
21
17
  """
22
18
 
23
19
  from __future__ import annotations
@@ -46,7 +42,6 @@ def _empty_store() -> dict:
46
42
  "version": CREDENTIALS_VERSION,
47
43
  "tokens": {},
48
44
  "repo_index": {},
49
- "repos": {},
50
45
  }
51
46
 
52
47
 
@@ -70,16 +65,10 @@ def load_store() -> dict:
70
65
  data["tokens"] = {}
71
66
  if not isinstance(data.get("repo_index"), dict):
72
67
  data["repo_index"] = _repo_index_from_tokens(data["tokens"])
73
- if not isinstance(data.get("repos"), dict):
74
- data["repos"] = {}
68
+ data.pop("repos", None)
75
69
  return data
76
70
 
77
71
 
78
- def _repo_key(repo_root: Path) -> str:
79
- """Canonical store key for a repo root (absolute, symlinks resolved)."""
80
- return str(repo_root.resolve())
81
-
82
-
83
72
  def _repo_name_key(repo_full_name: str) -> str:
84
73
  return repo_full_name.strip().lower()
85
74
 
@@ -124,14 +113,11 @@ def _write_store(store: dict) -> Path:
124
113
  return path
125
114
 
126
115
 
127
- def save_token(
128
- token: str, *, repo_root: Path, repo_full_names: list[str] | None = None
129
- ) -> Path:
116
+ def save_token(token: str, *, repo_full_names: list[str] | None = None) -> Path:
130
117
  """Persist ``token`` and return the credentials file path.
131
118
 
132
119
  ``repo_full_names`` are canonical GitHub ``owner/repo`` names visible to the
133
- token. The legacy path entry is still written so older CLIs can read the
134
- file during a rolling upgrade.
120
+ token.
135
121
  """
136
122
  store = load_store()
137
123
  if repo_full_names is not None:
@@ -159,20 +145,17 @@ def save_token(
159
145
  store["tokens"][token] = normalized
160
146
  for repo in normalized:
161
147
  repo_index[repo] = token
162
- store["repos"][_repo_key(repo_root)] = token
163
148
  return _write_store(store)
164
149
 
165
150
 
166
- def remove_token(*, repo_root: Path, repo_full_name: str | None = None) -> bool:
151
+ def remove_token(*, repo_full_name: str | None = None) -> bool:
167
152
  """Delete this repo's saved credential. Return ``True`` if one was removed."""
168
153
  store = load_store()
169
- key = _repo_key(repo_root)
170
- token = store["repos"].pop(key, None)
171
- removed = token is not None
154
+ removed = False
172
155
  if repo_full_name is not None:
173
156
  repo_key = _repo_name_key(repo_full_name)
174
157
  indexed_token = store["repo_index"].pop(repo_key, None)
175
- target_token = token or indexed_token
158
+ target_token = indexed_token
176
159
  for saved_token, repos in list(store["tokens"].items()):
177
160
  if target_token is not None and saved_token != target_token:
178
161
  continue
@@ -192,23 +175,6 @@ def remove_token(*, repo_root: Path, repo_full_name: str | None = None) -> bool:
192
175
  if saved_token == target_token:
193
176
  break
194
177
  removed = removed or indexed_token is not None
195
- if token:
196
- repo_refs = 0
197
- for saved in store["repos"].values():
198
- if saved == token:
199
- repo_refs += 1
200
- indexed_refs = [
201
- indexed_token
202
- for indexed_token in store["repo_index"].values()
203
- if indexed_token == token
204
- ]
205
- if (
206
- repo_refs == 0
207
- and not indexed_refs
208
- and token in store["tokens"]
209
- and repo_full_name is None
210
- ):
211
- del store["tokens"][token]
212
178
  if removed:
213
179
  _write_store(store)
214
180
  return removed
@@ -219,8 +185,8 @@ def resolve_token(
219
185
  ) -> str | None:
220
186
  """Return the stored token for ``repo_full_name`` / ``repo_root``.
221
187
 
222
- Repo-name matching is primary and survives reclones/moved folders. The
223
- legacy exact path match is retained so existing credentials keep working.
188
+ Repo-name matching survives reclones/moved folders because it uses the
189
+ checkout's GitHub ``owner/repo`` identity instead of the local path.
224
190
  """
225
191
  store = load_store()
226
192
  if repo_full_name is not None:
@@ -228,10 +194,7 @@ def resolve_token(
228
194
  token = store["repo_index"].get(local)
229
195
  if token:
230
196
  return token
231
- if repo_root is None:
232
- return None
233
- token = store["repos"].get(_repo_key(repo_root))
234
- return token or None
197
+ return None
235
198
 
236
199
 
237
200
  def describe_source(
@@ -246,8 +209,6 @@ def describe_source(
246
209
  and resolve_token(repo_root, repo_full_name) is not None
247
210
  ):
248
211
  return f"the saved token for {repo_full_name.strip().lower()}"
249
- if repo_root is not None and resolve_token(repo_root) is not None:
250
- return f"the saved token for {_repo_key(repo_root)}"
251
212
  if (os.environ.get(API_TOKEN_ENV) or "").strip():
252
213
  return f"the {API_TOKEN_ENV} environment variable"
253
214
  return None
@@ -174,9 +174,7 @@ def login(
174
174
  "the dashboard, then re-run `asrt login`."
175
175
  )
176
176
 
177
- path = save_token(
178
- token, repo_root=repo_root, repo_full_names=[s.repo for s in stack_list]
179
- )
177
+ path = save_token(token, repo_full_names=[s.repo for s in stack_list])
180
178
  names = ", ".join(f"'{s.name}'" for s in matched)
181
179
  typer.echo(f"✓ {local} is connected to stack(s): {names}")
182
180
  typer.echo(f"Saved token for {repo_root} to {path}")
@@ -190,7 +188,7 @@ def logout() -> None:
190
188
  exit_with_error("Not inside a git repository.")
191
189
 
192
190
  local = current_repo_full_name(repo_root)
193
- if remove_token(repo_root=repo_root, repo_full_name=local):
191
+ if remove_token(repo_full_name=local):
194
192
  typer.echo(f"Removed saved token for {repo_root}.")
195
193
  else:
196
194
  typer.echo(f"No saved token for {repo_root}.")
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "assertion-cli"
7
- version = "0.5.18"
7
+ version = "0.5.19"
8
8
  description = "CLI for the Assertion API"
9
9
  readme = "README.md"
10
10
  requires-python = ">=3.13"
@@ -52,7 +52,7 @@ def test_login_saves_when_repo_matches_stack(repo: Path) -> None:
52
52
  assert result.exit_code == 0, result.output
53
53
  assert "connected to stack" in result.output.lower()
54
54
  assert route.called
55
- assert credentials.resolve_token(repo) == "alk_new"
55
+ assert credentials.resolve_token(repo, "acme/mvp") == "alk_new"
56
56
  assert credentials.resolve_token(None, "acme/mvp") == "alk_new"
57
57
  assert credentials.resolve_token(None, "acme/docs") == "alk_new"
58
58
 
@@ -96,7 +96,7 @@ def test_login_no_remote_does_not_save_or_call_network(
96
96
 
97
97
 
98
98
  def test_logout_removes_token(repo: Path) -> None:
99
- credentials.save_token("alk_new", repo_root=repo)
99
+ credentials.save_token("alk_new", repo_full_names=["acme/mvp"])
100
100
 
101
101
  result = runner.invoke(main.app, ["logout"])
102
102
 
@@ -114,7 +114,7 @@ def test_logout_when_nothing_saved(repo: Path) -> None:
114
114
 
115
115
  @respx.mock
116
116
  def test_whoami_reports_saved_token(repo: Path) -> None:
117
- credentials.save_token("alk_new", repo_root=repo)
117
+ credentials.save_token("alk_new", repo_full_names=["acme/mvp"])
118
118
  respx.get(STACKS_URL).mock(return_value=_stacks_response("acme/mvp", "acme/other"))
119
119
 
120
120
  result = runner.invoke(main.app, ["whoami"])
@@ -26,14 +26,12 @@ def repo(tmp_path: Path) -> Path:
26
26
 
27
27
 
28
28
  def test_save_and_resolve_round_trip(repo: Path) -> None:
29
- credentials.save_token(
30
- "alk_one", repo_root=repo, repo_full_names=["acme/mvp", "Acme/Docs"]
31
- )
29
+ credentials.save_token("alk_one", repo_full_names=["acme/mvp", "Acme/Docs"])
32
30
  assert credentials.resolve_token(repo, "ACME/MVP") == "alk_one"
33
31
 
34
32
 
35
33
  def test_resolve_unknown_repo_returns_none(repo: Path, tmp_path: Path) -> None:
36
- credentials.save_token("alk_one", repo_root=repo, repo_full_names=["acme/mvp"])
34
+ credentials.save_token("alk_one", repo_full_names=["acme/mvp"])
37
35
  other = tmp_path / "other"
38
36
  other.mkdir()
39
37
  assert credentials.resolve_token(other) is None
@@ -44,28 +42,25 @@ def test_resolve_none_repo_root() -> None:
44
42
 
45
43
 
46
44
  def test_save_writes_file_mode_0600(repo: Path) -> None:
47
- path = credentials.save_token("alk_one", repo_root=repo)
45
+ path = credentials.save_token("alk_one")
48
46
  mode = stat.S_IMODE(path.stat().st_mode)
49
47
  assert mode == 0o600
50
48
 
51
49
 
52
50
  def test_store_shape(repo: Path) -> None:
53
- path = credentials.save_token(
54
- "alk_one", repo_root=repo, repo_full_names=["Acme/MVP", "acme/mvp"]
55
- )
51
+ path = credentials.save_token("alk_one", repo_full_names=["Acme/MVP", "acme/mvp"])
56
52
  data = json.loads(path.read_text())
57
53
  assert data["version"] == credentials.CREDENTIALS_VERSION
58
54
  assert data["tokens"]["alk_one"] == ["acme/mvp"]
59
55
  assert data["repo_index"]["acme/mvp"] == "alk_one"
60
- assert data["repos"][str(repo.resolve())] == "alk_one"
56
+ assert "repos" not in data
61
57
 
62
58
 
63
59
  def test_save_is_idempotent_overwrite(repo: Path) -> None:
64
- credentials.save_token("alk_one", repo_root=repo, repo_full_names=["acme/mvp"])
65
- credentials.save_token("alk_two", repo_root=repo, repo_full_names=["acme/mvp"])
60
+ credentials.save_token("alk_one", repo_full_names=["acme/mvp"])
61
+ credentials.save_token("alk_two", repo_full_names=["acme/mvp"])
66
62
  assert credentials.resolve_token(repo, "acme/mvp") == "alk_two"
67
63
  store = credentials.load_store()
68
- assert len(store["repos"]) == 1
69
64
  assert len(store["tokens"]) == 1
70
65
  assert store["repo_index"] == {"acme/mvp": "alk_two"}
71
66
 
@@ -74,8 +69,8 @@ def test_distinct_repos_get_distinct_entries(tmp_path: Path) -> None:
74
69
  a, b = tmp_path / "a", tmp_path / "b"
75
70
  a.mkdir()
76
71
  b.mkdir()
77
- credentials.save_token("alk_a", repo_root=a, repo_full_names=["acme/a"])
78
- credentials.save_token("alk_b", repo_root=b, repo_full_names=["acme/b"])
72
+ credentials.save_token("alk_a", repo_full_names=["acme/a"])
73
+ credentials.save_token("alk_b", repo_full_names=["acme/b"])
79
74
  assert credentials.resolve_token(a, "acme/a") == "alk_a"
80
75
  assert credentials.resolve_token(b, "acme/b") == "alk_b"
81
76
 
@@ -85,7 +80,6 @@ def test_load_store_missing_file_is_empty() -> None:
85
80
  "version": credentials.CREDENTIALS_VERSION,
86
81
  "tokens": {},
87
82
  "repo_index": {},
88
- "repos": {},
89
83
  }
90
84
 
91
85
 
@@ -97,20 +91,19 @@ def test_load_store_tolerates_corrupt_file(_isolate_home: Path) -> None:
97
91
  "version": credentials.CREDENTIALS_VERSION,
98
92
  "tokens": {},
99
93
  "repo_index": {},
100
- "repos": {},
101
94
  }
102
95
 
103
96
 
104
97
  def test_remove_token(repo: Path) -> None:
105
- credentials.save_token("alk_one", repo_root=repo, repo_full_names=["acme/mvp"])
106
- assert credentials.remove_token(repo_root=repo, repo_full_name="acme/mvp") is True
98
+ credentials.save_token("alk_one", repo_full_names=["acme/mvp"])
99
+ assert credentials.remove_token(repo_full_name="acme/mvp") is True
107
100
  assert credentials.resolve_token(repo, "acme/mvp") is None
108
101
  # Removing again is a no-op.
109
- assert credentials.remove_token(repo_root=repo) is False
102
+ assert credentials.remove_token() is False
110
103
 
111
104
 
112
105
  def test_describe_source_repo_entry(repo: Path) -> None:
113
- credentials.save_token("alk_one", repo_root=repo, repo_full_names=["acme/mvp"])
106
+ credentials.save_token("alk_one", repo_full_names=["acme/mvp"])
114
107
  assert credentials.describe_source(repo, "acme/mvp") == (
115
108
  "the saved token for acme/mvp"
116
109
  )
@@ -128,15 +121,17 @@ def test_describe_source_repo_entry_wins_over_env(
128
121
  repo: Path, monkeypatch: pytest.MonkeyPatch
129
122
  ) -> None:
130
123
  monkeypatch.setenv(credentials.API_TOKEN_ENV, "alk_env")
131
- credentials.save_token("alk_one", repo_root=repo)
132
- assert credentials.describe_source(repo) == f"the saved token for {repo.resolve()}"
124
+ credentials.save_token("alk_one", repo_full_names=["acme/mvp"])
125
+ assert credentials.describe_source(repo, "acme/mvp") == (
126
+ "the saved token for acme/mvp"
127
+ )
133
128
 
134
129
 
135
130
  def test_describe_source_none(repo: Path) -> None:
136
131
  assert credentials.describe_source(repo) is None
137
132
 
138
133
 
139
- def test_resolve_legacy_path_store(repo: Path) -> None:
134
+ def test_load_store_drops_legacy_path_store(repo: Path) -> None:
140
135
  path = credentials.credentials_path()
141
136
  path.parent.mkdir(parents=True, exist_ok=True)
142
137
  path.write_text(
@@ -144,7 +139,9 @@ def test_resolve_legacy_path_store(repo: Path) -> None:
144
139
  encoding="utf-8",
145
140
  )
146
141
 
147
- assert credentials.resolve_token(repo, "acme/mvp") == "alk_old"
142
+ store = credentials.load_store()
143
+ assert "repos" not in store
144
+ assert credentials.resolve_token(repo, "acme/mvp") is None
148
145
 
149
146
 
150
147
  def test_load_store_builds_repo_index_from_token_only_v2_store() -> None:
@@ -162,26 +159,26 @@ def test_load_store_builds_repo_index_from_token_only_v2_store() -> None:
162
159
  def test_resolve_repo_name_after_reclone(repo: Path, tmp_path: Path) -> None:
163
160
  moved = tmp_path / "moved"
164
161
  moved.mkdir()
165
- credentials.save_token("alk_one", repo_root=repo, repo_full_names=["acme/mvp"])
162
+ credentials.save_token("alk_one", repo_full_names=["acme/mvp"])
166
163
 
167
164
  assert credentials.resolve_token(moved, "acme/mvp") == "alk_one"
168
165
 
169
166
 
170
167
  def test_remove_token_keeps_other_repo_names(repo: Path) -> None:
171
168
  credentials.save_token(
172
- "alk_one", repo_root=repo, repo_full_names=["acme/mvp", "acme/docs"]
169
+ "alk_one", repo_full_names=["acme/mvp", "acme/docs"]
173
170
  )
174
171
 
175
- assert credentials.remove_token(repo_root=repo, repo_full_name="acme/mvp") is True
172
+ assert credentials.remove_token(repo_full_name="acme/mvp") is True
176
173
  assert credentials.resolve_token(None, "acme/mvp") is None
177
174
  assert credentials.resolve_token(None, "acme/docs") == "alk_one"
178
175
 
179
176
 
180
177
  def test_resaving_same_token_removes_stale_repo_index_entries(repo: Path) -> None:
181
178
  credentials.save_token(
182
- "alk_one", repo_root=repo, repo_full_names=["acme/mvp", "acme/docs"]
179
+ "alk_one", repo_full_names=["acme/mvp", "acme/docs"]
183
180
  )
184
- credentials.save_token("alk_one", repo_root=repo, repo_full_names=["acme/mvp"])
181
+ credentials.save_token("alk_one", repo_full_names=["acme/mvp"])
185
182
 
186
183
  store = credentials.load_store()
187
184
  assert store["tokens"]["alk_one"] == ["acme/mvp"]
File without changes
File without changes
File without changes
File without changes
File without changes