code-aide 1.0.2__tar.gz → 1.1.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.
Files changed (36) hide show
  1. code_aide-1.1.0/.github/workflows/publish.yml +46 -0
  2. {code_aide-1.0.2 → code_aide-1.1.0}/AGENTS.md +3 -0
  3. {code_aide-1.0.2 → code_aide-1.1.0}/PKG-INFO +36 -2
  4. {code_aide-1.0.2 → code_aide-1.1.0}/README.md +35 -1
  5. code_aide-1.1.0/TODO.md +39 -0
  6. {code_aide-1.0.2 → code_aide-1.1.0}/pyproject.toml +4 -1
  7. {code_aide-1.0.2 → code_aide-1.1.0}/src/code_aide/__init__.py +1 -1
  8. {code_aide-1.0.2 → code_aide-1.1.0}/src/code_aide/commands_actions.py +17 -9
  9. {code_aide-1.0.2 → code_aide-1.1.0}/src/code_aide/config.py +26 -0
  10. {code_aide-1.0.2 → code_aide-1.1.0}/src/code_aide/data/tools.json +12 -7
  11. {code_aide-1.0.2 → code_aide-1.1.0}/src/code_aide/entry.py +7 -4
  12. {code_aide-1.0.2 → code_aide-1.1.0}/tests/test_commands_actions.py +93 -2
  13. code_aide-1.0.2/.github/workflows/publish.yml +0 -15
  14. {code_aide-1.0.2 → code_aide-1.1.0}/.github/workflows/ci.yml +0 -0
  15. {code_aide-1.0.2 → code_aide-1.1.0}/.gitignore +0 -0
  16. {code_aide-1.0.2 → code_aide-1.1.0}/CLAUDE.md +0 -0
  17. {code_aide-1.0.2 → code_aide-1.1.0}/LICENSE +0 -0
  18. {code_aide-1.0.2 → code_aide-1.1.0}/src/code_aide/__main__.py +0 -0
  19. {code_aide-1.0.2 → code_aide-1.1.0}/src/code_aide/commands_tools.py +0 -0
  20. {code_aide-1.0.2 → code_aide-1.1.0}/src/code_aide/console.py +0 -0
  21. {code_aide-1.0.2 → code_aide-1.1.0}/src/code_aide/constants.py +0 -0
  22. {code_aide-1.0.2 → code_aide-1.1.0}/src/code_aide/detection.py +0 -0
  23. {code_aide-1.0.2 → code_aide-1.1.0}/src/code_aide/install.py +0 -0
  24. {code_aide-1.0.2 → code_aide-1.1.0}/src/code_aide/operations.py +0 -0
  25. {code_aide-1.0.2 → code_aide-1.1.0}/src/code_aide/prereqs.py +0 -0
  26. {code_aide-1.0.2 → code_aide-1.1.0}/src/code_aide/status.py +0 -0
  27. {code_aide-1.0.2 → code_aide-1.1.0}/src/code_aide/versions.py +0 -0
  28. {code_aide-1.0.2 → code_aide-1.1.0}/tests/test_commands_tools.py +0 -0
  29. {code_aide-1.0.2 → code_aide-1.1.0}/tests/test_config.py +0 -0
  30. {code_aide-1.0.2 → code_aide-1.1.0}/tests/test_console.py +0 -0
  31. {code_aide-1.0.2 → code_aide-1.1.0}/tests/test_constants.py +0 -0
  32. {code_aide-1.0.2 → code_aide-1.1.0}/tests/test_detection.py +0 -0
  33. {code_aide-1.0.2 → code_aide-1.1.0}/tests/test_install.py +0 -0
  34. {code_aide-1.0.2 → code_aide-1.1.0}/tests/test_operations.py +0 -0
  35. {code_aide-1.0.2 → code_aide-1.1.0}/tests/test_status.py +0 -0
  36. {code_aide-1.0.2 → code_aide-1.1.0}/tests/test_versions.py +0 -0
