-
Notifications
You must be signed in to change notification settings - Fork 16
[CFX-4857][CFX-4611] Added support for pulumi login during start and dotenv setup #344
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
2f642de
1b6ae7e
5bbb471
b271cc8
590dab5
f4a3af2
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,30 @@ | ||
| // Copyright 2025 DataRobot, Inc. and its affiliates. | ||
| // | ||
| // Licensed under the Apache License, Version 2.0 (the "License"); | ||
| // you may not use this file except in compliance with the License. | ||
| // You may obtain a copy of the License at | ||
| // | ||
| // http://www.apache.org/licenses/LICENSE-2.0 | ||
| // | ||
| // Unless required by applicable law or agreed to in writing, software | ||
| // distributed under the License is distributed on an "AS IS" BASIS, | ||
| // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
| // See the License for the specific language governing permissions and | ||
| // limitations under the License. | ||
|
|
||
| package dotenv | ||
|
|
||
| import ( | ||
| "os" | ||
| "testing" | ||
| ) | ||
|
|
||
| func TestMain(m *testing.M) { | ||
| // Clear environment variables that might leak from the host environment | ||
| // into tests, ensuring tests have a clean isolated environment. | ||
| os.Unsetenv("DATAROBOT_ENDPOINT") | ||
| os.Unsetenv("DATAROBOT_API_TOKEN") | ||
| os.Unsetenv("PULUMI_CONFIG_PASSPHRASE") | ||
|
|
||
| os.Exit(m.Run()) | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -45,25 +45,30 @@ const ( | |
| listScreen = screens(iota) | ||
| editorScreen | ||
| wizardScreen | ||
| pulumiScreen | ||
| ) | ||
|
|
||
| type Model struct { | ||
| screen screens | ||
| initialScreen screens | ||
| DotenvFile string | ||
| variables []envbuilder.Variable | ||
| err error | ||
| textarea textarea.Model | ||
| contents string | ||
| width int | ||
| height int | ||
| SuccessCmd tea.Cmd | ||
| prompts []envbuilder.UserPrompt | ||
| currentPromptIndex int | ||
| currentPrompt promptModel | ||
| hasPrompts *bool // Cache whether prompts are available | ||
| ShowAllPrompts bool // When true, show all prompts regardless of defaults | ||
| skippedPrompts int // Count of prompts skipped due to having defaults | ||
| screen screens | ||
| initialScreen screens | ||
| DotenvFile string | ||
| variables []envbuilder.Variable | ||
| err error | ||
| textarea textarea.Model | ||
| contents string | ||
| width int | ||
| height int | ||
| SuccessCmd tea.Cmd | ||
| prompts []envbuilder.UserPrompt | ||
| currentPromptIndex int | ||
| currentPrompt promptModel | ||
| hasPrompts *bool // Cache whether prompts are available | ||
| ShowAllPrompts bool // When true, show all prompts regardless of defaults | ||
| skippedPrompts int // Count of prompts skipped due to having defaults | ||
| pulumiModel *pulumiLoginModel // Sub-model for Pulumi login flow, shown before wizard if needed | ||
| NeedsPulumiLogin bool // Set by callers before Init(); true when login or passphrase setup is needed | ||
| PulumiAlreadyLoggedIn bool // Set by callers; when true, Pulumi screen skips backend selection | ||
| NeedsPulumiPassphrase bool // Set by callers; when true, passphrase prompt is shown after login | ||
| } | ||
|
|
||
| type ( | ||
|
|
@@ -160,7 +165,14 @@ func (m Model) loadPrompts() tea.Cmd { | |
| return func() tea.Msg { | ||
| currentDir := filepath.Dir(m.DotenvFile) | ||
|
|
||
| userPrompts, err := envbuilder.GatherUserPrompts(currentDir, m.variables) | ||
| variables := m.variables | ||
| if len(variables) == 0 { | ||
| // Read from .env file (falls back to default template when file doesn't exist) | ||
| // so that promptsWithValues can apply defaults and env var values correctly. | ||
| variables, _, _ = readDotenvFileVariables(m.DotenvFile) | ||
| } | ||
|
|
||
| userPrompts, err := envbuilder.GatherUserPrompts(currentDir, variables) | ||
| if err != nil { | ||
| return errMsg{err} | ||
| } | ||
|
|
@@ -245,7 +257,32 @@ func (m Model) Init() tea.Cmd { | |
| return tea.Batch(m.loadVariables(), tea.WindowSize()) | ||
| } | ||
|
|
||
| func (m Model) handlePulumiUpdate(msg tea.Msg) (tea.Model, tea.Cmd) { | ||
| switch msg.(type) { | ||
| case pulumiLoginCompleteMsg: | ||
| // Pulumi setup finished — reload prompts so the newly saved passphrase | ||
| // is picked up before the wizard starts. | ||
| m.pulumiModel = nil | ||
| m.NeedsPulumiLogin = false | ||
|
|
||
| return m, m.loadPrompts() | ||
|
cursor[bot] marked this conversation as resolved.
|
||
| } | ||
|
|
||
| subModel, cmd := m.pulumiModel.Update(msg) | ||
|
|
||
| if plm, ok := subModel.(pulumiLoginModel); ok { | ||
| m.pulumiModel = &plm | ||
| } | ||
|
|
||
| return m, cmd | ||
| } | ||
|
|
||
| func (m Model) Update(msg tea.Msg) (tea.Model, tea.Cmd) { //nolint: cyclop | ||
| // If Pulumi login sub-model is active, delegate to it | ||
| if m.pulumiModel != nil { | ||
| return m.handlePulumiUpdate(msg) | ||
| } | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. WindowSizeMsg lost during Pulumi login flowLow Severity When
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This seems like a valid issue @carsongee |
||
|
|
||
| switch msg := msg.(type) { | ||
| case tea.WindowSizeMsg: | ||
| m.width = msg.Width | ||
|
|
@@ -281,9 +318,19 @@ func (m Model) Update(msg tea.Msg) (tea.Model, tea.Cmd) { //nolint: cyclop | |
|
|
||
| if len(m.prompts) == 0 { | ||
| m.screen = listScreen | ||
|
|
||
| return m, nil | ||
| } | ||
|
|
||
| // Check if Pulumi login/passphrase setup is needed before the wizard | ||
| if m.NeedsPulumiLogin { | ||
| plm := newPulumiLoginModel(m.PulumiAlreadyLoggedIn, m.NeedsPulumiPassphrase) | ||
| m.pulumiModel = &plm | ||
| m.screen = pulumiScreen | ||
|
|
||
| return m, plm.Init() | ||
| } | ||
|
|
||
| return m.moveToNextPrompt() | ||
| case openEditorMsg: | ||
| m.screen = editorScreen | ||
|
|
@@ -307,6 +354,8 @@ func (m Model) Update(msg tea.Msg) (tea.Model, tea.Cmd) { //nolint: cyclop | |
| } | ||
|
|
||
| switch m.screen { | ||
| case pulumiScreen: | ||
| // Handled above via m.pulumiModel delegation | ||
| case listScreen: | ||
| switch msg := msg.(type) { | ||
| case tea.KeyMsg: | ||
|
|
@@ -385,6 +434,10 @@ func (m Model) View() string { | |
| var sb strings.Builder | ||
|
|
||
| switch m.screen { | ||
| case pulumiScreen: | ||
| if m.pulumiModel != nil { | ||
| sb.WriteString(m.pulumiModel.View()) | ||
| } | ||
| case listScreen: | ||
| sb.WriteString(m.viewListScreen()) | ||
| case editorScreen: | ||
|
|
||


Uh oh!
There was an error while loading. Please reload this page.