onboard

package
v0.1.21 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Nov 25, 2025 License: Apache-2.0 Imports: 14 Imported by: 0

README

Onboarding Wizard

This directory contains the implementation of the tusk init onboarding wizard, a terminal UI (TUI) that guides users through configuring Tusk Drift for their service.

Architecture Overview

The wizard is built using Bubble Tea.

Key Components
onboard/
├── run.go              # Entry point - initializes and runs the wizard
├── model.go            # Model - application state
├── flow.go             # Step interface and flow control
├── steps.go            # Step implementations (all wizard steps)
├── update.go           # Update - handles user input and state transitions
├── view.go             # View - renders the UI
├── helpers.go          # Helper functions (defaults, validation, state clearing)
├── config.go           # Config types and YAML generation
├── yaml.go             # YAML formatting utilities
├── docker.go           # Docker detection helpers
├── detect_project.go   # Project type detection
└── compose_override.go # Docker Compose override file generation

The Step Interface

Each step in the wizard implements the Step interface defined in flow.go:

type Step interface {
    ID() onboardStep
    InputIndex() int
    Question(*Model) string
    Description(*Model) string
    Default(*Model) string
    Validate(*Model, string) error
    Apply(*Model, string)
    Help(*Model) string
    ShouldSkip(*Model) bool
    Clear(*Model)
}
Method Responsibilities
  • ID(): Returns the unique step identifier (e.g., stepServiceName)
  • InputIndex(): Returns which text input field to use (0-7), or -1 for non-input steps
  • Question(): The main prompt shown to the user
  • Description(): Additional explanatory text below the question
  • Default(): Default value if user presses Enter without typing
  • Validate(): Validates user input; returns nil if valid, error if invalid
  • Apply(): Updates the model with validated input
  • Help(): Footer help text (back button is added automatically by the view)
  • ShouldSkip(): Whether to skip this step based on current state
  • Clear(): Clears this step's state when navigating backward
BaseStep

Most methods have sensible defaults provided by BaseStep. Embed it and override only what you need:

type BaseStep struct{}

func (BaseStep) Validate(*Model, string) error { return nil }
func (BaseStep) Apply(*Model, string)          {}
func (BaseStep) Help(*Model) string            { return "enter: use default • esc: quit" }
func (BaseStep) ShouldSkip(*Model) bool        { return false }
func (BaseStep) Clear(*Model)                  {}

Step Types

1. Info Steps (No Input)

Steps that display information and wait for Enter:

type IntroStep struct{ BaseStep }

func (IntroStep) ID() onboardStep        { return stepIntro }
func (IntroStep) InputIndex() int        { return -1 }  // No input needed
func (IntroStep) Question(*Model) string { return "Welcome message" }
func (IntroStep) Description(*Model) string { return "Press [enter] to continue." }
func (IntroStep) Help(*Model) string     { return "enter: continue • esc: quit" }
2. Yes/No Steps

Steps that wait for y or n keypresses (handled in update.go):

type DockerSetupStep struct{ BaseStep }

func (DockerSetupStep) ID() onboardStep        { return stepDockerSetup }
func (DockerSetupStep) InputIndex() int        { return -1 }
func (DockerSetupStep) Question(*Model) string { return "Will you use Docker? (y/n)" }
func (DockerSetupStep) Help(*Model) string     { return "y: yes • n: no • esc: quit" }
func (DockerSetupStep) Clear(m *Model)         { m.UseDocker = false }
3. Text Input Steps

Steps that collect text input from the user:

type ServiceNameStep struct{ BaseStep }

func (ServiceNameStep) ID() onboardStep           { return stepServiceName }
func (ServiceNameStep) InputIndex() int           { return 1 }  // Uses inputs[1]
func (ServiceNameStep) Question(*Model) string    { return "What's your service name?" }
func (ServiceNameStep) Description(*Model) string { return "e.g., \"acme-backend\"" }
func (ServiceNameStep) Default(m *Model) string   { return m.serviceNameDefault() }
func (ServiceNameStep) Apply(m *Model, v string)  { m.ServiceName = v }
func (ServiceNameStep) Clear(m *Model)            { m.ServiceName = "" }
4. Conditional Steps

Steps that are skipped based on state:

type StopCommandStep struct{ BaseStep }

func (StopCommandStep) ShouldSkip(m *Model) bool { return !m.UseDocker }
// ... other methods

