Skip to content

setup-project.py: the credential-helper warnings speak where an insteadOf rule sends github.com over ssh, or a URL-scoped helper answers, and the check reads ~ files git does not read #1013

Closed

Description

@brettheap

Goal: setup-project.py's two credential-helper [??] warnings (the no-helper one, and #1008's store-holding-no-githubproxy.fjygbaifeng.eu.org-login one) stay silent on a machine where git will not ask a credential helper at all (a url.<base>.insteadOf rule sends github.com over ssh) or where a helper under a URL-scoped key does answer, and the check finds the ~ files store reads by asking git for them, so a HOME git cannot expand no longer sends it to files git never reads.

Filed by lane openRepoShape-3, from RV1008's review of #1008 (issuecomment-6278166602).

State. Read at origin/main 7fa60a57 and at #1008's head b2dbc8b2 (open, a draft, found READY by RV1008 with no MUST). #1008 closes #992 and is not merged, so the store warning, and with it NIT-1 to NIT-5 below, exist only at that head; the line numbers are #1008's, in setup-project.py and tests/test_setup_project_py.py. SHOULD-1's no-helper half is at main too, where the same code is _credential_helper_configured (:1288) and its warning (:1333). This follows #1008 and does not block it.

  • _credential_helpers (:1289) asks git for two keys only, credential.https://githubproxy.fjygbaifeng.eu.org.helper and credential.helper (git config --get-all, :1303), from the folder the run starts in. It never asks which URL git will use for github.com.
  • _why_no_login (:1380-1406) says there is no login when that list is empty (the no-helper sentence, byte for byte as at main) or when every helper is store and no file of theirs holds a github.com login. _check_credential_helper (:1409) prints the [??] and, at a terminal, offers gh auth setup-git. Only opts.local_mode returns before it.
  • _store_files (:1310) builds the two files store reads from os.environ.get("HOME") or os.path.expanduser("~") (:1326) and $XDG_CONFIG_HOME, or ~/.config where that is unset or empty.
  • The scaffold supports the ssh machines: SSH_KEY_CLAUSE (scaffold-project.py:686 at main) and the docstring of _exists_remedy (scaffold-project.py: a --reuse-empty-repo re-run can stop at a git, ssh or helper prompt on its pushes and seed fetch, and an ssh-rewrite operator's refusal gives git's generic line and a remedy that does not apply #915) say that where an insteadOf rule sends https://github.com/ over ssh, git logs in with an ssh key, and gh auth setup-git does nothing for it. The preflight's remedy is that very command.

What happens. Three groups. Exit codes and steps are unchanged in every row; what differs is the [??] line and, at a terminal, its offer. Each machine below is a hand-made git config.

RV1008's SHOULD-1, both warnings. With url.git@github.com:.insteadOf https://github.com/ in git's config, git ls-remote --get-url https://github.com/demoorg/x.git prints git@github.com:demoorg/x.git, so the push goes over ssh and git never asks a credential helper. Both warnings still speak there (RV1008's rows, read again by lane 3 at main 3864b18c and at #1008's head b2dbc8b2, git 2.43.0, --preflight exit 0 each time):

the machine                                     main    #1008 head
insteadOf rule, no helper                       [??]    [??], the same line byte for byte
insteadOf rule, `store` over an empty
  ~/.git-credentials                            silent  [??] and the offer

So the no-helper warning has always been blind to an insteadOf rule, and #1008's store warning adds a second false [??] for the same machines. A rule keyed to one org (url.git@github.com:demoorg/.insteadOf https://github.com/demoorg/) rewrites only that org: measured, git ls-remote --get-url gives git@github.com:demoorg/x.git for demoorg and https://github.com/other/x.git for other. A url.<base>.pushInsteadOf rule alone leaves --get-url at the https:// URL.

RV1008's NIT-1, a URL-scoped helper. With store in credential.helper and a helper under another spelling of the scoped key, credential.https://github.com/.helper (with the trailing slash), git asks that helper: measured, git credential fill with the prompt off exits 0 and prints a login from a made-up helper, where over store alone it exits 128 with fatal: could not read Username for 'https://github.com': terminal prompts disabled. The check reads only credential.https://githubproxy.fjygbaifeng.eu.org.helper (no slash), so it sees store alone: main silent, #1008's head [??] over an empty store file. Lane 3's row at both trees reads the same. #1008's decision 1 says only that such a helper "stays invisible to both warnings", which for the head is a new false [??], since main was silent over store there. git config --get-urlmatch credential.helper https://github.com/demoorg/x.git prints only the best match (the scoped helper, not store), so it is no drop-in fix.

RV1008's NIT-5, HOME unset and Git for Windows' own HOME. With HOME unset git cannot expand ~: git -c <k>='~/.git-credentials' config --type=path --get <k> prints fatal: failed to expand user dir in: '~/.git-credentials' and exits 128 (lane 3 read the same), so git's store reads no ~ file at all. The check falls back to os.path.expanduser("~") (:1326), the passwd home: lane 3's --preflight with HOME unset and store over nothing names <passwd home>/.git-credentials and <passwd home>/.config/git/credentials, two files git never reads there. Git for Windows also chooses its own HOME (HOMEDRIVE and HOMEPATH), which the check does not read; #1008 said that was not measured, and it is not measured here either.

Also in this issue, three smaller ones from the same review.

Evidence.

Direction. As RV1008 gives it.

  1. SHOULD-1, both warnings. Ask git ls-remote --get-url (local, no network) for the github.com URL the run will give git, and skip both warnings where the answer does not start with https://. Ask with the org --org names (opts.org) where the run has one: a rule keyed to https://github.com/<org>/ answers for that org only (measured above). A pushInsteadOf rule alone does not change the answer, and the warnings stay as they are there; a row pins that.
  2. NIT-1. --get-urlmatch is no drop-in. Either read every credential.<url>.helper key whose URL matches github.com (git config --get-regexp) and count those helpers with the other two keys, or stay silent where such a key exists; the writer chooses, and a row pins the choice. Say in _check_credential_helper's docstring which spellings of the key it reads.
  3. NIT-5. Ask git for each ~ path: git -c <k>='~/.git-credentials' config --type=path --get <k>, and the same for ~/.config/git/credentials where XDG_CONFIG_HOME is unset or empty. Measured: with HOME=/fup1008/home it prints /fup1008/home/.git-credentials; with HOME unset it exits 128, which means "git reads no ~ file", so the check names none. That also covers Git for Windows' choice of HOME.
  4. NIT-2. Reword :1390, and give :1367-1368 the reason, to say that git's store reads a file it may not open as empty and dies on a folder, so this check cannot say what such a file holds and says nothing. Keep the silence.
  5. NIT-3. Rewrap :1416 in the same edit.
  6. NIT-4. Add one real-git row: GIT_CONFIG_SYSTEM holding credential.helper=store, an empty scratch HOME, a global config without it, asserting the [??].
  7. No code outside setup-project.py and its test file, no flag or --help line: AGENTS.md, docs/cli.md and the handbook stay as they are, and setup-project.py is not a pinned copy, so no project re-pins. Re-read the README and handbook lines above after the fix, since a silent case is added to "whichever is missing".

Verify.

  • --preflight at a real git, run from a folder other than the checkout, under a stub gh that exits 97 on all but --version and auth status, with GH_TOKEN=bogus, an empty GH_CONFIG_DIR, GIT_SSH_COMMAND=false, and system config, global config and HOME in scratch. Each row exits 0 and prints the following:
  • In tests/test_setup_project_py.py: a row per case above, and the NIT-4 real-git row, which fails with RV1008's mutant R1 (helpers read with --global only).
  • git grep of setup-project.py for "a file this cannot read, may answer" finds nothing, and no line of :1289-1470 is longer than 79 columns.
  • tests/test_setup_project_py.py, tests/test_setup_project_dry_run_offers.py, the docs guards (tests/test_agents_md_codes.py, tests/test_cli_reference.py, tests/test_update_add_codes_documented.py and tests/test_repo_hygiene.py) and tests/test_no_auto_maintenance.py pass, one file at a time under a stub gh.

Size. Small to medium: one git ls-remote --get-url call and an early return in _check_credential_helper, one git config --type=path call in _store_files, two docstring edits and a rewrap, and about seven test rows. Medium if NIT-1 reads every URL-scoped key.

Lane: openreposhape-3 (openRepoShape-3)

Activity

  1. added this to the v1.2.0 milestone on Oct 19, 2026
  2. brettheap commented on Oct 19, 2026

    @brettheap
    ContributorAuthor

    CLAIMED — lane openRepoShape-3, session b30e8b49-f249-4668-adb1-1dbfa93c09e1@Eagle, 2026-10-19T22:45:10Z, for #1013

    Logged in lanes/log/openRepoShape-3.md at 40f29b5c9e0809a041d2441a4ca078b9efc95177.

    The three reads (lane-collision-protocol Rule 1):

    1. existing `CLAIMED —` comments on opensoft/openRepoShape#1013:
       none
    2. `gh pr list --repo opensoft/openRepoShape --state all --search "#1013"`, kept where the row or its body names `#1013`:
       none
    3. `git ls-remote --heads git@github.com:opensoft/openRepoShape` branches naming `1013` as a whole token:
       none
    
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions