From ef8d031427bcdcf513ab99a9935062b72f54859c Mon Sep 17 00:00:00 2001 From: Marek Rychlik Date: Sat, 21 Feb 2026 10:30:01 -0700 Subject: [PATCH 1/2] Improve Forge auth error guidance for PR flow --- agentic.el | 35 +++++++++++++++++++++++++++++------ 1 file changed, 29 insertions(+), 6 deletions(-) diff --git a/agentic.el b/agentic.el index 581cd01..55acbe7 100644 --- a/agentic.el +++ b/agentic.el @@ -596,21 +596,44 @@ Never returns nil; unreadable files yield \"\"." ;; Forge: open PR ;; ------------------------------------------------------------------- +(defun agentic--forge-credentials-help () + "Return short setup instructions for Forge/GitHub credentials." + (string-join + '("Forge authenticates to GitHub via `ghub` and `auth-source`." + "Add a Personal Access Token entry such as:" + " machine api.github.com login YOUR_GITHUB_USERNAME password YOUR_TOKEN" + "Store it in `~/.authinfo.gpg` (recommended) or another file from `auth-sources`." + "You can also run `M-x ghub-create-token` to generate/store a token interactively.") + "\n")) + +(defun agentic--signal-forge-auth-error (err) + "Raise a user-facing Forge authentication error from ERR." + (let ((msg (error-message-string err))) + (if (string-match-p "[Bb]ad credentials\\|401\\|403" msg) + (user-error "agentic: Forge authentication failed (%s).\n\n%s" + msg + (agentic--forge-credentials-help)) + (signal (car err) (cdr err))))) + ;;;###autoload -(defun agentic/forge-open-pr (title body) +(defun agentic/forge-open-pr () "Open a GitHub pull request for the current branch via Forge. -TITLE and BODY are used to populate the PR. Ensure `forge` is configured -for this repository (`M-x forge-add-repository` first time)." - (interactive "sPR title: \nsPR body: ") +Ensure `forge` is configured for this repository +(`M-x forge-add-repository` first time). If Forge reports a credentials error, +configure GitHub credentials for `ghub` in `auth-source` (see helper message)." + (interactive) (agentic--ensure-forge) (let ((repo (or (forge-get-repository t) (progn (call-interactively #'forge-add-repository) (forge-get-repository t))))) (unless repo (user-error "agentic: no Forge repository configured")) (magit-push-current-to-pushremote nil) - (forge-create-pullreq repo title body) - (message "agentic: PR created (check your browser or Forge buffer)."))) + (condition-case err + (progn + (forge-create-pullreq) + (message "agentic: PR submit buffer opened (complete title/body in Forge).")) + (error (agentic--signal-forge-auth-error err))))) (provide 'agentic) ;;; agentic.el ends here From 3e4646ff6bc30a8b83abd252465ff9fe679824e2 Mon Sep 17 00:00:00 2001 From: Marek Rychlik Date: Sat, 21 Feb 2026 10:30:57 -0700 Subject: [PATCH 2/2] Preflight Forge auth-source credentials for PR creation --- agentic.el | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/agentic.el b/agentic.el index 55acbe7..bcc6166 100644 --- a/agentic.el +++ b/agentic.el @@ -601,11 +601,19 @@ Never returns nil; unreadable files yield \"\"." (string-join '("Forge authenticates to GitHub via `ghub` and `auth-source`." "Add a Personal Access Token entry such as:" - " machine api.github.com login YOUR_GITHUB_USERNAME password YOUR_TOKEN" + " machine api.github.com login YOUR_GITHUB_USERNAME^forge password YOUR_TOKEN" + "(`login USERNAME^forge` is recommended so Forge/ghub can select the token reliably.)" "Store it in `~/.authinfo.gpg` (recommended) or another file from `auth-sources`." "You can also run `M-x ghub-create-token` to generate/store a token interactively.") "\n")) + +(defun agentic--forge-auth-source-configured-p () + "Return non-nil when auth-source has a likely GitHub token for Forge/ghub." + (and (require 'auth-source nil t) + (or (auth-source-search :host "api.github.com" :max 1 :require '(:secret)) + (auth-source-search :host "github.com" :max 1 :require '(:secret))))) + (defun agentic--signal-forge-auth-error (err) "Raise a user-facing Forge authentication error from ERR." (let ((msg (error-message-string err))) @@ -628,6 +636,9 @@ configure GitHub credentials for `ghub` in `auth-source` (see helper message)." (progn (call-interactively #'forge-add-repository) (forge-get-repository t))))) (unless repo (user-error "agentic: no Forge repository configured")) + (unless (agentic--forge-auth-source-configured-p) + (user-error "agentic: no GitHub credentials found in `auth-source`.\n\n%s" + (agentic--forge-credentials-help))) (magit-push-current-to-pushremote nil) (condition-case err (progn