Adding a New Step

Step 1: Define the Step Constant

Add your step to the onboardStep enum in model.go:

const (
    stepValidateRepo onboardStep = iota
    stepIntro
    // ... existing steps
    stepYourNewStep  // Add here
    stepConfirm
    stepDone
)
Step 2: Create the Step Type

Add your step implementation to steps.go:

type YourNewStep struct{ BaseStep }

func (YourNewStep) ID() onboardStep { return stepYourNewStep }
func (YourNewStep) InputIndex() int { return 8 }  // Next available index, or -1
func (YourNewStep) Question(*Model) string {
    return "Your question here?"
}
func (YourNewStep) Description(*Model) string {
    return "Additional context or examples"
}
func (YourNewStep) Default(*Model) string {
    return "default-value"
}
func (YourNewStep) Validate(_ *Model, v string) error {
    // Validate input
    if v == "" {
        return fmt.Errorf("Value cannot be empty")
    }
    return nil
}
func (YourNewStep) Apply(m *Model, v string) {
    m.YourNewField = v
}
func (YourNewStep) Clear(m *Model) {
    m.YourNewField = ""
}
Step 3: Add State to Model

Add the field to store your step's data in model.go:

type Model struct {
    // ... existing fields
    YourNewField string
}
Step 4: Register the Step

Add your step to the flow in steps.go's stepsList():

func stepsList() []Step {
    return []Step{
        ValidateRepoStep{},
        IntroStep{},
        // ... existing steps
        YourNewStep{},  // Add in the desired order
        ConfirmStep{},
        DoneStep{},
    }
}
Step 5: Use the Value in Config

If your step's value should be saved to the config file, update getCurrentConfig() in config.go:

func (m *Model) getCurrentConfig() Config {
    cfg := Config{
        // ... existing config
        YourNewField: m.YourNewField,
    }
    return cfg
}
Step 6: (Optional) Add Custom View Logic

If your step needs special rendering beyond the default, add a case in view.go:

case stepYourNewStep:
    // Custom rendering logic
    body.WriteString("Special formatting for your step\n")
Step 7: (Optional) Handle Special Input

If your step uses custom key handling (like y/n), add logic in update.go:

case "y":
    switch m.flow.Current(m.stepIdx).ID() {
    case stepYourNewStep:
        // Handle 'y' keypress
        m.advance()
        return m, nil
    }

Input Field Management

The wizard pre-allocates text input fields for efficiency. Each input step must declare which field it uses via InputIndex().

Current allocation: Inputs 0-7 are used. If adding a new input step, use the next available index (8, 9, etc.).

The number of inputs is calculated dynamically in run.go based on the maximum InputIndex() across all steps.

Navigation & History

Forward Navigation
  • User presses Enter → commitCurrent() validates and applies input → advance() moves to next step
  • Steps with ShouldSkip() == true are automatically skipped by Flow.NextIndex()
Backward Navigation
  • User presses Ctrl+B or Left Arrow → pops from history → clearValuesFromStep() resets dependent state
  • History is managed in update.go's advance() method
  • Steps excluded from history: stepValidateRepo, stepConfirm, stepDone
Auto-Skip Logic

When a step is auto-skipped (e.g., Docker type when only one Docker option exists), use manual stepIdx increment instead of advance() to avoid adding it to history:

m.advance()  // Adds current step to history
m.stepIdx = m.flow.NextIndex(m.stepIdx, m)  // Skip without history

State Clearing

When navigating backward, clearValuesFromStep() in helpers.go resets the state of the target step and all state that comes after it. This ensures users can change earlier decisions without stale data.

Viewport Scrolling

The confirmation step (stepConfirm) uses a Bubble Tea viewport to allow scrolling through the YAML config preview. This is managed in:

  • model.go: viewport field and viewportReady flag
  • update.go: updateViewportSize() and viewport key handling
  • view.go: Viewport rendering and content setting

Testing Locally

Run the wizard with:

cd /path/to/your/nodejs/project
tusk init

The wizard will:

  1. Validate you're in a Node.js project (has package.json)
  2. Guide you through configuration
  3. Generate .tusk/config.yaml
  4. Optionally create docker-compose.tusk-override.yml

Common Patterns

Dynamic Defaults

Use model state to compute defaults:

