Skip to content

fix(release): repair Homebrew/WinGet publish auth for external-repo checkouts - #2161

Merged
tamirdresher merged 2 commits into
devfrom
fix/external-checkout-auth
Oct 3, 2026
Merged

tamirdresher merged 2 commits into
devfrom
fix/external-checkout-auth

Conversation

@tamirdresher

Copy link
Copy Markdown
Collaborator

Problem

The v1.0.0 release run (#37104124444) failed in both \publish-homebrew\ and \publish-winget\ at their \�ctions/checkout\ steps, which clone external repos (\�radygaster/homebrew-squad, \microsoft/winget-pkgs, \ amirdresher/winget-pkgs) using a custom classic PAT:

\
fatal: could not read Username for 'https://github.com': terminal prompts disabled
\\

This happened on the original run and again identically on a manual \gh run rerun --failed, ruling out a transient infra blip. These are the only 4 places in the repo where \�ctions/checkout\ is used with a custom PAT against an external repository (every other checkout in the repo uses the default same-repo \GITHUB_TOKEN), and it's the first time this exact code path has ever executed (the jobs were added 2026-08-27).

Fix

Rather than guess at \�ctions/checkout's internal credential-helper/\includeIf\ mechanics, this removes the dependency on it entirely for these 4 steps:

  • All three target repos are public, so the initial clone never actually needs authentication — switched to plain anonymous \git clone.
  • Push credentials (only needed later, for \git push/\gh pr create) are set via a local, non-global \git config --local http..extraheader, scoped to just that one clone directory — never embedded in a remote URL, never printed, never persisted outside that job's ephemeral workspace.
  • Added an explicit preflight step to each job (\gh api user\ + .permissions.push\ check) so an actually-invalid/expired PAT fails fast with a clear, actionable error instead of a confusing low-level git auth error.

No changes to job graph, secrets, triggers, or permission scopes.

Validation

  • YAML parses cleanly.
  • Will be exercised live via a \workflow_dispatch\ of \squad-standalone-release.yml\ for the existing \�1.0.0\ tag after this merges and promotes to \main\ — that run doubles as the real functional test (no new npm/NuGet/GH Release artifacts are created or re-uploaded; it only resumes the still-pending Homebrew cask update and WinGet PR submission for the already-published v1.0.0).

Co-authored-by: Copilot App 223556219+Copilot@users.noreply.github.com

…/WinGet publish

The publish-homebrew and publish-winget jobs used actions/checkout with a
custom classic PAT against external repositories (bradygaster/homebrew-squad,
microsoft/winget-pkgs, tamirdresher/winget-pkgs). This failed deterministically
in the v1.0.0 release run (reproduced on rerun) with:
  fatal: could not read Username for 'https://github.com': terminal prompts disabled

Root cause not fully isolated (token validity could not be checked from
outside Actions), so this change removes the dependency on actions/checkout's
token/includeIf mechanism entirely rather than guessing around it:

- All three target repos are public, so the initial read/clone never actually
  needs authentication - switched to plain anonymous 'git clone'.
- Push credentials (needed only for the later 'git push'/gh pr create steps)
  are now set via a local, non-global 'git config --local http.<url>.extraheader'
  scoped to just that one clone directory - never embedded in a remote URL,
  never printed, and cleaned up automatically when the job's workspace is
  discarded.
- Added an explicit preflight step to each job that validates the relevant
  token via 'gh api user' and checks '.permissions.push' on the target repo
  before attempting any clone/push, so an actually-invalid/expired PAT fails
  fast with a clear, actionable error instead of surfacing as a confusing
  low-level git auth error.

No changes to job graph, secrets, or permissions scopes.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Copilot AI balanced review requested due to automatic review settings October 3, 2026 07:37
@github-actions

github-actions Bot commented Oct 3, 2026 •

Copy link
Copy Markdown
Contributor

🛫 PR Readiness Check

ℹ️ This comment updates on each push. Last checked: commit 8d95301

PR Scope: 🔧 Infrastructure

⚠️ 2 item(s) to address before review

Status Check Details
❌ Single commit 2 commits — consider squashing before review
✅ Not in draft Ready for review
✅ Branch up to date Up to date with dev
❌ Copilot review No Copilot review yet — it may still be processing
✅ Changeset present No source files changed — changeset not required
✅ Scope clean No .squad/ or docs/proposals/ files
✅ No merge conflicts No merge conflicts
✅ Copilot threads resolved 0 active Copilot thread(s) resolved (1 outdated skipped)
✅ CI passing All checks passing

Files Changed (1 file, +75 −23)

File +/−
.github/workflows/squad-standalone-release.yml +75 −23

Total: +75 −23


This check runs automatically on every push. Fix any ❌ items and push again.
See CONTRIBUTING.md and PR Requirements for details.

@github-actions

github-actions Bot commented Oct 3, 2026

Copy link
Copy Markdown
Contributor

🟢 Impact Analysis — PR #2161

Risk tier: 🟢 LOW

📊 Summary

Metric Count
Files changed 1
Files added 0
Files modified 1
Files deleted 0
Modules touched 1

🎯 Risk Factors

  • 1 files changed (≤5 → LOW)
  • 1 module(s) touched (≤1 → LOW)

📦 Modules Affected

ci-workflows (1 file)
  • .github/workflows/squad-standalone-release.yml

This report is generated automatically for every PR. See #733 for details.

@github-actions

github-actions Bot commented Oct 3, 2026 •

Copy link
Copy Markdown
Contributor

🔒 Security Review

Authoritative evidence: base-controlled pull_request_target reporter.

🔒 Security review: 8 warning(s).

Severity Category Finding Location
🟡 warning secrets-reference Non-standard secret reference in workflow — verify this secret is necessary and scoped correctly. .github/workflows/squad-standalone-release.yml:434
🟡 warning secrets-reference Non-standard secret reference in workflow — verify this secret is necessary and scoped correctly. .github/workflows/squad-standalone-release.yml:464
🟡 warning secrets-reference Non-standard secret reference in workflow — verify this secret is necessary and scoped correctly. .github/workflows/squad-standalone-release.yml:601
🟡 warning secrets-reference Non-standard secret reference in workflow — verify this secret is necessary and scoped correctly. .github/workflows/squad-standalone-release.yml:753
🟡 warning secrets-reference Non-standard secret reference in workflow — verify this secret is necessary and scoped correctly. .github/workflows/squad-standalone-release.yml:761
🟡 warning secrets-reference Non-standard secret reference in workflow — verify this secret is necessary and scoped correctly. .github/workflows/squad-standalone-release.yml:771
🟡 warning pii-env-var Environment variable with sensitive name pattern (CREDENTIALS) — ensure this isn't hardcoded. .github/workflows/squad-standalone-release.yml:460
🟡 warning pii-env-var Environment variable with sensitive name pattern (CREDENTIALS) — ensure this isn't hardcoded. .github/workflows/squad-standalone-release.yml:754

Automated security review — informational only.

@github-actions

github-actions Bot commented Oct 3, 2026

Copy link
Copy Markdown
Contributor

🏗️ Architectural Review

Authoritative evidence: base-controlled pull_request_target reporter.

⚠️ Architectural review: 1 info.

Severity Category Finding Files
ℹ️ info template-sync Template files changed in .github/workflows/ but not in other template locations. If these templates should stay in sync, consider updating the others too. Changed: .github/workflows/, Unchanged: templates/, .squad-templates/, packages/squad-cli/templates/

Automated architectural review — informational only.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Changes recommended

Existing workflow regression tests still assert the removed checkout steps and will fail.

1 open finding
What changed in this PR

Replaces failing authenticated external-repository checkouts with anonymous clones and locally scoped push credentials.

Changes:

  • Adds PAT authentication and push-access preflights.
  • Replaces Homebrew and WinGet checkout actions with Git clones.
  • Configures local authorization headers for subsequent pushes.
File Description
.github/​workflows/​squad-standalone-release.yml Updates external repository cloning and authentication.

🧠 Review effort: Balanced


💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

fetch-depth: 1
token: ${{ secrets.HOMEBREW_TAP_TOKEN }}
persist-credentials: true
- name: Clone Homebrew tap (read is anonymous; credential is scoped locally for the later push only)
…e credential persistence

The contract test (test/standalone-release-workflow.test.ts) asserts the
Homebrew tap checkout and the 'Check out existing WinGet version branch'
step remain real actions/checkout steps with specific with: fields
(repository/ref/path/token) - replacing them with raw git clone broke
that contract and failed the test job on PR #2161.

Revert those two specific steps to actions/checkout, but add
persist-credentials: false so the action does not attempt to write its
own git credential config (the suspected source of the original
'could not read Username... terminal prompts disabled' failure).
Credential configuration for the later git push is now done explicitly
via a scoped, local-only http.extraheader in a separate step - never
persisted globally, never logged, never embedded in a remote URL.

The two clones that are not covered by the contract test (the
read-only winget-base base clone and the new-branch clone from
microsoft/winget-pkgs master) remain anonymous git clone, since no
credential is needed to read these public repos.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
@tamirdresher
tamirdresher merged commit 8c0311c into dev Oct 3, 2026
18 checks passed
@tamirdresher
tamirdresher deleted the fix/external-checkout-auth branch October 3, 2026 08:18
@tamirdresher

Copy link
Copy Markdown
Collaborator Author

@bradygaster — brew shipped: the stable Squad Homebrew cask is now 1.0.0. Both macOS checksums were matched to the published release assets, and the cask was verified after publication.

WinGet submission is the remaining channel item; we have not yet confirmed an upstream PR URL and will share it once available. This is not an all-channels-complete report.

Please review the release automation repair here and the activation-pin update https://github.com/bradygaster/squad/pull/2163, subject to the normal checks. Sharing here because Teams is currently unavailable.

bradygaster pushed a commit that referenced this pull request Oct 3, 2026
…heckouts (#2164)

* fix(release): repair Homebrew/WinGet publish auth for external-repo checkouts (#2161)

* fix(release): replace broken external-repo checkout auth for Homebrew/WinGet publish

The publish-homebrew and publish-winget jobs used actions/checkout with a
custom classic PAT against external repositories (bradygaster/homebrew-squad,
microsoft/winget-pkgs, tamirdresher/winget-pkgs). This failed deterministically
in the v1.0.0 release run (reproduced on rerun) with:
  fatal: could not read Username for 'https://github.com': terminal prompts disabled

Root cause not fully isolated (token validity could not be checked from
outside Actions), so this change removes the dependency on actions/checkout's
token/includeIf mechanism entirely rather than guessing around it:

- All three target repos are public, so the initial read/clone never actually
  needs authentication - switched to plain anonymous 'git clone'.
- Push credentials (needed only for the later 'git push'/gh pr create steps)
  are now set via a local, non-global 'git config --local http.<url>.extraheader'
  scoped to just that one clone directory - never embedded in a remote URL,
  never printed, and cleaned up automatically when the job's workspace is
  discarded.
- Added an explicit preflight step to each job that validates the relevant
  token via 'gh api user' and checks '.permissions.push' on the target repo
  before attempting any clone/push, so an actually-invalid/expired PAT fails
  fast with a clear, actionable error instead of surfacing as a confusing
  low-level git auth error.

No changes to job graph, secrets, or permissions scopes.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>

* fix(release): keep actions/checkout for contract-tested steps, disable credential persistence

The contract test (test/standalone-release-workflow.test.ts) asserts the
Homebrew tap checkout and the 'Check out existing WinGet version branch'
step remain real actions/checkout steps with specific with: fields
(repository/ref/path/token) - replacing them with raw git clone broke
that contract and failed the test job on PR #2161.

Revert those two specific steps to actions/checkout, but add
persist-credentials: false so the action does not attempt to write its
own git credential config (the suspected source of the original
'could not read Username... terminal prompts disabled' failure).
Credential configuration for the later git push is now done explicitly
via a scoped, local-only http.extraheader in a separate step - never
persisted globally, never logged, never embedded in a remote URL.

The two clones that are not covered by the contract test (the
read-only winget-base base clone and the new-branch clone from
microsoft/winget-pkgs master) remain anonymous git clone, since no
credential is needed to read these public repos.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>

---------

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <Copilot@users.noreply.github.com>

* fix(release): avoid token-authenticated checkout for Homebrew tap read

The Homebrew tap checkout previously used actions/checkout with
'token: secrets.HOMEBREW_TAP_TOKEN' and 'persist-credentials: false'.
persist-credentials only controls whether the credential is scrubbed
AFTER the step completes - it does not change how the step's own
initial fetch authenticates. The real production failure (run
37104124444, job 111157909375) showed this exact checkout failing with
'fatal: could not read Username ... terminal prompts disabled' despite
a valid, non-empty token (preflight passed) - meaning the prior
persist-credentials:false change alone did not address the failing
mechanism.

bradygaster/homebrew-squad is a public repository, so the read-only
clone does not need any credential at all. Replace the token-bearing
actions/checkout with a plain anonymous 'git clone', and continue to
configure the push credential as a locally-scoped git config entry
(set only after the clone, only for the later push step) - this
removes the token from the path that was actually failing while
preserving scoped, non-persisted auth for the write operation.

Root cause of the exact actions/checkout auth-setup failure itself
remains unconfirmed (no definitive matching upstream report found);
this change eliminates the observed failure path rather than claiming
a confirmed upstream bug.

Updates the standalone-release-workflow contract test to assert the
new anonymous-clone + scoped-push-credential shape instead of the
token-bearing checkout shape.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>

* fix(release): apply same anonymous-clone pattern to WinGet branch reuse

The 'Check out existing WinGet version branch' step (exercised only
when re-publishing to an already-open version branch) used the same
token-bearing actions/checkout + persist-credentials:false shape that
was just shown to be unreliable for the Homebrew tap checkout. This
exact path has never been exercised by a real production run (the
only successful standalone-release run on record predates this
branch-reuse code and always took the branch_exists=false path), so
it carries the same latent risk without any positive evidence it
works.

tamirdresher/winget-pkgs is a public fork, so apply the identical fix:
anonymous git clone for the read, scoped local push credential
configured afterward only for the subsequent push. Update the
matching contract test.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>

---------

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <Copilot@users.noreply.github.com>
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.

3 participants