@@ -0,0 +1,46 @@
1
+ name: Publish to PyPI
2
+ on:
3
+ push:
4
+ tags: ["v*"]
5
+ jobs:
6
+ publish:
7
+ runs-on: ubuntu-latest
8
+ permissions:
9
+ contents: write
10
+ id-token: write
11
+ steps:
12
+ - uses: actions/checkout@v4
13
+ with:
14
+ fetch-depth: 0
15
+ - uses: astral-sh/setup-uv@v5
16
+ - run: uv build
17
+ - uses: pypa/gh-action-pypi-publish@release/v1
18
+ - name: Build commit changelog
19
+ id: changelog
20
+ run: |
21
+ set -euo pipefail
22
+ current_tag="${GITHUB_REF_NAME}"
23
+ previous_tag="$(git describe --tags --abbrev=0 "${current_tag}^" 2>/dev/null || true)"
24
+
25
+ {
26
+ echo "body<<EOF"
27
+ echo "## Commits"
28
+ echo
29
+ if [ -n "${previous_tag}" ]; then
30
+ echo "Range: \`${previous_tag}..${current_tag}\`"
31
+ echo
32
+ git log --pretty=format:'* %s (%h)' "${previous_tag}..${current_tag}"
33
+ else
34
+ echo "First tagged release."
35
+ echo
36
+ git log --pretty=format:'* %s (%h)' "${current_tag}"
37
+ fi
38
+ echo
39
+ echo "EOF"
40
+ } >> "${GITHUB_OUTPUT}"
41
+ - name: Create GitHub release notes
42
+ uses: softprops/action-gh-release@v2
43
+ with:
44
+ tag_name: ${{ github.ref_name }}
45
+ generate_release_notes: true
46
+ body: ${{ steps.changelog.outputs.body }}
@@ -7,6 +7,9 @@
7
7
  user's local cache (~/.config/code-aide/versions.json)
8
8
  - All tests should pass before committing
9
9
  - Run `black` formatter on python before commits
10
+ - Write useful commit messages: start subjects with past-tense action verbs
11
+ (`Added`, `Changed`, `Fixed`, `Removed`), keep them user-facing, and keep
12
+ commits focused.
10
13
  - Python 3.11+ compatible
11
14
  - Keep files under 300 lines where practical
12
15
  - Run `format-markdown` on markdown files before commits (if it is available)
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: code-aide
3
- Version: 1.0.2
3
+ Version: 1.1.0
4
4
  Summary: Manage AI coding CLI tools (Claude, Copilot, Cursor, Gemini, Amp, Codex)
5
5
  Project-URL: Homepage, https://github.com/dajobe/code-aide
6
6
  Project-URL: Repository, https://github.com/dajobe/code-aide
@@ -62,7 +62,7 @@ code-aide install
62
62
  # Install with automatic prerequisite installation (Node.js, npm)
63
63
  code-aide install -p
64
64
 
65
- # Upgrade installed tools
65
+ # Upgrade installed tools (no args = only out-of-date tools)
66
66
  code-aide upgrade [NAMES]
67
67
 
68
68
  # Remove tools
@@ -73,6 +73,9 @@ code-aide update-versions -n
73
73
 
74
74
  # Update version cache
75
75
  code-aide update-versions -y
76
+
77
+ # Update bundled version baseline (developer use, before releases)
78
+ code-aide update-versions -b -y
76
79
  ```
77
80
 
78
81
  ## Supported Tools
@@ -133,6 +136,37 @@ uv run pytest tests/ -v
133
136
  uv run pytest tests/test_install.py::TestDetectOsArch -v
134
137
  ```
135
138
 
139
+ ## Release
140
+
141
+ `publish.yml` publishes to PyPI when a Git tag matching `v*` is pushed.
142
+
143
+ 1. Update the bundled version baseline:
144
+ - `code-aide update-versions -b -y`
145
+ - `git add src/code_aide/data/tools.json`
146
+ - `git commit -m "Updated bundled version data"`
147
+ 2. Update the version string in `src/code_aide/__init__.py` (`__version__`).
148
+ `pyproject.toml` reads it automatically via Hatchling.
149
+ 3. Run checks:
150
+ - `uv run pytest tests/ -v`
151
+ - `uv build`
152
+ 4. Commit the release version bump:
153
+ - `git add src/code_aide/__init__.py`
154
+ - `git commit -m "Bumped version to X.Y.Z"`
155
+ 5. Write useful commit messages before tagging:
156
+ - Start subject lines with an action verb in past tense (`Added`, `Changed`,
157
+ `Fixed`, `Removed`).
158
+ - Keep subjects user-facing so auto-generated release notes are meaningful.
159
+ - Group related changes into focused commits instead of one broad commit.
160
+ - Example: `Fixed timeout handling in status command`
161
+ 6. Tag and push:
162
+ - `git tag vX.Y.Z`
163
+ - `git push origin main --follow-tags`
164
+ 7. Confirm GitHub Actions:
165
+ - CI should pass.
166
+ - Publish workflow should upload to PyPI and create GitHub Release notes.
167
+ - Release notes should include generated notes plus a commit summary from the
168
+ previous tag to the current tag.
169
+
136
170
  ## License
