@@ -2,8 +2,10 @@ package cli
2
2
3
3
import (
4
4
"fmt"
5
+ "net/http"
5
6
"time"
6
7
8
+ "github.com/google/uuid"
7
9
"golang.org/x/xerrors"
8
10
9
11
"github.com/coder/coder/v2/cli/clibase"
@@ -35,19 +37,14 @@ func (r *RootCmd) start() *clibase.Cmd {
35
37
return err
36
38
}
37
39
38
- template , err := client .Template (inv .Context (), workspace .TemplateID )
39
- if err != nil {
40
- return err
41
- }
42
-
43
40
buildOptions , err := asWorkspaceBuildParameters (parameterFlags .buildOptions )
44
41
if err != nil {
45
42
return xerrors .Errorf ("unable to parse build options: %w" , err )
46
43
}
47
44
48
45
buildParameters , err := prepStartWorkspace (inv , client , prepStartWorkspaceArgs {
49
- Action : WorkspaceStart ,
50
- Template : template ,
46
+ Action : WorkspaceStart ,
47
+ TemplateVersionID : workspace . LatestBuild . TemplateVersionID ,
51
48
52
49
LastBuildParameters : lastBuildParameters ,
53
50
@@ -58,11 +55,26 @@ func (r *RootCmd) start() *clibase.Cmd {
58
55
return err
59
56
}
60
57
61
- build , err := client . CreateWorkspaceBuild ( inv . Context (), workspace . ID , codersdk.CreateWorkspaceBuildRequest {
58
+ req := codersdk.CreateWorkspaceBuildRequest {
62
59
Transition : codersdk .WorkspaceTransitionStart ,
63
60
RichParameterValues : buildParameters ,
64
- })
65
- if err != nil {
61
+ TemplateVersionID : workspace .LatestBuild .TemplateVersionID ,
62
+ }
63
+
64
+ build , err := client .CreateWorkspaceBuild (inv .Context (), workspace .ID , req )
65
+ // It's possible for a workspace build to fail due to the template requiring starting
66
+ // workspaces with the active version.
67
+ if cerr , ok := codersdk .AsError (err ); ok && cerr .StatusCode () == http .StatusUnauthorized {
68
+ build , err = startWorkspaceActiveVersion (inv , client , startWorkspaceActiveVersionArgs {
69
+ BuildOptions : buildOptions ,
70
+ LastBuildParameters : lastBuildParameters ,
71
+ PromptBuildOptions : parameterFlags .promptBuildOptions ,
72
+ Workspace : workspace ,
73
+ })
74
+ if err != nil {
75
+ return xerrors .Errorf ("start workspace with active template version: %w" , err )
76
+ }
77
+ } else if err != nil {
66
78
return err
67
79
}
68
80
@@ -82,8 +94,8 @@ func (r *RootCmd) start() *clibase.Cmd {
82
94
}
83
95
84
96
type prepStartWorkspaceArgs struct {
85
- Action WorkspaceCLIAction
86
- Template codersdk. Template
97
+ Action WorkspaceCLIAction
98
+ TemplateVersionID uuid. UUID
87
99
88
100
LastBuildParameters []codersdk.WorkspaceBuildParameter
89
101
@@ -94,7 +106,7 @@ type prepStartWorkspaceArgs struct {
94
106
func prepStartWorkspace (inv * clibase.Invocation , client * codersdk.Client , args prepStartWorkspaceArgs ) ([]codersdk.WorkspaceBuildParameter , error ) {
95
107
ctx := inv .Context ()
96
108
97
- templateVersion , err := client .TemplateVersion (ctx , args .Template . ActiveVersionID )
109
+ templateVersion , err := client .TemplateVersion (ctx , args .TemplateVersionID )
98
110
if err != nil {
99
111
return nil , xerrors .Errorf ("get template version: %w" , err )
100
112
}
@@ -110,3 +122,43 @@ func prepStartWorkspace(inv *clibase.Invocation, client *codersdk.Client, args p
110
122
WithBuildOptions (args .BuildOptions )
111
123
return resolver .Resolve (inv , args .Action , templateVersionParameters )
112
124
}
125
+
126
+ type startWorkspaceActiveVersionArgs struct {
127
+ BuildOptions []codersdk.WorkspaceBuildParameter
128
+ LastBuildParameters []codersdk.WorkspaceBuildParameter
129
+ PromptBuildOptions bool
130
+ Workspace codersdk.Workspace
131
+ }
132
+
133
+ func startWorkspaceActiveVersion (inv * clibase.Invocation , client * codersdk.Client , args startWorkspaceActiveVersionArgs ) (codersdk.WorkspaceBuild , error ) {
134
+ _ , _ = fmt .Fprintln (inv .Stdout , "Failed to restart with the template version from your last build. Policy may require you to restart with the current active template version." )
135
+
136
+ template , err := client .Template (inv .Context (), args .Workspace .TemplateID )
137
+ if err != nil {
138
+ return codersdk.WorkspaceBuild {}, xerrors .Errorf ("get template: %w" , err )
139
+ }
140
+
141
+ buildParameters , err := prepStartWorkspace (inv , client , prepStartWorkspaceArgs {
142
+ Action : WorkspaceStart ,
143
+ TemplateVersionID : template .ActiveVersionID ,
144
+
145
+ LastBuildParameters : args .LastBuildParameters ,
146
+
147
+ PromptBuildOptions : args .PromptBuildOptions ,
148
+ BuildOptions : args .BuildOptions ,
149
+ })
150
+ if err != nil {
151
+ return codersdk.WorkspaceBuild {}, err
152
+ }
153
+
154
+ build , err := client .CreateWorkspaceBuild (inv .Context (), args .Workspace .ID , codersdk.CreateWorkspaceBuildRequest {
155
+ Transition : codersdk .WorkspaceTransitionStart ,
156
+ RichParameterValues : buildParameters ,
157
+ TemplateVersionID : template .ActiveVersionID ,
158
+ })
159
+ if err != nil {
160
+ return codersdk.WorkspaceBuild {}, err
161
+ }
162
+
163
+ return build , nil
164
+ }
0 commit comments