@@ -1042,7 +1042,7 @@ func (api *API) markDevcontainerDirty(configPath string, modifiedAt time.Time) {
1042
1042
logger .Info (api .ctx ,"marking devcontainer as dirty" )
1043
1043
dc .Dirty = true
1044
1044
}
1045
- if api .ignoredDevcontainers [dc .WorkspaceFolder ] {
1045
+ if _ , ok := api .ignoredDevcontainers [dc .WorkspaceFolder ]; ok {
1046
1046
logger .Debug (api .ctx ,"clearing devcontainer ignored state" )
1047
1047
delete (api .ignoredDevcontainers ,dc .WorkspaceFolder )// Allow re-reading config.
1048
1048
}
@@ -1051,37 +1051,6 @@ func (api *API) markDevcontainerDirty(configPath string, modifiedAt time.Time) {
1051
1051
}
1052
1052
}
1053
1053
1054
- // markDevcontainerIgnored marks a devcontainer as ignored. Must not be called
1055
- // with the API lock held.
1056
- func (api * API )markDevcontainerIgnored (ctx context.Context ,dc codersdk.WorkspaceAgentDevcontainer ,proc subAgentProcess )subAgentProcess {
1057
- logger := api .logger .With (
1058
- slog .F ("devcontainer_id" ,dc .ID ),
1059
- slog .F ("devcontainer_name" ,dc .Name ),
1060
- slog .F ("workspace_folder" ,dc .WorkspaceFolder ),
1061
- slog .F ("config_path" ,dc .ConfigPath ),
1062
- )
1063
-
1064
- // We only allow ignore to be set in the root customization layer to
1065
- // prevent weird interactions with devcontainer features.
1066
- logger .Debug (ctx ,"marking devcontainer as ignored" )
1067
- proc .stop ()
1068
- if proc .agent .ID != uuid .Nil {
1069
- // If we stop the subagent, we also need to delete it.
1070
- client := * api .subAgentClient .Load ()
1071
- if err := client .Delete (ctx ,proc .agent .ID );err != nil {
1072
- api .logger .Error (ctx ,"delete subagent failed" ,slog .Error (err ),slog .F ("subagent_id" ,proc .agent .ID ))
1073
- }
1074
- }
1075
- // Reset agent and containerID to force config re-reading if ignore is toggled.
1076
- proc .agent = SubAgent {}
1077
- proc .containerID = ""
1078
- api .mu .Lock ()
1079
- api .ignoredDevcontainers [dc .WorkspaceFolder ]= true
1080
- api .mu .Unlock ()
1081
-
1082
- return proc
1083
- }
1084
-
1085
1054
// cleanupSubAgents removes subagents that are no longer managed by
1086
1055
// this agent. This is usually only run at startup to ensure a clean
1087
1056
// slate. This method has an internal timeout to prevent blocking
@@ -1172,11 +1141,24 @@ func (api *API) maybeInjectSubAgentIntoContainerLocked(ctx context.Context, dc c
1172
1141
return xerrors .Errorf ("read devcontainer config: %w" ,err )
1173
1142
}
1174
1143
1175
- if config .Configuration .Customizations .Coder .Ignore {
1176
- api .mu .Unlock ()
1177
- proc = api .markDevcontainerIgnored (ctx ,dc ,proc )
1178
- api .mu .Lock ()
1144
+ ignore := config .Configuration .Customizations .Coder .Ignore
1145
+ if ignore {
1146
+ proc .stop ()
1147
+ if proc .agent .ID != uuid .Nil {
1148
+ // Unlock while doing the delete operation.
1149
+ api .mu .Unlock ()
1150
+ client := * api .subAgentClient .Load ()
1151
+ if err := client .Delete (ctx ,proc .agent .ID );err != nil {
1152
+ api .mu .Lock ()
1153
+ return xerrors .Errorf ("delete subagent: %w" ,err )
1154
+ }
1155
+ api .mu .Lock ()
1156
+ }
1157
+ // Reset agent and containerID to force config re-reading if ignore is toggled.
1158
+ proc .agent = SubAgent {}
1159
+ proc .containerID = ""
1179
1160
api .injectedSubAgentProcs [dc .WorkspaceFolder ]= proc
1161
+ api .ignoredDevcontainers [dc .WorkspaceFolder ]= ignore
1180
1162
return nil
1181
1163
}
1182
1164
}
@@ -1219,7 +1201,11 @@ func (api *API) maybeInjectSubAgentIntoContainerLocked(ctx context.Context, dc c
1219
1201
ranSubAgent := false
1220
1202
1221
1203
// Clean up if injection fails.
1204
+ var ignored ,setIgnored bool
1222
1205
defer func () {
1206
+ if setIgnored {
1207
+ api .ignoredDevcontainers [dc .WorkspaceFolder ]= ignored
1208
+ }
1223
1209
if ! ranSubAgent {
1224
1210
proc .stop ()
1225
1211
if ! api .closed {
@@ -1273,7 +1259,6 @@ func (api *API) maybeInjectSubAgentIntoContainerLocked(ctx context.Context, dc c
1273
1259
}
1274
1260
1275
1261
var (
1276
- ignore bool
1277
1262
appsWithPossibleDuplicates []SubAgentApp
1278
1263
workspaceFolder = DevcontainerDefaultContainerWorkspaceFolder
1279
1264
)
@@ -1297,13 +1282,15 @@ func (api *API) maybeInjectSubAgentIntoContainerLocked(ctx context.Context, dc c
1297
1282
return err
1298
1283
}
1299
1284
1300
- ignore = config . Configuration . Customizations . Coder . Ignore
1301
- workspaceFolder = config . Workspace . WorkspaceFolder
1302
-
1303
- if ignore {
1285
+ // We only allow ignoreto be set in the root customization layer to
1286
+ // prevent weird interactions with devcontainer features.
1287
+ ignored , setIgnored = config . Configuration . Customizations . Coder . Ignore , true
1288
+ if ignored {
1304
1289
return nil
1305
1290
}
1306
1291
1292
+ workspaceFolder = config .Workspace .WorkspaceFolder
1293
+
1307
1294
// NOTE(DanielleMaywood):
1308
1295
// We only want to take an agent name specified in the root customization layer.
1309
1296
// This restricts the ability for a feature to specify the agent name. We may revisit
@@ -1350,8 +1337,19 @@ func (api *API) maybeInjectSubAgentIntoContainerLocked(ctx context.Context, dc c
1350
1337
api .logger .Error (ctx ,"unable to read devcontainer config" ,slog .Error (err ))
1351
1338
}
1352
1339
1353
- if ignore {
1354
- proc = api .markDevcontainerIgnored (ctx ,dc ,proc )
1340
+ if ignored {
1341
+ proc .stop ()
1342
+ if proc .agent .ID != uuid .Nil {
1343
+ // If we stop the subagent, we also need to delete it.
1344
+ client := * api .subAgentClient .Load ()
1345
+ if err := client .Delete (ctx ,proc .agent .ID );err != nil {
1346
+ return xerrors .Errorf ("delete subagent: %w" ,err )
1347
+ }
1348
+ }
1349
+ // Reset agent and containerID to force config re-reading if
1350
+ // ignore is toggled.
1351
+ proc .agent = SubAgent {}
1352
+ proc .containerID = ""
1355
1353
return nil
1356
1354
}
1357
1355