From ac2b839013500e4b3329a8bb8eab0413a182c3d5 Mon Sep 17 00:00:00 2001 From: Cian Johnston Date: Fri, 5 Sep 2025 14:36:00 +0100 Subject: [PATCH 1/4] ci: fix go version to that defined in go.mod (#438) Our version of Go we reference in our .github/** doesn't match that in go.mod. To fix this, I've updated the version of Go and added a check to ensure they're all in sync. --- .github/workflows/release.yml | 16 +++++++++++----- .github/workflows/test.yml | 33 +++++++++++++++++++++------------ scripts/check_go_version.sh | 35 +++++++++++++++++++++++++++++++++++ 3 files changed, 67 insertions(+), 17 deletions(-) create mode 100755 scripts/check_go_version.sh diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index a6b823b9..4dccabd6 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -19,15 +19,18 @@ jobs: name: Run Integration Tests runs-on: ubuntu-latest steps: + - name: Check out code into the Go module directory + uses: actions/checkout@v5 + + - name: Check Go Versions + run: ./scripts/check_go_version.sh + - name: Set up Go uses: actions/setup-go@v5 with: - go-version: "1.22" + go-version: "1.24.2" id: go - - name: Check out code into the Go module directory - uses: actions/checkout@v5 - - name: Get dependencies run: | go mod download @@ -74,13 +77,16 @@ jobs: - name: Checkout uses: actions/checkout@v5 + - name: Check Go Versions + run: ./scripts/check_go_version.sh + - name: Unshallow run: git fetch --prune --unshallow - name: Set up Go uses: actions/setup-go@v5 with: - go-version: '1.22' + go-version: "1.24.2" - name: Import GPG key id: import_gpg diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 8b27f78d..14c4ec60 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -19,15 +19,18 @@ jobs: runs-on: ubuntu-latest timeout-minutes: 5 steps: + - name: Check out code into the Go module directory + uses: actions/checkout@v5 + + - name: Check Go Versions + run: ./scripts/check_go_version.sh + - name: Set up Go uses: actions/setup-go@v5 with: - go-version: "1.22" + go-version: "1.24.2" id: go - - name: Check out code into the Go module directory - uses: actions/checkout@v5 - - name: Get dependencies run: | go mod download @@ -92,10 +95,16 @@ jobs: - "1.10.*" - "1.11.*" steps: + - name: Check out code into the Go module directory + uses: actions/checkout@v5 + + - name: Check Go Versions + run: ./scripts/check_go_version.sh + - name: Set up Go uses: actions/setup-go@v5 with: - go-version: "1.22" + go-version: "1.24.2" id: go - uses: hashicorp/setup-terraform@v3 @@ -103,9 +112,6 @@ jobs: terraform_version: ${{ matrix.terraform }} terraform_wrapper: false - - name: Check out code into the Go module directory - uses: actions/checkout@v5 - - name: Get dependencies run: | go mod download @@ -122,10 +128,16 @@ jobs: runs-on: ubuntu-latest timeout-minutes: 5 steps: + - name: Check out code into the Go module directory + uses: actions/checkout@v5 + + - name: Check Go Versions + run: ./scripts/check_go_version.sh + - name: Set up Go uses: actions/setup-go@v5 with: - go-version: "1.22" + go-version: "1.24.2" id: go - uses: hashicorp/setup-terraform@v3 @@ -133,9 +145,6 @@ jobs: terraform_version: "latest" terraform_wrapper: false - - name: Check out code into the Go module directory - uses: actions/checkout@v5 - - name: Get dependencies run: | go mod download diff --git a/scripts/check_go_version.sh b/scripts/check_go_version.sh new file mode 100755 index 00000000..2b56ceae --- /dev/null +++ b/scripts/check_go_version.sh @@ -0,0 +1,35 @@ +#!/usr/bin/env bash +set -euo pipefail + +MOD_VERSION=$(go mod edit -json | jq -r .Go) +echo "go.mod version: $MOD_VERSION" +STATUS=0 + +if [[ " $* " == *" --fix "* ]]; then + for wf in .github/workflows/*.{yml,yaml}; do + sed -i "s/go-version:.*/go-version: \"${MOD_VERSION}\"/g" "${wf}" + done + exit 0 +fi + +for wf in .github/workflows/*.{yml,yaml}; do + WF_VERSIONS=$(yq -r '.jobs[].steps[] | select(.with["go-version"]) | .with["go-version"]' -o=tsv "$wf" | grep -v '^---$' || true) + if [[ -z "$WF_VERSIONS" ]]; then + continue + fi + + UNIQUE_WF_VERSIONS=$(sort -u <<<"$WF_VERSIONS") + for ver in $UNIQUE_WF_VERSIONS; do + if [[ $ver != "$MOD_VERSION" ]]; then + STATUS=1 + echo "❌ $wf: go.mod=$MOD_VERSION but workflow uses $(tr '\n' ' ' <<<"$UNIQUE_WF_VERSIONS")" + continue + fi + done +done + +if [[ $STATUS -eq 1 ]]; then + echo "Re-run this script with --fix to automatically update workflows to match go.mod" +fi + +exit $STATUS From e26aeb89f14bf748ddc5cc78620c63521a8d14ef Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 5 Sep 2025 14:58:53 +0100 Subject: [PATCH 2/4] build(deps): Bump actions/setup-go from 5 to 6 (#437) Bumps [actions/setup-go](https://github.com/actions/setup-go) from 5 to 6. - [Release notes](https://github.com/actions/setup-go/releases) - [Commits](https://github.com/actions/setup-go/compare/v5...v6) --- updated-dependencies: - dependency-name: actions/setup-go dependency-version: '6' dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/release.yml | 4 ++-- .github/workflows/test.yml | 6 +++--- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 4dccabd6..d52ff5cd 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -26,7 +26,7 @@ jobs: run: ./scripts/check_go_version.sh - name: Set up Go - uses: actions/setup-go@v5 + uses: actions/setup-go@v6 with: go-version: "1.24.2" id: go @@ -84,7 +84,7 @@ jobs: run: git fetch --prune --unshallow - name: Set up Go - uses: actions/setup-go@v5 + uses: actions/setup-go@v6 with: go-version: "1.24.2" diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 14c4ec60..d93f59f7 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -26,7 +26,7 @@ jobs: run: ./scripts/check_go_version.sh - name: Set up Go - uses: actions/setup-go@v5 + uses: actions/setup-go@v6 with: go-version: "1.24.2" id: go @@ -102,7 +102,7 @@ jobs: run: ./scripts/check_go_version.sh - name: Set up Go - uses: actions/setup-go@v5 + uses: actions/setup-go@v6 with: go-version: "1.24.2" id: go @@ -135,7 +135,7 @@ jobs: run: ./scripts/check_go_version.sh - name: Set up Go - uses: actions/setup-go@v5 + uses: actions/setup-go@v6 with: go-version: "1.24.2" id: go From c8bc37a5caa446d80c8d3ea966a702d90771d71e Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 8 Sep 2025 09:08:05 +0100 Subject: [PATCH 3/4] build(deps): Bump golang.org/x/mod from 0.27.0 to 0.28.0 (#440) Bumps [golang.org/x/mod](https://github.com/golang/mod) from 0.27.0 to 0.28.0. - [Commits](https://github.com/golang/mod/compare/v0.27.0...v0.28.0) --- updated-dependencies: - dependency-name: golang.org/x/mod dependency-version: 0.28.0 dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- go.mod | 12 ++++++------ go.sum | 24 ++++++++++++------------ 2 files changed, 18 insertions(+), 18 deletions(-) diff --git a/go.mod b/go.mod index 43c7f536..1fcf7fa3 100644 --- a/go.mod +++ b/go.mod @@ -13,7 +13,7 @@ require ( github.com/robfig/cron/v3 v3.0.1 github.com/stretchr/testify v1.11.0 golang.org/x/exp v0.0.0-20240613232115-7f521ea00fb8 - golang.org/x/mod v0.27.0 + golang.org/x/mod v0.28.0 golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 ) @@ -78,13 +78,13 @@ require ( go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.27.0 // indirect go.opentelemetry.io/otel/metric v1.34.0 // indirect go.opentelemetry.io/otel/trace v1.34.0 // indirect - golang.org/x/crypto v0.40.0 // indirect - golang.org/x/net v0.42.0 // indirect + golang.org/x/crypto v0.41.0 // indirect + golang.org/x/net v0.43.0 // indirect golang.org/x/sync v0.16.0 // indirect - golang.org/x/sys v0.34.0 // indirect - golang.org/x/text v0.27.0 // indirect + golang.org/x/sys v0.35.0 // indirect + golang.org/x/text v0.28.0 // indirect golang.org/x/time v0.5.0 // indirect - golang.org/x/tools v0.35.0 // indirect + golang.org/x/tools v0.36.0 // indirect google.golang.org/appengine v1.6.8 // indirect google.golang.org/genproto v0.0.0-20230410155749-daa745c078e1 // indirect google.golang.org/grpc v1.72.1 // indirect diff --git a/go.sum b/go.sum index 894f7fdf..98df4041 100644 --- a/go.sum +++ b/go.sum @@ -224,23 +224,23 @@ golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACk golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= -golang.org/x/crypto v0.40.0 h1:r4x+VvoG5Fm+eJcxMaY8CQM7Lb0l1lsmjGBQ6s8BfKM= -golang.org/x/crypto v0.40.0/go.mod h1:Qr1vMER5WyS2dfPHAlsOj01wgLbsyWtFn/aY+5+ZdxY= +golang.org/x/crypto v0.41.0 h1:WKYxWedPGCTVVl5+WHSSrOBT0O8lx32+zxmHxijgXp4= +golang.org/x/crypto v0.41.0/go.mod h1:pO5AFd7FA68rFak7rOAGVuygIISepHftHnr8dr6+sUc= golang.org/x/exp v0.0.0-20240613232115-7f521ea00fb8 h1:yixxcjnhBmY0nkL253HFVIm0JsFHwrHdT3Yh6szTnfY= golang.org/x/exp v0.0.0-20240613232115-7f521ea00fb8/go.mod h1:jj3sYF3dwk5D+ghuXyeI3r5MFf+NT2An6/9dOA95KSI= golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= -golang.org/x/mod v0.27.0 h1:kb+q2PyFnEADO2IEF935ehFUXlWiNjJWtRNgBLSfbxQ= -golang.org/x/mod v0.27.0/go.mod h1:rWI627Fq0DEoudcK+MBkNkCe0EetEaDSwJJkCcjpazc= +golang.org/x/mod v0.28.0 h1:gQBtGhjxykdjY9YhZpSlZIsbnaE2+PgjfLWUQTnoZ1U= +golang.org/x/mod v0.28.0/go.mod h1:yfB/L0NOf/kmEbXjzCPOx1iK1fRutOydrCMsqRhEBxI= golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= -golang.org/x/net v0.42.0 h1:jzkYrhi3YQWD6MLBJcsklgQsoAcw89EcZbJw8Z614hs= -golang.org/x/net v0.42.0/go.mod h1:FF1RA5d3u7nAYA4z2TkclSCKh68eSXtiFwcWQpPXdt8= +golang.org/x/net v0.43.0 h1:lat02VYK2j4aLzMzecihNvTlJNQUq316m2Mr9rnM6YE= +golang.org/x/net v0.43.0/go.mod h1:vhO1fvI4dGsIjh73sWfUVjj3N7CA9WkKJNQm2svM6Jg= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= @@ -262,16 +262,16 @@ golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.34.0 h1:H5Y5sJ2L2JRdyv7ROF1he/lPdvFsd0mJHFw2ThKHxLA= -golang.org/x/sys v0.34.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k= +golang.org/x/sys v0.35.0 h1:vz1N37gP5bs89s7He8XuIYXpyY0+QlsKmzipCbUtyxI= +golang.org/x/sys v0.35.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= golang.org/x/text v0.3.8/go.mod h1:E6s5w1FMmriuDzIBO73fBruAKo1PCIq6d2Q6DHfQ8WQ= -golang.org/x/text v0.27.0 h1:4fGWRpyh641NLlecmyl4LOe6yDdfaYNrGb2zdfo4JV4= -golang.org/x/text v0.27.0/go.mod h1:1D28KMCvyooCX9hBiosv5Tz/+YLxj0j7XhWjpSUF7CU= +golang.org/x/text v0.28.0 h1:rhazDwis8INMIwQ4tpjLDzUhx6RlXqZNPEM0huQojng= +golang.org/x/text v0.28.0/go.mod h1:U8nCwOR8jO/marOQ0QbDiOngZVEBB7MAiitBuMjXiNU= golang.org/x/time v0.5.0 h1:o7cqy6amK/52YcAKIPlM3a+Fpj35zvRj2TP+e1xFSfk= golang.org/x/time v0.5.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= @@ -279,8 +279,8 @@ golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtn golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= -golang.org/x/tools v0.35.0 h1:mBffYraMEf7aa0sB+NuKnuCy8qI/9Bughn8dC2Gu5r0= -golang.org/x/tools v0.35.0/go.mod h1:NKdj5HkL/73byiZSJjqJgKn3ep7KjFkBOkR/Hps3VPw= +golang.org/x/tools v0.36.0 h1:kWS0uv/zsvHEle1LbV5LE8QujrxB3wfQyxHfhOk0Qkg= +golang.org/x/tools v0.36.0/go.mod h1:WBDiHKJK8YgLHlcQPYQzNCkUxUypCaa5ZegCVutKm+s= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= From bb2167ecc44506469c77380367ad1c3bc08f475e Mon Sep 17 00:00:00 2001 From: Rafael Rodriguez Date: Wed, 10 Sep 2025 09:55:38 -0500 Subject: [PATCH 4/4] feat: add tooltip field to workspace app (#435) * feat: add tooltip field to workspace app * remove duplicate test * run make gen * update tooltip max length to 2048 --- docs/resources/app.md | 2 + examples/resources/coder_app/resource.tf | 1 + provider/app.go | 18 +++++++ provider/app_test.go | 61 ++++++++++++++++++++++++ 4 files changed, 82 insertions(+) diff --git a/docs/resources/app.md b/docs/resources/app.md index 6be99cf3..35a9951b 100644 --- a/docs/resources/app.md +++ b/docs/resources/app.md @@ -31,6 +31,7 @@ resource "coder_app" "code-server" { display_name = "VS Code" icon = "${data.coder_workspace.me.access_url}/icon/code.svg" url = "http://localhost:13337" + tooltip = "You need to [Install Coder Desktop](https://coder.com/docs/user-guides/desktop#install-coder-desktop) to use this button." share = "owner" subdomain = false open_in = "window" @@ -71,6 +72,7 @@ resource "coder_app" "vim" { - `order` (Number) The order determines the position of app in the UI presentation. The lowest order is shown first and apps with equal order are sorted by name (ascending order). - `share` (String) Determines the level which the application is shared at. Valid levels are `"owner"` (default), `"authenticated"` and `"public"`. Level `"owner"` disables sharing on the app, so only the workspace owner can access it. Level `"authenticated"` shares the app with all authenticated users. Level `"public"` shares it with any user, including unauthenticated users. Permitted application sharing levels can be configured site-wide via a flag on `coder server` (Enterprise only). - `subdomain` (Boolean) Determines whether the app will be accessed via it's own subdomain or whether it will be accessed via a path on Coder. If wildcards have not been setup by the administrator then apps with `subdomain` set to `true` will not be accessible. Defaults to `false`. +- `tooltip` (String) Markdown text that is displayed when hovering over workspace apps. - `url` (String) An external url if `external=true` or a URL to be proxied to from inside the workspace. This should be of the form `http://localhost:PORT[/SUBPATH]`. Either `command` or `url` may be specified, but not both. ### Read-Only diff --git a/examples/resources/coder_app/resource.tf b/examples/resources/coder_app/resource.tf index 8aea7b99..8dab8807 100644 --- a/examples/resources/coder_app/resource.tf +++ b/examples/resources/coder_app/resource.tf @@ -16,6 +16,7 @@ resource "coder_app" "code-server" { display_name = "VS Code" icon = "${data.coder_workspace.me.access_url}/icon/code.svg" url = "http://localhost:13337" + tooltip = "You need to [Install Coder Desktop](https://coder.com/docs/user-guides/desktop#install-coder-desktop) to use this button." share = "owner" subdomain = false open_in = "window" diff --git a/provider/app.go b/provider/app.go index 52996a72..dd0428a1 100644 --- a/provider/app.go +++ b/provider/app.go @@ -27,6 +27,7 @@ var ( const ( appDisplayNameMaxLength = 64 // database column limit appGroupNameMaxLength = 64 + appTooltipMaxLength = 2048 ) func appResource() *schema.Resource { @@ -273,6 +274,23 @@ func appResource() *schema.Resource { return diag.Errorf(`invalid "coder_app" open_in value, must be one of "tab", "slim-window": %q`, valStr) }, }, + "tooltip": { + Type: schema.TypeString, + Description: "Markdown text that is displayed when hovering over workspace apps.", + ForceNew: true, + Optional: true, + ValidateDiagFunc: func(val any, c cty.Path) diag.Diagnostics { + valStr, ok := val.(string) + if !ok { + return diag.Errorf("expected string, got %T", val) + } + + if len(valStr) > appTooltipMaxLength { + return diag.Errorf("tooltip is too long (max %d characters)", appTooltipMaxLength) + } + return nil + }, + }, }, } } diff --git a/provider/app_test.go b/provider/app_test.go index 2b9a5580..b8d4c8e7 100644 --- a/provider/app_test.go +++ b/provider/app_test.go @@ -4,6 +4,7 @@ import ( "fmt" "regexp" "strconv" + "strings" "testing" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" @@ -44,6 +45,7 @@ func TestApp(t *testing.T) { order = 4 hidden = false open_in = "slim-window" + tooltip = "You need to [Install Coder Desktop](https://coder.com/docs/user-guides/desktop#install-coder-desktop) to use this button." } `, Check: func(state *terraform.State) error { @@ -68,6 +70,7 @@ func TestApp(t *testing.T) { "order", "hidden", "open_in", + "tooltip", } { value := resource.Primary.Attributes[key] t.Logf("%q = %q", key, value) @@ -535,4 +538,62 @@ func TestApp(t *testing.T) { }) } }) + + t.Run("Tooltip", func(t *testing.T) { + t.Parallel() + + cases := []struct { + name string + tooltip string + expectError *regexp.Regexp + }{ + { + name: "Empty", + tooltip: "", + }, + { + name: "ValidTooltip", + tooltip: "You need to [Install Coder Desktop](https://coder.com/docs/user-guides/desktop" + + "#install-coder-desktop) to use this button.", + }, + { + name: "TooltipTooLong", + tooltip: strings.Repeat("a", 2049), + expectError: regexp.MustCompile("tooltip is too long"), + }, + } + + for _, c := range cases { + c := c + + t.Run(c.name, func(t *testing.T) { + t.Parallel() + + config := fmt.Sprintf(` + provider "coder" {} + resource "coder_agent" "dev" { + os = "linux" + arch = "amd64" + } + resource "coder_app" "code-server" { + agent_id = coder_agent.dev.id + slug = "code-server" + display_name = "Testing" + url = "http://localhost:13337" + open_in = "slim-window" + tooltip = "%s" + } + `, c.tooltip) + + resource.Test(t, resource.TestCase{ + ProviderFactories: coderFactory(), + IsUnitTest: true, + Steps: []resource.TestStep{{ + Config: config, + ExpectError: c.expectError, + }}, + }) + }) + } + }) }