mirror of
https://github.com/coder/coder.git
synced 2026-06-03 13:08:25 +00:00
c664e4f72d
`coder templates version list` makes a call to determine the `active`
version:
```
➜ ~ coder templates version list aws-linux-dynamic
NAME CREATED AT CREATED BY STATUS ACTIVE
infallible_feistel2 2025-10-10T10:34:02+11:00 rowansmith Succeeded Active
mystifying_almeida1 2025-10-10T10:32:38+11:00 rowansmith Succeeded
```
but this is not carried across to the `-ojson` output version, so this
PR implements that in order to support programattic addressing.
It is added a top level entry. If it should be nested under
`TemplateVersion` let me know.
```
➜ ~ ./Downloads/coder-cli-templateversions-json-active templates version list aws-linux-dynamic -ojson | jq '.[] | select(.active == true) | { active, id: .TemplateVersion.id }'
{
"active": true,
"id": "38f66eae-ec63-49b7-a9d2-cdb79c379d19"
}
➜ ~ ./Downloads/coder-cli-templateversions-json-active templates version list aws-linux-dynamic -ojson |jq '.[] | select(.active == true)'
{
"TemplateVersion": {
"id": "38f66eae-ec63-49b7-a9d2-cdb79c379d19",
"template_id": "1a84ce78-06a6-41ad-99e4-8ea5d9b91e89",
"organization_id": "35f75f20-890e-4095-95f1-bb8f2ba02e79",
"created_at": "2025-10-10T10:34:02.254357+11:00",
"updated_at": "2025-10-10T10:34:46.594032+11:00",
"name": "infallible_feistel2",
"message": "Uploaded from the CLI",
"job": {
"id": "8afd05ca-b4be-48d5-a6b9-82dcfd12c960",
"created_at": "2025-10-10T10:34:02.251234+11:00",
"started_at": "2025-10-10T10:34:02.257301+11:00",
"completed_at": "2025-10-10T10:34:46.594032+11:00",
"status": "succeeded",
"worker_id": "a0940ade-ecdd-47c2-98c6-f2a4e5eb0733",
"file_id": "05fd653c-3a3f-4e5c-856b-29407732e1b1",
"tags": {
"owner": "",
"scope": "organization"
},
"queue_position": 0,
"queue_size": 0,
"organization_id": "35f75f20-890e-4095-95f1-bb8f2ba02e79",
"initiator_id": "d20c05ff-ecf3-4521-a99d-516c8befbaa6",
"input": {
"template_version_id": "38f66eae-ec63-49b7-a9d2-cdb79c379d19"
},
"type": "template_version_import",
"metadata": {
"template_version_name": "",
"template_id": "00000000-0000-0000-0000-000000000000",
"template_name": "",
"template_display_name": "",
"template_icon": ""
},
"logs_overflowed": false
},
"readme": "---\ndxxxxx,
"created_by": {
"id": "d20c05ff-ecf3-4521-a99d-516c8befbaa6",
"username": "rowansmith",
"name": "rowan smith"
},
"archived": false,
"has_external_agent": false
},
"active": true
}
```
155 lines
5.3 KiB
Go
155 lines
5.3 KiB
Go
package cli_test
|
|
|
|
import (
|
|
"bytes"
|
|
"context"
|
|
"encoding/json"
|
|
"testing"
|
|
|
|
"github.com/stretchr/testify/assert"
|
|
"github.com/stretchr/testify/require"
|
|
|
|
"github.com/coder/coder/v2/cli/clitest"
|
|
"github.com/coder/coder/v2/coderd/coderdtest"
|
|
"github.com/coder/coder/v2/codersdk"
|
|
"github.com/coder/coder/v2/pty/ptytest"
|
|
)
|
|
|
|
func TestTemplateVersions(t *testing.T) {
|
|
t.Parallel()
|
|
t.Run("ListVersions", func(t *testing.T) {
|
|
t.Parallel()
|
|
client := coderdtest.New(t, &coderdtest.Options{IncludeProvisionerDaemon: true})
|
|
owner := coderdtest.CreateFirstUser(t, client)
|
|
member, _ := coderdtest.CreateAnotherUser(t, client, owner.OrganizationID)
|
|
version := coderdtest.CreateTemplateVersion(t, client, owner.OrganizationID, nil)
|
|
_ = coderdtest.AwaitTemplateVersionJobCompleted(t, client, version.ID)
|
|
template := coderdtest.CreateTemplate(t, client, owner.OrganizationID, version.ID)
|
|
|
|
inv, root := clitest.New(t, "templates", "versions", "list", template.Name)
|
|
clitest.SetupConfig(t, member, root)
|
|
|
|
pty := ptytest.New(t).Attach(inv)
|
|
|
|
errC := make(chan error)
|
|
go func() {
|
|
errC <- inv.Run()
|
|
}()
|
|
|
|
require.NoError(t, <-errC)
|
|
|
|
pty.ExpectMatch(version.Name)
|
|
pty.ExpectMatch(version.CreatedBy.Username)
|
|
pty.ExpectMatch("Active")
|
|
})
|
|
|
|
t.Run("ListVersionsJSON", func(t *testing.T) {
|
|
t.Parallel()
|
|
client := coderdtest.New(t, &coderdtest.Options{IncludeProvisionerDaemon: true})
|
|
owner := coderdtest.CreateFirstUser(t, client)
|
|
member, _ := coderdtest.CreateAnotherUser(t, client, owner.OrganizationID)
|
|
version := coderdtest.CreateTemplateVersion(t, client, owner.OrganizationID, nil)
|
|
_ = coderdtest.AwaitTemplateVersionJobCompleted(t, client, version.ID)
|
|
template := coderdtest.CreateTemplate(t, client, owner.OrganizationID, version.ID)
|
|
|
|
inv, root := clitest.New(t, "templates", "versions", "list", template.Name, "--output", "json")
|
|
clitest.SetupConfig(t, member, root)
|
|
|
|
var stdout bytes.Buffer
|
|
inv.Stdout = &stdout
|
|
|
|
require.NoError(t, inv.Run())
|
|
|
|
var rows []struct {
|
|
TemplateVersion codersdk.TemplateVersion `json:"TemplateVersion"`
|
|
Active bool `json:"active"`
|
|
}
|
|
require.NoError(t, json.Unmarshal(stdout.Bytes(), &rows))
|
|
require.Len(t, rows, 1)
|
|
assert.Equal(t, version.ID, rows[0].TemplateVersion.ID)
|
|
assert.True(t, rows[0].Active)
|
|
})
|
|
}
|
|
|
|
func TestTemplateVersionsPromote(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
t.Run("PromoteVersion", func(t *testing.T) {
|
|
t.Parallel()
|
|
client := coderdtest.New(t, &coderdtest.Options{IncludeProvisionerDaemon: true})
|
|
owner := coderdtest.CreateFirstUser(t, client)
|
|
|
|
// Create a template with two versions
|
|
version1 := coderdtest.CreateTemplateVersion(t, client, owner.OrganizationID, completeWithAgent())
|
|
coderdtest.AwaitTemplateVersionJobCompleted(t, client, version1.ID)
|
|
|
|
template := coderdtest.CreateTemplate(t, client, owner.OrganizationID, version1.ID)
|
|
|
|
version2 := coderdtest.CreateTemplateVersion(t, client, owner.OrganizationID, completeWithAgent(), func(ctvr *codersdk.CreateTemplateVersionRequest) {
|
|
ctvr.TemplateID = template.ID
|
|
ctvr.Name = "2.0.0"
|
|
})
|
|
coderdtest.AwaitTemplateVersionJobCompleted(t, client, version2.ID)
|
|
|
|
// Ensure version1 is active
|
|
updatedTemplate, err := client.Template(context.Background(), template.ID)
|
|
assert.NoError(t, err)
|
|
assert.Equal(t, version1.ID, updatedTemplate.ActiveVersionID)
|
|
|
|
args := []string{
|
|
"templates",
|
|
"versions",
|
|
"promote",
|
|
"--template", template.Name,
|
|
"--template-version", version2.Name,
|
|
}
|
|
|
|
inv, root := clitest.New(t, args...)
|
|
//nolint:gocritic // Creating a workspace for another user requires owner permissions.
|
|
clitest.SetupConfig(t, client, root)
|
|
errC := make(chan error)
|
|
go func() {
|
|
errC <- inv.Run()
|
|
}()
|
|
|
|
require.NoError(t, <-errC)
|
|
|
|
// Verify that version2 is now the active version
|
|
updatedTemplate, err = client.Template(context.Background(), template.ID)
|
|
require.NoError(t, err)
|
|
assert.Equal(t, version2.ID, updatedTemplate.ActiveVersionID)
|
|
})
|
|
|
|
t.Run("PromoteNonExistentVersion", func(t *testing.T) {
|
|
t.Parallel()
|
|
client := coderdtest.New(t, &coderdtest.Options{IncludeProvisionerDaemon: true})
|
|
owner := coderdtest.CreateFirstUser(t, client)
|
|
member, _ := coderdtest.CreateAnotherUser(t, client, owner.OrganizationID)
|
|
|
|
version := coderdtest.CreateTemplateVersion(t, client, owner.OrganizationID, nil)
|
|
_ = coderdtest.AwaitTemplateVersionJobCompleted(t, client, version.ID)
|
|
template := coderdtest.CreateTemplate(t, client, owner.OrganizationID, version.ID)
|
|
|
|
inv, root := clitest.New(t, "templates", "versions", "promote", "--template", template.Name, "--template-version", "non-existent-version")
|
|
clitest.SetupConfig(t, member, root)
|
|
|
|
err := inv.Run()
|
|
require.Error(t, err)
|
|
require.Contains(t, err.Error(), "get template version by name")
|
|
})
|
|
|
|
t.Run("PromoteVersionInvalidTemplate", func(t *testing.T) {
|
|
t.Parallel()
|
|
client := coderdtest.New(t, &coderdtest.Options{IncludeProvisionerDaemon: true})
|
|
owner := coderdtest.CreateFirstUser(t, client)
|
|
member, _ := coderdtest.CreateAnotherUser(t, client, owner.OrganizationID)
|
|
|
|
inv, root := clitest.New(t, "templates", "versions", "promote", "--template", "non-existent-template", "--template-version", "some-version")
|
|
clitest.SetupConfig(t, member, root)
|
|
|
|
err := inv.Run()
|
|
require.Error(t, err)
|
|
require.Contains(t, err.Error(), "get template by name")
|
|
})
|
|
}
|