Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 13 additions & 1 deletion cmd/lk/agent.go
Original file line number Diff line number Diff line change
Expand Up @@ -248,7 +248,7 @@ var (
{
Name: "deploy",
Usage: "Deploy a new version of the agent",
Before: createAgentClient,
Before: prepareAgentDeploy,
Action: deployAgent,
Flags: []cli.Flag{
attributesFlag,
Expand Down Expand Up @@ -435,6 +435,18 @@ func noAgentError() error {
"To get started, see: https://docs.livekit.io/agents/quickstart")
}

func prepareAgentDeploy(ctx context.Context, cmd *cli.Command) (context.Context, error) {
// The prebuilt upload client has no deployment selector. Check
// before client setup, secret updates, or acquiring an image push target.
if deployment := cmd.String("deployment"); deployment != "" &&
(cmd.String("image") != "" || cmd.String("image-tar") != "") {
return ctx, fmt.Errorf("--deployment %q is not supported with --image or --image-tar; "+
"prebuilt image deployments use the default production deployment. "+
"Deploy from source to target a named deployment; omit --deployment only if production is intended", deployment)
}
return createAgentClient(ctx, cmd)
}

func createAgentClient(ctx context.Context, cmd *cli.Command) (context.Context, error) {
return createAgentClientWithOpts(ctx, cmd)
}
Expand Down
72 changes: 72 additions & 0 deletions cmd/lk/agent_deploy_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
package main

import (
"context"
"io"
"testing"

"github.com/livekit/livekit-cli/v2/pkg/config"
"github.com/stretchr/testify/require"
"github.com/urfave/cli/v3"
)

func TestAgentDeployRejectsImageDeployment(t *testing.T) {
cmd := agentDeployTestCommand(t)

err := cmd.Run(context.Background(), []string{"deploy", "--image", "local:latest", "--deployment", "staging"})

require.ErrorContains(t, err, "--deployment \"staging\" is not supported with --image or --image-tar")
}

func TestAgentDeployRejectsImageTarDeployment(t *testing.T) {
cmd := agentDeployTestCommand(t)

err := cmd.Run(context.Background(), []string{"deploy", "--image-tar", "image.tar", "--deployment", "staging"})

require.ErrorContains(t, err, "--deployment \"staging\" is not supported with --image or --image-tar")
require.Nil(t, agentsClient, "rejection must happen before client creation")
}

func TestAgentDeployAllowsPrebuiltWithoutDeployment(t *testing.T) {
cmd := agentDeployTestCommand(t)

err := cmd.Run(context.Background(), []string{"deploy", "--image-tar", "image.tar"})

require.NoError(t, err)
}

func TestAgentDeployAllowsNamedSourceDeployment(t *testing.T) {
cmd := agentDeployTestCommand(t)

err := cmd.Run(context.Background(), []string{"deploy", "--deployment", "staging"})

require.NoError(t, err)
}

func agentDeployTestCommand(t *testing.T) *cli.Command {
t.Helper()
// Client setup uses package globals, so these tests must not run in parallel.
oldProject, oldConfig, oldClient, oldDir := project, lkConfig, agentsClient, workingDir
t.Cleanup(func() {
project, lkConfig, agentsClient, workingDir = oldProject, oldConfig, oldClient, oldDir
})
project = &config.ProjectConfig{URL: "https://fixture.livekit.cloud", APIKey: "fixture-key", APISecret: "fixture-secret"}
lkConfig, agentsClient = nil, nil
workingDir = t.TempDir()

agent := findCommandByName(AgentCommands, "agent")
deploy := findCommandByName(agent.Commands, "deploy")
return &cli.Command{
Name: "deploy",
Before: deploy.Before,
Writer: io.Discard,
ErrWriter: io.Discard,
Flags: []cli.Flag{
&cli.StringFlag{Name: "image"},
&cli.StringFlag{Name: "image-tar"},
&cli.StringFlag{Name: "deployment"},
},
// Exercise the registered Before hook without loading or deploying an image.
Action: func(context.Context, *cli.Command) error { return nil },
}
}
Loading