func (s ServiceNameStep) Default(m *Model) string {
    if m.DockerAppName != "" {
        return m.DockerAppName
    }
    return inferServiceNameFromDir()
}
Dynamic Questions/Descriptions

Tailor prompts based on state:

func (s StartCommandStep) Question(m *Model) string {
    if m.DockerType == dockerTypeCompose {
        return "What's your Docker Compose start command?"
    }
    return "How do you start your service?"
}
Validation with Custom Errors
func (ServicePortStep) Validate(_ *Model, v string) error {
    _, err := strconv.Atoi(trimFirstToken(v))
    if err != nil {
        return fmt.Errorf("Invalid port: must be an integer")
    }
    return nil
}
Conditional Skipping
func (DockerTypeStep) ShouldSkip(m *Model) bool {
    return !m.UseDocker  // Skip if not using Docker
}

Troubleshooting

Blank screen on a step
  • Check that View() returns content for your step
  • Ensure InputIndex() returns a valid index if it's an input step
  • Verify the step isn't being auto-skipped unintentionally
Input not appearing
  • Confirm InputIndex() returns a valid index (0-7, or higher if you added more)
  • Check that the input is focused in advance() via focusActiveInput()
Validation not working
  • Ensure Validate() returns an error (not nil) for invalid input
  • Check that commitCurrent() is being called (happens on Enter for input steps)

Todos

  • Service compatibility check to support more languages and SDKs
  • Onboarding wizard currently does not support word wrapping for narrower windows

Documentation

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func RunOnboardingWizard

func RunOnboardingWizard() error

Types

type BaseStep

type BaseStep struct{}

func (BaseStep) Apply

func (BaseStep) Apply(*Model, string)

func (BaseStep) Clear

func (BaseStep) Clear(*Model)

func (BaseStep) Help

func (BaseStep) Help(*Model) string

func (BaseStep) ShouldSkip

func (BaseStep) ShouldSkip(*Model) bool

func (BaseStep) Validate

func (BaseStep) Validate(*Model, string) error

type Communication

type Communication struct {
	Type    string `yaml:"type,omitempty"`
	TCPPort int    `yaml:"tcp_port,omitempty"`
}

type Config

type Config struct {
	Service       Service       `yaml:"service"`
	Traces        Traces        `yaml:"traces"`
	TestExecution TestExecution `yaml:"test_execution"`
	Recording     Recording     `yaml:"recording"`
	TuskAPI       *TuskAPI      `yaml:"tusk_api,omitempty"`
}

type ConfirmStep

type ConfirmStep struct{ BaseStep }

func (ConfirmStep) Default

func (ConfirmStep) Default(*Model) string

func (ConfirmStep) Description

func (ConfirmStep) Description(*Model) string

func (ConfirmStep) Help

func (ConfirmStep) Help(*Model) string

func (ConfirmStep) ID

func (ConfirmStep) ID() onboardStep

func (ConfirmStep) InputIndex

func (ConfirmStep) InputIndex() int

func (ConfirmStep) Question

func (ConfirmStep) Question(*Model) string

type DockerCompose

type DockerCompose struct {
	Services map[string]any `yaml:"services"`
}

type DockerSetupStep

type DockerSetupStep struct{ BaseStep }

func (DockerSetupStep) Clear

func (DockerSetupStep) Clear(m *Model)

func (DockerSetupStep) Default

func (DockerSetupStep) Default(*Model) string

func (DockerSetupStep) Description

func (DockerSetupStep) Description(*Model) string

func (DockerSetupStep) Help

func (DockerSetupStep) Help(*Model) string

func (DockerSetupStep) ID

func (DockerSetupStep) ID() onboardStep

func (DockerSetupStep) InputIndex

func (DockerSetupStep) InputIndex() int

func (DockerSetupStep) Question

func (DockerSetupStep) Question(*Model) string

type DockerTypeStep

type DockerTypeStep struct{ BaseStep }

func (DockerTypeStep) Default

func (DockerTypeStep) Default(*Model) string

func (DockerTypeStep) Description

func (DockerTypeStep) Description(*Model) string

func (DockerTypeStep) Help

func (DockerTypeStep) Help(*Model) string

func (DockerTypeStep) ID

func (DockerTypeStep) ID() onboardStep

func (DockerTypeStep) InputIndex

func (DockerTypeStep) InputIndex() int

func (DockerTypeStep) Question

func (DockerTypeStep) Question(*Model) string

