Skip to content

feat(ais_core): implement repo_resolve library + minimal migration (#470, Issue #1b) - #487

Open
SaJaToGu wants to merge 1 commit into
devfrom
ais-fix-470-repo-resolution
Open

feat(ais_core): implement repo_resolve library + minimal migration (#470, Issue #1b)#487
SaJaToGu wants to merge 1 commit into
devfrom
ais-fix-470-repo-resolution

Conversation

@SaJaToGu

Copy link
Copy Markdown
Owner

Closes #470 (Issue #1b — Wave 1b, Repo-Resolution)

Strict Parallel-Implementation + Comparison-Tests approach

Per the #470 review feedback, this PR follows the
expand-and-contract pattern: implement the new library
functionality in parallel to existing script logic, pin the
existing behaviour with characterization tests, write
comparison tests that show library and legacy agree on the
simple (owner, repo) case, then migrate ONE small
integration point
with no broad refactor.

What's in this PR

ais_core/repo_resolve.py — new library

  • ResolvedRepo (NamedTuple): owner, repo, remote, local_path
  • resolve_from_owner_repo(owner, repo) -> ResolvedRepo
    • No GitHub API call. Validates GitHub naming rules
      (1-39 owner, 1-100 repo, alnum + - _ . + no
      leading/trailing separators), strips whitespace, returns
      ResolvedRepo with canonical
      https://github.com/{owner}/{repo} and local_path=None.
  • resolve_from_git_remote(path) -> ResolvedRepo
    • Reads remote.origin.url via local git -C path config --get
      (no network). Parses via urllib.parse for HTTPS, ssh://,
      and git@host:owner/repo forms.
    • Returns ResolvedRepo with local_path set.
  • resolve_repo_hint(hint) -> ResolvedRepo
    • Dispatch:
      • existing directory → resolve_from_git_remote
      • "owner/repo" → split + resolve_from_owner_repo
      • bare "repo"resolve_from_owner_repo with
        GITHUB_USER env-var default

Internal helpers: _validate_component, _read_git_remote_url,
_parse_git_remote_url, _canonical_remote, _parse_http_or_ssh.

tests/test_ais_core/test_repo_resolve.py — 34 tests

  • Unit tests for each public function
  • URL parser tests (HTTPS with/without .git, with
    trailing slash, SSH short form, ssh:// form, invalid input)
  • Characterization test_legacy_resolve() helper pins the
    pre-0.10.0 Issue #1b — Repo-Resolution extrahieren (ein Script nutzt es) #470 behaviour. NOT exported as a production function;
    test-only, and explicitly documents that the library CHANGES
    whitespace handling (semantic tightening) versus the legacy.
  • Comparison tests — library and _legacy_resolve() agree
    on the (owner, repo) case for realistic owners
    (SaJaToGu, python, microsoft).
  • No-network testmock.patch on subprocess.run and
    urllib.request.urlopen confirms resolve_from_owner_repo
    makes no network calls.

scripts/solve_issues.py — ONE small integration point

After the preflight_checks block, this single call exercises the
library code path:

if args.repo:
    from ais_core.repo_resolve import resolve_from_owner_repo
    _resolved_repo = resolve_from_owner_repo(user, args.repo)
    del _resolved_repo  # suppress unused-variable lint

The result is deliberately unused. Per the strict-pattern
directive, the migration is a single integration point that
proves the library works against the script's actual values, with
no broad refactor of the existing args.repo / user handling.
Old logic for "owner from config" stays untouched.

Out of scope (intentional)

  • No GitHub API integration — resolve_from_owner_repo does
    not verify the repo exists on github.com.
  • No SSH-vs-HTTPS preference — canonical remote is always HTTPS.
  • No GitHub Enterprise / sub-group support.
  • No routing of args.repo / user through the library beyond
    the one smoke-use call.
  • No removal of the test-helper _legacy_resolve() — it is
    pinned in test_legacy_resolve_basic to keep the
    comparison-test infrastructure intact.

Tests

python -m unittest tests.test_ais_core.test_repo_resolve \ tests.test_ais_core.test_json_contract \ tests.test_ais_core.test_run_state \ tests.test_ais_core.test_secret_filter \ tests.test_ais_core.test_issue_resolve

120 tests, 1.068s, all OK.

LOC

File Lines
ais_core/repo_resolve.py 294
tests/test_ais_core/test_repo_resolve.py 361
scripts/solve_issues.py (delta) +9

Parent issue

Part of #468 (Release 0.10.0 — AIS Tooling Interface).

@SaJaToGu
SaJaToGu force-pushed the ais-fix-470-repo-resolution branch from b8edeb7 to fc4731c Compare June 28, 2026 16:06
…ssue #1b)

Strict parallel-implementation + comparison-tests approach (per #470
review):

1. ais_core/repo_resolve.py: full implementation of the three
   resolvers from the issue acceptance criteria, plus internal
   helpers _validate_component, _read_git_remote_url,
   _parse_git_remote_url, _canonical_remote, _parse_http_or_ssh.

   - resolve_from_owner_repo(owner, repo): pure normalize, no API
     call, validates GitHub naming rules (1-39 owner, 1-100 repo,
     alnum + - _ . + no leading/trailing separators).
   - resolve_from_git_remote(path): reads remote.origin.url via
     'git -C path config --get' (local git binary, no network),
     parses via urllib.parse for HTTPS / ssh:// / git@ forms.
   - resolve_repo_hint(hint): dispatches to the appropriate
     resolver — directory hint -> git-remote, 'owner/repo' ->
     split+normalize, bare 'repo' -> GITHUB_USER env default.

2. tests/test_ais_core/test_repo_resolve.py: 34 tests covering
   - Unit tests for each public function
   - Direct URL-parser tests (https with/without .git, with
     trailing slash, ssh short form, ssh:// form, invalid)
   - Characterization test: _legacy_resolve() helper pins the
     pre-#470 behaviour (NOT exported, test-only, documents that
     the library CHANGES whitespace handling as an explicit
     semantic tightening)
   - Comparison tests: library and _legacy_resolve() agree on
     the (owner, repo) case for realistic owners
   - No-network test: monkey-patch subprocess/socket to ensure
     resolve_from_owner_repo makes no network calls

3. scripts/solve_issues.py: ONE small migration point after the
   preflight_checks block. Calls resolve_from_owner_repo(user,
   args.repo) to validate the integration. The result is
   currently unused; no broad refactor of args.repo / user
   handling per the strict-pattern directive. Old logic for
   owner-from-config stays untouched.

Tests: 120 OK in 1.068s (full ais_core suite: repo_resolve,
json_contract, run_state, secret_filter, issue_resolve).

Refs #470
@SaJaToGu
SaJaToGu force-pushed the ais-fix-470-repo-resolution branch from fc4731c to 8028c57 Compare June 28, 2026 20:18
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

0.10.0 Issue #1b — Repo-Resolution extrahieren (ein Script nutzt es)

1 participant