137
171
 
138
172
  Apache-2.0
@@ -36,7 +36,7 @@ code-aide install
36
36
  # Install with automatic prerequisite installation (Node.js, npm)
37
37
  code-aide install -p
38
38
 
39
- # Upgrade installed tools
39
+ # Upgrade installed tools (no args = only out-of-date tools)
40
40
  code-aide upgrade [NAMES]
41
41
 
42
42
  # Remove tools
@@ -47,6 +47,9 @@ code-aide update-versions -n
47
47
 
48
48
  # Update version cache
49
49
  code-aide update-versions -y
50
+
51
+ # Update bundled version baseline (developer use, before releases)
52
+ code-aide update-versions -b -y
50
53
  ```
51
54
 
52
55
  ## Supported Tools
@@ -107,6 +110,37 @@ uv run pytest tests/ -v
107
110
  uv run pytest tests/test_install.py::TestDetectOsArch -v
108
111
  ```
109
112
 
113
+ ## Release
114
+
115
+ `publish.yml` publishes to PyPI when a Git tag matching `v*` is pushed.
116
+
117
+ 1. Update the bundled version baseline:
118
+ - `code-aide update-versions -b -y`
119
+ - `git add src/code_aide/data/tools.json`
120
+ - `git commit -m "Updated bundled version data"`
121
+ 2. Update the version string in `src/code_aide/__init__.py` (`__version__`).
122
+ `pyproject.toml` reads it automatically via Hatchling.
123
+ 3. Run checks:
124
+ - `uv run pytest tests/ -v`
125
+ - `uv build`
126
+ 4. Commit the release version bump:
127
+ - `git add src/code_aide/__init__.py`
128
+ - `git commit -m "Bumped version to X.Y.Z"`
129
+ 5. Write useful commit messages before tagging:
130
+ - Start subject lines with an action verb in past tense (`Added`, `Changed`,
131
+ `Fixed`, `Removed`).
132
+ - Keep subjects user-facing so auto-generated release notes are meaningful.
133
+ - Group related changes into focused commits instead of one broad commit.
134
+ - Example: `Fixed timeout handling in status command`
135
+ 6. Tag and push:
136
+ - `git tag vX.Y.Z`
137
+ - `git push origin main --follow-tags`
138
+ 7. Confirm GitHub Actions:
139
+ - CI should pass.
140
+ - Publish workflow should upload to PyPI and create GitHub Release notes.
141
+ - Release notes should include generated notes plus a commit summary from the
142
+ previous tag to the current tag.
143
+
110
144
  ## License
111
145
 
112
146
  Apache-2.0
@@ -0,0 +1,39 @@
1
+ # TODO
2
+
3
+ Keep the project focused on managing AI coding CLI tools (install, upgrade,
4
+ remove, status, and version metadata).
5
+
6
+ ## Reliability and Correctness
7
+
8
+ - [ ] Handle missing `node` cleanly during prerequisite checks
9
+ (`FileNotFoundError` path in Node version probing).
10
+ - [ ] Read tool version output from both stdout and stderr so status does not
11
+ miss installed versions.
12
+ - [ ] Make version cache writes atomic (write temp file + rename) to avoid
13
+ partial/corrupted `versions.json`.
14
+
15
+ ## Security and Integrity
16
+
17
+ - [ ] Add integrity verification for direct-download tarballs (not only install
18
+ script SHA256).
19
+ - [ ] Extend tool metadata to support tarball checksum/signature fields where
20
+ applicable.
21
+
22
+ ## CLI and Automation UX
23
+
24
+ - [ ] Add `--json` output mode for `list`, `status`, and `update-versions`.
25
+ - [ ] Add a focused `doctor` command for environment checks (PATH,
26
+ prerequisites, command health).
27
+ - [ ] Consider `install --force` for reinstall/repair flows.
28
+ - [ ] Add cleanup support for stale direct-download versions no longer in use.
29
+
30
+ ## Platform and Package Detection
31
+
32
+ - [ ] Broaden system package metadata detection beyond Gentoo-specific tooling
33
+ where practical.
34
+
35
+ ## Maintainability and Tests
36
+
37
+ - [ ] Split larger modules into smaller focused files where practical
38
+ (`commands_actions.py`, `versions.py`, `install.py`).
39
+ - [ ] Add tests for prerequisite edge cases and cache write behavior.
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "code-aide"
3
- version = "1.0.2"
3
+ dynamic = ["version"]
4
4
  description = "Manage AI coding CLI tools (Claude, Copilot, Cursor, Gemini, Amp, Codex)"
5
5
  readme = "README.md"
6
6
  authors = [
@@ -37,6 +37,9 @@ code-aide = "code_aide.__main__:main"
37
37
  requires = ["hatchling"]
38
38
  build-backend = "hatchling.build"
39
39
 
40
+ [tool.hatch.version]
41
+ path = "src/code_aide/__init__.py"
42
+
40
43
  [tool.pytest.ini_options]
41
44
  testpaths = ["tests"]
42
45
 
@@ -1,3 +1,3 @@
1
1
  """code-aide - Manage AI coding CLI tools."""
2
2
 
3
- __version__ = "1.0.2"
3
+ __version__ = "1.1.0"
@@ -26,6 +26,7 @@ from code_aide.config import (
26
26
  load_bundled_tools,
27
27
  load_versions_cache,
28
28
  merge_cached_versions,
29
+ save_bundled_versions,
29
30
  save_updated_versions,
30
31
  )
31
32
 
@@ -233,7 +234,8 @@ def cmd_update_versions(args: argparse.Namespace) -> None:
233
234
  """Handle update-versions command: check upstream for latest tool versions."""
234
235
  bundled = load_bundled_tools()
235
236
  tools = bundled.get("tools", {})
236
- merge_cached_versions(tools, load_versions_cache())
237
+ if not args.bundled:
238
+ merge_cached_versions(tools, load_versions_cache())
237
239
 
238
240
  config: Dict[str, Any] = {"tools": tools}
239
241
 
@@ -290,11 +292,19 @@ def cmd_update_versions(args: argparse.Namespace) -> None:
290
292
  tool_entry["latest_date"] = date
291
293
  version_info_changed = True
292
294
 
295
+ def _save(tools: dict) -> str:
296
+ """Save versions to bundled or user cache. Returns description."""
297
+ if args.bundled:
298
+ path = save_bundled_versions(tools)
299
+ return path
300
+ save_updated_versions(tools)
301
+ return "~/.config/code-aide/versions.json"
302
+
293
303
  updates = [result for result in results if result["update"]]
294
304
  if not updates:
295
305
  if version_info_changed and not args.dry_run:
296
- save_updated_versions(config["tools"])
297
- print("Updated latest version info in ~/.config/code-aide/versions.json.")
306
+ dest = _save(config["tools"])
307
+ print(f"Updated latest version info in {dest}.")
298
308
  if version_info_changed:
299
309
  print(
300
310
  "No installer checksum updates required "
@@ -325,18 +335,16 @@ def cmd_update_versions(args: argparse.Namespace) -> None:
325
335
  return
326
336
  if answer not in ("y", "yes"):
327
337
  if version_info_changed:
328
- save_updated_versions(config["tools"])
329
- print(
330
- "Updated latest version info in ~/.config/code-aide/versions.json."
331
- )
338
+ dest = _save(config["tools"])
339
+ print(f"Updated latest version info in {dest}.")
332
340
  else:
333
341
  print("No changes made.")
334
342
  return
335
343
 
336
344
  updated = apply_sha256_updates(config, results)
337
- save_updated_versions(config["tools"])
345
+ dest = _save(config["tools"])
338
346
 
339
- print(f"\nUpdated {len(updated)} tool(s) in ~/.config/code-aide/versions.json:")
347
+ print(f"\nUpdated {len(updated)} tool(s) in {dest}:")
340
348
  for name in updated:
341
349
  print(f" {name}")
342
350
  if version_info_changed:
@@ -103,3 +103,29 @@ def save_updated_versions(tools: dict) -> None:
103
103
  if entry:
104
104
  cache_data["tools"][tool_key] = entry
105
105
  save_versions_cache(cache_data)
106
+
107
+
108
+ def save_bundled_versions(tools: dict) -> str:
109
+ """Update dynamic fields in the bundled data/tools.json.
110
+
111
+ Loads the existing bundled file to preserve static fields, then
112
+ overwrites only the dynamic version fields from the provided tools
113
+ dict. Returns the file path written.
114
+ """
115
+ ref = importlib.resources.files("code_aide").joinpath("data/tools.json")
116
+ path = str(ref)
117
+
118
+ with open(path, encoding="utf-8") as f:
119
+ bundled = json.load(f)
120
+
121
+ for tool_key, tool_data in tools.items():
122
+ if tool_key in bundled.get("tools", {}):
123
+ for field in DYNAMIC_FIELDS:
124
+ if field in tool_data:
125
+ bundled["tools"][tool_key][field] = tool_data[field]
126
+
127
+ with open(path, "w", encoding="utf-8") as f:
128
+ json.dump(bundled, f, indent=2)
129
+ f.write("\n")
130
+
131
+ return path
@@ -30,8 +30,13 @@
30
30
  "command": "claude",
31
31
  "install_type": "self_managed",
32
32
  "npm_package": "@anthropic-ai/claude-code",
33
- "upgrade_command": ["claude", "upgrade"],
34
- "prerequisites": ["npm"],
33
+ "upgrade_command": [
34
+ "claude",
35
+ "upgrade"
36
+ ],
37
+ "prerequisites": [
38
+ "npm"
39
+ ],
35
40
  "min_node_version": null,
36
41
  "next_steps": "Run 'claude' and then use '/login' to authenticate",
37
42
  "version_args": [
@@ -39,8 +44,8 @@
39
44
  ],
40
45
  "docs_url": "https://docs.anthropic.com/en/docs/build-with-claude/claude-code",
41
46
  "default_install": true,
42
- "latest_version": "2.1.62",
43
- "latest_date": "2026-02-27"
47
+ "latest_version": "2.1.63",
48
+ "latest_date": "2026-02-28"
44
49
  },
45
50
  "gemini": {
46
51
  "name": "Gemini CLI",
@@ -57,7 +62,7 @@
57
62
  ],
58
63
  "docs_url": "https://github.com/google-gemini/gemini-cli",
59
64
  "default_install": true,
60
- "latest_version": "0.30.1",
65
+ "latest_version": "0.31.0",
61
66
  "latest_date": "2026-02-27"
62
67
  },