func (DockerTypeStep) ShouldSkip

func (DockerTypeStep) ShouldSkip(m *Model) bool

type DoneStep

type DoneStep struct{ BaseStep }

func (DoneStep) Default

func (DoneStep) Default(*Model) string

func (DoneStep) Description

func (DoneStep) Description(*Model) string

func (DoneStep) Help

func (DoneStep) Help(*Model) string

func (DoneStep) ID

func (DoneStep) ID() onboardStep

func (DoneStep) InputIndex

func (DoneStep) InputIndex() int

func (DoneStep) Question

func (DoneStep) Question(*Model) string

type Flow

type Flow struct {
	// contains filtered or unexported fields
}

func NewFlow

func NewFlow(steps []Step) *Flow

func (*Flow) Current

func (f *Flow) Current(i int) Step

func (*Flow) NextIndex

func (f *Flow) NextIndex(i int, m *Model) int

func (*Flow) PrevIndex

func (f *Flow) PrevIndex(history []int) (int, []int, bool)

type IntroStep

type IntroStep struct{ BaseStep }

func (IntroStep) Default

func (IntroStep) Default(*Model) string

func (IntroStep) Description

func (IntroStep) Description(*Model) string

func (IntroStep) Help

func (IntroStep) Help(*Model) string

func (IntroStep) ID

func (IntroStep) ID() onboardStep

func (IntroStep) InputIndex

func (IntroStep) InputIndex() int

func (IntroStep) Question

func (IntroStep) Question(*Model) string

type Model

type Model struct {

	// State
	ServiceName       string
	ServicePort       string
	StartCmd          string
	StopCmd           string
	ReadinessCmd      string
	ReadinessTimeout  string
	ReadinessInterval string
	SamplingRate      string

	UseDocker                bool
	DockerType               dockerType
	DockerImageName          string
	DockerAppName            string
	DockerComposeServiceName string // For docker compose override, may not be the same as ServiceName

	SDKCompatible bool

	Err           error
	ValidationErr error
	// contains filtered or unexported fields
}

func (*Model) Init

func (m *Model) Init() tea.Cmd

func (*Model) Update

func (m *Model) Update(msg tea.Msg) (tea.Model, tea.Cmd)

func (*Model) View

func (m *Model) View() string

type Readiness

type Readiness struct {
	Command  string `yaml:"command"`
	Timeout  string `yaml:"timeout"`
	Interval string `yaml:"interval"`
}

type ReadinessCommandStep

type ReadinessCommandStep struct{ BaseStep }

func (ReadinessCommandStep) Apply

func (ReadinessCommandStep) Apply(m *Model, v string)

func (ReadinessCommandStep) Clear

func (ReadinessCommandStep) Clear(m *Model)

func (ReadinessCommandStep) Default

func (s ReadinessCommandStep) Default(m *Model) string

func (ReadinessCommandStep) Description

func (ReadinessCommandStep) Description(*Model) string

func (ReadinessCommandStep) ID

func (ReadinessCommandStep) ID() onboardStep

func (ReadinessCommandStep) InputIndex

func (ReadinessCommandStep) InputIndex() int

func (ReadinessCommandStep) Question

func (ReadinessCommandStep) Question(*Model) string

type ReadinessIntervalStep

type ReadinessIntervalStep struct{ BaseStep }

func (ReadinessIntervalStep) Apply

func (ReadinessIntervalStep) Apply(m *Model, v string)

func (ReadinessIntervalStep) Clear

func (ReadinessIntervalStep) Clear(m *Model)

func (ReadinessIntervalStep) Default

func (ReadinessIntervalStep) Description

func (ReadinessIntervalStep) Description(*Model) string

func (ReadinessIntervalStep) ID

func (ReadinessIntervalStep) ID() onboardStep

func (ReadinessIntervalStep) InputIndex

func (ReadinessIntervalStep) InputIndex() int

func (ReadinessIntervalStep) Question

func (ReadinessIntervalStep) Question(*Model) string

type ReadinessTimeoutStep

type ReadinessTimeoutStep struct{ BaseStep }

func (ReadinessTimeoutStep) Apply

func (ReadinessTimeoutStep) Apply(m *Model, v string)

func (ReadinessTimeoutStep) Clear

func (ReadinessTimeoutStep) Clear(m *Model)

func (ReadinessTimeoutStep) Default

func (ReadinessTimeoutStep) Default(*Model) string

