Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit6dc8fc3

Browse files
committed
fix: only allow promoting successful template versions
1 parente8b84eb commit6dc8fc3

File tree

11 files changed

+212
-36
lines changed

11 files changed

+212
-36
lines changed

‎coderd/coderdtest/coderdtest.go

Lines changed: 33 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -760,21 +760,51 @@ func UpdateTemplateVersion(t *testing.T, client *codersdk.Client, organizationID
760760
returntemplateVersion
761761
}
762762

763+
funcAwaitTemplateVersionJobRunning(t*testing.T,client*codersdk.Client,version uuid.UUID) codersdk.TemplateVersion {
764+
t.Helper()
765+
766+
ctx,cancel:=context.WithTimeout(context.Background(),testutil.WaitShort)
767+
defercancel()
768+
769+
t.Logf("waiting for template version %s build job to start",version)
770+
vartemplateVersion codersdk.TemplateVersion
771+
require.Eventually(t,func()bool {
772+
varerrerror
773+
templateVersion,err=client.TemplateVersion(ctx,version)
774+
iferr!=nil {
775+
returnfalse
776+
}
777+
t.Logf("template version job status: %s",templateVersion.Job.Status)
778+
switchtemplateVersion.Job.Status {
779+
casecodersdk.ProvisionerJobPending:
780+
returnfalse
781+
casecodersdk.ProvisionerJobRunning:
782+
returntrue
783+
default:
784+
t.FailNow()
785+
returnfalse
786+
}
787+
},testutil.WaitShort,testutil.IntervalFast,"make sure you set `IncludeProvisionerDaemon`!")
788+
t.Logf("template version %s job has started",version)
789+
returntemplateVersion
790+
}
791+
763792
// AwaitTemplateImportJobCompleted awaits for an import job to reach completed status.
764793
funcAwaitTemplateVersionJobCompleted(t*testing.T,client*codersdk.Client,version uuid.UUID) codersdk.TemplateVersion {
765794
t.Helper()
766795

767796
ctx,cancel:=context.WithTimeout(context.Background(),testutil.WaitLong)
768797
defercancel()
769798

770-
t.Logf("waiting for template versionjob %s",version)
799+
t.Logf("waiting for template version%s build job to complete",version)
771800
vartemplateVersion codersdk.TemplateVersion
772801
require.Eventually(t,func()bool {
773802
varerrerror
774803
templateVersion,err=client.TemplateVersion(ctx,version)
804+
t.Logf("template version job status: %s",templateVersion.Job.Status)
775805
returnassert.NoError(t,err)&&templateVersion.Job.CompletedAt!=nil
776-
},testutil.WaitLong,testutil.IntervalMedium)
777-
t.Logf("gottemplate versionjob %s",version)
806+
},testutil.WaitLong,testutil.IntervalMedium,"make sure you set `IncludeProvisionerDaemon`!")
807+
t.Logf("template version%s job has completed",version)
778808
returntemplateVersion
779809
}
780810

‎coderd/insights_test.go

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2078,7 +2078,7 @@ func TestTemplateInsights_RBAC(t *testing.T) {
20782078
t.Run("AsOwner",func(t*testing.T) {
20792079
t.Parallel()
20802080

2081-
client:=coderdtest.New(t,&coderdtest.Options{})
2081+
client:=coderdtest.New(t,nil)
20822082
admin:=coderdtest.CreateFirstUser(t,client)
20832083

20842084
ctx,cancel:=context.WithTimeout(context.Background(),testutil.WaitShort)
@@ -2102,7 +2102,7 @@ func TestTemplateInsights_RBAC(t *testing.T) {
21022102
t.Run("AsTemplateAdmin",func(t*testing.T) {
21032103
t.Parallel()
21042104

2105-
client:=coderdtest.New(t,&coderdtest.Options{})
2105+
client:=coderdtest.New(t,nil)
21062106
admin:=coderdtest.CreateFirstUser(t,client)
21072107

21082108
templateAdmin,_:=coderdtest.CreateAnotherUser(t,client,admin.OrganizationID,rbac.RoleTemplateAdmin())
@@ -2128,7 +2128,7 @@ func TestTemplateInsights_RBAC(t *testing.T) {
21282128
t.Run("AsRegularUser",func(t*testing.T) {
21292129
t.Parallel()
21302130

2131-
client:=coderdtest.New(t,&coderdtest.Options{})
2131+
client:=coderdtest.New(t,nil)
21322132
admin:=coderdtest.CreateFirstUser(t,client)
21332133

21342134
regular,_:=coderdtest.CreateAnotherUser(t,client,admin.OrganizationID)
@@ -2207,7 +2207,7 @@ func TestGenericInsights_RBAC(t *testing.T) {
22072207
t.Run("AsOwner",func(t*testing.T) {
22082208
t.Parallel()
22092209

2210-
client:=coderdtest.New(t,&coderdtest.Options{})
2210+
client:=coderdtest.New(t,nil)
22112211
admin:=coderdtest.CreateFirstUser(t,client)
22122212

22132213
ctx,cancel:=context.WithTimeout(context.Background(),testutil.WaitShort)
@@ -2229,7 +2229,7 @@ func TestGenericInsights_RBAC(t *testing.T) {
22292229
t.Run("AsTemplateAdmin",func(t*testing.T) {
22302230
t.Parallel()
22312231

2232-
client:=coderdtest.New(t,&coderdtest.Options{})
2232+
client:=coderdtest.New(t,nil)
22332233
admin:=coderdtest.CreateFirstUser(t,client)
22342234

22352235
templateAdmin,_:=coderdtest.CreateAnotherUser(t,client,admin.OrganizationID,rbac.RoleTemplateAdmin())
@@ -2253,7 +2253,7 @@ func TestGenericInsights_RBAC(t *testing.T) {
22532253
t.Run("AsRegularUser",func(t*testing.T) {
22542254
t.Parallel()
22552255

2256-
client:=coderdtest.New(t,&coderdtest.Options{})
2256+
client:=coderdtest.New(t,nil)
22572257
admin:=coderdtest.CreateFirstUser(t,client)
22582258

22592259
regular,_:=coderdtest.CreateAnotherUser(t,client,admin.OrganizationID)

‎coderd/templateversions.go

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ import (
2020

2121
"github.com/coder/coder/v2/coderd/audit"
2222
"github.com/coder/coder/v2/coderd/database"
23+
"github.com/coder/coder/v2/coderd/database/db2sdk"
2324
"github.com/coder/coder/v2/coderd/database/dbtime"
2425
"github.com/coder/coder/v2/coderd/database/provisionerjobs"
2526
"github.com/coder/coder/v2/coderd/externalauth"
@@ -1038,6 +1039,22 @@ func (api *API) patchActiveTemplateVersion(rw http.ResponseWriter, r *http.Reque
10381039
})
10391040
return
10401041
}
1042+
job,err:=api.Database.GetProvisionerJobByID(ctx,version.JobID)
1043+
iferr!=nil {
1044+
httpapi.Write(ctx,rw,http.StatusInternalServerError, codersdk.Response{
1045+
Message:"Internal error fetching template version job status.",
1046+
Detail:err.Error(),
1047+
})
1048+
return
1049+
}
1050+
jobStatus:=db2sdk.ProvisionerJobStatus(job)
1051+
ifjobStatus!=codersdk.ProvisionerJobSucceeded {
1052+
httpapi.Write(ctx,rw,http.StatusPreconditionFailed, codersdk.Response{
1053+
Message:"Only versions that have been built successfully can be promoted.",
1054+
Detail:fmt.Sprintf("Attempted to promote a version with a %s build",jobStatus),
1055+
})
1056+
return
1057+
}
10411058

10421059
err=api.Database.InTx(func(store database.Store)error {
10431060
err=store.UpdateTemplateActiveVersionByID(ctx, database.UpdateTemplateActiveVersionByIDParams{

‎coderd/templateversions_test.go

Lines changed: 64 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -241,7 +241,9 @@ func TestPatchCancelTemplateVersion(t *testing.T) {
241241
})
242242
t.Run("AlreadyCanceled",func(t*testing.T) {
243243
t.Parallel()
244-
client:=coderdtest.New(t,&coderdtest.Options{IncludeProvisionerDaemon:true})
244+
client:=coderdtest.New(t,&coderdtest.Options{
245+
IncludeProvisionerDaemon:true,
246+
})
245247
user:=coderdtest.CreateFirstUser(t,client)
246248
version:=coderdtest.CreateTemplateVersion(t,client,user.OrganizationID,&echo.Responses{
247249
Parse:echo.ParseComplete,
@@ -255,15 +257,7 @@ func TestPatchCancelTemplateVersion(t *testing.T) {
255257
ctx,cancel:=context.WithTimeout(context.Background(),testutil.WaitLong)
256258
defercancel()
257259

258-
require.Eventually(t,func()bool {
259-
varerrerror
260-
version,err=client.TemplateVersion(ctx,version.ID)
261-
if!assert.NoError(t,err) {
262-
returnfalse
263-
}
264-
t.Logf("Status: %s",version.Job.Status)
265-
returnversion.Job.Status==codersdk.ProvisionerJobRunning
266-
},testutil.WaitShort,testutil.IntervalFast)
260+
coderdtest.AwaitTemplateVersionJobRunning(t,client,version.ID)
267261
err:=client.CancelTemplateVersion(ctx,version.ID)
268262
require.NoError(t,err)
269263
err=client.CancelTemplateVersion(ctx,version.ID)
@@ -280,7 +274,9 @@ func TestPatchCancelTemplateVersion(t *testing.T) {
280274
// Running -> Canceling is the best we can do for now.
281275
t.Run("Canceling",func(t*testing.T) {
282276
t.Parallel()
283-
client:=coderdtest.New(t,&coderdtest.Options{IncludeProvisionerDaemon:true})
277+
client:=coderdtest.New(t,&coderdtest.Options{
278+
IncludeProvisionerDaemon:true,
279+
})
284280
user:=coderdtest.CreateFirstUser(t,client)
285281
version:=coderdtest.CreateTemplateVersion(t,client,user.OrganizationID,&echo.Responses{
286282
Parse:echo.ParseComplete,
@@ -557,13 +553,60 @@ func TestPatchActiveTemplateVersion(t *testing.T) {
557553
require.Equal(t,http.StatusNotFound,apiErr.StatusCode())
558554
})
559555

560-
t.Run("DoesNotBelong",func(t*testing.T) {
556+
t.Run("CanceledBuild",func(t*testing.T) {
557+
t.Parallel()
558+
client:=coderdtest.New(t,&coderdtest.Options{
559+
IncludeProvisionerDaemon:true,
560+
})
561+
user:=coderdtest.CreateFirstUser(t,client)
562+
version:=coderdtest.CreateTemplateVersion(t,client,user.OrganizationID,nil)
563+
template:=coderdtest.CreateTemplate(t,client,user.OrganizationID,version.ID)
564+
version=coderdtest.UpdateTemplateVersion(t,client,user.OrganizationID,nil,template.ID)
565+
566+
ctx,cancel:=context.WithTimeout(context.Background(),testutil.WaitLong)
567+
defercancel()
568+
569+
err:=client.CancelTemplateVersion(ctx,version.ID)
570+
require.NoError(t,err)
571+
coderdtest.AwaitTemplateVersionJobCompleted(t,client,version.ID)
572+
err=client.UpdateActiveTemplateVersion(ctx,template.ID, codersdk.UpdateActiveTemplateVersion{
573+
ID:version.ID,
574+
})
575+
varapiErr*codersdk.Error
576+
require.ErrorAs(t,err,&apiErr)
577+
require.Equal(t,http.StatusPreconditionFailed,apiErr.StatusCode())
578+
})
579+
580+
t.Run("PendingBuild",func(t*testing.T) {
561581
t.Parallel()
562582
client:=coderdtest.New(t,nil)
563583
user:=coderdtest.CreateFirstUser(t,client)
564584
version:=coderdtest.CreateTemplateVersion(t,client,user.OrganizationID,nil)
565585
template:=coderdtest.CreateTemplate(t,client,user.OrganizationID,version.ID)
586+
version=coderdtest.UpdateTemplateVersion(t,client,user.OrganizationID,nil,template.ID)
587+
588+
ctx,cancel:=context.WithTimeout(context.Background(),testutil.WaitLong)
589+
defercancel()
590+
591+
err:=client.UpdateActiveTemplateVersion(ctx,template.ID, codersdk.UpdateActiveTemplateVersion{
592+
ID:version.ID,
593+
})
594+
varapiErr*codersdk.Error
595+
require.ErrorAs(t,err,&apiErr)
596+
require.Equal(t,http.StatusPreconditionFailed,apiErr.StatusCode())
597+
})
598+
599+
t.Run("DoesNotBelong",func(t*testing.T) {
600+
t.Parallel()
601+
client:=coderdtest.New(t,&coderdtest.Options{
602+
IncludeProvisionerDaemon:true,
603+
})
604+
user:=coderdtest.CreateFirstUser(t,client)
605+
version:=coderdtest.CreateTemplateVersion(t,client,user.OrganizationID,nil)
606+
template:=coderdtest.CreateTemplate(t,client,user.OrganizationID,version.ID)
566607
version=coderdtest.CreateTemplateVersion(t,client,user.OrganizationID,nil)
608+
_=coderdtest.CreateTemplate(t,client,user.OrganizationID,version.ID)
609+
_=coderdtest.AwaitTemplateVersionJobCompleted(t,client,version.ID)
567610

568611
ctx,cancel:=context.WithTimeout(context.Background(),testutil.WaitLong)
569612
defercancel()
@@ -576,13 +619,18 @@ func TestPatchActiveTemplateVersion(t *testing.T) {
576619
require.Equal(t,http.StatusBadRequest,apiErr.StatusCode())
577620
})
578621

579-
t.Run("Found",func(t*testing.T) {
622+
t.Run("SuccessfulBuild",func(t*testing.T) {
580623
t.Parallel()
581624
auditor:=audit.NewMock()
582-
client:=coderdtest.New(t,&coderdtest.Options{IncludeProvisionerDaemon:true,Auditor:auditor})
625+
client:=coderdtest.New(t,&coderdtest.Options{
626+
IncludeProvisionerDaemon:true,
627+
Auditor:auditor,
628+
})
583629
user:=coderdtest.CreateFirstUser(t,client)
584630
version:=coderdtest.CreateTemplateVersion(t,client,user.OrganizationID,nil)
585631
template:=coderdtest.CreateTemplate(t,client,user.OrganizationID,version.ID)
632+
version=coderdtest.UpdateTemplateVersion(t,client,user.OrganizationID,nil,template.ID)
633+
_=coderdtest.AwaitTemplateVersionJobCompleted(t,client,version.ID)
586634

587635
ctx,cancel:=context.WithTimeout(context.Background(),testutil.WaitLong)
588636
defercancel()
@@ -592,8 +640,8 @@ func TestPatchActiveTemplateVersion(t *testing.T) {
592640
})
593641
require.NoError(t,err)
594642

595-
require.Len(t,auditor.AuditLogs(),5)
596-
assert.Equal(t,database.AuditActionWrite,auditor.AuditLogs()[4].Action)
643+
require.Len(t,auditor.AuditLogs(),6)
644+
assert.Equal(t,database.AuditActionWrite,auditor.AuditLogs()[5].Action)
597645
})
598646
}
599647

‎coderd/workspaceagents_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -253,11 +253,11 @@ func TestWorkspaceAgent(t *testing.T) {
253253
req.TemplateID=template.ID
254254
})
255255

256+
coderdtest.AwaitTemplateVersionJobCompleted(t,client,version.ID)
256257
err=client.UpdateActiveTemplateVersion(ctx,template.ID, codersdk.UpdateActiveTemplateVersion{
257258
ID:version.ID,
258259
})
259260
require.NoError(t,err)
260-
coderdtest.AwaitTemplateVersionJobCompleted(t,client,version.ID)
261261
// Creating another workspace is just easier.
262262
workspace=coderdtest.CreateWorkspace(t,client,user.OrganizationID,template.ID)
263263
build:=coderdtest.AwaitWorkspaceBuildJobCompleted(t,client,workspace.LatestBuild.ID)

‎coderd/workspaces_test.go

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -426,9 +426,10 @@ func TestPostWorkspacesByOrganization(t *testing.T) {
426426

427427
t.Run("NoTemplateAccess",func(t*testing.T) {
428428
t.Parallel()
429-
client:=coderdtest.New(t,nil)
429+
client:=coderdtest.New(t,&coderdtest.Options{
430+
IncludeProvisionerDaemon:true,
431+
})
430432
first:=coderdtest.CreateFirstUser(t,client)
431-
432433
other,_:=coderdtest.CreateAnotherUser(t,client,first.OrganizationID,rbac.RoleMember(),rbac.RoleOwner())
433434

434435
ctx,cancel:=context.WithTimeout(context.Background(),testutil.WaitLong)
@@ -440,6 +441,7 @@ func TestPostWorkspacesByOrganization(t *testing.T) {
440441
require.NoError(t,err)
441442
version:=coderdtest.CreateTemplateVersion(t,other,org.ID,nil)
442443
template:=coderdtest.CreateTemplate(t,other,org.ID,version.ID)
444+
_=coderdtest.AwaitTemplateVersionJobCompleted(t,client,version.ID)
443445

444446
_,err=client.CreateWorkspace(ctx,first.OrganizationID,codersdk.Me, codersdk.CreateWorkspaceRequest{
445447
TemplateID:template.ID,

‎site/src/components/Pill/Pill.stories.tsx

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,3 +64,11 @@ export const WarningLight: Story = {
6464
lightBorder:true,
6565
},
6666
};
67+
68+
exportconstNeutral:Story={
69+
args:{
70+
text:"Neutral",
71+
type:"neutral",
72+
lightBorder:true,
73+
},
74+
};

‎site/src/components/Pill/Pill.tsx

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,13 @@
1-
import{PaletteColor,Theme}from"@mui/material/styles";
1+
import{typePaletteColor,typeTheme}from"@mui/material/styles";
22
import{makeStyles}from"@mui/styles";
3-
import{FC}from"react";
4-
import{PaletteIndex}from"theme/theme";
3+
import{typeFC,typeReactNode}from"react";
4+
import{typePaletteIndex}from"theme/theme";
55
import{combineClasses}from"utils/combineClasses";
66

77
exportinterfacePillProps{
88
className?:string;
9-
icon?:React.ReactNode;
10-
text:string;
9+
icon?:ReactNode;
10+
text:ReactNode;
1111
type?:PaletteIndex;
1212
lightBorder?:boolean;
1313
title?:string;

‎site/src/pages/TemplatePage/TemplateVersionsPage/VersionRow.tsx

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,11 @@ export const VersionRow: React.FC<VersionRowProps> = ({
3232
onClick:()=>navigate(version.name),
3333
});
3434

35+
constjobStatus=version.job.status;
36+
if(jobStatus==="canceled"){
37+
returnnull;
38+
}
39+
3540
return(
3641
<TimelineEntry
3742
data-testid={`version-${version.id}`}
@@ -78,10 +83,20 @@ export const VersionRow: React.FC<VersionRowProps> = ({
7883
<Stackdirection="row"alignItems="center"spacing={2}>
7984
{isActive&&<Pilltext="Active"type="success"/>}
8085
{isLatest&&<Pilltext="Newest"type="info"/>}
86+
{jobStatus==="pending"&&(
87+
<Pilltext={<>Pending&hellip;</>}type="warning"lightBorder/>
88+
)}
89+
{jobStatus==="running"&&(
90+
<Pilltext={<>Building&hellip;</>}type="warning"lightBorder/>
91+
)}
92+
{jobStatus==="canceling"&&(
93+
<Pilltext={<>Canceling&hellip;</>}type="neutral"lightBorder/>
94+
)}
95+
{jobStatus==="failed"&&<Pilltext="Failed"type="error"/>}
8196
{onPromoteClick&&(
8297
<Button
8398
className={styles.promoteButton}
84-
disabled={isActive}
99+
disabled={isActive||jobStatus!=="succeeded"}
85100
onClick={(e)=>{
86101
e.preventDefault();
87102
e.stopPropagation();

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp