Skip to content

Commit a8341f3

Browse files
authored
Merge branch 'main' into dependabot/go_modules/github.com/fatih/color-1.17.0
2 parents acdc150 + ff617cc commit a8341f3

File tree

193 files changed

+5097
-1372
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

193 files changed

+5097
-1372
lines changed

.github/actions/setup-go/action.yaml

+1-1
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ description: |
44
inputs:
55
version:
66
description: "The Go version to use."
7-
default: "1.21.9"
7+
default: "1.22.3"
88
runs:
99
using: "composite"
1010
steps:

.github/workflows/ci.yaml

+4-1
Original file line numberDiff line numberDiff line change
@@ -211,6 +211,9 @@ jobs:
211211
- name: Setup sqlc
212212
uses: ./.github/actions/setup-sqlc
213213

214+
- name: Setup Terraform
215+
uses: ./.github/actions/setup-tf
216+
214217
- name: go install tools
215218
run: |
216219
go install google.golang.org/protobuf/cmd/protoc-gen-go@v1.30
@@ -919,7 +922,7 @@ jobs:
919922
uses: actions/dependency-review-action@v4.3.2
920923
with:
921924
allow-licenses: Apache-2.0, BSD-2-Clause, BSD-3-Clause, CC0-1.0, ISC, MIT, MIT-0, MPL-2.0
922-
allow-dependencies-licenses: "pkg:golang/github.com/pelletier/go-toml/v2"
925+
allow-dependencies-licenses: "pkg:golang/github.com/coder/wgtunnel@0.1.13-0.20240522110300-ade90dfb2da0"
923926
license-check: true
924927
vulnerability-check: false
925928
- name: "Report"

.vscode/settings.json

-1
Original file line numberDiff line numberDiff line change
@@ -195,7 +195,6 @@
195195
"**.pb.go": true,
196196
"**/*.gen.json": true,
197197
"**/testdata/*": true,
198-
"**Generated.ts": true,
199198
"coderd/apidoc/**": true,
200199
"docs/api/*.md": true,
201200
"docs/templates/*.md": true,

Makefile

+7
Original file line numberDiff line numberDiff line change
@@ -493,6 +493,7 @@ gen: \
493493
coderd/apidoc/swagger.json \
494494
.prettierignore.include \
495495
.prettierignore \
496+
provisioner/terraform/testdata/version \
496497
site/.prettierrc.yaml \
497498
site/.prettierignore \
498499
site/.eslintignore \
@@ -684,6 +685,12 @@ provisioner/terraform/testdata/.gen-golden: $(wildcard provisioner/terraform/tes
684685
go test ./provisioner/terraform -run="Test.*Golden$$" -update
685686
touch "$@"
686687

688+
provisioner/terraform/testdata/version:
689+
if [[ "$(shell cat provisioner/terraform/testdata/version.txt)" != "$(shell terraform version -json | jq -r '.terraform_version')" ]]; then
690+
./provisioner/terraform/testdata/generate.sh
691+
fi
692+
.PHONY: provisioner/terraform/testdata/version
693+
687694
scripts/ci-report/testdata/.gen-golden: $(wildcard scripts/ci-report/testdata/*) $(wildcard scripts/ci-report/*.go)
688695
go test ./scripts/ci-report -run=TestOutputMatchesGoldenFile -update
689696
touch "$@"

README.md

+4
Original file line numberDiff line numberDiff line change
@@ -122,3 +122,7 @@ We are always working on new integrations. Feel free to open an issue to request
122122
We are always happy to see new contributors to Coder. If you are new to the Coder codebase, we have
123123
[a guide on how to get started](https://coder.com/docs/v2/latest/CONTRIBUTING). We'd love to see your
124124
contributions!
125+
126+
## Hiring
127+
128+
Apply [here](https://cdr.co/github-apply) if you're interested in joining our team.

cli/configssh.go

+3-3
Original file line numberDiff line numberDiff line change
@@ -230,12 +230,12 @@ func (r *RootCmd) configSSH() *serpent.Command {
230230
Annotations: workspaceCommand,
231231
Use: "config-ssh",
232232
Short: "Add an SSH Host entry for your workspaces \"ssh coder.workspace\"",
233-
Long: formatExamples(
234-
example{
233+
Long: FormatExamples(
234+
Example{
235235
Description: "You can use -o (or --ssh-option) so set SSH options to be used for all your workspaces",
236236
Command: "coder config-ssh -o ForwardAgent=yes",
237237
},
238-
example{
238+
Example{
239239
Description: "You can use --dry-run (or -n) to see the changes that would be made",
240240
Command: "coder config-ssh --dry-run",
241241
},

cli/create.go

+2-2
Original file line numberDiff line numberDiff line change
@@ -35,8 +35,8 @@ func (r *RootCmd) create() *serpent.Command {
3535
Annotations: workspaceCommand,
3636
Use: "create [name]",
3737
Short: "Create a workspace",
38-
Long: formatExamples(
39-
example{
38+
Long: FormatExamples(
39+
Example{
4040
Description: "Create a workspace for another user (if you have permission)",
4141
Command: "coder create <username>/<workspace_name>",
4242
},

cli/dotfiles.go

+2-2
Original file line numberDiff line numberDiff line change
@@ -28,8 +28,8 @@ func (r *RootCmd) dotfiles() *serpent.Command {
2828
Use: "dotfiles <git_repo_url>",
2929
Middleware: serpent.RequireNArgs(1),
3030
Short: "Personalize your workspace by applying a canonical dotfiles repository",
31-
Long: formatExamples(
32-
example{
31+
Long: FormatExamples(
32+
Example{
3333
Description: "Check out and install a dotfiles repository without prompts",
3434
Command: "coder dotfiles --yes git@github.com:example/dotfiles.git",
3535
},

cli/externalauth.go

+3-3
Original file line numberDiff line numberDiff line change
@@ -35,8 +35,8 @@ func (r *RootCmd) externalAuthAccessToken() *serpent.Command {
3535
Short: "Print auth for an external provider",
3636
Long: "Print an access-token for an external auth provider. " +
3737
"The access-token will be validated and sent to stdout with exit code 0. " +
38-
"If a valid access-token cannot be obtained, the URL to authenticate will be sent to stdout with exit code 1\n" + formatExamples(
39-
example{
38+
"If a valid access-token cannot be obtained, the URL to authenticate will be sent to stdout with exit code 1\n" + FormatExamples(
39+
Example{
4040
Description: "Ensure that the user is authenticated with GitHub before cloning.",
4141
Command: `#!/usr/bin/env sh
4242
@@ -49,7 +49,7 @@ else
4949
fi
5050
`,
5151
},
52-
example{
52+
Example{
5353
Description: "Obtain an extra property of an access token for additional metadata.",
5454
Command: "coder external-auth access-token slack --extra \"authed_user.id\"",
5555
},

cli/organization.go

+4-3
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ func (r *RootCmd) organizations() *serpent.Command {
3030
r.currentOrganization(),
3131
r.switchOrganization(),
3232
r.createOrganization(),
33+
r.organizationRoles(),
3334
},
3435
}
3536

@@ -43,12 +44,12 @@ func (r *RootCmd) switchOrganization() *serpent.Command {
4344
cmd := &serpent.Command{
4445
Use: "set <organization name | ID>",
4546
Short: "set the organization used by the CLI. Pass an empty string to reset to the default organization.",
46-
Long: "set the organization used by the CLI. Pass an empty string to reset to the default organization.\n" + formatExamples(
47-
example{
47+
Long: "set the organization used by the CLI. Pass an empty string to reset to the default organization.\n" + FormatExamples(
48+
Example{
4849
Description: "Remove the current organization and defer to the default.",
4950
Command: "coder organizations set ''",
5051
},
51-
example{
52+
Example{
5253
Description: "Switch to a custom organization.",
5354
Command: "coder organizations set my-org",
5455
},

cli/organizationroles.go

+113
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,113 @@
1+
package cli
2+
3+
import (
4+
"fmt"
5+
"slices"
6+
"strings"
7+
8+
"golang.org/x/xerrors"
9+
10+
"github.com/coder/coder/v2/cli/cliui"
11+
"github.com/coder/coder/v2/codersdk"
12+
"github.com/coder/serpent"
13+
)
14+
15+
func (r *RootCmd) organizationRoles() *serpent.Command {
16+
cmd := &serpent.Command{
17+
Use: "roles",
18+
Short: "Manage organization roles.",
19+
Aliases: []string{"role"},
20+
Handler: func(inv *serpent.Invocation) error {
21+
return inv.Command.HelpHandler(inv)
22+
},
23+
Hidden: true,
24+
Children: []*serpent.Command{
25+
r.showOrganizationRoles(),
26+
},
27+
}
28+
return cmd
29+
}
30+
31+
func (r *RootCmd) showOrganizationRoles() *serpent.Command {
32+
formatter := cliui.NewOutputFormatter(
33+
cliui.ChangeFormatterData(
34+
cliui.TableFormat([]assignableRolesTableRow{}, []string{"name", "display_name", "built_in", "site_permissions", "org_permissions", "user_permissions"}),
35+
func(data any) (any, error) {
36+
input, ok := data.([]codersdk.AssignableRoles)
37+
if !ok {
38+
return nil, xerrors.Errorf("expected []codersdk.AssignableRoles got %T", data)
39+
}
40+
rows := make([]assignableRolesTableRow, 0, len(input))
41+
for _, role := range input {
42+
rows = append(rows, assignableRolesTableRow{
43+
Name: role.Name,
44+
DisplayName: role.DisplayName,
45+
SitePermissions: fmt.Sprintf("%d permissions", len(role.SitePermissions)),
46+
OrganizationPermissions: fmt.Sprintf("%d organizations", len(role.OrganizationPermissions)),
47+
UserPermissions: fmt.Sprintf("%d permissions", len(role.UserPermissions)),
48+
Assignable: role.Assignable,
49+
BuiltIn: role.BuiltIn,
50+
})
51+
}
52+
return rows, nil
53+
},
54+
),
55+
cliui.JSONFormat(),
56+
)
57+
58+
client := new(codersdk.Client)
59+
cmd := &serpent.Command{
60+
Use: "show [role_names ...]",
61+
Short: "Show role(s)",
62+
Middleware: serpent.Chain(
63+
r.InitClient(client),
64+
),
65+
Handler: func(inv *serpent.Invocation) error {
66+
ctx := inv.Context()
67+
org, err := CurrentOrganization(r, inv, client)
68+
if err != nil {
69+
return err
70+
}
71+
72+
roles, err := client.ListOrganizationRoles(ctx, org.ID)
73+
if err != nil {
74+
return xerrors.Errorf("listing roles: %w", err)
75+
}
76+
77+
if len(inv.Args) > 0 {
78+
// filter roles
79+
filtered := make([]codersdk.AssignableRoles, 0)
80+
for _, role := range roles {
81+
if slices.ContainsFunc(inv.Args, func(s string) bool {
82+
return strings.EqualFold(s, role.Name)
83+
}) {
84+
filtered = append(filtered, role)
85+
}
86+
}
87+
roles = filtered
88+
}
89+
90+
out, err := formatter.Format(inv.Context(), roles)
91+
if err != nil {
92+
return err
93+
}
94+
95+
_, err = fmt.Fprintln(inv.Stdout, out)
96+
return err
97+
},
98+
}
99+
formatter.AttachOptions(&cmd.Options)
100+
101+
return cmd
102+
}
103+
104+
type assignableRolesTableRow struct {
105+
Name string `table:"name,default_sort"`
106+
DisplayName string `table:"display_name"`
107+
SitePermissions string ` table:"site_permissions"`
108+
// map[<org_id>] -> Permissions
109+
OrganizationPermissions string `table:"org_permissions"`
110+
UserPermissions string `table:"user_permissions"`
111+
Assignable bool `table:"assignable"`
112+
BuiltIn bool `table:"built_in"`
113+
}

cli/organizationroles_test.go

+51
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
package cli_test
2+
3+
import (
4+
"bytes"
5+
"testing"
6+
7+
"github.com/google/uuid"
8+
"github.com/stretchr/testify/require"
9+
10+
"github.com/coder/coder/v2/cli/clitest"
11+
"github.com/coder/coder/v2/coderd/coderdtest"
12+
"github.com/coder/coder/v2/coderd/database"
13+
"github.com/coder/coder/v2/coderd/database/dbgen"
14+
"github.com/coder/coder/v2/coderd/rbac"
15+
"github.com/coder/coder/v2/testutil"
16+
)
17+
18+
func TestShowOrganizationRoles(t *testing.T) {
19+
t.Parallel()
20+
21+
t.Run("OK", func(t *testing.T) {
22+
t.Parallel()
23+
24+
ownerClient, db := coderdtest.NewWithDatabase(t, &coderdtest.Options{})
25+
owner := coderdtest.CreateFirstUser(t, ownerClient)
26+
client, _ := coderdtest.CreateAnotherUser(t, ownerClient, owner.OrganizationID, rbac.RoleUserAdmin())
27+
28+
const expectedRole = "test-role"
29+
dbgen.CustomRole(t, db, database.CustomRole{
30+
Name: expectedRole,
31+
DisplayName: "Expected",
32+
SitePermissions: nil,
33+
OrgPermissions: nil,
34+
UserPermissions: nil,
35+
OrganizationID: uuid.NullUUID{
36+
UUID: owner.OrganizationID,
37+
Valid: true,
38+
},
39+
})
40+
41+
ctx := testutil.Context(t, testutil.WaitMedium)
42+
inv, root := clitest.New(t, "organization", "roles", "show")
43+
clitest.SetupConfig(t, client, root)
44+
45+
buf := new(bytes.Buffer)
46+
inv.Stdout = buf
47+
err := inv.WithContext(ctx).Run()
48+
require.NoError(t, err)
49+
require.Contains(t, buf.String(), expectedRole)
50+
})
51+
}

cli/portforward.go

+6-6
Original file line numberDiff line numberDiff line change
@@ -35,24 +35,24 @@ func (r *RootCmd) portForward() *serpent.Command {
3535
Use: "port-forward <workspace>",
3636
Short: `Forward ports from a workspace to the local machine. For reverse port forwarding, use "coder ssh -R".`,
3737
Aliases: []string{"tunnel"},
38-
Long: formatExamples(
39-
example{
38+
Long: FormatExamples(
39+
Example{
4040
Description: "Port forward a single TCP port from 1234 in the workspace to port 5678 on your local machine",
4141
Command: "coder port-forward <workspace> --tcp 5678:1234",
4242
},
43-
example{
43+
Example{
4444
Description: "Port forward a single UDP port from port 9000 to port 9000 on your local machine",
4545
Command: "coder port-forward <workspace> --udp 9000",
4646
},
47-
example{
47+
Example{
4848
Description: "Port forward multiple TCP ports and a UDP port",
4949
Command: "coder port-forward <workspace> --tcp 8080:8080 --tcp 9000:3000 --udp 5353:53",
5050
},
51-
example{
51+
Example{
5252
Description: "Port forward multiple ports (TCP or UDP) in condensed syntax",
5353
Command: "coder port-forward <workspace> --tcp 8080,9000:3000,9090-9092,10000-10002:10010-10012",
5454
},
55-
example{
55+
Example{
5656
Description: "Port forward specifying the local address to bind to",
5757
Command: "coder port-forward <workspace> --tcp 1.2.3.4:8080:8080",
5858
},

cli/root.go

+8-8
Original file line numberDiff line numberDiff line change
@@ -181,12 +181,12 @@ func (r *RootCmd) Command(subcommands []*serpent.Command) (*serpent.Command, err
181181
`
182182
cmd := &serpent.Command{
183183
Use: "coder [global-flags] <subcommand>",
184-
Long: fmt.Sprintf(fmtLong, buildinfo.Version()) + formatExamples(
185-
example{
184+
Long: fmt.Sprintf(fmtLong, buildinfo.Version()) + FormatExamples(
185+
Example{
186186
Description: "Start a Coder server",
187187
Command: "coder server",
188188
},
189-
example{
189+
Example{
190190
Description: "Get started by creating a template from an example",
191191
Command: "coder templates init",
192192
},
@@ -753,16 +753,16 @@ func isTTYWriter(inv *serpent.Invocation, writer io.Writer) bool {
753753
return isatty.IsTerminal(file.Fd())
754754
}
755755

756-
// example represents a standard example for command usage, to be used
757-
// with formatExamples.
758-
type example struct {
756+
// Example represents a standard example for command usage, to be used
757+
// with FormatExamples.
758+
type Example struct {
759759
Description string
760760
Command string
761761
}
762762

763-
// formatExamples formats the examples as width wrapped bulletpoint
763+
// FormatExamples formats the examples as width wrapped bulletpoint
764764
// descriptions with the command underneath.
765-
func formatExamples(examples ...example) string {
765+
func FormatExamples(examples ...Example) string {
766766
var sb strings.Builder
767767

768768
padStyle := cliui.DefaultStyles.Wrap.With(pretty.XPad(4, 0))

0 commit comments

Comments
 (0)