func (ReadinessTimeoutStep) Description

func (ReadinessTimeoutStep) Description(*Model) string

func (ReadinessTimeoutStep) ID

func (ReadinessTimeoutStep) ID() onboardStep

func (ReadinessTimeoutStep) InputIndex

func (ReadinessTimeoutStep) InputIndex() int

func (ReadinessTimeoutStep) Question

func (ReadinessTimeoutStep) Question(*Model) string

type Recording

type Recording struct {
	SamplingRate          float64 `yaml:"sampling_rate"`
	ExportSpans           bool    `yaml:"export_spans"`
	EnableEnvVarRecording bool    `yaml:"enable_env_var_recording"`
}

type RecordingIntroStep

type RecordingIntroStep struct{ BaseStep }

func (RecordingIntroStep) Default

func (RecordingIntroStep) Default(*Model) string

func (RecordingIntroStep) Description

func (RecordingIntroStep) Description(*Model) string

func (RecordingIntroStep) Help

func (RecordingIntroStep) ID

func (RecordingIntroStep) ID() onboardStep

func (RecordingIntroStep) InputIndex

func (RecordingIntroStep) InputIndex() int

func (RecordingIntroStep) Question

func (RecordingIntroStep) Question(*Model) string

type RecordingSamplingRateStep

type RecordingSamplingRateStep struct{ BaseStep }

func (RecordingSamplingRateStep) Apply

func (RecordingSamplingRateStep) Apply(m *Model, v string)

func (RecordingSamplingRateStep) Clear

func (RecordingSamplingRateStep) Clear(m *Model)

func (RecordingSamplingRateStep) Default

func (RecordingSamplingRateStep) Description

func (RecordingSamplingRateStep) Description(*Model) string

func (RecordingSamplingRateStep) ID

func (RecordingSamplingRateStep) ID() onboardStep

func (RecordingSamplingRateStep) InputIndex

func (RecordingSamplingRateStep) InputIndex() int

func (RecordingSamplingRateStep) Question

func (RecordingSamplingRateStep) Validate

func (RecordingSamplingRateStep) Validate(_ *Model, v string) error

type ReplayIntroStep

type ReplayIntroStep struct{ BaseStep }

func (ReplayIntroStep) Default

func (ReplayIntroStep) Default(*Model) string

func (ReplayIntroStep) Description

func (ReplayIntroStep) Description(*Model) string

func (ReplayIntroStep) Help

func (ReplayIntroStep) Help(*Model) string

func (ReplayIntroStep) ID

func (ReplayIntroStep) ID() onboardStep

func (ReplayIntroStep) InputIndex

func (ReplayIntroStep) InputIndex() int

func (ReplayIntroStep) Question

func (ReplayIntroStep) Question(*Model) string

type SDKCompatibilityStep

type SDKCompatibilityStep struct{ BaseStep }

func (SDKCompatibilityStep) Clear

func (SDKCompatibilityStep) Clear(m *Model)

func (SDKCompatibilityStep) Default

func (SDKCompatibilityStep) Default(*Model) string

func (SDKCompatibilityStep) Description

func (SDKCompatibilityStep) Description(*Model) string

func (SDKCompatibilityStep) Help

func (SDKCompatibilityStep) ID

func (SDKCompatibilityStep) ID() onboardStep

func (SDKCompatibilityStep) InputIndex

func (SDKCompatibilityStep) InputIndex() int

func (SDKCompatibilityStep) Question

func (SDKCompatibilityStep) Question(*Model) string

type Service

type Service struct {
	ID            string         `yaml:"id,omitempty"`
	Name          string         `yaml:"name"`
	Port          int            `yaml:"port"`
	Start         Start          `yaml:"start"`
	Stop          *Stop          `yaml:"stop,omitempty"`
	Communication *Communication `yaml:"communication,omitempty"`
	Readiness     Readiness      `yaml:"readiness_check"`
}

type ServiceNameStep

type ServiceNameStep struct{ BaseStep }

func (ServiceNameStep) Apply

func (ServiceNameStep) Apply(m *Model, v string)

func (ServiceNameStep) Clear

func (ServiceNameStep) Clear(m *Model)

func (ServiceNameStep) Default

func (s ServiceNameStep) Default(m *Model) string

func (ServiceNameStep) Description

func (ServiceNameStep) Description(*Model) string

