Update auth docs and implement GitHub providers#1683
Conversation
|
Warning This PR exceeds the recommended limit of 1,000 lines.Large PRs are difficult to review and may be rejected due to their size. Please verify that this PR does not address multiple issues. |
|
Warning Rate limit exceeded@osterman has exceeded the limit for the number of commits or files that can be reviewed per hour. Please wait 20 minutes and 23 seconds before requesting another review. ⌛ How to resolve this issue?After the wait time has elapsed, a review can be triggered using the We recommend that you space out your commits to avoid hitting the rate limit. 🚦 How do rate limits work?CodeRabbit enforces hourly rate limits for each developer per organization. Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout. Please see our FAQ for further information. 📒 Files selected for processing (18)
📝 WalkthroughWalkthroughThis PR implements GitHub authentication with OAuth Device Flow (user authentication) and JWT-based GitHub App flows, adding new CLI commands for git-credential helper and logout, creating provider and identity implementations, defining new credential types, integrating storage support, and providing comprehensive documentation and tests. Changes
Sequence Diagram(s)sequenceDiagram
participant User
participant CLI as Atmos CLI
participant DeviceFlow as Device Flow<br/>Client
participant GitHub as GitHub API
participant Store as Credential<br/>Store
User->>CLI: atmos auth login
CLI->>DeviceFlow: StartDeviceFlow()
DeviceFlow->>GitHub: POST /device/code
GitHub-->>DeviceFlow: device_code, user_code, verification_uri
DeviceFlow-->>CLI: DeviceFlowResponse
CLI->>User: Display user_code & verification_uri
User->>GitHub: Visit verification_uri<br/>Enter user_code
CLI->>DeviceFlow: PollForToken(device_code)
loop Poll with backoff
DeviceFlow->>GitHub: POST /token (with device_code)
alt Authorization pending
GitHub-->>DeviceFlow: authorization_pending
else Token ready
GitHub-->>DeviceFlow: access_token, expires_in
DeviceFlow-->>CLI: token
end
end
CLI->>Store: Store credentials
Store-->>CLI: Success
CLI->>User: Success message
sequenceDiagram
participant App as Atmos CLI
participant GitHub as GitHub API
participant Store as Credential<br/>Store
App->>App: Load GitHub App config<br/>(app_id, installation_id, private_key)
App->>App: Generate JWT<br/>(RS256, 10-min expiry)
App->>GitHub: GET /app/installations/{installation_id}/access_tokens<br/>with JWT + permissions
GitHub-->>App: access_token, expires_at (1-hour)
App->>Store: Store credentials<br/>(token, app_id, installation_id, expiry)
Store-->>App: Success
App->>App: Use token in requests
Note over App: Token auto-refreshes<br/>on next command if expired
Estimated code review effort🎯 4 (Complex) | ⏱️ ~60 minutes The implementation spans multiple authentication flows (Device Flow, JWT, OIDC refactor), introduces new credential types and storage integration, adds CLI commands with UI components, and includes substantial test coverage across provider, identity, and credential lifecycles. While the changes are well-organized by cohort and documentation is thorough, each authentication provider requires independent reasoning around token lifecycle, error handling, and security considerations (key management, token expiration, scope validation). The heterogeneity of changes—mixing providers, identities, types, factories, CLI, and tests—requires distributed review attention across distinct subsystems. Possibly related PRs
Suggested reviewers
Pre-merge checks and finishing touches❌ Failed checks (1 warning)
✅ Passed checks (2 passed)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Actionable comments posted: 14
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (2)
pkg/auth/providers/github/oidc.go (2)
97-103: Prefer ATMOS_ env overrides with viper.BindEnv.Per guidelines, bind an ATMOS_ alternative and prefer it when present.
Suggested diffs:
func (p *oidcProvider) isGitHubActions() bool { - if err := viper.BindEnv("github.actions", "GITHUB_ACTIONS"); err != nil { + if err := viper.BindEnv("github.actions", "ATMOS_GITHUB_ACTIONS"); err != nil { log.Trace("Failed to bind github.actions environment variable", "error", err) } - return viper.GetString("github.actions") == "true" + if v := viper.GetString("github.actions"); v != "" { + return v == "true" + } + _ = viper.BindEnv("github.actions", "GITHUB_ACTIONS") + return viper.GetString("github.actions") == "true" } @@ func (p *oidcProvider) requestParams() (string, string, error) { - if err := viper.BindEnv("github.oidc.request_token", "ACTIONS_ID_TOKEN_REQUEST_TOKEN"); err != nil { + if err := viper.BindEnv("github.oidc.request_token", "ATMOS_GITHUB_OIDC_REQUEST_TOKEN"); err != nil { log.Trace("Failed to bind github.oidc.request_token environment variable", "error", err) } - token := viper.GetString("github.oidc.request_token") + if viper.GetString("github.oidc.request_token") == "" { + _ = viper.BindEnv("github.oidc.request_token", "ACTIONS_ID_TOKEN_REQUEST_TOKEN") + } + token := viper.GetString("github.oidc.request_token") @@ - if err := viper.BindEnv("github.oidc.request_url", "ACTIONS_ID_TOKEN_REQUEST_URL"); err != nil { + if err := viper.BindEnv("github.oidc.request_url", "ATMOS_GITHUB_OIDC_REQUEST_URL"); err != nil { log.Trace("Failed to bind github.oidc.request_url environment variable", "error", err) } - requestURL := viper.GetString("github.oidc.request_url") + if viper.GetString("github.oidc.request_url") == "" { + _ = viper.BindEnv("github.oidc.request_url", "ACTIONS_ID_TOKEN_REQUEST_URL") + } + requestURL := viper.GetString("github.oidc.request_url") @@ func (p *oidcProvider) resolveJWT(ctx context.Context, requestURL, token, aud string) (string, error) { - if err := viper.BindEnv("github.oidc.id_token", "ACTIONS_ID_TOKEN"); err != nil { + if err := viper.BindEnv("github.oidc.id_token", "ATMOS_GITHUB_OIDC_ID_TOKEN"); err != nil { log.Trace("Failed to bind github.oidc.id_token environment variable", "error", err) } - if jwt := viper.GetString("github.oidc.id_token"); jwt != "" { + if jwt := viper.GetString("github.oidc.id_token"); jwt != "" { return jwt, nil } + _ = viper.BindEnv("github.oidc.id_token", "ACTIONS_ID_TOKEN") + if jwt := viper.GetString("github.oidc.id_token"); jwt != "" { + return jwt, nil + }Also applies to: 106-123, 136-149
58-95: Add perf.Track to Authenticate (and constructor) per perf guidelines.Authenticate is a public entrypoint and networked; add defer perf.Track(...) with package-qualified name and atmosConfig (or nil) immediately at function start, followed by a blank line.
🧹 Nitpick comments (35)
pkg/auth/providers/github/keychain_store_test.go (2)
12-47: Stabilize tests with go-keyring MockInit to avoid flaky OS prompts.For unit-style tests (GetNotFound/DeleteNotFound), initialize the in-memory keyring to avoid platform dependencies and CI flakiness.
func TestOSKeychainStore_GetNotFound(t *testing.T) { - if testing.Short() { - t.Skip("Skipping keychain integration test in short mode") - } + keyring.MockInit() @@ func TestOSKeychainStore_DeleteNotFound(t *testing.T) { - if testing.Short() { - t.Skip("Skipping keychain integration test in short mode") - } + keyring.MockInit()Keep TestOSKeychainStore_Integration as an opt-in integration test (skipped in short mode). Based on learnings.
Also applies to: 49-68, 70-89
22-25: Handle cleanup errors to satisfy linters.Explicitly handle Delete errors or annotate with //nolint:errcheck and a reason to pass golangci-lint.
-// Clean up any existing test data. -_ = keyring.Delete(service, account) -defer keyring.Delete(service, account) +// Clean up any existing test data. +if err := keyring.Delete(service, account); err != nil && !errors.Is(err, keyring.ErrNotFound) { + t.Logf("pre-cleanup: %v", err) +} +defer func() { + if err := keyring.Delete(service, account); err != nil && !errors.Is(err, keyring.ErrNotFound) { + t.Logf("post-cleanup: %v", err) + } +}()pkg/auth/providers/github/keychain_store.go (3)
10-15: Fix comment punctuation to satisfy godot.Ensure each bullet ends with a period.
-// Uses github.com/zalando/go-keyring which provides cross-platform support: -// - macOS: Keychain Access -// - Windows: Credential Manager -// - Linux: Secret Service (GNOME Keyring, KWallet). +// Uses github.com/zalando/go-keyring which provides cross-platform support. +// - macOS: Keychain Access. +// - Windows: Credential Manager. +// - Linux: Secret Service (GNOME Keyring, KWallet).
35-42: Include service/account context in Set error for parity.Mirror Get/Delete context in Set for better diagnostics.
- if err != nil { - return fmt.Errorf("failed to store token in %s keychain: %w", runtime.GOOS, err) - } + if err != nil { + return fmt.Errorf("failed to store token in %s keychain (service=%s account=%s): %w", runtime.GOOS, service, account, err) + }
15-20: Consider exposing DeleteAll to support ‘logout all’.go-keyring v0.2.6 provides DeleteAll; offering it via KeychainStore enables “atmos auth logout” to wipe all entries for a service without knowing accounts. Optional but handy.
Example (requires interface change):
- Add: DeleteAll(service string) error
- Impl: return keyring.DeleteAll(service)
GITHUB_MERMAID_DIAGRAMS.md (1)
241-241: Wrap the bare URL in a markdown link.The bare URL should be formatted as a markdown link for better practices.
Apply this change:
-1. **Mermaid Live Editor**: https://mermaid.live - paste and preview +1. **Mermaid Live Editor**: [https://mermaid.live](https://mermaid.live) - paste and previewIMPLEMENTATION_STATUS.md (1)
195-229: Consider adding language identifiers to code blocks.The code blocks showing file listings would be clearer with language identifiers. This is optional for planning docs but improves readability.
For example:
-``` +```text pkg/auth/providers/github/user.go # 248 lines ...docs/prd/github-authentication-providers.md (1)
194-231: Consider adding language identifiers to ASCII diagram blocks.The architecture diagrams would be clearer with a
textlanguage identifier. This helps readers and tools understand the content type.For example:
-``` +```text ┌─────────────────────────────────────────────────────────────┐ │ Atmos CLI │ ...website/docs/cli/commands/auth/usage.mdx (2)
252-274: Tighten GitHub sections with tiny clarifications.
- Consider noting default token lifetimes inline: user (~8h), app (~1h).
- For the OIDC example (Line 304), keep audience as shown and add a one‑liner that AWS roles typically require "sts.amazonaws.com".
- Optional: Add a short example showing how to wire the git credential helper to pair with these providers.
I can draft the extra lines if you want.
Also applies to: 275-294, 296-305
358-364: Remove duplicate dotenv example line.Two identical lines are listed.
- atmos auth env --format dotenv - atmos auth env --format dotenv + atmos auth env --format dotenvcmd/auth_git_credential.go (3)
17-43: Harden Cobra command ergonomics.
- Hide helper from normal help and silence usage on errors.
var authGitCredentialCmd = &cobra.Command{ Use: "git-credential", Short: "Git credential helper for GitHub authentication", Long: `Act as a Git credential helper for GitHub authentication. @@ ValidArgs: []string{"get", "store", "erase"}, DisableFlagParsing: false, FParseErrWhitelist: struct{ UnknownFlags bool }{UnknownFlags: false}, RunE: executeGitCredentialCommand, + SilenceUsage: true, + Hidden: true, }
71-76: Tighten host check to avoid false positives.Avoid matching hosts like notgithub.com.
- if !strings.Contains(input["host"], "github.com") { + host := input["host"] + if host != "github.com" && host != "api.github.com" && host != "gist.github.com" { // Return empty response for non-GitHub hosts. return nil }Please confirm if you want to support additional GitHub subdomains (enterprise is out of scope for now).
77-82: Avoid full stack processing for this helper.No stacks needed; skip for speed.
- atmosConfig, err := cfg.InitCliConfig(schema.ConfigAndStacksInfo{}, true) + atmosConfig, err := cfg.InitCliConfig(schema.ConfigAndStacksInfo{}, false)GITHUB_IDENTITY_PLAN.md (1)
370-386: Polish markdown for easier reading and linting.
- Add languages to fenced code blocks (yaml, bash, go).
- Replace bare URLs with markdown links.
- Deduplicate repeated headings.
Happy to push a quick cleanup commit if desired.
Also applies to: 404-420, 523-556
cmd/auth_logout.go (2)
3-14: Sort stdlib imports alphabetically.Keep stdlib group alpha per guidelines.
import ( - "context" - "os" - "fmt" + "context" + "fmt" + "os"
16-44: Cobra ergonomics: silence usage.Prevents noisy usage on expected errors.
var authLogoutCmd = &cobra.Command{ Use: "logout", Short: "Log out and clear cached credentials", @@ RunE: executeLogoutCommand, + SilenceUsage: true, }pkg/auth/providers/github/device_flow_client_test.go (1)
14-26: Nice coverage. Two optional nits.
- Add t.Parallel() at the start of tests to speed execution.
- Consider generating a mock for the keychain interface via mockgen to align with repo conventions.
No blockers.
Also applies to: 27-64, 65-106, 107-132, 133-158, 159-171, 173-189, 191-205, 206-219, 221-237, 239-264, 265-293
pkg/auth/providers/github/app.go (2)
231-239: Use bytes.NewReader and drop custom reader.Simplifies code and reduces surface area.
- var body io.Reader + var body io.Reader if len(requestBody) > 0 { jsonData, err := json.Marshal(requestBody) if err != nil { return "", time.Time{}, fmt.Errorf("failed to marshal request body: %w", err) } - body = &readSeeker{data: jsonData} + body = bytes.NewReader(jsonData) } @@ -// readSeeker is a helper to make []byte compatible with io.Reader. -type readSeeker struct { - data []byte - pos int -} - -func (r *readSeeker) Read(p []byte) (n int, err error) { - if r.pos >= len(r.data) { - return 0, io.EOF - } - n = copy(p, r.data[r.pos:]) - r.pos += n - return n, nil -} +// (reader helper removed; bytes.NewReader used instead)Also applies to: 293-306
245-248: Set a User-Agent header.GitHub API prefers a UA; include Atmos version if available.
req.Header.Set("Authorization", "Bearer "+jwtToken) req.Header.Set("Accept", "application/vnd.github+json") req.Header.Set("Content-Type", "application/json") +req.Header.Set("User-Agent", "Atmos (Cloud Posse; +https://atmos.tools)")pkg/auth/providers/github/app_test.go (4)
223-233: Make HTTP rewrite robust and keep timeouts.String-slicing server.URL is brittle and the new http.Client loses the default timeout. Prefer parsing the URL and preserving a timeout.
Apply:
+ "net/url" @@ - appProv.httpClient = &http.Client{ - Transport: &roundTripperFunc{ - fn: func(req *http.Request) (*http.Response, error) { - // Rewrite URL to point to test server. - req.URL.Scheme = "http" - req.URL.Host = server.URL[7:] // Remove "http://". - return http.DefaultTransport.RoundTrip(req) - }, - }, - } + srvURL, _ := url.Parse(server.URL) + appProv.httpClient = &http.Client{ + Timeout: 30 * time.Second, + Transport: &roundTripperFunc{ + fn: func(req *http.Request) (*http.Response, error) { + req.URL.Scheme = srvURL.Scheme + req.URL.Host = srvURL.Host + return http.DefaultTransport.RoundTrip(req) + }, + }, + }
254-270: Also assert repositories are forwarded.You already verify permissions; add a check that repositories are included when specified.
Apply:
var reqBody map[string]interface{} json.NewDecoder(r.Body).Decode(&reqBody) permissions, ok := reqBody["permissions"].(map[string]interface{}) assert.True(t, ok) assert.Equal(t, "read", permissions["contents"]) + + repos, ok := reqBody["repositories"].([]interface{}) + assert.True(t, ok) + assert.ElementsMatch(t, []interface{}{"repo1"}, repos)
25-41: Add a PKCS#8 private key test.Provider likely supports PKCS1 and PKCS8. Add a PKCS8 case to avoid regressions.
Example to append near file end:
+func TestAppProvider_LoadPrivateKey_PKCS8(t *testing.T) { + key, err := rsa.GenerateKey(rand.Reader, 2048) + require.NoError(t, err) + pkcs8Bytes, err := x509.MarshalPKCS8PrivateKey(key) + require.NoError(t, err) + pemBytes := pem.EncodeToMemory(&pem.Block{Type: "PRIVATE KEY", Bytes: pkcs8Bytes}) + + dir := t.TempDir() + keyPath := filepath.Join(dir, "key.pem") + require.NoError(t, os.WriteFile(keyPath, pemBytes, 0600)) + + cfg := &schema.Provider{ + Kind: KindApp, + Spec: map[string]interface{}{ + "app_id": "12345", + "installation_id": "67890", + "private_key_path": keyPath, + }, + } + p, err := NewAppProvider("github-app", cfg) + require.NoError(t, err) + assert.NotNil(t, p) +}
43-160: Parallelize table tests.Call t.Parallel() inside the t.Run to speed up and isolate subtests.
for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { + t.Parallel() provider, err := NewAppProvider(tt.provName, tt.config) ... }) }pkg/auth/providers/github/user_test.go (3)
18-73: Add test for invalid provider kind.Constructor should reject non-
github/userkinds.Append:
+func TestNewUserProvider_InvalidKind(t *testing.T) { + cfg := &schema.Provider{Kind: "github/app", Spec: map[string]interface{}{"client_id": "x"}} + p, err := NewUserProvider("github-user", cfg) + assert.Error(t, err) + assert.Nil(t, p) + assert.ErrorIs(t, err, errUtils.ErrInvalidProviderKind) +}
18-73: Assert optional fields parsing.Coverage for
token_lifetimeandkeychain_serviceimproves confidence.Append:
+func TestNewUserProvider_OptionalFields(t *testing.T) { + cfg := &schema.Provider{ + Kind: KindUser, + Spec: map[string]interface{}{ + "client_id": "id", + "token_lifetime": "6h", + "keychain_service":"atmos-github-work", + }, + } + p, err := NewUserProvider("github-user", cfg) + require.NoError(t, err) + up := p.(*userProvider) + assert.Equal(t, 6*time.Hour, up.tokenLifetime) + assert.Equal(t, "atmos-github-work", up.keychainSvc) +}
95-133: Parallelize tests.Add t.Parallel() to top-level tests and inside t.Run where applicable to speed up CI and catch racey tests.
Example:
func TestUserProvider_Authenticate_WithCachedToken(t *testing.T) { + t.Parallel() ctrl := gomock.NewController(t) ... }Also applies to: 134-191, 192-227, 229-287, 289-318, 320-353, 355-369, 370-383, 385-404, 406-416
SUMMARY.md (2)
236-253: Tighten security wording.“Never expose in logs or errors” — consider “Do not include raw tokens/keys in logs or error messages.”
- - Never expose in logs or errors + - Do not include raw tokens or private keys in logs or error messages.
281-286: Update SUMMARY.md to include pinned dependency versions.The go.mod file pins
github.com/suzuki-shunsuke/ghtknto v0.2.2 andgithub.com/golang-jwt/jwt/v5to v5.3.0. Update the dependency list in SUMMARY.md to match:
github.com/suzuki-shunsuke/ghtkn v0.2.2- Device Flow (already added)github.com/golang-jwt/jwt/v5 v5.3.0- JWT signing (to be added)This ensures the planning document stays synchronized with the actual pinned versions.
website/docs/cli/commands/auth/providers/github-user.mdx (3)
199-206: Add language to output code fence.Silence MD040 by marking the block as text.
-**Output:** -``` +**Output:** +```text To authenticate with GitHub: 1. Visit: https://github.com/login/device 2. Enter code: ABCD-1234 @@ ✓ Successfully authenticated--- `367-374`: **Deduplicate “Related” sections.** There are two “Related” headings. Keep one and merge links. - Remove the later “Related” or rename it to “More resources,” ensuring links are consolidated. Also applies to: 834-841 --- `183-191`: **Shell commands: drop leading $ for lint clarity.** MD014 flags `$` prefixes without showing output. Use plain commands or mark as shell-session with outputs. ```diff -git config --global credential.helper '!atmos auth git-credential' +git config --global credential.helper '!atmos auth git-credential'And prefer fenced language
bashfor commands andtext/consolefor outputs.DOCUMENTATION_STRUCTURE_PROPOSAL.md (1)
112-224: Add fenced languages in the template.A few example fences in the template lack a language, tripping MD040.
- Use yaml, bash, mermaid, text appropriately in all template examples.
pkg/auth/providers/github/device_flow_client.go (1)
117-121: Use server-provided polling interval (avoid rate limiting).You decode Interval but never use it; PollForToken always ticks at defaultInterval. Persist interval on StartDeviceFlow and use it when polling.
Apply:
type realDeviceFlowClient struct { clientID string scopes []string keychainSvc string httpClient *http.Client keychainStore KeychainStore + pollInterval time.Duration } func NewDeviceFlowClient(clientID string, scopes []string, keychainSvc string) DeviceFlowClient { return &realDeviceFlowClient{ clientID: clientID, scopes: scopes, keychainSvc: keychainSvc, httpClient: &http.Client{ Timeout: 30 * time.Second, }, - keychainStore: newOSKeychainStore(), + keychainStore: newOSKeychainStore(), + pollInterval: time.Duration(defaultInterval) * time.Second, } } // StartDeviceFlow initiates the Device Flow and returns device/user codes. func (c *realDeviceFlowClient) StartDeviceFlow(ctx context.Context) (*DeviceFlowResponse, error) { @@ // Set default interval if not provided. if result.Interval == 0 { result.Interval = defaultInterval } + c.pollInterval = time.Duration(result.Interval) * time.Second return &result, nil } // PollForToken polls GitHub for the access token after user authorization. func (c *realDeviceFlowClient) PollForToken(ctx context.Context, deviceCode string) (string, error) { defer perf.Track(nil, "github.realDeviceFlowClient.PollForToken")() - ticker := time.NewTicker(time.Duration(defaultInterval) * time.Second) + ticker := time.NewTicker(c.pollInterval) defer ticker.Stop()Also applies to: 30-36, 49-60, 105-110
pkg/auth/providers/github/user.go (2)
59-61: Use the constant for kind checks.Prefer KindUser over the raw string.
- if config.Kind != "github/user" { + if config.Kind != KindUser {
89-93: Don’t silently ignore invalid token_lifetime.If ParseDuration fails, return an error so misconfig doesn’t silently fall back to default.
- if lifetimeStr, ok := config.Spec["token_lifetime"].(string); ok && lifetimeStr != "" { - if duration, err := time.ParseDuration(lifetimeStr); err == nil { - tokenLifetime = duration - } - } + if lifetimeStr, ok := config.Spec["token_lifetime"].(string); ok && lifetimeStr != "" { + duration, err := time.ParseDuration(lifetimeStr) + if err != nil { + return nil, fmt.Errorf("%w: invalid token_lifetime %q: %v", errUtils.ErrInvalidProviderConfig, lifetimeStr, err) + } + tokenLifetime = duration + }
cmd/auth_git_credential.go
Outdated
| // Check if identity is a GitHub provider. | ||
| providerKind, err := authManager.GetProviderKindForIdentity(identityName) | ||
| if err != nil || (providerKind != "github/user" && providerKind != "github/app") { | ||
| // Not a GitHub identity, return empty. | ||
| return nil | ||
| } | ||
|
|
There was a problem hiding this comment.
🛠️ Refactor suggestion | 🟠 Major
🧩 Analysis chain
Prefer provider kind constants (if exported).
Using string literals risks drift.
If feasible, import the provider kind constants (e.g., githubprov.KindUser, githubprov.KindApp) and compare against those. Otherwise, keep as-is but consider centralizing kinds in a shared package.
🏁 Script executed:
#!/bin/bash
# Find where provider kind constants live to avoid importing provider internals into cmd.
rg -nP --type=go -C2 'Kind(User|App|OIDC)\s*=\s*"github/' pkg | sed -n '1,120p'Length of output: 710
Use provider kind constants from pkg/auth/providers/github.
The constants KindUser and KindApp are already exported in pkg/auth/providers/github/constants.go. Replace the string literals "github/user" and "github/app" with these constants to centralize provider kinds and prevent drift. This is a straightforward import and refactor at lines 100-106.
🤖 Prompt for AI Agents
In cmd/auth_git_credential.go around lines 100 to 106, the code uses string
literals "github/user" and "github/app" to check provider kind; replace those
literals with the exported constants from pkg/auth/providers/github (KindUser
and KindApp), add the import for pkg/auth/providers/github, and update the
conditional to compare providerKind against github.KindUser and github.KindApp
so provider kinds are centralized and less error-prone.
| // Authenticate and get credentials. | ||
| ctx := context.Background() | ||
| whoami, err := authManager.Authenticate(ctx, identityName) | ||
| if err != nil { | ||
| return fmt.Errorf("authentication failed: %w", err) | ||
| } | ||
|
|
||
| // Extract GitHub token from environment variables. | ||
| token, ok := whoami.Environment["GITHUB_TOKEN"] | ||
| if !ok || token == "" { | ||
| return fmt.Errorf("%w: no GITHUB_TOKEN in authentication result", errUtils.ErrAuthenticationFailed) | ||
| } |
There was a problem hiding this comment.
🛠️ Refactor suggestion | 🟠 Major
Wrap with sentinel error consistently.
Aligns with errors policy.
- whoami, err := authManager.Authenticate(ctx, identityName)
- if err != nil {
- return fmt.Errorf("authentication failed: %w", err)
- }
+ whoami, err := authManager.Authenticate(ctx, identityName)
+ if err != nil {
+ return fmt.Errorf("%w: %v", errUtils.ErrAuthenticationFailed, err)
+ }
@@
- if !ok || token == "" {
- return fmt.Errorf("%w: no GITHUB_TOKEN in authentication result", errUtils.ErrAuthenticationFailed)
- }
+ if !ok || token == "" {
+ return fmt.Errorf("%w: no GITHUB_TOKEN in authentication result", errUtils.ErrAuthenticationFailed)
+ }Committable suggestion skipped: line range outside the PR's diff.
🤖 Prompt for AI Agents
In cmd/auth_git_credential.go around lines 107 to 118, the Authenticate error
return is not wrapped with the sentinel errUtils.ErrAuthenticationFailed while
the later GITHUB_TOKEN check correctly uses the sentinel; change the
Authenticate failure return to wrap and return the sentinel error (preserving
the original error as context) so both failure paths consistently use
errUtils.ErrAuthenticationFailed with the underlying error included.
| // executeLogoutCommand performs logout and credential cleanup. | ||
| func executeLogoutCommand(cmd *cobra.Command, args []string) error { | ||
| // Load atmos configuration. | ||
| atmosConfig, err := cfg.InitCliConfig(schema.ConfigAndStacksInfo{}, true) | ||
| if err != nil { | ||
| return fmt.Errorf("failed to load atmos config: %w", err) | ||
| } | ||
|
|
||
| // Create auth manager. | ||
| authManager, err := createAuthManager(&atmosConfig.Auth) | ||
| if err != nil { | ||
| return fmt.Errorf("failed to create auth manager: %w", err) | ||
| } | ||
|
|
||
| // Check if logout all. | ||
| logoutAll, _ := cmd.Flags().GetBool("all") | ||
|
|
||
| if logoutAll { | ||
| return logoutAllIdentities(authManager) | ||
| } | ||
|
|
||
| // Get identity from flag or use default. | ||
| identityName, _ := cmd.Flags().GetString("identity") | ||
| if identityName == "" { | ||
| defaultIdentity, err := authManager.GetDefaultIdentity() | ||
| if err != nil { | ||
| return fmt.Errorf("%w: no default identity configured and no identity specified: %v", errUtils.ErrNoDefaultIdentity, err) | ||
| } | ||
| identityName = defaultIdentity | ||
| } | ||
|
|
||
| return logoutIdentity(authManager, identityName) | ||
| } |
There was a problem hiding this comment.
🛠️ Refactor suggestion | 🟠 Major
🧩 Analysis chain
Add perf.Track and strengthen typing + behavior.
- Track perf on the command and helpers.
- Use a concrete AuthManager interface instead of interface{}.
- Implement provider‑specific cleanup (keychain delete) before shipping.
func executeLogoutCommand(cmd *cobra.Command, args []string) error {
+ defer perf.Track(nil, "cmd.authLogout.executeLogoutCommand")()
@@
- return logoutIdentity(authManager, identityName)
+ return logoutIdentity(authManager, identityName)
}
-// logoutIdentity logs out a single identity.
-func logoutIdentity(authManager interface{}, identityName string) error {
+// logoutIdentity logs out a single identity.
+func logoutIdentity(authManager types.AuthManager, identityName string) error {
+ defer perf.Track(nil, "cmd.authLogout.logoutIdentity")()
ctx := context.Background()
@@
- log.Info("Logging out from identity", "identity", identityName)
+ log.Info("Logging out from identity", "identity", identityName)
+ // TODO: call provider-specific cleanup via authManager (e.g., delete keychain entries for github/user).
@@
return nil
}
-// logoutAllIdentities logs out all configured identities.
-func logoutAllIdentities(authManager interface{}) error {
+// logoutAllIdentities logs out all configured identities.
+func logoutAllIdentities(authManager types.AuthManager) error {
+ defer perf.Track(nil, "cmd.authLogout.logoutAllIdentities")()
@@
return nil
}If types.AuthManager is not available publicly, define a minimal local interface in this file exposing the needed methods (e.g., ListIdentities, Logout(identity)).
Also applies to: 79-105, 106-121
🏁 Script executed:
#!/bin/bash
# Locate the concrete AuthManager type and any existing Logout/List APIs.
rg -nP --type=go -C2 '\btype\s+.*AuthManager\b|func\s+\(.*\)\s+Logout\(|ListIdentit' pkg internal cmdLength of output: 3788
🏁 Script executed:
#!/bin/bash
# Get the full AuthManager interface definition
rg -nP --type=go -A20 'type AuthManager interface \{' pkg/auth/types/interfaces.goLength of output: 947
🏁 Script executed:
#!/bin/bash
# Inspect the current state of logoutIdentity and logoutAllIdentities
rg -nP --type=go -B2 -A12 'func logout(Identity|All)' cmd/auth_logout.goLength of output: 1307
🏁 Script executed:
#!/bin/bash
# Check if Logout is defined anywhere in AuthManager or its implementations
rg -nP --type=go 'Logout\(' pkg/auth/types/ pkg/auth/manager.goLength of output: 0
🏁 Script executed:
#!/bin/bash
# Check for Logout in manager.go and executeLogoutCommand instrumentation status
rg -nP --type=go 'func.*Logout|executeLogoutCommand' pkg/auth/manager.go cmd/auth_logout.goLength of output: 241
🏁 Script executed:
#!/bin/bash
# Check executeLogoutCommand definition to see current state
cat cmd/auth_logout.go | head -80 | tail -40Length of output: 1271
Add perf.Track instrumentation and fix interface typing for logout functions.
The interface{} usage in logoutIdentity and logoutAllIdentities should be replaced with a concrete type. However, types.AuthManager currently lacks a Logout method. Two approaches work:
- Add
Logout(ctx context.Context, identityName string) errorto theAuthManagerinterface inpkg/auth/types/interfaces.go, then implement it inpkg/auth/manager.go. - Define a minimal local interface in
cmd/auth_logout.gowith only the methods needed for logout (e.g.,ListIdentities,GetProviderForIdentity, provider-specific logout calls).
Additionally:
- Add
defer perf.Track(atmosConfig, "cmd.authLogout.executeLogoutCommand")()toexecuteLogoutCommand(line 46) with a blank line after. - Add
defer perf.Track(nil, "cmd.authLogout.logoutIdentity")()tologoutIdentity(line 80) with a blank line after. - Add
defer perf.Track(nil, "cmd.authLogout.logoutAllIdentities")()tologoutAllIdentities(line 107) with a blank line after. - Implement provider-specific cleanup (keychain deletion) rather than placeholder—this is blocking production readiness.
| // realDeviceFlowClient implements the DeviceFlowClient interface for actual GitHub API calls. | ||
| // This implementation is inspired by ghtkn: https://github.com/suzuki-shunsuke/ghtkn | ||
| type realDeviceFlowClient struct { |
There was a problem hiding this comment.
godot: add trailing period.
Add a period to the “Inspired by …” comment to satisfy godot.
-// This implementation is inspired by ghtkn: https://github.com/suzuki-shunsuke/ghtkn
+// This implementation is inspired by ghtkn: https://github.com/suzuki-shunsuke/ghtkn.🤖 Prompt for AI Agents
pkg/auth/providers/github/device_flow_client.go around lines 28 to 30: the
comment ending "inspired by ghtkn: https://github.com/suzuki-shunsuke/ghtkn" is
missing a trailing period; update the comment to add a final period after the
URL so the sentence ends with proper punctuation.
| // Get retrieves a token from the OS keychain. | ||
| func (s *osKeychainStore) Get(service string, account string) (string, error) { | ||
| token, err := keyring.Get(service, account) | ||
| if err != nil { | ||
| // go-keyring returns ErrNotFound on all platforms when item doesn't exist. | ||
| if err == keyring.ErrNotFound { | ||
| return "", fmt.Errorf("token not found in %s keychain for service=%s account=%s", runtime.GOOS, service, account) | ||
| } | ||
| return "", fmt.Errorf("failed to get token from %s keychain: %w", runtime.GOOS, err) | ||
| } | ||
| return token, nil | ||
| } |
There was a problem hiding this comment.
Adopt a static sentinel for “not found” and wrap errors accordingly.
Per guidelines, return a static error (from errors/errors.go) and wrap with context; avoid forcing callers to string-compare. Use errors.Is for keyring.ErrNotFound.
Proposed diff (assumes new sentinel errUtils.ErrCredentialNotFound):
@@
-import (
- "fmt"
- "runtime"
-
- "github.com/zalando/go-keyring"
-)
+import (
+ "errors"
+ "fmt"
+ "runtime"
+
+ errUtils "github.com/cloudposse/atmos/errors"
+ "github.com/zalando/go-keyring"
+)
@@
- if err != nil {
- // go-keyring returns ErrNotFound on all platforms when item doesn't exist.
- if err == keyring.ErrNotFound {
- return "", fmt.Errorf("token not found in %s keychain for service=%s account=%s", runtime.GOOS, service, account)
- }
- return "", fmt.Errorf("failed to get token from %s keychain: %w", runtime.GOOS, err)
- }
+ if err != nil {
+ // Normalize not-found to a static sentinel and wrap with context.
+ if errors.Is(err, keyring.ErrNotFound) {
+ return "", fmt.Errorf("%w: token not found in %s keychain (service=%s account=%s)", errUtils.ErrCredentialNotFound, runtime.GOOS, service, account)
+ }
+ return "", fmt.Errorf("failed to get token from %s keychain (service=%s account=%s): %w", runtime.GOOS, service, account, err)
+ }
@@
- if err != nil {
- // go-keyring returns ErrNotFound if item doesn't exist.
- if err == keyring.ErrNotFound {
- return fmt.Errorf("token not found in %s keychain for service=%s account=%s", runtime.GOOS, service, account)
- }
- return fmt.Errorf("failed to delete token from %s keychain: %w", runtime.GOOS, err)
- }
+ if err != nil {
+ if errors.Is(err, keyring.ErrNotFound) {
+ return fmt.Errorf("%w: token not found in %s keychain (service=%s account=%s)", errUtils.ErrCredentialNotFound, runtime.GOOS, service, account)
+ }
+ return fmt.Errorf("failed to delete token from %s keychain (service=%s account=%s): %w", runtime.GOOS, service, account, err)
+ }Add the sentinel in errors/errors.go:
+// ErrCredentialNotFound indicates a missing credential in a backing store.
+var ErrCredentialNotFound = errors.New("credential not found")Also applies to: 44-55
🤖 Prompt for AI Agents
In pkg/auth/providers/github/keychain_store.go around lines 22 to 33 (and
similarly for lines 44 to 55), replace the current string-based "not found"
behavior by returning the static sentinel error errUtils.ErrCredentialNotFound
from errors/errors.go when keyring.Get (and keyring.Delete/Get equivalents)
yields keyring.ErrNotFound; detect that condition using errors.Is(err,
keyring.ErrNotFound) and for other failures wrap the original error with
fmt.Errorf("%w: <context>") to preserve cause; ensure the returned not-found
case wraps the sentinel (e.g., fmt.Errorf("%w: token not found in %s keychain
for service=%s account=%s", errUtils.ErrCredentialNotFound, runtime.GOOS,
service, account)) so callers can use errors.Is to check for
ErrCredentialNotFound.
| ### Logout and Revoke Token | ||
|
|
||
| ```shell | ||
| atmos auth logout -i my-github | ||
| ``` | ||
|
|
||
| To fully revoke the token, visit: https://github.com/settings/tokens | ||
|
|
There was a problem hiding this comment.
🧩 Analysis chain
Fix token revocation guidance (OAuth vs PAT).
Device Flow uses an OAuth App; revocation happens under Authorized OAuth Apps, not the PAT tokens page.
-To fully revoke the token, visit: https://github.com/settings/tokens
+To fully revoke the token, go to GitHub Settings → Applications → Authorized OAuth Apps and revoke the app.
+See: https://docs.github.com/apps/oauth-apps/maintaining-oauth-apps/reviewing-your-authorized-oauth-apps🌐 Web query:
Where do users revoke OAuth Device Flow tokens on GitHub, and what is the official docs URL?
💡 Result:
Revoke location: In GitHub → your profile → Settings → Applications → Authorized OAuth Apps (select the app → Revoke). Device-flow (OAuth) tokens are revoked there the same as other OAuth app tokens. [1]
Official docs: "Authorizing OAuth apps" — https://docs.github.com/en/apps/oauth-apps/building-oauth-apps/authorizing-oauth-apps. [2]
Sources:
[1] Reviewing your authorized OAuth apps (GitHub Docs).
[2] Authorizing OAuth apps — Device flow (GitHub Docs).
Update token revocation guidance for OAuth Device Flow.
Device Flow tokens are revoked from GitHub Settings → Applications → Authorized OAuth Apps, not the PAT tokens page. The current link incorrect for this flow.
-To fully revoke the token, visit: https://github.com/settings/tokens
+To fully revoke the token, go to GitHub Settings → Applications → Authorized OAuth Apps and revoke the app.
+See: https://docs.github.com/en/apps/oauth-apps/building-oauth-apps/authorizing-oauth-apps📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| ### Logout and Revoke Token | |
| ```shell | |
| atmos auth logout -i my-github | |
| ``` | |
| To fully revoke the token, visit: https://github.com/settings/tokens | |
| ### Logout and Revoke Token | |
🤖 Prompt for AI Agents
In website/docs/cli/commands/auth/providers/github-user.mdx around lines 207 to
214, the guidance and link for revoking tokens points to the Personal Access
Tokens page but Device Flow tokens must be revoked via GitHub Settings →
Applications → Authorized OAuth Apps; update the text to instruct users to
revoke the token from Authorized OAuth Apps and change the link to the
Authorized OAuth Apps page
(https://github.com/settings/connections/applications) so it correctly reflects
the OAuth Device Flow revocation location.
|
Warning Changelog Entry RequiredThis PR is labeled Action needed: Add a new blog post in Example filename: Alternatively: If this change doesn't require a changelog entry, remove the |
- Add GitHub User provider (github/user) following AWS SSO pattern - Implement OAuth 2.0 Device Authorization Grant (RFC 8628) - Remove provider-level caching - auth manager stores credentials - Add Charm Bracelet styled UI for device flow instructions - Add spinner during token polling with Ctrl+C support - Add styled success message in auth login command - Implement github/token identity for unified credential handling - Add GitHub credential support to credential store - Register GitHub providers and identities in factory - Update documentation for GitHub authentication - Update test golden snapshot for new auth subcommands 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
There was a problem hiding this comment.
Actionable comments posted: 0
♻️ Duplicate comments (1)
website/docs/cli/commands/auth/providers/github-user.mdx (1)
216-223: Update token revocation guidance for OAuth Device Flow.Device Flow tokens are managed under GitHub Settings → Applications → Authorized OAuth Apps, not the Personal Access Tokens page. The current link is incorrect for this authentication method.
Apply this diff:
-To fully revoke the token, visit: https://github.com/settings/tokens +To fully revoke the token, go to GitHub Settings → Applications → Authorized OAuth Apps and revoke the app. +See: https://docs.github.com/en/apps/oauth-apps/building-oauth-apps/authorizing-oauth-apps
🧹 Nitpick comments (2)
docs/prd/github-authentication-providers.md (1)
194-231: Consider adding language identifiers to fenced code blocks.The ASCII diagrams at lines 194, 237, 276, and 308 could use language identifiers (e.g., ````text`) to satisfy markdownlint, though this is purely stylistic.
Apply this pattern to the code blocks:
-``` +```text ┌─────────────────────────────────────────────────────────────┐pkg/auth/providers/github/user.go (1)
319-334: Consider extracting TTY detection for reusability (optional).The TTY detection logic here is correct but could be extracted to a shared utility function if other providers or commands need similar functionality in the future.
Example extraction:
// In pkg/utils or pkg/ui/terminal package: func HasTTY(f *os.File) bool { fileInfo, err := f.Stat() return err == nil && (fileInfo.Mode()&os.ModeCharDevice) != 0 }Then use:
hasTTY := utils.HasTTY(os.Stderr) if !hasTTY { fmt.Fprintln(os.Stderr, "Waiting for authentication... (Press Ctrl+C to cancel)") } else { // Run spinner... }
📜 Review details
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
Disabled knowledge base sources:
- Linear integration is disabled by default for public repositories
You can enable these sources in your CodeRabbit configuration.
📒 Files selected for processing (16)
IMPLEMENTATION_COMPLETE.md(1 hunks)cmd/auth_login.go(2 hunks)docs/prd/github-authentication-providers.md(1 hunks)go.mod(2 hunks)pkg/auth/credentials/store.go(2 hunks)pkg/auth/factory/factory.go(5 hunks)pkg/auth/identities/github/token.go(1 hunks)pkg/auth/providers/github/constants.go(1 hunks)pkg/auth/providers/github/device_flow_client.go(1 hunks)pkg/auth/providers/github/mock_device_flow_client_test.go(1 hunks)pkg/auth/providers/github/user.go(1 hunks)pkg/auth/providers/github/user_test.go(1 hunks)tests/snapshots/TestCLICommands_atmos_auth_invalid-command.stderr.golden(1 hunks)website/docs/cli/commands/auth/providers/github-app.mdx(1 hunks)website/docs/cli/commands/auth/providers/github-user.mdx(1 hunks)website/docs/cli/commands/auth/usage.mdx(2 hunks)
🚧 Files skipped from review as they are similar to previous changes (3)
- pkg/auth/providers/github/device_flow_client.go
- pkg/auth/providers/github/mock_device_flow_client_test.go
- pkg/auth/providers/github/user_test.go
🧰 Additional context used
📓 Path-based instructions (10)
**/*
📄 CodeRabbit inference engine (CLAUDE.md)
Target minimum 80% coverage on new/changed lines; exclude mock files from coverage: **/mock_.go, mock_.go, **/mock/*.go.
Files:
docs/prd/github-authentication-providers.mdtests/snapshots/TestCLICommands_atmos_auth_invalid-command.stderr.goldencmd/auth_login.gowebsite/docs/cli/commands/auth/usage.mdxpkg/auth/identities/github/token.gopkg/auth/providers/github/constants.gopkg/auth/factory/factory.gopkg/auth/credentials/store.gowebsite/docs/cli/commands/auth/providers/github-user.mdxgo.modpkg/auth/providers/github/user.gowebsite/docs/cli/commands/auth/providers/github-app.mdxIMPLEMENTATION_COMPLETE.md
cmd/**/*.go
📄 CodeRabbit inference engine (.cursor/rules/atmos-rules.mdc)
cmd/**/*.go: Use Cobra's recommended command structure with a root command and subcommands
Implement each CLI command in a separate file under cmd/
Use Viper for managing configuration, environment variables, and flags in the CLI
Keep separation of concerns between CLI interface (cmd) and business logic
Use kebab-case for command-line flags
Provide comprehensive help text for all commands and flags
Include examples in Cobra command help
Use Viper for configuration management; support files, env vars, and flags with precedence flags > env > config > defaults
Follow single responsibility; separate command interface from business logic
Provide meaningful user feedback and include progress indicators for long-running operations
Provide clear error messages to users and troubleshooting hints where appropriate
cmd/**/*.go: Follow Cobra command pattern: one command per file; load examples via //go:embed and render via utils.PrintfMarkdown in RunE.
Telemetry for new commands is automatic via RootCmd.ExecuteC(); for non-standard paths use telemetry.CaptureCmd or telemetry.CaptureCmdString.
Files:
cmd/auth_login.go
**/*.go
📄 CodeRabbit inference engine (.cursor/rules/atmos-rules.mdc)
**/*.go: All code must pass golangci-lint checks
Follow Go error handling idioms and use meaningful error messages
Wrap errors with context using fmt.Errorf("context: %w", err)
Consider custom error types for domain-specific errors
Follow standard Go coding style; run gofmt and goimports
Use snake_case for environment variables
Document complex logic with inline comments
**/*.go: All comments must end with periods; enforced by golangci-lint godot across all Go comments.
Organize imports into three groups (stdlib, third-party, Atmos) separated by blank lines and sorted alphabetically within each group; keep existing aliases.
All errors must be wrapped using static errors defined in errors/errors.go; prefer errors.Join for multiple, fmt.Errorf with %w for context, and errors.Is for checks; never rely on string comparisons.
Prefer cross-platform implementations: use SDKs over external binaries; use filepath/os facilities; gate OS-specific logic with runtime.GOOS or build tags.
Files:
cmd/auth_login.gopkg/auth/identities/github/token.gopkg/auth/providers/github/constants.gopkg/auth/factory/factory.gopkg/auth/credentials/store.gopkg/auth/providers/github/user.go
**/!(*_test).go
📄 CodeRabbit inference engine (.cursor/rules/atmos-rules.mdc)
Document all exported functions, types, and methods with Go doc comments
Files:
cmd/auth_login.gopkg/auth/identities/github/token.gopkg/auth/providers/github/constants.gopkg/auth/factory/factory.gopkg/auth/credentials/store.gopkg/auth/providers/github/user.go
{cmd,internal,pkg}/**/*.go
📄 CodeRabbit inference engine (CLAUDE.md)
{cmd,internal,pkg}/**/*.go: Adddefer perf.Track()to all public functions and critical private ones, include a blank line after it, and use package-qualified names (e.g., "exec.ProcessComponent"). Use atmosConfig if available, else nil.
Always bind environment variables with viper.BindEnv; every var must have an ATMOS_ alternative and prefer ATMOS_ over external names.
Distinguish structured logging from UI output: UI prompts/errors/status to stderr; data/results to stdout; logging for system/debug only; no UI via logging.
Most text UI must go to stderr (via utils.PrintfMessageToTUI or fmt.Fprintf(os.Stderr,...)); only data/results to stdout.
Files:
cmd/auth_login.gopkg/auth/identities/github/token.gopkg/auth/providers/github/constants.gopkg/auth/factory/factory.gopkg/auth/credentials/store.gopkg/auth/providers/github/user.go
{pkg,internal,cmd}/**/*.go
📄 CodeRabbit inference engine (CLAUDE.md)
Always use mockgen for interface mocks; never write manual mocks with many stub methods.
Files:
cmd/auth_login.gopkg/auth/identities/github/token.gopkg/auth/providers/github/constants.gopkg/auth/factory/factory.gopkg/auth/credentials/store.gopkg/auth/providers/github/user.go
website/**
📄 CodeRabbit inference engine (.cursor/rules/atmos-rules.mdc)
website/**: Update website documentation in website/ when adding features
Ensure consistency between CLI help text and website documentation
Follow the website's documentation structure and style
Keep website code in website/ and follow its architecture/style; test changes locally
Keep CLI and website documentation in sync; document new features with examples and use casesAlways build the website (cd website && npm run build) after modifying docs, images, sidebars, or site components to catch broken links/formatting.
Files:
website/docs/cli/commands/auth/usage.mdxwebsite/docs/cli/commands/auth/providers/github-user.mdxwebsite/docs/cli/commands/auth/providers/github-app.mdx
website/docs/cli/commands/**/**/*.mdx
📄 CodeRabbit inference engine (CLAUDE.md)
All new commands/flags/parameters must be documented in Docusaurus MDX under website/docs/cli/commands//.mdx using definition lists (
) for arguments and flags and the provided frontmatter/template.
Files:
website/docs/cli/commands/auth/usage.mdxwebsite/docs/cli/commands/auth/providers/github-user.mdxwebsite/docs/cli/commands/auth/providers/github-app.mdx
pkg/**/*.go
📄 CodeRabbit inference engine (.cursor/rules/atmos-rules.mdc)
Place business logic in pkg rather than in cmd
Files:
pkg/auth/identities/github/token.gopkg/auth/providers/github/constants.gopkg/auth/factory/factory.gopkg/auth/credentials/store.gopkg/auth/providers/github/user.go
go.{mod,sum}
📄 CodeRabbit inference engine (.cursor/rules/atmos-rules.mdc)
go.{mod,sum}: Manage dependencies with Go modules
Keep dependencies up to date
Files:
go.mod
🧠 Learnings (4)
📚 Learning: 2025-09-10T17:34:52.568Z
Learnt from: Benbentwo
PR: cloudposse/atmos#1475
File: pkg/auth/providers/github/oidc.go:96-100
Timestamp: 2025-09-10T17:34:52.568Z
Learning: The ATMOS_ environment variable binding guideline applies to Atmos configuration variables, not external service-required environment variables like GitHub Actions OIDC variables (GITHUB_ACTIONS, ACTIONS_ID_TOKEN_*) which must use their standard names.
Applied to files:
website/docs/cli/commands/auth/usage.mdx
📚 Learning: 2025-07-05T20:59:02.914Z
Learnt from: aknysh
PR: cloudposse/atmos#1363
File: internal/exec/template_utils.go:18-18
Timestamp: 2025-07-05T20:59:02.914Z
Learning: In the Atmos project, gomplate v4 is imported with a blank import (`_ "github.com/hairyhenderson/gomplate/v4"`) alongside v3 imports to resolve AWS SDK version conflicts. V3 uses older AWS SDK versions that conflict with newer AWS modules used by Atmos. A full migration to v4 requires extensive refactoring due to API changes and should be handled in a separate PR.
Applied to files:
go.mod
📚 Learning: 2025-10-19T22:59:32.333Z
Learnt from: CR
PR: cloudposse/atmos#0
File: CLAUDE.md:0-0
Timestamp: 2025-10-19T22:59:32.333Z
Learning: Applies to **/*.go : All comments must end with periods; enforced by golangci-lint godot across all Go comments.
Applied to files:
pkg/auth/providers/github/user.go
📚 Learning: 2025-10-19T22:59:32.333Z
Learnt from: CR
PR: cloudposse/atmos#0
File: CLAUDE.md:0-0
Timestamp: 2025-10-19T22:59:32.333Z
Learning: Applies to {cmd,internal,pkg}/**/*.go : Most text UI must go to stderr (via utils.PrintfMessageToTUI or fmt.Fprintf(os.Stderr,...)); only data/results to stdout.
Applied to files:
pkg/auth/providers/github/user.go
🧬 Code graph analysis (5)
cmd/auth_login.go (1)
pkg/ui/theme/colors.go (4)
ColorGreen(11-11)ColorDarkGray(15-15)ColorWhite(20-20)ColorCheckmark(19-19)
pkg/auth/identities/github/token.go (8)
pkg/perf/perf.go (1)
Track(121-138)pkg/logger/log.go (2)
Errorf(59-61)Debug(24-26)errors/errors.go (3)
ErrInvalidAuthConfig(341-341)ErrInvalidIdentityKind(342-342)ErrAuthenticationFailed(346-346)pkg/schema/schema.go (2)
Context(381-396)ConfigAndStacksInfo(460-539)pkg/auth/types/interfaces.go (1)
ICredentials(129-135)pkg/auth/types/github_user_credentials.go (1)
GitHubUserCredentials(8-12)pkg/auth/types/github_app_credentials.go (1)
GitHubAppCredentials(8-14)pkg/auth/types/github_oidc_credentials.go (1)
OIDCCredentials(14-18)
pkg/auth/factory/factory.go (5)
pkg/auth/providers/github/constants.go (3)
KindOIDC(12-12)KindUser(6-6)KindApp(9-9)pkg/auth/providers/github/oidc.go (1)
NewOIDCProvider(28-41)pkg/auth/providers/github/user.go (1)
NewUserProvider(50-106)pkg/auth/providers/github/app.go (1)
NewAppProvider(36-106)pkg/auth/identities/github/token.go (1)
NewTokenIdentity(25-41)
pkg/auth/credentials/store.go (2)
pkg/auth/types/github_user_credentials.go (1)
GitHubUserCredentials(8-12)pkg/auth/types/github_app_credentials.go (1)
GitHubAppCredentials(8-14)
pkg/auth/providers/github/user.go (7)
pkg/perf/perf.go (1)
Track(121-138)pkg/logger/log.go (3)
Errorf(59-61)Debug(24-26)Info(34-36)errors/errors.go (3)
ErrInvalidProviderConfig(345-345)ErrInvalidProviderKind(344-344)ErrAuthenticationFailed(346-346)pkg/auth/providers/github/constants.go (2)
KindUser(6-6)DefaultClientID(24-24)pkg/auth/providers/github/device_flow_client.go (1)
NewDeviceFlowClient(37-45)pkg/auth/types/github_user_credentials.go (1)
GitHubUserCredentials(8-12)pkg/ui/theme/colors.go (4)
ColorBorder(23-23)ColorCyan(12-12)ColorGreen(11-11)ColorWhite(20-20)
🪛 LanguageTool
docs/prd/github-authentication-providers.md
[grammar] ~49-~49: Please add a punctuation mark at the end of paragraph.
Context: ...endencies**: ghtkn library, OS keychain APIs #### FR-002: GitHub App Authentication...
(PUNCTUATION_PARAGRAPH_END)
[grammar] ~63-~63: Please add a punctuation mark at the end of paragraph.
Context: ...encies**: golang-jwt library, go-github library #### FR-003: Configurable Permissions ...
(PUNCTUATION_PARAGRAPH_END)
[typographical] ~94-~94: Consider using a typographic opening quote here.
Context: ... (Get, Set, GetKey methods) - Support {{ atmos.Store "github-user" ... }} template function ...
(EN_QUOTES)
[style] ~114-~114: This phrase is redundant (‘I’ stands for ‘interface’). Use simply “CLI”.
Context: ...mands - Description: User-friendly CLI interface for GitHub authentication - **Acceptanc...
(ACRONYM_TAUTOLOGY)
[grammar] ~188-~188: Please add a punctuation mark at the end of paragraph.
Context: ...c.) - Compatible with GitHub Enterprise Server ## 3. Architecture ### 3.1 Component ...
(PUNCTUATION_PARAGRAPH_END)
[typographical] ~838-~838: Consider using a typographic opening quote here.
Context: ... - FAQ ### 10.2 Blog Post Title: "Secure GitHub Authentication with Atmos:...
(EN_QUOTES)
[typographical] ~838-~838: Consider using a typographic close quote here.
Context: ...on with Atmos: User Tokens & GitHub Apps" Content: - Problem statement (toke...
(EN_QUOTES)
[grammar] ~852-~852: Please add a punctuation mark at the end of paragraph.
Context: ...ase 2 feature, manual specification for MVP 2. Multi-Installation Support: How...
(PUNCTUATION_PARAGRAPH_END)
[grammar] ~855-~855: Please add a punctuation mark at the end of paragraph.
Context: ...e providers with different installation_ids 3. Token Refresh UI: Should we sho...
(PUNCTUATION_PARAGRAPH_END)
[grammar] ~858-~858: Please add a punctuation mark at the end of paragraph.
Context: ...cision**: Yes, warn at 5 minutes before expiration 4. Keychain Fallback: What if keyc...
(PUNCTUATION_PARAGRAPH_END)
[grammar] ~861-~861: Please add a punctuation mark at the end of paragraph.
Context: ...gradation to environment variables with warning 5. Repository Glob Patterns: Imple...
(PUNCTUATION_PARAGRAPH_END)
[grammar] ~864-~864: Please add a punctuation mark at the end of paragraph.
Context: ...rt * and ** wildcards in repository patterns 6. GitHub Enterprise Support: How ...
(PUNCTUATION_PARAGRAPH_END)
[grammar] ~867-~867: Please add a punctuation mark at the end of paragraph.
Context: ... base_url parameter for custom GitHub instances ## 12. Success Criteria ### Phase 1: ...
(PUNCTUATION_PARAGRAPH_END)
[uncategorized] ~973-~973: If this is a compound adjective that modifies the following noun, use a hyphen.
Context: ... - Clear browser cache after auth 4. Rate Limiting - Respect GitHub API limits - C...
(EN_COMPOUND_ADJECTIVE_INTERNAL)
website/docs/cli/commands/auth/usage.mdx
[uncategorized] ~130-~130: The official name of this software platform is spelled with a capital “H”.
Context: ...### GitHub Providers - GitHub User: [github/user](/cli/commands/auth/providers/git...
(GITHUB)
[uncategorized] ~131-~131: The official name of this software platform is spelled with a capital “H”.
Context: ... personal development - GitHub App: [github/app](/cli/commands/auth/providers/gith...
(GITHUB)
[uncategorized] ~132-~132: The official name of this software platform is spelled with a capital “H”.
Context: ... automation and bots - GitHub OIDC: [github/oidc](/cli/commands/auth/providers/git...
(GITHUB)
[uncategorized] ~258-~258: The official name of this software platform is spelled with a capital “H”.
Context: ... the box with zero configuration**. See [github/user provider documentation](/cli/comm...
(GITHUB)
[uncategorized] ~277-~277: The official name of this software platform is spelled with a capital “H”.
Context: ...or bots and CI/CD with JWT signing. See [github/app provider documentation](/cli/comma...
(GITHUB)
[uncategorized] ~297-~297: The official name of this software platform is spelled with a capital “H”.
Context: ...cation in GitHub Actions workflows. See [github/oidc provider documentation](/cli/comm...
(GITHUB)
website/docs/cli/commands/auth/providers/github-user.mdx
[uncategorized] ~14-~14: The official name of this software platform is spelled with a capital “H”.
Context: ...ser Authentication :::note Purpose The github/user provider authenticates as a GitHu...
(GITHUB)
[grammar] ~274-~274: Please add a punctuation mark at the end of paragraph.
Context: ..., workflow- **Package publishing**: Addwrite:packages` ### Environment Varia...
(PUNCTUATION_PARAGRAPH_END)
[style] ~286-~286: This word has been used in one of the immediately preceding sentences. Using a synonym could make your text more interesting to read, unless the repetition is intentional.
Context: ...//github.com/suzuki-shunsuke/ghtkn), an excellent standalone tool for GitHub token manage...
(EN_REPEATEDWORDS_EXCELLENT)
[style] ~297-~297: This word has been used in one of the immediately preceding sentences. Using a synonym could make your text more interesting to read, unless the repetition is intentional.
Context: ...| Recommendation: Use ghtkn if you need standalone GitHub token management. Use...
(EN_REPEATEDWORDS_NEED)
[uncategorized] ~297-~297: The official name of this software platform is spelled with a capital “H”.
Context: ...lone GitHub token management. Use Atmos github/user if you're already using Atmos for...
(GITHUB)
[typographical] ~301-~301: Consider using a typographic opening quote here.
Context: ...uthentication. ## Troubleshooting ### "Token not found in keychain" The token ...
(EN_QUOTES)
[typographical] ~301-~301: Consider using a typographic close quote here.
Context: ...ooting ### "Token not found in keychain" The token has expired or been deleted....
(EN_QUOTES)
[typographical] ~309-~309: Consider using a typographic opening quote here.
Context: ... atmos auth login -i my-github ``` ### "Failed to store token in keychain" Keyc...
(EN_QUOTES)
[typographical] ~309-~309: Consider using a typographic close quote here.
Context: ... ### "Failed to store token in keychain" Keychain access may be denied. On macO...
(EN_QUOTES)
[typographical] ~318-~318: Consider using a typographic opening quote here.
Context: ...ry/Keychains/login.keychain-db ``` ### "Device code expired" You took too long ...
(EN_QUOTES)
[typographical] ~318-~318: Consider using a typographic close quote here.
Context: ...eychain-db ``` ### "Device code expired" You took too long to authorize. Device...
(EN_QUOTES)
[typographical] ~326-~326: Consider using typographic quotation marks here.
Context: ... atmos auth login -i my-github ``` ### "Insufficient scope" Your token doesn't have the required p...
(EN_QUOTES)
website/docs/cli/commands/auth/providers/github-app.mdx
[uncategorized] ~14-~14: The official name of this software platform is spelled with a capital “H”.
Context: ...App Authentication :::note Purpose The github/app provider authenticates as a GitHub...
(GITHUB)
[typographical] ~175-~175: Consider using typographic quotation marks here.
Context: ...ture docs URL - Webhook: Uncheck "Active" (not needed for CLI use) ### 2. Config...
(EN_QUOTES)
[grammar] ~263-~263: Please add a punctuation mark at the end of paragraph.
Context: ...ly - Never caches tokens beyond command execution ### Private Key Security - **Never co...
(PUNCTUATION_PARAGRAPH_END)
[typographical] ~387-~387: Consider using a typographic opening quote here.
Context: ...m-aws-rds" ``` ## Troubleshooting ### "Failed to generate JWT" Cause: Inva...
(EN_QUOTES)
[typographical] ~387-~387: Consider using a typographic close quote here.
Context: ...bleshooting ### "Failed to generate JWT" Cause: Invalid private key format ...
(EN_QUOTES)
[typographical] ~396-~396: Consider using a typographic opening quote here.
Context: ...openssl rsa -in key.pem -check ``` ### "Installation token request failed with s...
(EN_QUOTES)
[typographical] ~396-~396: Consider using a typographic close quote here.
Context: ...ion token request failed with status 404" Cause: Invalid installation_id or ...
(EN_QUOTES)
[typographical] ~405-~405: Consider using a typographic opening quote here.
Context: ...Check app has not been uninstalled ### "Failed to parse private key" Cause:...
(EN_QUOTES)
[typographical] ~405-~405: Consider using a typographic close quote here.
Context: ...talled ### "Failed to parse private key" Cause: Private key contains invali...
(EN_QUOTES)
[typographical] ~411-~411: Consider using typographic quotation marks here.
Context: ...private key in GitHub app settings ### "Insufficient permissions" Cause: App doesn't have required p...
(EN_QUOTES)
IMPLEMENTATION_COMPLETE.md
[uncategorized] ~8-~8: The official name of this software platform is spelled with a capital “H”.
Context: ...Providers - ✅ GitHub User Provider (pkg/auth/providers/github/user.go) - OAuth Device Flow with **ze...
(GITHUB)
[uncategorized] ~9-~9: The official name of this software platform is spelled with a capital “H”.
Context: ...Auth App** - ✅ GitHub App Provider (pkg/auth/providers/github/app.go) - JWT + Installation Tokens - ...
(GITHUB)
[uncategorized] ~10-~10: The official name of this software platform is spelled with a capital “H”.
Context: ...on Tokens - ✅ GitHub OIDC Provider (pkg/auth/providers/github/oidc.go) - Already existed, updated - ...
(GITHUB)
[uncategorized] ~11-~11: The official name of this software platform is spelled with a capital “H”.
Context: ...ed, updated - ✅ Device Flow Client (pkg/auth/providers/github/device_flow_client.go) - Real implemen...
(GITHUB)
[uncategorized] ~12-~12: The official name of this software platform is spelled with a capital “H”.
Context: ...plementation - ✅ OS Keychain Store (pkg/auth/providers/github/keychain_store.go) - Cross-platform - ...
(GITHUB)
[uncategorized] ~13-~13: The official name of this software platform is spelled with a capital “H”.
Context: ...ss-platform - ✅ Provider Constants (pkg/auth/providers/github/constants.go) - KindUser, KindApp, Kin...
(GITHUB)
[uncategorized] ~16-~16: The official name of this software platform is spelled with a capital “H”.
Context: ...ls Types - ✅ GitHubUserCredentials (pkg/auth/types/github_user_credentials.go) - ✅ **GitHubAppCr...
(GITHUB)
[uncategorized] ~17-~17: The official name of this software platform is spelled with a capital “H”.
Context: ...ials.go) - ✅ **GitHubAppCredentials** (pkg/auth/types/github_app_credentials.go`) #### Commands - ✅...
(GITHUB)
[uncategorized] ~24-~24: The official name of this software platform is spelled with a capital “H”.
Context: ...(pkg/auth/factory/factory.go) - Added github/user and github/app - ✅ **Provider Cons...
(GITHUB)
[uncategorized] ~24-~24: The official name of this software platform is spelled with a capital “H”.
Context: ...ry/factory.go`) - Added github/user and github/app - ✅ Provider Constants - Used t...
(GITHUB)
[uncategorized] ~85-~85: The official name of this software platform is spelled with a capital “H”.
Context: ... ### ❌ NOT Implemented (Correctly) - ❌ pkg/store/github_user_store.go - WRONG ARCHITECTURE...
(GITHUB)
[uncategorized] ~86-~86: The official name of this software platform is spelled with a capital “H”.
Context: ..._store.go- **WRONG ARCHITECTURE** - ❌pkg/store/github_app_store.go` - WRONG ARCHITECTURE ...
(GITHUB)
[typographical] ~88-~88: Consider using a typographic opening quote here.
Context: ... - NOT NEEDED - ❌ Template function {{ atmos.Store "github-user" }} - NOT NEEDED ### ✅...
(EN_QUOTES)
[grammar] ~88-~88: Please add a punctuation mark at the end of paragraph.
Context: ...{ atmos.Store "github-user" }}` - NOT NEEDED ### ✅ Correct Architecture GitHub au...
(PUNCTUATION_PARAGRAPH_END)
🪛 markdownlint-cli2 (0.18.1)
docs/prd/github-authentication-providers.md
194-194: Fenced code blocks should have a language specified
(MD040, fenced-code-language)
237-237: Fenced code blocks should have a language specified
(MD040, fenced-code-language)
276-276: Fenced code blocks should have a language specified
(MD040, fenced-code-language)
308-308: Fenced code blocks should have a language specified
(MD040, fenced-code-language)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (9)
- GitHub Check: Build (linux)
- GitHub Check: Build (windows)
- GitHub Check: Build (macos)
- GitHub Check: Run pre-commit hooks
- GitHub Check: website-deploy-preview
- GitHub Check: Analyze (go)
- GitHub Check: Lint (golangci)
- GitHub Check: autofix
- GitHub Check: Summary
🔇 Additional comments (19)
tests/snapshots/TestCLICommands_atmos_auth_invalid-command.stderr.golden (1)
8-14: Snapshot correctly updated for new auth subcommands.The updated subcommand list accurately reflects the addition of
git-credentialandlogoutto theatmos authcommand tree. Alphabetical ordering is maintained, and formatting is consistent.go.mod (2)
3-3: Toolchain update looks good.The Go toolchain bump to 1.25.1 is appropriate for this feature addition.
45-45: JWT dependency correctly promoted to direct.This aligns with the GitHub App provider implementation that signs JWTs for installation tokens.
pkg/auth/credentials/store.go (2)
55-60: Store implementation for GitHub credentials looks good.The new credential types follow the established pattern for AWS and OIDC credentials. Type strings match between Store and Retrieve methods.
105-116: Retrieve implementation for GitHub credentials is consistent.Error handling and unmarshaling follow the same pattern as existing credential types.
IMPLEMENTATION_COMPLETE.md (1)
1-175: Implementation tracking document is comprehensive.This provides a clear summary of what was completed and what remains optional. Nice work documenting the 80.8% test coverage achievement.
pkg/auth/identities/github/token.go (3)
24-41: Constructor implementation follows guidelines.Uses
defer perf.Track(), validates config, and provides clear error messages with wrapped errors.
59-84: Authenticate method handles multiple credential types correctly.The type switch properly handles GitHubUserCredentials, GitHubAppCredentials, and OIDCCredentials with appropriate logging for each path.
107-112: PostAuthenticate no-op is appropriate.The comment clearly explains that environment variables are handled elsewhere by the auth manager, so this no-op is intentional.
pkg/auth/factory/factory.go (2)
28-33: Provider factory correctly uses constants.The refactoring from hardcoded "github/oidc" to
githubProviders.KindOIDCand addition of KindUser and KindApp improves maintainability and reduces typo risk.
53-54: GitHub token identity properly registered.The new "github/token" identity kind is correctly wired to the NewTokenIdentity constructor.
cmd/auth_login.go (1)
55-101: Styled authentication output enhances user experience.The lipgloss-based UI provides clear visual feedback while maintaining proper output to stderr per coding guidelines. Conditional field rendering handles varying authentication result types appropriately.
pkg/auth/providers/github/constants.go (2)
4-13: Provider kind constants improve maintainability.Centralizing these constants prevents typos and makes refactoring easier across the codebase.
15-24: DefaultClientID documentation is excellent.The comment clearly explains the source (GitHub CLI), why it's safe to embed, and how users can override it. This level of documentation is helpful for future maintainers.
website/docs/cli/commands/auth/providers/github-app.mdx (1)
1-450: Excellent documentation page for GitHub App authentication.The documentation is comprehensive, well-structured, and covers all essential aspects: authentication flow, configuration, permissions, usage examples, security considerations, and troubleshooting. The Mermaid diagrams effectively illustrate the JWT-based flow, and the examples are practical and correct.
website/docs/cli/commands/auth/usage.mdx (2)
125-132: Well-organized provider categorization.The addition of "AWS Providers" and "GitHub Providers" subsections improves documentation navigation and clearly separates authentication methods by cloud provider.
252-313: Comprehensive GitHub authentication section with clear examples.The new section effectively consolidates GitHub authentication methods (User, App, OIDC) with practical configuration examples and links to detailed provider documentation. The examples are correct and align with the provider implementations.
website/docs/cli/commands/auth/providers/github-user.mdx (1)
1-215: Comprehensive documentation for GitHub User authentication.The documentation effectively covers OAuth Device Flow authentication with excellent structure, practical examples, and clear security guidance. The zero-config setup using the default GitHub CLI OAuth app is particularly well-explained, making it easy for users to get started.
Also applies to: 224-400
pkg/auth/providers/github/user.go (1)
1-362: Solid implementation of GitHub User authentication via OAuth Device Flow.The provider correctly implements Device Flow authentication with proper error handling, UI output to stderr, perf tracking, and cross-platform TTY detection. All coding guidelines are followed: comments end with periods, errors use static types from errUtils, and UI interactions go to stderr.
- Extract helper functions to reduce cyclomatic and cognitive complexity - loadPrivateKey: Split into loadPrivateKeyPEM and parseRSAPrivateKey - NewUserProvider: Extract config parsing into helper functions - pollOnce: Extract response processing and logging - Spinner functions: Extract TTY handling into spinnerUI type - Fix function length issues (max 60 lines) - pollOnce: Reduced from 71 to 33 lines by extracting helpers - runSpinnerDuringPoll: Reduced from 62 to 30 lines with spinnerUI - runSpinnerDuringWebFlow: Reduced from 62 to 30 lines with spinnerUI - Fix revive function-result-limit - pollOnce: Wrap 4 return values into pollResult struct - Add static error sentinels in errors/errors.go - ErrPrivateKeyEnvNotSet - ErrPrivateKeyConfigMissing - ErrPEMDecodeFailed - ErrPrivateKeyNotRSA - ErrInstallationTokenRequest - Replace magic numbers with named constants - loginBoxWidth = 60 for display box width - loginLabelWidth = 12 for label width - httpClientTimeout = 30 for GitHub API timeout - deviceFlowHTTPTimeout = 30 for device flow timeout - logKeyIdentity = "identity" for logging - Add justified nolint directives - auth_git_credential.go: error=nil intentional per git protocol - auth_logout.go: authManager unused until TODO implemented - app.go: os.Getenv expected pattern for GitHub App keys - Fix comment capitalization for godot linter - All constant comments now start without lowercase variable names All linting issues resolved - make lint passes with 0 issues. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
|
Important Cloud Posse Engineering Team Review RequiredThis pull request modifies files that require Cloud Posse's review. Please be patient, and a core maintainer will review your changes. To expedite this process, reach out to us on Slack in the |
|
|
||
| // Output credentials in git credential helper format. | ||
| fmt.Printf("username=x-access-token\n") | ||
| fmt.Printf("password=%s\n", token) |
Check failure
Code scanning / CodeQL
Clear-text logging of sensitive information High
Copilot Autofix
AI 5 months ago
Copilot could not generate an autofix suggestion
Copilot could not generate an autofix suggestion for this alert. Try pushing a new commit or if the problem persists contact support.
|
💥 This pull request now has conflicts. Could you fix it @osterman? 🙏 |
Added PR links to milestones across all initiatives: Auth Initiative: - EKS Kubeconfig → PR #1884 - ECR Authentication → PR #1859 - GitHub Apps → PR #1683 Developer Experience: - Streaming Terraform UI → PR #1908 - Native CI integration → PR #1891 Workflows: - Unified task execution → PR #1901 - New workflow step types → PR #1899 Extensibility: - Added !unset YAML function → PR #1521 - Added !append YAML function → PR #1513 Vendoring: - Vendor registry pattern → PR #1889 - Just-in-time vendoring → PR #1877 - Component workdir provisioning → PR #1876 Terragrunt Parity: - Multi-stack formats → PR #1842 CI/CD: - CI Summary Templates → PR #1891 - Terraform command registry → PR #1891
* feat: Add comprehensive roadmap page with initiatives and milestones - Add Roadmap component with interactive initiative cards - Create MilestoneList, MilestoneDrawer, and ProgressBar components - Add Tooltip component for PR/issue titles with theme-aware styling - Implement responsive design with flexbox alignment fixes - Add extensive roadmap data with documented milestones across 10 initiatives - Add changelog and docs links to all relevant milestones - Update Docusaurus navbar with Roadmap link 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com> * fix: Address CodeRabbit review comments for roadmap components - Fix type mismatch: use undefined instead of null for selectedMilestone - Make changelogSlugs optional in Initiative interface - Replace fragile status className construction with explicit mapping - Reduce tooltip z-index from 9999 to 1002 (just above drawer) - Add scroll/resize listeners for tooltip position updates - Improve keyboard accessibility with tabIndex, aria-describedby, role="tooltip" 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * fix: Update Customizable list output description Focus on custom column views rather than output formats. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * refactor: Move Component-aware tab completion to DX initiative Tab completion is more about developer experience than discoverability. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * refactor(roadmap): rename 'Customizable list output' to 'Customizable list columns' Clarifies that this is an improvement to existing list commands (added Q1 2025), not a new feature. The Q4 2025 milestone added customizable column support. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * docs(roadmap): update initiative names and add new milestones - Rename 'Migration & Code Generation' to 'Feature Parity with Terragrunt' - Rename 'Quality & Community' to 'Code Quality and Community' - Change 'Learning section' to 'New learning section' - Add Native Terraform to migration guides list - Add Roadmap milestone to Documentation initiative 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * fix(roadmap): correct design patterns docs link Changed /design-patterns/design-patterns to /design-patterns 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * feat(roadmap): add 'Request a Feature' link to initiatives section Adds a prominent link to GitHub feature request issue template for users who want to suggest new features for the roadmap. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * feat(roadmap): add 'View Features' link to GitHub issues Adds a link to browse existing feature requests and issues alongside the 'Request a Feature' link. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * fix(roadmap): rename 'View Features' to 'View Issues' 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * refactor(roadmap): reorganize Feature Parity with Terragrunt initiative Changes to Feature Parity with Terragrunt: - Keep: File-scoped locals - Rename: Stack name field → Imperative stack names - Rename: Generate section inheritance → File generation (generate blocks) - Rename: Backend provisioning → Automatic backend provisioning - Add: AWS context YAML functions (!aws.account-id, !aws.region, etc.) - Remove: Metadata inheritance (merged into other features) Moved to Extensibility & Custom Components: - !literal YAML function - metadata.name for component workspace keys 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * feat(roadmap): add planned Terragrunt parity features - Automatic source provisioning (no vendoring required) - Concurrent component provisioning - plan --all and apply --all commands - Automatic provider caching 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * feat(roadmap): update DX milestones - Update parent directory search description to emphasize running from any directory - Add filesystem paths for components feature 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * fix(roadmap): use neutral blue gradient for progress bars Replace orange/red colors with lighter blues to avoid 'behind schedule' connotation - progress just means 'not as far along yet', not delayed. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * refactor(roadmap): reorganize quality and docs initiatives - Rename 'Code Quality and Community' to 'Code Quality and Test Coverage' - Rename 'Documentation Overhaul' to 'Documentation Overhaul and Community Announcements' - Move 'Changelog introduction' from quality to docs initiative - Rename migration guides milestone to 'Added migration guides' 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * feat(roadmap): add nightly releases and PR feature releases to quality initiative 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * feat(roadmap): add 'Push for stability' to quality initiative 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * fix(roadmap): clarify backend provisioning vs backend generation Backend provisioning is about provisioning the backend itself (S3 bucket, DynamoDB table) for cold-start scenarios, not just generating backend.tf files. * fix(roadmap): remove DynamoDB from backend provisioning description DynamoDB locking is no longer needed for S3 state backends. * fix(roadmap): mention native S3 state locking for backend provisioning * feat(roadmap): mark --all flags as shipped, add PR links for planned features - Mark 'plan --all' and 'apply --all' as shipped (Q4 2025) - Add PR #1877 link for automatic source provisioning - Add PR #1882 link for automatic provider caching * feat(roadmap): add comprehensive PR links to milestones Added PR links to milestones across all initiatives: Auth Initiative: - EKS Kubeconfig → PR #1884 - ECR Authentication → PR #1859 - GitHub Apps → PR #1683 Developer Experience: - Streaming Terraform UI → PR #1908 - Native CI integration → PR #1891 Workflows: - Unified task execution → PR #1901 - New workflow step types → PR #1899 Extensibility: - Added !unset YAML function → PR #1521 - Added !append YAML function → PR #1513 Vendoring: - Vendor registry pattern → PR #1889 - Just-in-time vendoring → PR #1877 - Component workdir provisioning → PR #1876 Terragrunt Parity: - Multi-stack formats → PR #1842 CI/CD: - CI Summary Templates → PR #1891 - Terraform command registry → PR #1891 * feat(roadmap): improve milestone labels with descriptive context Update milestone labels to describe what each feature does rather than just listing the command or feature name: - Discoverability: Change "Added `atmos list stacks`" to "`atmos list stacks` to browse all configured stacks" etc. - Auth: Change "EKS Kubeconfig integration" to "Automatic EKS kubeconfig tied to identities" and similar for ECR 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * feat(roadmap): add Featured Improvements section with 6 key highlights Add a prominent Featured Improvements section near the top of the roadmap page showcasing major capabilities: 1. Dev Container Support - Consistent development environments 2. Toolchain Management - Automatic tool installation and versioning 3. Cloud Authentication - Unified identity layer across clouds 4. Beautiful Workflows - Multi-step automation with typed inputs 5. Source Provisioning - Just-in-time component fetching (in-progress) 6. Native CI/CD Support - Local = CI experience (in-progress) Also fixes: - Provider auto-generation marked as shipped (Q3 2025) - Devcontainer docs link corrected 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * feat(roadmap): enhance featured section and milestone grouping - Add PRD links to featured items (devcontainer, keyring-backends, provisioner-system, terraform-registry-migration) - Fix statuses: Toolchain Management and Beautiful Workflows changed from shipped to in-progress - Update quarters: Native CI/CD, Toolchain, Workflows, and Source Provisioning set to Q1 2026 - Add sorting by status (shipped first) and quarter (earlier first) - Implement milestone grouping with categories (Featured Improvements, Everything Else) and priorities (high, nice-to-have) - Add PR links for Toolchain Management (#1686) and Beautiful Workflows (#1899) - Update Cloud Authentication description with "Zero local config required" - Rename "Initiatives" section to "Major Initiatives" 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * feat(roadmap): add benefits field, clickable featured cards, and overall progress stats - Add benefits field to all 89 milestones explaining "Why It Matters" - Add benefits to 6 featured items with benefit-focused explanations - Create FeaturedDrawer component for featured card detail view - Make featured cards clickable with drawer showing description/benefits - Create RoadmapStats component showing overall progress (shipped/in-progress/planned) - Add animated progress bar with color-coded segments - Expand changelog-check.yml to also require roadmap.js updates for minor/major PRs - Update CLAUDE.md with roadmap update requirements 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * fix(roadmap): simplify drawer links to reduce visual noise Remove heavy background colors from drawer link buttons and convert them to simple inline text links that wrap horizontally. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * fix(roadmap): use plain colors for drawer links, one per line - Change links to use neutral emphasis colors instead of brand colors - Display each link on its own line for cleaner vertical layout 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * style(roadmap): use brightening instead of underline for drawer link hover Change drawer link hover behavior to brighten text color instead of adding underline for cleaner visual feedback. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * docs(roadmap): add CI/local parity to cloud auth benefits Highlight that cloud authentication works identically in CI and locally, a key differentiator for the unified auth system. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * style(roadmap): increase gap between progress bar and Major Initiatives Add more breathing room between the Overall Progress section and the Major Initiatives heading below it. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * style(roadmap): double gap between progress bar and Major Initiatives Increase bottom margin from 3rem to 6rem for more visual separation. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * docs(roadmap): mark Terragrunt parity milestones as featured Mark all major Terragrunt feature parity milestones as featured: - File-scoped locals - Imperative stack names - File generation (generate blocks) - Automatic backend provisioning - AWS context YAML functions - Multi-stack formats (YAML, JSON and HCL) - Automatic provider caching - Automatic source provisioning - Provider auto-generation - Concurrent component provisioning Also link PR #1876 (workdir provisioning) to concurrent component provisioning milestone. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * fix(roadmap): address CodeRabbit review feedback - Add target="_blank" and rel="noopener noreferrer" to external GitHub links in FeaturedSection.tsx (PRD and PR links) - Add target="_blank" and rel="noopener noreferrer" to external GitHub links in InitiativeCard.tsx (issues and PRs) - Add target="_blank" and rel="noopener noreferrer" to external GitHub links in FeaturedDrawer.tsx (PRD and PR links) - Guard against division by zero in RoadmapStats.tsx progress bar width calculations 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * docs(blog): introduce the Atmos product roadmap Add a blog post announcing the new public product roadmap page, highlighting: - Featured improvements like Dev Containers, Cloud Auth, and Workflows - Major initiatives including Terragrunt parity and documentation overhaul - Overall progress tracking across all milestones - How to get involved and provide feedback 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * docs(roadmap): reconcile changelog announcements with roadmap Add missing changelog links to existing milestones: - workflow-file-auto-discovery - automatic-backend-provisioning - path-based-component-resolution - aws-yaml-functions - product-roadmap Add new milestones for shipped features: - Auth: auth shell, SSO auto-provisioning, identity flag for describe - DX: terminal themes, helpful errors, provenance tracking, global env, metadata inheritance, interactive terraform prompts - Extensibility: !random, !env stack manifest support, circular dependency detection, deferred evaluation, boolean flags Update progress percentages: - Auth: 80% → 85% - DX: 75% → 90% - Extensibility: 50% → 80% 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * fix(roadmap): correct broken documentation links Update doc links to use correct paths: - /cli/configuration/configuration → /cli/configuration - /cli/commands/commands → /cli/commands 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * address comments and feedback * address comments and feedback --------- Co-authored-by: Claude Haiku 4.5 <noreply@anthropic.com> Co-authored-by: Andriy Knysh <aknysh@users.noreply.github.com> Co-authored-by: aknysh <andriy.knysh@gmail.com>
|
💥 This pull request now has conflicts. Could you fix it @osterman? 🙏 |
what
This PR implements GitHub User and GitHub App authentication providers, enhancing Atmos's capabilities for secure credential management in various workflows. It also refactors the authentication documentation to improve organization and discoverability.
why
github/user,github/app,github/oidc) for better maintainability and discoverability.references
ghtkn. User tokens are cached in OS keychains with an 8-hour lifetime.atmos auth git-credentialfor seamless Git operations.atmos auth logoutfor keychain cleanup and guidance on token revocation.github/user,github/app, andgithub/oidc.usage.mdxto link to new pages and deduplicate OIDC content.KindUser,KindApp,KindOIDC) for all GitHub providers.closes #XXX (Placeholder for actual issue number)
Summary by CodeRabbit
Release Notes
New Features
atmos auth git-credentialcommand for seamless Git integrationatmos auth logoutcommand to revoke GitHub credentialsDocumentation
Chores