63
68
  "amp": {
@@ -75,8 +80,8 @@
75
80
  ],
76
81
  "docs_url": "https://ampcode.com/manual",
77
82
  "default_install": false,
78
- "latest_version": "0.0.1772222620-g1de875",
79
- "latest_date": "2026-02-27"
83
+ "latest_version": "0.0.1772308894-g06c525",
84
+ "latest_date": "2026-02-28"
80
85
  },
81
86
  "codex": {
82
87
  "name": "Codex CLI",
@@ -40,7 +40,6 @@ def main() -> None:
40
40
  install_parser.add_argument(
41
41
  "tools",
42
42
  nargs="*",
43
- choices=list(TOOLS.keys()),
44
43
  help="Tools to install (default: all)",
45
44
  )
46
45
  install_parser.add_argument(
@@ -62,8 +61,7 @@ def main() -> None:
62
61
  upgrade_parser.add_argument(
63
62
  "tools",
64
63
  nargs="*",
65
- choices=list(TOOLS.keys()),
66
- help="Tools to upgrade (default: all)",
64
+ help="Tools to upgrade (default: out-of-date only)",
67
65
  )
68
66
  upgrade_parser.set_defaults(func=cmd_upgrade)
69
67
 
@@ -71,7 +69,6 @@ def main() -> None:
71
69
  remove_parser.add_argument(
72
70
  "tools",
73
71
  nargs="*",
74
- choices=list(TOOLS.keys()),
75
72
  help="Tools to remove (default: all)",
76
73
  )
77
74
  remove_parser.set_defaults(func=cmd_remove)
@@ -103,6 +100,12 @@ def main() -> None:
103
100
  action="store_true",
104
101
  help="Show full SHA256 hashes",
105
102
  )
103
+ update_versions_parser.add_argument(
104
+ "-b",
105
+ "--bundled",
106
+ action="store_true",
107
+ help="Update bundled data/tools.json instead of user cache (developer use)",
108
+ )
106
109
  update_versions_parser.set_defaults(func=cmd_update_versions)
107
110
 
108
111
  args = parser.parse_args()
@@ -2,10 +2,12 @@
2
2
 
3
3
  import contextlib
4
4
  import io
5
+ import sys
5
6
  import unittest
6
7
  from unittest import mock
7
8
 
8
9
  from code_aide import commands_actions
10
+ from code_aide import entry
9
11
 
10
12
 
11
13
  class TestCmdInstall(unittest.TestCase):
@@ -55,7 +57,13 @@ class TestCmdUpdateVersions(unittest.TestCase):
55
57
  args = type(
56
58
  "Args",
57
59
  (),
58
- {"tools": ["missing"], "dry_run": False, "yes": False, "verbose": False},
60
+ {
61
+ "tools": ["missing"],
62
+ "dry_run": False,
63
+ "yes": False,
64
+ "verbose": False,
65
+ "bundled": False,
66
+ },
59
67
  )()
60
68
  with mock.patch.object(
61
69
  commands_actions,
@@ -71,7 +79,13 @@ class TestCmdUpdateVersions(unittest.TestCase):
71
79
  args = type(
72
80
  "Args",
73
81
  (),
74
- {"tools": [], "dry_run": True, "yes": False, "verbose": False},
82
+ {
83
+ "tools": [],
84
+ "dry_run": True,
85
+ "yes": False,
86
+ "verbose": False,
87
+ "bundled": False,
88
+ },
75
89
  )()
76
90
  with (
77
91
  mock.patch.object(
@@ -109,3 +123,80 @@ class TestCmdUpdateVersions(unittest.TestCase):
109
123
  commands_actions.cmd_update_versions(args)
110
124
  self.assertIn("No upstream config changes detected.", buf.getvalue())
111
125
  mock_save.assert_not_called()
126
+
127
+
128
+ def test_bundled_flag_skips_cache_and_saves_to_bundled(self):
129
+ args = type(
130
+ "Args",
131
+ (),
132
+ {
133
+ "tools": [],
134
+ "dry_run": False,
135
+ "yes": True,
136
+ "verbose": False,
137
+ "bundled": True,
138
+ },
139
+ )()
140
+ bundled_tools = {
141
+ "tools": {
142
+ "ok": {
143
+ "install_type": "npm",
144
+ "npm_package": "pkg",
145
+ "latest_version": "1.0.0",
146
+ "latest_date": "2026-01-01",
147
+ }
148
+ }
149
+ }
150
+ with (
151
+ mock.patch.object(
152
+ commands_actions,
153
+ "load_bundled_tools",
154
+ return_value=bundled_tools,
155
+ ),
156
+ mock.patch.object(
157
+ commands_actions, "load_versions_cache", return_value={}
158
+ ) as mock_cache,
159
+ mock.patch.object(
160
+ commands_actions, "merge_cached_versions"
161
+ ) as mock_merge,
162
+ mock.patch.object(
163
+ commands_actions,
164
+ "check_npm_tool",
165
+ return_value={
166
+ "tool": "ok",
167
+ "type": "npm",
168
+ "version": "2.0.0",
169
+ "date": "2026-02-01",
170
+ "status": "ok",
171
+ "update": None,
172
+ },
173
+ ),
174
+ mock.patch.object(commands_actions, "print_check_results_table"),
175
+ mock.patch.object(commands_actions, "save_updated_versions") as mock_save,
176
+ mock.patch.object(
177
+ commands_actions, "save_bundled_versions", return_value="/fake/path"
178
+ ) as mock_bundled,
179
+ ):
180
+ buf = io.StringIO()
181
+ with contextlib.redirect_stdout(buf):
182
+ commands_actions.cmd_update_versions(args)
183
+
184
+ mock_cache.assert_not_called()
185
+ mock_merge.assert_not_called()
186
+ mock_save.assert_not_called()
187
+ mock_bundled.assert_called_once()
188
+
189
+
190
+ class TestUpgradeNoArgsParsing(unittest.TestCase):
191
+ """Test that 'code-aide upgrade' with no arguments parses successfully."""
192
+
193
+ def test_upgrade_with_no_args_parses_to_empty_tools_list(self):
194
+ with (
195
+ mock.patch.object(sys, "argv", ["code-aide", "upgrade"]),
196
+ mock.patch.object(entry, "cmd_upgrade") as mock_upgrade,
197
+ ):
198
+ entry.main()
199
+ mock_upgrade.assert_called_once()
200
+ (args,) = mock_upgrade.call_args[0]
201
+ self.assertEqual(args.command, "upgrade")
202
+ self.assertEqual(args.tools, [])
@@ -1,15 +0,0 @@
1
- name: Publish to PyPI
2
- on:
3
- push:
4
- tags: ["v*"]
5
- jobs:
6
- publish:
7
- runs-on: ubuntu-latest
8
- permissions:
9
- contents: read
10
- id-token: write
11
- steps:
12
- - uses: actions/checkout@v4
13
- - uses: astral-sh/setup-uv@v5
14
- - run: uv build
15
- - uses: pypa/gh-action-pypi-publish@release/v1
File without changes
File without changes
File without changes