func (ServiceNameStep) ID

func (ServiceNameStep) ID() onboardStep

func (ServiceNameStep) InputIndex

func (ServiceNameStep) InputIndex() int

func (ServiceNameStep) Question

func (ServiceNameStep) Question(*Model) string

type ServicePortStep

type ServicePortStep struct{ BaseStep }

func (ServicePortStep) Apply

func (ServicePortStep) Apply(m *Model, v string)

func (ServicePortStep) Clear

func (ServicePortStep) Clear(m *Model)

func (ServicePortStep) Default

func (s ServicePortStep) Default(m *Model) string

func (ServicePortStep) Description

func (ServicePortStep) Description(*Model) string

func (ServicePortStep) ID

func (ServicePortStep) ID() onboardStep

func (ServicePortStep) InputIndex

func (ServicePortStep) InputIndex() int

func (ServicePortStep) Question

func (ServicePortStep) Question(*Model) string

func (ServicePortStep) Validate

func (ServicePortStep) Validate(_ *Model, v string) error

type Start

type Start struct {
	Command string `yaml:"command"`
}

type StartCommandStep

type StartCommandStep struct{ BaseStep }

func (StartCommandStep) Apply

func (StartCommandStep) Apply(m *Model, v string)

func (StartCommandStep) Clear

func (StartCommandStep) Clear(m *Model)

func (StartCommandStep) Default

func (s StartCommandStep) Default(m *Model) string

func (StartCommandStep) Description

func (s StartCommandStep) Description(m *Model) string

func (StartCommandStep) ID

func (StartCommandStep) ID() onboardStep

func (StartCommandStep) InputIndex

func (StartCommandStep) InputIndex() int

func (StartCommandStep) Question

func (s StartCommandStep) Question(m *Model) string

type Step

type Step interface {
	ID() onboardStep
	InputIndex() int               // Index of the input field (0-based) for this step, -1 if no input is required
	Question(*Model) string        // Prompt for the user
	Description(*Model) string     // Additional information displayed below the question
	Default(*Model) string         // Default input value (empty string if not applicable)
	Validate(*Model, string) error // User input validation (returns nil if valid, error if invalid)
	Apply(*Model, string)          // Updates the model with the accepted user input. Called after validation succeeds.
	Help(*Model) string            // Help text displayed in the footer for the current step. Back navigation keys will be dynamically added.
	ShouldSkip(*Model) bool        // Whether the step should be skipped (based on current state)
	Clear(*Model)                  // Clears the current step's state
}

type Stop

type Stop struct {
	Command string `yaml:"command,omitempty"`
}

type StopCommandStep

type StopCommandStep struct{ BaseStep }

func (StopCommandStep) Apply

func (StopCommandStep) Apply(m *Model, v string)

func (StopCommandStep) Clear

func (StopCommandStep) Clear(m *Model)

func (StopCommandStep) Default

func (s StopCommandStep) Default(m *Model) string

func (StopCommandStep) Description

func (StopCommandStep) Description(*Model) string

func (StopCommandStep) ID

func (StopCommandStep) ID() onboardStep

func (StopCommandStep) InputIndex

func (StopCommandStep) InputIndex() int

func (StopCommandStep) Question

func (StopCommandStep) Question(*Model) string

func (StopCommandStep) ShouldSkip

func (StopCommandStep) ShouldSkip(m *Model) bool

type TestExecution

type TestExecution struct {
	Timeout string `yaml:"timeout"`
}

type Traces

type Traces struct {
	Dir string `yaml:"dir"`
}

type TuskAPI

type TuskAPI struct {
	URL string `yaml:"url"`
}

type ValidateRepoStep

type ValidateRepoStep struct{ BaseStep }

func (ValidateRepoStep) Default

func (ValidateRepoStep) Default(*Model) string

func (ValidateRepoStep) Description

func (ValidateRepoStep) Description(*Model) string

func (ValidateRepoStep) Help

func (ValidateRepoStep) Help(*Model) string

func (ValidateRepoStep) ID

func (ValidateRepoStep) ID() onboardStep

func (ValidateRepoStep) InputIndex

func (ValidateRepoStep) InputIndex() int

func (ValidateRepoStep) Question

func (ValidateRepoStep) Question(*Model) string

func (ValidateRepoStep) ShouldSkip

func (ValidateRepoStep) ShouldSkip(*Model) bool

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL