fix: don't configure the external-auth URL as a Composer GitHub token#180
Merged
Conversation
`coder external-auth access-token github` prints the token to stdout and exits 0, but when the user has no linked GitHub account it prints the *authentication URL* to stdout and exits 1. The token capture discarded that exit code with `|| true`, so workspaces whose owner had never authorized the deployment's GitHub app configured this as their OAuth token: [github-oauth.github.com] https://staging-coder.ddev.com/external-auth/github Every github.com dist download then failed with "Could not authenticate against github.com", and because Composer disables source fallback once authentication fails, all three composer install attempts failed the same way — the retry loop can't help, nothing here is transient. This is strictly worse than configuring no token at all: with none, Composer downloads anonymously and succeeds, which is exactly what happens once the bogus value is unset. - Honor the exit code, so only a real token is used. - Validate the token against api.github.com/user before configuring it, so an expired or revoked GITHUB_TOKEN fails loudly here instead of opaquely during install. - Unset any token a previous run configured when we don't have a valid one. Composer's global config lives in a persistent DDEV volume, so a bad value keeps breaking every later start even after this code stops writing one. Also stop running the cache rebuild when SETUP_FAILED is set — it sat outside the guard and appended a misleading "drush is not available" error after the real failure. Applied to drupal-contrib too, which had an identical copy of the block. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
|
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
A
drupal12workspace on staging failed all threecomposer installattempts withCould not authenticate against github.com, and never reached the Drupal install. The cause is the Composer GitHub OAuth token setup added in #166.coder external-auth access-token githubprints the token to stdout and exits 0 — but when the user has no linked GitHub account it prints the authentication URL to stdout and exits 1. The capture discarded that exit code with|| true, so the workspace configured this as its OAuth token:Composer then failed every dist download and, because it disables source fallback once authentication fails, never retried anonymously:
The retry loop can't help — nothing about this is transient. A bad token is strictly worse than no token: with none, Composer downloads anonymously and succeeds. Verified in the failing workspace — unsetting the value alone makes
ddev composer installexit 0.api.github.com/userbefore configuring it, so an expired or revokedGITHUB_TOKENfails loudly here rather than opaquely mid-install. This matters for the CI path in particular:drupal-integration-test.ymlpasses GitHub Actions' ephemeralsecrets.GITHUB_TOKENas a template variable, so any workspace created from that template version after the workflow ends gets a long-expired token.SETUP_FAILEDis set. It sat outside the guard and appended a misleadingdrush is not available/Failed to run drush crafter the real failure, burying the cause.Applied to
drupal-contribtoo, which had a byte-identical copy of the token block. (Its separate Drupal-12 Guzzle problem is untouched — see #179.)Why this surfaced now
Not a Coder change. Both deployments run identical Coder (
v2.34.4+19d9274) with differentdeployment_ids, so external-auth links are per-deployment. The only recent commit touchingcoder external-auth access-token(coder/coder#26883) is not in any release, and preserves the exit-code behavior anyway.The bug has been latent since #166. Three paths supply a token, and only the third is broken:
github_tokenvar--variable github_token=staging-push.ymldoesn't pass it)Test plan
terraform fmt -recursivecleanterraform validatepasses fordrupal-coreanddrupal-contribterraform testpasses for both (6 + 6)bash -non both renderedstartup_scriptheredocs (Terraform escapes resolved) —terraform validatedoes not check the embedded shell[github-oauth.github.com]held the external-auth URL; clearing it madeddev composer installexit 0access-tokenexit 1 → URL not used; garbage token → rejected by theapi.github.com/usercheck;--unset→ safe no-op when nothing is configureddrush si -y demo_umami→[OK] Installation complete,drush crOK, bootstrap successful,http 200Release/Deployment Notes
The fix makes an unlinked account a clean anonymous-download path rather than a hard failure. If authenticated downloads are wanted for ordinary users, that's a separate change: add
data "coder_external_auth" "github" { id = "github"; optional = true }so Coder surfaces a "Login with GitHub" button at workspace creation. No template currently declares one, which is why nothing ever prompted for the link.Workspaces already poisoned by the old code self-heal on next start via the
--unsetbranch.🤖 Generated with Claude Code