Compare commits

..

876 Commits

Author SHA1 Message Date
Jon Ayers 1372bf82f5 chore: revert "chore: remove workspace_actions experiment (#10030)" (#10363) 2023-10-20 13:21:53 -05:00
Asher 57c9d88703 chore(site): remove terminal xservice (#10234)
* Remove terminalXService

This is a prelude to the change I actually want to make, which is to
send the size of the terminal on the web socket URL after we do a fit.
I have found xstate so confusing that it was easier to just rewrite it.

* Fix hanging tests

I am not really sure what ws.connected is doing but it seems to somehow
block updates.  Something to do with `act()` maybe?

Basically, the useEffect creating the terminal never updates once the
config query finishes, so the web socket is never created, and the test
hangs forever.

It might have been working before only because the web socket was
created using xstate rather than useEffect and once it connected it
would unblock and React could update again but this is just a guess.

* Ignore other config changes

The terminal only cares about the renderer specifically, no need to
recreate the terminal if something else changes.

* Break out port forward URL open to util

Felt like this could be broken out to reduce the component size.  Also
trying to figure out why it is causing the terminal to create multiple
times.

* Prevent handleWebLink change from recreating terminal

Depending on the timing, handleWebLink was causing the terminal to get
recreated.  We only need to create the terminal once unless the render
type changes.

Recreating the terminal was also recreating the web socket pointlessly.
2023-10-20 10:18:17 -08:00
Muhammad Atif Ali 5ebb702e00 chore: add OIDC provider logos (#10365)
* chore: add OIDC provider logos

* Add files via upload

* fmt
2023-10-20 19:30:05 +03:00
Eric Paulsen 9dbc913798 fix: additional cluster SA, role names (#10366) 2023-10-20 11:44:16 -04:00
Kira Pilot ed5567ba28 fix: show dormant and suspended users in groups (#10333)
* fix: show dormant and suspended users in groups

* added status column
2023-10-20 11:36:00 -04:00
Bruno Quaresma ac322724b0 chore(site): replace custom LoadingButton from the one in MUI (#10351) 2023-10-20 09:57:27 -03:00
Bruno Quaresma 3d9bfdd5dc chore(site): remove update check service (#10355) 2023-10-20 09:41:34 -03:00
Bruno Quaresma 1ba5169109 chore(site): remove search users and groups xservice (#10353) 2023-10-20 09:33:07 -03:00
Jon Ayers d33526108f feat: add frontend support for mandating active template version (#10338) 2023-10-19 18:21:52 -05:00
Jon Ayers f5f150d568 feat: add cli support for --require-active-version (#10337) 2023-10-19 17:16:15 -05:00
Ammar Bandukwala b799014832 docs: rework telemetry doc and add CLI warning (#10354) 2023-10-19 15:50:20 -05:00
Kira Pilot 9c9319f81e fix: resolve User is not unauthenticated error seen on logout (#10349)
* fix: do not cache getAuthenticatedUser call

* use initialQuery, add back meta tag for initial load of users

* lift initialUserData
2023-10-19 14:50:53 -04:00
Michael Smith ab2904a676 feat: add user groups column to users table (#10284)
* refactor: extract UserRoleCell into separate component

* wip: add placeholder Groups column

* fix: remove redundant css styles

* refactor: update EditRolesButton to use Sets to detect selections

* wip: commit progress for updated roles column

* wip: commit current role pill progress

* fix: update state sync logic

* chore: add groupsByUserId query options factory

* fix: update return value of select function

* chore: drill groups data down to cell component

* wip: commit current cell progress

* fix: remove redundant classes

* wip: commit current styling progress

* fix: update line height for CTA

* fix: update spacing

* chore: add tooltip for Groups column header

* fix: remove tsbuild file

* refactor: consolidate tooltip components

* fix: update font size defaults inside theme

* fix: expand hoverable/clickable area of groups cell

* fix: remove possible undefined cases from HelpTooltip

* chore: add popover functionality to groups

* wip: commit progress on groups tooltip

* fix: remove zero-height group name visual bug

* feat: get basic version of user group tooltips done

* perf: move sort order callback outside loop

* fix: update spacing for tooltip

* feat: make popovers entirely hover-based

* fix: disable scroll locking for popover

* docs: add comments explaining some pitfalls with Popover component

* refactor: simplify userRoleCell implementation

* feat: complete main feature

* fix: prevent scroll lock for role tooltips

* fix: change import to type import

* refactor: simplify how groups are clustered

* refactor: update UserRoleCell to use Popover

* refactor: remove unnecessary fragment

* chore: add id/aria support for Popover

* refactor: update UserGroupsCell to use Popover

* chore: redo visual design for UserGroupsCell

* fix: shrink UserGroupsCell text

* fix: update UsersTable test to include groups info
2023-10-19 14:31:48 -04:00
Bruno Quaresma 557adab224 chore(site): remove template ACL XService (#10332) 2023-10-19 14:59:08 -03:00
dependabot[bot] 21f87313bd chore: bump github.com/aws/smithy-go from 1.14.2 to 1.15.0 (#10282)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-10-19 16:08:56 +03:00
Muhammad Atif Ali 42c21d400f fix(docs): update external-auth docs to use coder_external_auth (#10347) 2023-10-19 12:30:48 +00:00
Bruno Quaresma f677c4470b chore(site): add custom popover component (#10319) 2023-10-19 09:13:21 -03:00
Bruno Quaresma b8c7b56fda fix(site): fix tabs in the template layout (#10334) 2023-10-19 09:12:41 -03:00
Marcin Tojek c4f590581e feat: expose template insights as Prometheus metrics (#10325) 2023-10-19 08:45:12 +00:00
Jon Ayers 997493d4ae feat: add template setting to require active template version (#10277) 2023-10-18 17:07:21 -05:00
Colin Adler 1ad998ee3a fix: add requester IP to workspace build audit logs (#10242) 2023-10-18 15:08:02 -05:00
Colin Adler 504cedf15a feat: add telemetry for external provisioners (#10322) 2023-10-18 14:20:30 -05:00
Mathias Fredriksson 9b73020f11 ci(.github): set DataDog upload timeout (#10328) 2023-10-18 20:07:52 +03:00
Bruno Quaresma c93fe8ddbe chore(site): remove template version machine (#10315) 2023-10-18 09:18:03 -03:00
Muhammad Atif Ali fe05fd1e6e docs: update vscode web docs (#10327) 2023-10-18 12:13:44 +00:00
Kayla Washburn 2b5e02f5b2 refactor: improve e2e test reporting (#10304) 2023-10-17 16:11:42 -06:00
Muhammad Atif Ali ab456276dc docs: add v2.3.1 changelog (#10313)
* add v2.3.1 changelog

* fmt

* explain

* simplify

* update

* simplify

* cleanup

* refresh

* update

* cleanup and fmt

* Update v2.3.1.md

cleanup

* add new commits

---------

Co-authored-by: Ben <me@bpmct.net>
2023-10-17 21:45:38 +00:00
Eric Paulsen 09d995c8dc fix: set K8s deployment strategy to Recreate (#10321) 2023-10-17 21:06:35 +00:00
Kayla Washburn 619df23ad1 chore: fix linting issues and generated files (#10317) 2023-10-17 14:41:35 -06:00
Muhammad Atif Ali 492da15890 chore: delete filebrowser.db (#10320) 2023-10-17 18:59:35 +00:00
Kira Pilot 1656249e07 feat: add all safe experiments to the deployment page (#10276)
* added new option table type for experiments

* added tests

* fixed go tests

* added go test for new param

* removing query change

* clearing ExperimentsAll

* dont mutate ExperimentsAll

* added new route for safe experiments

* added new route for safe experiments

* added test for new route

* PR feedback

* altered design

* alias children
2023-10-17 14:49:19 -04:00
Bruno Quaresma 35f9e2ef7f refactor(site): refactor create workspace button (#10303) 2023-10-17 13:31:51 -03:00
Michael Smith 0f2d4fdb6d fix: prevent metadata queries from short-circuiting (#10312)
* fix: prevent metadata queries from short-circuiting

* fix: use correct type definitions
2023-10-17 10:20:56 -06:00
Mathias Fredriksson 8f39ec5cc3 fix(scaletest/templates): fix bugs and improve debugging (#10316) 2023-10-17 15:18:49 +00:00
Kayla Washburn 2f4ca0f566 chore: use emotion for styling (pt. 6) (#10298) 2023-10-17 09:14:13 -06:00
Muhammad Atif Ali a49e6b88f9 docs: reorganize template docs (#10297)
* docs: rework our "templates" section

* wikistuff

* fix formatting

* add diagram

* reorganize some things

* docs: improve workspaces and templates doc (#9139)

* Reorg, updated/new screenshots, consistent terminology

* First pass

* Another pass

* Added integration section

* New outline for template pages, small updates

* Revised outline for templates, added tutorial

* First pass at tutorial

* Some feedback from Ben.

* Update docs/workspaces.md

Co-authored-by: Muhammad Atif Ali <matifali@live.com>

* Update docs/workspaces.md

Co-authored-by: Muhammad Atif Ali <matifali@live.com>

* Update docs/workspaces.md

Co-authored-by: Muhammad Atif Ali <matifali@live.com>

* Fixed typos

* Expanded tutorial

I have read the CLA Document and I hereby sign the CLA

* New screenshots, improved tutorial, revised anatomy

* Improved tutorial. Anatomy is now a guided tour.

* First pass at guided tour

* Updated authentication info

* Reorganized the guided tour

* Edited more template pages

* Update docs/templates/tour.md

Co-authored-by: Muhammad Atif Ali <matifali@live.com>

* Update docs/templates/tour.md

Co-authored-by: Muhammad Atif Ali <matifali@live.com>

* Update docs/templates/tour.md

Co-authored-by: Muhammad Atif Ali <matifali@live.com>

* Update docs/templates/tutorial.md

Co-authored-by: Muhammad Atif Ali <matifali@live.com>

* Update docs/templates/tour.md

Co-authored-by: Muhammad Atif Ali <matifali@live.com>

* Update docs/templates/tour.md

Co-authored-by: Muhammad Atif Ali <matifali@live.com>

* Update docs/templates/tour.md

Co-authored-by: Muhammad Atif Ali <matifali@live.com>

* Update docs/templates/tour.md

Co-authored-by: Muhammad Atif Ali <matifali@live.com>

* Update docs/templates/tour.md

Co-authored-by: Muhammad Atif Ali <matifali@live.com>

* Revised devcontainers and docker-in-workspaces

* Edited and added screenshots

* Prepared first draft, except docs/templates/open-in-coder.md

* Fix typo

* remove legacy parameters and migration guide

* Use coder templates create

* Added screenshot for workspace template variables

* Made it prettier

* Fixed minor typos and markdown problems

* edits to repairing workspaces

* fix broken links in product

* Added troubleshooting, minor corrections.

* fix terminal links

* fmt

---------

Co-authored-by: Muhammad Atif Ali <matifali@live.com>
Co-authored-by: Ben Potter <me@bpmct.net>
Co-authored-by: Atif Ali <atif@coder.com>

* make fmt

* fix merge conflict

* make fmt

* make gen

* update

* lint

* Discard changes to coderd/database/queries.sql.go

* Discard changes to cli/templates.go

* Discard changes to cli/templateversionarchive.go

* Discard changes to cli/templateversions.go

* Update docker-in-workspaces.md

* replace ```sh with ```shell

* open-in-coder

* fmt

* mention coder_metadata in icons.md

* resource_metadata

* use shell

* modules.md

* mention coder registry module

* workspace.md

* resource_metadata

* remove duplication

* address comments

* cleanup

* fmt

* fix broken links

* fix numbering

* mention module registry

* add example

* demote heading

* remove top level entry from manifest

* fmt

---------

Co-authored-by: Ben <me@bpmct.net>
Co-authored-by: Marc Paquette <22124737+marcpaq@users.noreply.github.com>
2023-10-17 14:47:12 +00:00
dependabot[bot] b5e5b39de2 chore: bump @babel/traverse from 7.22.8 to 7.23.2 in /offlinedocs (#10294)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-10-16 23:39:04 +03:00
dependabot[bot] 2acf195b13 chore: bump @babel/traverse from 7.22.11 to 7.23.2 in /site (#10295)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-10-16 23:38:51 +03:00
Kayla Washburn eaea918a59 chore: use emotion for styling (pt. 5) (#10261) 2023-10-16 12:41:15 -06:00
Bruno Quaresma 4240200b5d fix(site): fix state used to check if creating was loading (#10296) 2023-10-16 15:53:50 +00:00
Mathias Fredriksson 43f26dfec5 feat(scaletest/templates): run all scenarios even on failure (#10290)
We now also end all failed phases and add the `error` tag in Grafana.
2023-10-16 18:18:05 +03:00
Ben Potter 9a0aac88e0 chore: fix broken links in docs (#10291)
https://github.com/coder/coder/actions/runs/6531396781/job/17732557812
2023-10-16 14:29:53 +00:00
Steven Masley 6ebe9b0402 feat: add UI for autostart workspace days (#10263)
* feat: add ui for selecting auto start days
2023-10-16 09:29:42 -05:00
Steven Masley 5a90228c60 feat: fix 404 on the first app loads when unauthenticated (#10262)
* feat: fix 404 on the first app loads when unauthenticated
* Update site/src/pages/LoginPage/LoginPage.tsx
2023-10-16 09:29:25 -05:00
Mathias Fredriksson 8ffe0e22b6 feat(scaletest/templates): gather pod logs at the end of a scale test (#10288) 2023-10-16 13:50:04 +00:00
Bruno Quaresma 8efa1239e7 fix(site): do not return next page if the current size is lower than the limit (#10287) 2023-10-16 13:39:48 +00:00
Mathias Fredriksson 3c49290dd7 feat(scaletest/templates): add comment parameter (#10285) 2023-10-16 13:28:23 +00:00
Cian Johnston 6875faf238 fix(coderd/provisionerdserver): pass through api ctx to provisionerdserver (#10259)
Passes through coderd API ctx to provisionerd server so we can cancel workspace updates when API is shutting down.
2023-10-16 13:50:07 +01:00
Bruno Quaresma 01792f064e fix(site): display empty component when workspace has no parameters (#10286) 2023-10-16 09:49:53 -03:00
Bruno Quaresma f64b9cab90 feat(site): decrease the number of statuses in the workspaces filter (#10283) 2023-10-16 12:46:06 +00:00
Mathias Fredriksson 493e2bd2ac feat(scaletest/templates): add repo branch parameter (#10279) 2023-10-16 12:25:32 +00:00
Cian Johnston dd86100f33 fix(scaletest): fix flake in Test_Runner/Cleanup (#10252)
* fix(scaletest/createworkspaces): address flake in Test_Runner/CleanupPendingBuild

* fix(scaletest): pass io.Writer to Cleanup()

* add some extra logs to workspacebuild cleanup

* fixup! fix(scaletest): pass io.Writer to Cleanup()

* remove race

* fmt

* address PR comments
2023-10-16 12:37:12 +01:00
Cian Johnston 1be24dcb5c feat(helm/provisioner): add extraTemplates (#10256)
Adds support for extraTemplates to the coder-provisioner chart to bring it in line with the coder chart.
2023-10-16 12:17:05 +01:00
Stephen Kirby 2029543eba chore(site): clarify autostop description (#10260)
* updated autostop description based on customer request

* edited for specificity

* make fmt
2023-10-13 12:24:37 -05:00
Steven Masley 39c0539d42 feat: add controls to template for determining startup days (#10226)
* feat: template controls which days can autostart
* Add unit test to test blocking autostart with DaysOfWeek
2023-10-13 11:57:18 -05:00
Ammar Bandukwala 98b6c8bcb0 chore(coderd): report full license in telemetry (#10258)
Will aid in cross-referencing deployments to sales accounts.
2023-10-13 11:43:06 -05:00
Kayla Washburn cbc0c39792 fix: display health alert in DeploymentBannerView (#10193) 2023-10-13 10:39:20 -06:00
Muhammad Atif Ali def980b973 chore(docs): fix syntax highlighting (#10247)
Due to some reason, our docs are not rendering syntax highlighting when the code block type is 'terraform'. Changing the type to `hcl` fixes this.
2023-10-13 18:50:24 +03:00
Mathias Fredriksson 76c65b1e1b fix(agent): send metadata in batches (#10225)
Fixes #9782

---

I recommend reviewing with ignore whitespace.
2023-10-13 17:48:25 +03:00
Mathias Fredriksson 4857d4bd55 feat(codersdk/agentsdk): use new agent metadata batch endpoint (#10224)
Part of #9782
2023-10-13 17:32:28 +03:00
Mathias Fredriksson 7eeba15d16 feat(coderd): add support for sending batched agent metadata (#10223)
Part of #9782
2023-10-13 16:37:55 +03:00
dependabot[bot] 1b1ab97c24 chore: bump github.com/google/go-cmp from 0.5.9 to 0.6.0 (#10248)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-10-13 13:27:22 +00:00
dependabot[bot] 13036dd088 chore: bump google.golang.org/api from 0.145.0 to 0.147.0 (#10249)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-10-13 16:17:35 +03:00
dependabot[bot] ab7dd24d97 ci: bump the github-actions group with 2 updates (#10250)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-10-13 16:17:21 +03:00
Cian Johnston d56f49f619 fix(coderd): make activitybump aware of default template ttl (#10253)
The refactored ActivityBump query did not take into account the
template-level TTL, resulting in potentially incorrect bump
amounts for workspaces that have both a user-defined and template-
defined TTL that differ.

This change is ported over from PR#10035 to reduce the overall
size of that PR.

Also includes a drive-by unit test in autobuild for checking template autostop/TTL.

Co-authored-by: Dean Sheather <dean@deansheather.com>
2023-10-13 13:53:02 +01:00
Marcin Tojek 2a4ac2a53c feat: expose user seat limits as Prometheus metrics (#10169) 2023-10-13 08:10:16 +00:00
Eric Paulsen 570f963aea clarify external auth regex (#10243)
* docs: clarify external auth regex

* cleanup
2023-10-13 04:27:12 +00:00
Kayla Washburn 5fc9ff29d1 docs: mention /icons in the template documentation (#10230)
Co-authored-by: Muhammad Atif Ali <atif@coder.com>
2023-10-12 15:32:23 -06:00
Steven Masley 88605b9d01 chore: add display name to member role (#10239)
* chore: add display name to member role
* Do not let member role be assignable
* Ignore org member role for assignability atm
2023-10-12 10:52:32 -05:00
Cian Johnston e5198a25a6 feat(scaletest): annotate scaletest pod when scaletest is in progress (#10235)
This PR modifies the scaletest-runner template to add a pod annotation to the scaletest runner pod.

The annotation key is set to com.coder.scaletest.phase and the annotation value is one of preparing, running, or complete.

This will allow checking if a scaletest is in progress, and preventing any operations that would interrupt a running scaletest.

Co-authored-by: Mathias Fredriksson <mafredri@gmail.com>
2023-10-12 14:36:15 +01:00
Mathias Fredriksson 782c22a293 test(coderd/database/dbtestutil): allow access to *sql.DB (#10238) 2023-10-12 15:07:16 +03:00
Mathias Fredriksson 7df40b85f2 chore(coderd/coderdtest): use testing.TB for use in benchmarks (#10237) 2023-10-12 15:03:16 +03:00
Cian Johnston 1e75762cb4 fix(cli): scaletest: create-worksapces: remove invalid character for kubernetes provider in implicit plan (#10228) 2023-10-12 09:21:40 +01:00
Muhammad Atif Ali 3adf86b608 chore(dogfood): use coder_extrenal_auth over deprecated coder_git_auth (#10208)
@kylecarbs does this need any changes on the Coder server?
For example adopting to the new `CODER_EXTERNAL_AUTH_X` variables?
2023-10-12 10:30:00 +03:00
dependabot[bot] 5f0457f160 chore: bump golang.org/x/net from 0.16.0 to 0.17.0 (#10232)
Bumps [golang.org/x/net](https://github.com/golang/net) from 0.16.0 to 0.17.0.
- [Commits](https://github.com/golang/net/compare/v0.16.0...v0.17.0)

---
updated-dependencies:
- dependency-name: golang.org/x/net
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-10-11 21:43:59 -05:00
Michael Smith 9bf3b35bbf fix: update create workspace button to recognize template names+display names (#10233)
* fix: only used 'unnamed' as a last resort for templates

* fix: update filter logic to read from name field
2023-10-12 00:23:45 +00:00
Kayla Washburn 6ef1beec13 chore: recrop some icons for more consistent sizing (#10229) 2023-10-11 15:59:47 -06:00
Asher a9077812e2 fix: use UTF-8 encoding with screen (#10190)
This will make characters like ❯ and ⇣ work, for example.
2023-10-11 13:25:04 -08:00
Asher a67a5a8105 Prevent terminal being created twice (#10200)
I missed this in code review.
2023-10-11 12:47:32 -08:00
Bruno Quaresma 301c045aad chore(site): remove create workspace xservice (#10217)
* Move xstate transitions to provider

* Centrlize auth logic in the provider

* Remove actor

* Remove auth xservice

* Add loader while AuthProvider is loading

* Simplify and fix a few computed states

* Add a few replaces

* Fix logout

* Remove unused import

* Fix RequireAuth test

* Fix wait loader

* Fix tests

* Remove unecessary type

* Rename workspace queries module

* Remove auto create from workspace xservice

* Move external auth into its own hook

* Remove permissions fetching from templateByName query

* Remove form load from service

* Remove create workspace service entirely

* refactor: update workspace automation to use useEffectEvent

---------

Co-authored-by: Parkreiner <michaelsmith@coder.com>
Co-authored-by: Michael Smith <throwawayclover@gmail.com>
2023-10-11 20:42:25 +00:00
Bruno Quaresma 5be4b12378 chore(site): refactor AuthProvider to not use authXService (#10184)
* Move xstate transitions to provider

* Centrlize auth logic in the provider

* Remove actor

* Remove auth xservice

* Add loader while AuthProvider is loading

* Simplify and fix a few computed states

* Add a few replaces

* Fix logout

* Remove unused import

* Fix RequireAuth test

* Fix wait loader

* Fix tests

* Wrap signout with callback
2023-10-11 16:13:32 -04:00
Kira Pilot 7c6687813d fix(site): ensure empty string error shows default message (#10196)
* fix(site): ensure empty string error shows default message

* added test

* added logging

* asserting axios message

* cleanup and add test
2023-10-11 13:54:58 -04:00
Cian Johnston 59ae69b7f2 chore(enterprise/cli): fix test flake in TestServerDBCrypt (#10222)
* increase randomness in names generated by server dbcrypt

* more randomness

* close PTYs when we are done with them
2023-10-11 17:38:20 +01:00
Ben Potter 04e67836a5 docs: add v2.3.0 changelog (#10221)
* docs: add v2.3.0 changelog

* mention archive version
2023-10-11 11:05:53 -05:00
Cian Johnston 98a076fb46 chore(pty/ptytest): add sync.Once to close (#10220) 2023-10-11 16:47:02 +01:00
Steven Masley ac623b4717 feat: implement basic archive ui to make archiving failed versions easy (#10182)
* feat: implement basic archive ui to make archiving failed versions easy.
2023-10-11 15:06:10 +00:00
Steven Masley 1e950fa9a8 feat: archive template versions to hide them from the ui (#10179)
* api + cli implementation
2023-10-11 09:26:22 -05:00
Bruno Quaresma edbd51955c chore(site): fix inconsistent fetching results on tests (#10215) 2023-10-11 11:17:56 -03:00
Colin Adler 43fa4349d6 chore: move single_tailnet experiment to * (#10188) 2023-10-11 08:50:45 -05:00
Mathias Fredriksson a2cd6640f3 fix(codersdk/agentsdk): improve ctx cancel in agent logs flush, fix test (#10214)
Fixes #9719
Related #9865
2023-10-11 12:42:30 +00:00
Marcin Tojek a1ee4d44aa fix: test: TestSSH_RemoteForward wait for startup script (#10211) 2023-10-11 14:17:04 +02:00
Cian Johnston e829cbf2db fix(scaletest/dashboard): fix early exit due to validate (#10212) 2023-10-11 11:51:06 +00:00
Cian Johnston ed8092c83d fix(scaletest/createworkspaces): address race condition between agent closer and cleanup (#10210) 2023-10-11 12:10:51 +01:00
Cian Johnston b3471bd23a fix(scaletest/dashboard): increase viewport size and handle deadlines (#10197)
- Set viewport size to avoid responsive mode
- Added way more debug logging
- Added facility to write a screenshot on error in verbose mode.
- Added a deadline for each iteraction of clicking on and waiting for a thing.
2023-10-11 11:10:08 +01:00
Cian Johnston dc117051e6 chore(docs): update admin/scale.md (#10168) 2023-10-11 09:40:43 +01:00
Muhammad Atif Ali fafecbd9b3 fix(dogfood): fix slackme module source (#10207)
This was pinned to the branch ref and is no more needed after the branch has been merged.
2023-10-11 08:29:25 +00:00
Spike Curtis 3c43216e99 fix: remove Parallel() call after timeout context (#10203)
Fixes test flake seen here: https://github.com/coder/coder/runs/17562370632

It's inherently flaky to create a context with a timeout and then later call `t.Parallel()` since it causes the test to wait until all non-parallel tests have completed before resuming execution.  By the time execution has resumed, the context may 
have expired.  The amount of time before resuming is dependent on machine resources and number of test cases, which are inherently variable.
2023-10-11 11:39:15 +04:00
Jon Ayers 4452a1484d fix: fix log spam related to skipping custom nice scores (#10206) 2023-10-11 02:32:50 -05:00
Spike Curtis 7c71053eab fix: stop leaking User into API handlers unless authorized
Fixes an issue where we extracted the `{user}` parameter from the URL and added it to the API Handler context regardless of whether the caller had permission to read the User.
2023-10-11 09:41:14 +04:00
Spike Curtis fbabb43cbb fix: ignore spurious node updates while waiting for errors (#10175)
fixes #9921
2023-10-11 09:22:20 +04:00
Kyle Carberry b0d2828f9e fix: append external auth env vars (#10201) 2023-10-11 05:17:08 +00:00
Jon Ayers ec9b480ac0 fix: use is-dormant instead of dormant_at (#10191) 2023-10-10 19:00:09 -05:00
Kyle Carberry 652e1a7d43 feat: add slackme module to dogfood (#10198) 2023-10-10 22:46:47 +00:00
Dean Sheather e7d9b8d858 feat: allow prefixes at the beginning of subdomain app hostnames (#10150) 2023-10-10 20:02:39 +00:00
Dean Sheather f48bc33e00 chore: remove cron schedule from quiet hours schedule page (#10187) 2023-10-10 19:55:28 +00:00
Jon Ayers 91555c3a85 feat: support configurable web terminal rendering (#10095)
* feat: support configurable web terminal rendering

- Added a deployment option for configuring web terminal rendering.
  Valid values are 'webgl', 'canvas', and 'dom'.
2023-10-10 13:18:02 -05:00
Jon Ayers 05a393cd06 feat: only display license warnings to privileged users (#10096) 2023-10-10 12:48:51 -05:00
Colin Adler 7e6b549170 chore: upgrade Terraform to 1.5.7 (#10186) 2023-10-10 12:46:59 -05:00
Colin Adler 21e0d540dc chore: upgrade Go to 1.20.10
https://groups.google.com/g/golang-announce/c/iNNxDTCjZvo/m/UDd7VKQuAAAJ?utm_medium=email&utm_source=footer
2023-10-10 12:23:54 -05:00
Kayla Washburn 7ea58eac18 chore: use emotion for styling (pt. 4) (#10149) 2023-10-10 10:46:45 -06:00
Colin Adler 00589d6422 chore: fix lint failures 2023-10-10 11:26:53 -05:00
Steven Masley 69d13f1676 chore: add archive column to template versions (#10178)
* chore: add archive column to template versions
2023-10-10 10:52:42 -05:00
Colin Adler c11f241622 feat: add --version flag to coder templates pull, default to active version (#10153)
Fixes https://github.com/coder/coder/issues/9837
2023-10-10 10:20:31 -05:00
Cian Johnston 2506415def chore(scaletest/templates/scaletest-runner): fix dashboard command invocation, autoscale provisioners (#10177)
add --retries on kubectl cp
remove --count parameter to scaletest dashboard
scale provisioners up and down

Co-authored-by: Mathias Fredriksson <mafredri@gmail.com>
2023-10-10 15:33:55 +01:00
Spike Curtis db8592fa93 chore: refactor workspace conversion to accept ownerName (#10171)
Refactors workspace conversion to accept the ownerName, rather than a slice of users, since all it does is search the slice for the owner and use the username.

This is in preparation for a fix to `postWorkspacesByOrganization()` that will remove the need to pass the user object.

Also avoids panicing if the required user is not in the slice, since `findUser` could return nil in the old code, which would then get dereferenced for the username.
2023-10-10 16:55:28 +04:00
Bruno Quaresma 19400d6794 fix(site): fix week range for insights (#10173) 2023-10-10 09:33:46 -03:00
Spike Curtis b780bff429 chore: drop unused redirectToLoginOnMe parameter (#10164)
The parameter seems to be vestigial from an earlier use of the middleware, but is always set to `false` in the code.
2023-10-10 16:13:00 +04:00
Michael Smith 5ae6cda89f feat: add warning message when trying to delete active template (#10142)
* refactor: clean up TemplatePageHeader

* chore: add react query configs for workspace lists

* feat: add delete-intercept functionality

* refactor: improve readability

* refactor: rename entities for readability/accuracy

* refactor: clean up variable names again

* refactor: remove redudant function calls

* fix: update logic check for safe deletions

* fix: update workspaces query logic

* fix: update call site for workspaces key
2023-10-10 08:04:54 -04:00
Spike Curtis 78b9201b31 chore: move AsSystemRestricted to caller (#10163)
Moves escalation to SystemRestricted out of the function that queries the database for the User. This is in prepartion for a refactor such that we don't need SystemRestricted in `ExtractUserParam` middleware.
2023-10-10 15:57:51 +04:00
Spike Curtis 8a47262faf fix: ignore logged errors in TestWorkspaceAgent/Timeout
fixes #10167

Annoyingly, there isn't a good way to stop the publish from being sent on shutdown, and subscribing to them in the test is too fragile because empty messages are sent in a bunch of places, so we can't reliably tell it's regarding timeouts.
2023-10-10 15:45:47 +04:00
Spike Curtis a0485c00ac chore: refactor ExtractUserParam to call function
Refactors `ExtractUserParam` to separate the part that actually obtains the user from the database and the part that sets it on the middleware context.  This is in preparation for further refactor that removes `ExtractUserParam` middleware from 
`organizations/{organization}/members/{user}` paths.
2023-10-10 15:00:53 +04:00
Cian Johnston c83af5e627 chore(cli): add linter to detect potential spurious usage of owner user in cli tests (#10133)
* Detects the following pattern where the CLI is initialized with a client authenticated as the "first user":

    client := coderdtest.New(t, ...)
    [...]
    user := coderdtest.CreateFirstUser(t, client)
    [...]
    clitest.SetupConfig(t, client, root)

* Updates documentation regarding role permissions on workspaces.
2023-10-10 11:14:20 +01:00
dependabot[bot] 017d7e9dad chore: bump github.com/prometheus/client_model to 0.5.0 (#10129)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-10-10 12:33:32 +03:00
Spike Curtis 211718f95a fix: fix MaliciousTar test case (#10158)
fixes #9895

Problem was that provisionerd tries to acquire the next job, and races with shutdown, triggering the assert in the handler.  Switches this test case to use the more robust handler.
2023-10-10 13:24:43 +04:00
Marcin Tojek f36fba2486 fix: revert: use CRC32 to shorten app subdomain
This reverts commit 0e28397c82.
2023-10-10 18:12:46 +10:00
Spike Curtis b039dc6989 fix: correct escaping in test regex (#10138)
Fixes regex escaping.  Spotted during a code read.
2023-10-10 08:42:39 +04:00
Kyle Carberry 9c098b218f feat: allow external auth providers to expose extra metadata (#10157) 2023-10-09 23:02:16 -05:00
Kyle Carberry 3eb9a43190 fix: use query to get external-auth by id (#10156) 2023-10-09 22:25:50 -05:00
Kyle Carberry a61f8ee45c fix: apply default ExtraTokenKeys to oauth (#10155) 2023-10-09 22:11:05 -05:00
Kyle Carberry 863c2e7b64 feat: allow storing extra oauth token properties in the database (#10152) 2023-10-09 18:49:30 -05:00
Kyle Carberry 35538e1051 feat: add external-auth cli (#10052)
* feat: add `external-auth` cli

* Add subcommands

* Improve descriptions

* Add external-auth subcommand

* Fix docs

* Fix gen

* Fix comment

* Fix golden file
2023-10-09 23:04:35 +00:00
Colin Adler 20438ae6c2 chore: run go mod tidy 2023-10-09 15:10:46 -05:00
Kayla Washburn 42fb6cab12 chore: add icons for popular programming languages (#10141) 2023-10-09 13:52:06 -06:00
dependabot[bot] cb3b617ee9 ci: bump the github-actions group with 2 updates (#10131)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-10-09 22:39:40 +03:00
dependabot[bot] af63909134 chore: bump google.golang.org/api from 0.143.0 to 0.145.0 (#10130)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-10-09 22:39:29 +03:00
dependabot[bot] 583d44e60e chore: bump the golang-x group with 6 updates (#10128)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-10-09 22:39:13 +03:00
Kayla Washburn 1cdc62b332 chore: reorganize storybook (#10144) 2023-10-09 13:26:38 -06:00
Kyle Carberry 54648b90ca fix: properly trim spaces so multi-line shebang executes (#10146) 2023-10-09 19:19:57 +00:00
Colin Adler 3bbfcc593e feat: add request_id to HTTP trace spans (#10145) 2023-10-09 14:05:10 -05:00
Muhammad Atif Ali 2881b8b252 chore: add vault icon (#10125) 2023-10-09 18:25:07 +00:00
Spike Curtis b9c7bc4d3c fix: check for nil pointer in AwaitWorkspaceAgents
CompletedAt is a pointer and can be nil, need to check before calling IsZero() on it

c.f. https://github.com/coder/coder/runs/17534657301
2023-10-09 22:12:28 +04:00
Bruno Quaresma 584a2e87c9 chore(site): remove create template xservice (#10112) 2023-10-09 14:10:48 -03:00
Spike Curtis 54fd350913 feat: improve logging for speedtest connections
part of #7963

improve connection logging for speedtest connections
2023-10-09 20:48:28 +04:00
Colin Adler 9e622d00a6 feat(cli): add coder users delete command (#10115) 2023-10-09 11:47:57 -05:00
Spike Curtis 24c80bf532 fix: remove AwaitWorkspaceAgents in goroutines
AwaitWorkspaceAgent calls testify.require which isn't allowed from a goroutine and causes cascading failures in the test suite such as: https://github.com/coder/coder/actions/runs/6458768855/job/17533163316

I don't believe these functions serve a direct purpose since nothing else is "waiting" for the functions to return before doing other things.
2023-10-09 20:37:23 +04:00
Spike Curtis 17e889af16 feat: improve logging for reconnectingPTY connections
part of #7963

improves connection logging on reconnectingPTY
2023-10-09 20:35:50 +04:00
Kyle Carberry b402f2a816 feat: add shebang support to scripts (#10134)
This enables much greater portability!
2023-10-09 10:57:57 -05:00
Kayla Washburn 17869ecb74 feat: select icons from emoji picker (#10119) 2023-10-09 09:50:24 -06:00
Kayla Washburn bda68b143a feat: add /icons page (#10093) 2023-10-09 09:49:26 -06:00
Spike Curtis 236e84c4d6 feat: add logging for forwarded TCP connections
part of #7963

log TCP connections as they are forwarded by gVisor
2023-10-09 19:41:26 +04:00
Kira Pilot 791144ddfd feat(site): disable rich parameters when using open in coder (#10114)
* feat(site): disable rich parameters when using open in coder

* updated docs

* chore(site): increase refetch interval for deployment health

* Revert "chore(site): increase refetch interval for deployment health"

This reverts commit 8e642be3fb.
2023-10-09 09:47:22 -04:00
Cian Johnston 5673aca408 feat(cli): add --parameter flag to exp scaletest command (#10132) 2023-10-09 14:08:24 +01:00
Marcin Tojek c6cf719f6c feat: show user limit on active users chart (#10101) 2023-10-09 13:38:41 +02:00
Michael Smith 38bb854c8b fix: update ErrorDialog logic and tests (#10111)
* fix: make error text less naggy

* fix: make input colors sync with confirmation text state

* fix: more color sync fixes

* fix: remove flaky warning messages in test

* fix: remove needless braces

* refactor: clean up code

* refactor: clean up code more
2023-10-06 19:40:37 -04:00
Kayla Washburn ae113179b3 chore: alias react-query (#10118) 2023-10-06 17:15:03 -06:00
Kira Pilot da47ac87db chore(site): increase refetch interval for deployment health (#10117) 2023-10-06 16:26:46 -04:00
Colin Adler 19dbf19177 fix(coder): properly check for missing organization membership
Fixes a possible panic introduced in https://github.com/coder/coder/pull/9781.
2023-10-06 14:57:21 -05:00
Kayla Washburn 71ad5909f2 chore: add icons.json file (#10085) 2023-10-06 13:46:37 -06:00
Colin Adler 36f3151b71 fix(enterprise/tailnet): properly detect legacy agents (#10083) 2023-10-06 16:49:26 +00:00
Colin Adler 03a7d2f70b chore: fix servertailnet test flake (#10110)
https://github.com/coder/coder/actions/runs/6424100765/job/17444018788?pr=10083#step:5:771
2023-10-06 11:31:53 -05:00
Kyle Carberry 2d2bea79a7 fix: convert the new dashboard theme to be an experiment (#10108) 2023-10-06 09:46:52 -05:00
Kyle Carberry 69b65693c9 fix: make the dark mode a bit less dark (#10107)
We got feedback from our Discord that it was a bit too dark,
so this brightens it up a little!
2023-10-06 14:09:21 +00:00
Kyle Carberry 23425d36a1 fix: invert the favicon on dark mode (#10097) 2023-10-06 07:55:11 -05:00
Spike Curtis 983e8c3ae8 feat: add API support for workspace automatic updates (#10099)
* Added automatic_updates to workspaces table

Signed-off-by: Spike Curtis <spike@coder.com>

* Queries and API updates

Signed-off-by: Spike Curtis <spike@coder.com>

* Golden files

Signed-off-by: Spike Curtis <spike@coder.com>

* Enable automatic updates on autostart

Signed-off-by: Spike Curtis <spike@coder.com>

* db migration number

Signed-off-by: Spike Curtis <spike@coder.com>

* fix imports and ts mock

Signed-off-by: Spike Curtis <spike@coder.com>

* code review updates

Signed-off-by: Spike Curtis <spike@coder.com>

---------

Signed-off-by: Spike Curtis <spike@coder.com>
2023-10-06 13:27:12 +04:00
Kyle Carberry d24d2d2c8d fix: use proper react hook for favicon theme (#10094)
I was using `useState` before, which didn't re-render on load.
2023-10-05 18:23:56 -05:00
Bruno Quaresma 127f65c98b fix(site): fix logo width on sign in (#10091) 2023-10-05 17:44:53 -05:00
Kyle Carberry 4ad080c3b9 fix: apply the same border for button groups (#10092) 2023-10-05 17:44:45 -05:00
Kyle Carberry 14c8824c83 fix: use proper state in system theme (#10090) 2023-10-05 17:32:52 -05:00
Kyle Carberry fa0a597530 fix: add build status favicons based on system theme (#10089) 2023-10-05 22:23:11 +00:00
Kyle Carberry f270d9d351 feat: make the dashboard darker (#10084)
* feat: make the dashboard darker

Coder is a the internal software development platform. It is not
designed to be opinionated on colors, but it should look great.

Focusing on neutrality for our default dashboard theme is great
for our ICP. Some organizations may lean towards colors more or
less, and that shouldn't influence their decision when exploring
Coder.

* Make it a lil more dark

* Improve button outline

* Lower the red brightness

* Improve the divider contrast
2023-10-05 16:46:38 -05:00
Bruno Quaresma 04e7748a9b feat(site): load previous builds (#10076) 2023-10-05 18:30:11 -03:00
Kyle Carberry 1eb21d247b feat: adjust favicon based on system color-scheme (#10087)
This will still default to light-theme, but support showing
a white favicon when the system-theme is dark.
2023-10-05 16:11:15 -05:00
Bruno Quaresma a5f8300c76 refactor(site): do not block the screen when disconnected (#10057)
Close https://github.com/coder/coder/issues/9858

Demo:
https://github.com/coder/coder/assets/3165839/d6d4d2d7-487a-4739-86c9-042242d9820f
2023-10-05 18:06:26 -03:00
Michael Smith 2d6c4fe90a feat(site): add WorkspacesButton component (#10011)
* chore: Add OverflowY component

* chore: Add PopoverContainer component

* chore: Add SearchBox

* feat: add WorkspacesButton

* chore: Install MUI utils package

* chore: integrate WorkspacesButton

* chore: reorganize files

* fix: resolve hover state visual glitch

* chore: Add story for OverflowY

* fix: remove dynamic name from OverflowY story

* chore: update stories again

* fix: remove all references to icons (for now)

* refactor: move flex shrink to be OverflowY concern

* fix: remove needless render key

* fix: make sure popover closes before navigation

* refactor: clean up WorkspacesButton to use more native MUI

* fix: update integration into rest of view

* fix: remove JS security concern

* refactor: parameterize button language

* revert: undo sql/go file change

* fix: remove permissions dependency

* fix: simplify button prop types

* fix: lift data dependencies to page component

* refactor: clean up props

* fix: update dependencies again for Storybook
2023-10-05 20:46:42 +00:00
Kyle Carberry ad47ef17e8 feat: allow reading the agent token from a file (#10080)
Adds `CODER_AGENT_TOKEN_FILE` which will read the agent token from
a file if `CODER_AGENT_TOKEN` is not provided. Using a Kubernetes
Secret with a volume-mounted file is a more secure way to provide
the agent token instead of an environment variable.
2023-10-05 15:41:05 -05:00
Jon Ayers eb4826a11f chore: remove workspace_actions experiment (#10030) 2023-10-05 14:18:35 -05:00
Kayla Washburn 3c87c4df1b feat: show descriptions for parameter options (#10068) 2023-10-05 13:14:28 -06:00
Jon Ayers b32d79ef0b fix: fix failed workspaces continuously auto-deleting (#10069)
- Fixes an issue where workspaces that are eligible for auto-deletion
  are retried every tick (1 minute) even if the previous deletion
  transition failed.

  The updated logic only attempts to delete workspaces that previously
  failed once a day (24 hours since last attempt).
2023-10-05 14:11:39 -05:00
Jon Ayers 91265678ad chore: add auditing to workspace dormancy (#10070)
- Adds an audit log for workspaces automatically transitioned to the dormant
  state.
- Imposes a mininum of 1 minute on cleanup-related fields. This is to
  prevent accidental API misuse from resulting in catastrophe.
2023-10-05 13:41:07 -05:00
Kyle Carberry 888b97fd86 chore: use JobStatus computed from the db (#10079)
Fixes `main`
2023-10-05 18:25:06 +00:00
Kayla Washburn 246dae0e1a chore: use emotion for styling (pt. 3) (#10026) 2023-10-05 10:49:44 -06:00
Kayla Washburn f001a57614 fix: only allow promoting successful template versions (#9998) 2023-10-05 10:49:25 -06:00
Mathias Fredriksson 48ee80a559 fix(cli): prevent sqlDB leaks in ConnectToPostgres (#10072) 2023-10-05 17:57:48 +03:00
Mathias Fredriksson 5d5a7da67f fix(scaletest): output error and trace instead of {} for json output (#10075) 2023-10-05 13:31:54 +00:00
Marcin Tojek ab9276bd08 feat: modify workspace_agent_stats index (#10073) 2023-10-05 14:49:08 +02:00
Colin Adler 30440915bc chore: add mod replace wireguard-go to fix race condition (#10071)
Fixes https://github.com/coder/coder/issues/10045
2023-10-04 23:47:01 -05:00
Steven Masley 5021e23105 chore: compute job status as column (#10024)
* chore: provisioner job status as column
* use provisioner job status for workspace searching
2023-10-04 20:57:46 -05:00
Colin Adler d5040441aa fix(site): change utils/delay import path (#10065) 2023-10-04 17:15:20 -05:00
Kyle Carberry df8e10cc4c chore: increase ForceCancelInterval for test flakes (#10066)
See https://github.com/coder/coder/actions/runs/6411239320/job/17406394658
2023-10-04 21:16:39 +00:00
Kyle Carberry bca7416069 fix: add --version flag to the root to support migrating customers (#10063) 2023-10-04 15:37:15 -05:00
Jon Ayers 1cd4405caf fix: change alpha badge color to violet (#10029)
- Makes it less scary.
2023-10-04 15:20:13 -05:00
Bruno Quaresma 03c377b754 fix(site): fix users page for template admins (#10060)
Fix https://github.com/coder/coder/issues/10053
2023-10-04 17:05:49 -03:00
Bruno Quaresma a8ed88b22e fix(site): fix chart label depending on interval (#10059)
Close https://github.com/coder/coder/issues/10056
2023-10-04 17:05:29 -03:00
Eric Paulsen 1076d16456 docs: update offline tf provider config (#10062) 2023-10-04 15:40:09 -04:00
Kyle Carberry fd06b7f7a0 fix: allow all environment variables to fallback prefix to HOMEBREW_ (#10050)
See the customer use-case in the code docs.
2023-10-04 18:57:49 +00:00
Kyle Carberry 252ec14556 fix: update the validation url for github enterprise (#10061)
This was wrong... not sure why.
2023-10-04 18:49:40 +00:00
Kyle Carberry 7f9b4ad9a8 fix: allow auditors to query deployment stats and insights (#10058)
This is a customer request.
2023-10-04 18:37:25 +00:00
Bruno Quaresma 516b88dc25 fix(site): disable auto fields when they are disabled in the template settings (#10022)
- Disable form inputs 
- Add disable badge + tooltip with more info

<img width="1679" alt="Screen Shot 2023-10-03 at 14 20 26" src="https://github.com/coder/coder/assets/3165839/7555eb77-19d9-4a13-965e-6d40c3b852dd">

Fix https://github.com/coder/coder/issues/9820
2023-10-04 15:00:09 -03:00
Ben Potter 46551e619d docs: add v2.2.1 changelog (#10055)
* fix external auth link

* chore v2.2.1 changelog
2023-10-04 17:02:14 +00:00
Kyle Carberry 64692f0b69 chore: update docs for external-auth (#10046) 2023-10-04 11:38:41 -05:00
Kyle Carberry defef4671c fix: silence bash deprecation warning on macOS runners (#10051)
See https://github.com/coder/coder/actions/runs/6407839577/job/17395535790?pr=10050
2023-10-04 15:36:27 +00:00
Cian Johnston 2c2e98cc39 fix(coderd): fetch workspace agent scripts and log sources using system auth ctx (#10043)
* add failing unit test
* fetch log sources and agent scripts using system auth ctx
2023-10-04 15:50:51 +01:00
Kyle Carberry 8e44dce5b3 chore: fix external-auth.mp4 docs video (#10048) 2023-10-04 14:39:13 +00:00
Bruno Quaresma 6651aff57b feat(site): add user activity on template insights (#10013)
Close https://github.com/coder/coder/issues/9497


https://github.com/coder/coder/assets/3165839/941e268c-6c06-47ae-b57d-665e01e804b0
2023-10-04 11:37:47 -03:00
Kyle Carberry b468415a81 chore: revert docs for git-auth until release (#10044) 2023-10-04 14:33:28 +00:00
Bruno Quaresma 5e0cb372b4 fix(site): fix orphan values on insights (#10036) 2023-10-04 10:16:59 -03:00
Cian Johnston 2405bbe1b9 fix(coderd/database/dbtestutil): fix typo in pgDump (#10033) 2023-10-04 13:21:45 +01:00
Michael Smith c7218b40c9 docs: update frontend contribution docs (#10028)
* docs: update frontend contribution docs

* fix: update docs formatting
2023-10-04 08:11:07 -04:00
Colin Adler 4ab52766d2 feat: add --net-admin option to install script (#9953) 2023-10-03 23:01:46 +00:00
Colin Adler 39846d69d3 feat: modify agent install script to give CAP_NET_ADMIN if available (#9908) 2023-10-03 17:34:29 -05:00
timquinlan 2a19b46ab7 update to gateway offline install docs, 2 typos, 2 command additions (#10027) 2023-10-03 17:58:26 -04:00
dependabot[bot] 6322e13046 chore: bump postcss from 8.4.27 to 8.4.31 in /site (#10019)
Bumps [postcss](https://github.com/postcss/postcss) from 8.4.27 to 8.4.31.
- [Release notes](https://github.com/postcss/postcss/releases)
- [Changelog](https://github.com/postcss/postcss/blob/main/CHANGELOG.md)
- [Commits](https://github.com/postcss/postcss/compare/8.4.27...8.4.31)

---
updated-dependencies:
- dependency-name: postcss
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-10-04 00:28:54 +03:00
Bruno Quaresma efdbb6f9e6 fix(site): remove 48 week option (#10025) 2023-10-03 18:25:03 -03:00
Kayla Washburn e6aeee2ba2 feat: warn users when renaming workspaces (#10023) 2023-10-03 15:04:34 -06:00
dependabot[bot] 4df5c1ddec chore: bump the alpine image from 3.18.3 to 3.18.4 in Dockerfile.base (#9993)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-10-03 14:09:50 -05:00
Bruno Quaresma bdb9954f87 feat(site): add support for weekly data on template insights (#9997)
Close https://github.com/coder/coder/issues/9495
2023-10-03 15:14:11 -03:00
Bruno Quaresma e7042e601c fix(site): fix navbar hover (#10021) 2023-10-03 14:10:51 -03:00
Kayla Washburn c194119689 chore: rename AwaitTemplateVersionJobCompleted and AwaitWorkspaceBuildJobCompleted (#10003) 2023-10-03 11:02:56 -06:00
Kayla Washburn 4b97ac269b chore: refactor Pill styles (#10004) 2023-10-03 10:47:28 -06:00
Kyle Carberry 5e3bf275da chore: check for valid regex in git auth configs (#10020) 2023-10-03 16:45:07 +00:00
Ammar Bandukwala 70a4e56c01 ci: switch to M1 runners
ci: switch to M1 runners
    
 Per
    https://github.blog/2023-10-02-introducing-the-new-apple-silicon-powered-m1-macos-larger-runner-for-github-actions/,
    we should see large performance improvements.
2023-10-03 10:54:20 -05:00
Kyle Carberry f16eb1331f chore: update multiple git providers docs (#10017)
* chore: update multiple git providers docs

* Improve var name

* Fix fmt
2023-10-03 15:27:02 +00:00
Kyle Carberry eeab33b1c3 fix: do not require client_secret for external auth providers (#10016)
Device-based auth does not need a client secret.
2023-10-03 14:29:34 +00:00
Cian Johnston 9aac15212b fix(cli): remove exp scaletest from slim binary (#9934)
- Removes the `exp scaletest` command from the slim binary 
- Updates scaletest-runner template to fetch the full binary from the running Coder instance
2023-10-03 15:13:04 +01:00
Kyle Carberry 45b53c285f feat: allow external services to be authable (#9996)
* feat: allow external services to be authable

* Refactor external auth config structure for defaults

* Add support for new config properties

* Change the name of external auth

* Move externalauth -> external-auth

* Run gen

* Fix tests

* Fix MW tests

* Fix git auth redirect

* Fix lint

* Fix name

* Allow any ID

* Fix invalid type test

* Fix e2e tests

* Fix comments

* Fix colors

* Allow accepting any type as string

* Run gen

* Fix href
2023-10-03 14:04:39 +00:00
Marcin Tojek f62f45a303 feat!: add sections parameter to template insights (#10010) 2023-10-03 15:44:50 +02:00
Marcin Tojek cb60409a8c feat: add index to workspace_agent_stats (#10009) 2023-10-03 11:13:44 +00:00
dependabot[bot] cc2772c646 chore: bump github.com/prometheus/client_golang from 1.16.0 to 1.17.0 (#9989)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-10-03 13:12:06 +03:00
Cian Johnston e55c25e037 chore: enable exhaustruct linter for database param structs (#9995) 2023-10-03 09:23:45 +01:00
Muhammad Atif Ali 352ec7bc4f chore(dogfood): rename project_directory to folder (#10008) 2023-10-03 07:11:58 +00:00
Monika Pawluczuk 4966ef02cf feat(cli): add reverse tunnelling SSH support for unix sockets (#9976) 2023-10-03 16:39:39 +10:00
Muhammad Atif Ali 465546eefd chore(dogfood): open vscode desktop in coder repo directory (#9999) 2023-10-03 08:55:25 +03:00
Eric Paulsen 3980dbd029 docs: add support to enterprise features (#10005) 2023-10-02 21:25:05 -05:00
Bruno Quaresma 9e1e365b32 chore(site): remove user search service (#9939) 2023-10-02 15:24:28 -03:00
Bruno Quaresma 42e25740eb chore(site): remove users and pagination services (#9932) 2023-10-02 15:10:51 -03:00
Kayla Washburn 885b2502ed chore: replace <ChooseOne> with alternatives when appropriate (#9907) 2023-10-02 10:51:35 -06:00
Kayla Washburn 148fa819ae chore: use emotion for styling (pt. 2) (#9951) 2023-10-02 10:48:11 -06:00
dependabot[bot] fabcc41a6b chore: bump @types/node from 18.17.0 to 18.18.1 in /offlinedocs (#9971)
Bumps [@types/node](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/node) from 18.17.0 to 18.18.1.
- [Release notes](https://github.com/DefinitelyTyped/DefinitelyTyped/releases)
- [Commits](https://github.com/DefinitelyTyped/DefinitelyTyped/commits/HEAD/types/node)

---
updated-dependencies:
- dependency-name: "@types/node"
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-10-02 10:06:59 -05:00
dependabot[bot] 6452008e32 chore: bump github.com/sqlc-dev/pqtype from 0.2.0 to 0.3.0 (#9991)
Bumps [github.com/sqlc-dev/pqtype](https://github.com/sqlc-dev/pqtype) from 0.2.0 to 0.3.0.
- [Release notes](https://github.com/sqlc-dev/pqtype/releases)
- [Commits](https://github.com/sqlc-dev/pqtype/compare/v0.2.0...v0.3.0)

---
updated-dependencies:
- dependency-name: github.com/sqlc-dev/pqtype
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-10-02 10:06:50 -05:00
dependabot[bot] f694204773 chore: bump @types/node from 18.17.0 to 18.18.1 in /site (#9967)
Bumps [@types/node](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/node) from 18.17.0 to 18.18.1.
- [Release notes](https://github.com/DefinitelyTyped/DefinitelyTyped/releases)
- [Commits](https://github.com/DefinitelyTyped/DefinitelyTyped/commits/HEAD/types/node)

---
updated-dependencies:
- dependency-name: "@types/node"
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-10-02 10:38:26 -04:00
dependabot[bot] 0a54506940 chore: bump the otel group with 3 updates (#9988)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-10-02 14:27:21 +00:00
dependabot[bot] f802fba89e chore: bump github.com/open-policy-agent/opa from 0.56.0 to 0.57.0 (#9992)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-10-02 14:15:58 +00:00
dependabot[bot] 89c2938b20 chore: bump google.golang.org/api from 0.142.0 to 0.143.0 (#9990)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-10-02 17:02:51 +03:00
dependabot[bot] 06411b8b17 ci: bump the github-actions group with 2 updates (#9994)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-10-02 17:02:41 +03:00
Marcin Tojek 57909e0c72 site(e2e): wait for empty workspaces (#9987) 2023-10-02 11:53:44 +00:00
Mathias Fredriksson 4b0565c895 feat(scaletest): add service banner status for runner (#9945) 2023-10-02 14:37:38 +03:00
Mathias Fredriksson e6d2ddb54b feat(scaletest): add apps to scaletest template (#9944) 2023-10-02 14:37:16 +03:00
Muhammad Atif Ali 1a07ee0b16 chore(site): make name bold in delete dialog
This makes the name bold in delete dialog and makes it readable.
<img width="439" alt="Screenshot 2023-09-24 at 03 30 55" src="https://github.com/coder/coder/assets/10648092/b97e634b-c7c8-4300-b78c-8091b3f2c9f0">

Edit: Tests are passed. thanks @aslilac
2023-10-02 13:57:21 +03:00
Cian Johnston 1c48610d56 feat(scaletest/dashboard): integrate chromedp (#9927)
* Adds a set of actions to automatically interact with a Coder instance using chromedp
* Integrates the chromedp actions into the scaletest dashboard command,
* Re-enables the previously disabled unit tests for scaletest/dashboard
* Removes previous dashboard actions based around codersdk
2023-10-02 10:40:17 +01:00
Muhammad Atif Ali 1906cc4806 Revert "chore: bump remark-gfm from 3.0.1 to 4.0.0 in /site (#9965)" (#9981)
This reverts commit 81a046e0a9.
2023-10-02 09:56:35 +02:00
dependabot[bot] 81a046e0a9 chore: bump remark-gfm from 3.0.1 to 4.0.0 in /site (#9965)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-10-02 10:31:56 +03:00
dependabot[bot] 247eeab3c8 chore: bump next from 13.4.12 to 13.5.3 in /offlinedocs (#9972)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-10-02 09:22:15 +03:00
dependabot[bot] 52b16f0622 chore: bump the eslint group in /site with 1 update
Bumps the eslint group in /site with 1 update: [eslint](https://github.com/eslint/eslint).

<details>
<summary>Release notes</summary>
<p><em>Sourced from <a href="https://github.com/eslint/eslint/releases">eslint's releases</a>.</em></p>
<blockquote>
<h2>v8.50.0</h2>
<h2>Features</h2>
<ul>
<li><a href="https://github.com/eslint/eslint/commit/27d5a9e57ad347982a68fcd0e75eafee42d344f0"><code>27d5a9e</code></a> feat: add suggestions to array-callback-return (<a href="https://redirect.github.com/eslint/eslint/issues/17590">#17590</a>) (Tanuj Kanti)</li>
<li><a href="https://github.com/eslint/eslint/commit/f9082ff3f3956a0a5a7d7659de63640a21c4de0f"><code>f9082ff</code></a> feat: flat-rule-tester make sure default config always matches (<a href="https://redirect.github.com/eslint/eslint/issues/17585">#17585</a>) (fnx)</li>
<li><a href="https://github.com/eslint/eslint/commit/83914adbfd5fce7d11b33d095ba6d6a39be0dbbc"><code>83914ad</code></a> feat: Implement SourceCode#applyInlineConfig() (<a href="https://redirect.github.com/eslint/eslint/issues/17351">#17351</a>) (Nicholas C. Zakas)</li>
<li><a href="https://github.com/eslint/eslint/commit/22a558228ff98f478fa308c9ecde361acc4caf20"><code>22a5582</code></a> feat: add rule <code>no-object-constructor</code>, deprecate <code>no-new-object</code> (<a href="https://redirect.github.com/eslint/eslint/issues/17576">#17576</a>) (Francesco Trotta)</li>
<li><a href="https://github.com/eslint/eslint/commit/85a3d9e967b19cb4a0189746499d81ef2f93e14e"><code>85a3d9e</code></a> feat: allowVoid option in array-callback-return (<a href="https://redirect.github.com/eslint/eslint/issues/17564">#17564</a>) (Tanuj Kanti)</li>
</ul>
<h2>Bug Fixes</h2>
<ul>
<li><a href="https://github.com/eslint/eslint/commit/cc4d26b5a59d510f2c878e973fd245e8eff27c2a"><code>cc4d26b</code></a> fix: Ensure deprecated context.parserServices warns (<a href="https://redirect.github.com/eslint/eslint/issues/17593">#17593</a>) (Nicholas C. Zakas)</li>
<li><a href="https://github.com/eslint/eslint/commit/1ea4cfb585dcb52ac3cb1522a32f25cfe507121b"><code>1ea4cfb</code></a> fix: Ensure all RuleTester tests all deprecated context methods (<a href="https://redirect.github.com/eslint/eslint/issues/17587">#17587</a>) (Nicholas C. Zakas)</li>
<li><a href="https://github.com/eslint/eslint/commit/aa1b657a9febcd03e9298c03ae2888762795e322"><code>aa1b657</code></a> fix: wrong suggestion and message in <code>no-misleading-character-class</code> (<a href="https://redirect.github.com/eslint/eslint/issues/17571">#17571</a>) (Yosuke Ota)</li>
</ul>
<h2>Documentation</h2>
<ul>
<li><a href="https://github.com/eslint/eslint/commit/180053759c6cf05a326c710353b4717fbf289ee0"><code>1800537</code></a> docs: Fix and standardize JSX code examples (<a href="https://redirect.github.com/eslint/eslint/issues/17591">#17591</a>) (Francesco Trotta)</li>
<li><a href="https://github.com/eslint/eslint/commit/48a44a73ac456739bdee348bbaf1840d2b1e4830"><code>48a44a7</code></a> docs: Add correct/incorrect tags to <code>prefer-arrow-callback</code> (<a href="https://redirect.github.com/eslint/eslint/issues/17589">#17589</a>) (Francesco Trotta)</li>
<li><a href="https://github.com/eslint/eslint/commit/20893d48b9012f2b61bbbfeac8bee70d68d90e5e"><code>20893d4</code></a> docs: fix incorrect tag's place (<a href="https://redirect.github.com/eslint/eslint/issues/17575">#17575</a>) (Tanuj Kanti)</li>
<li><a href="https://github.com/eslint/eslint/commit/bd7a71fd6b7efb0445393304e2d48c5c06d46a45"><code>bd7a71f</code></a> docs: Update README (GitHub Actions Bot)</li>
</ul>
<h2>Chores</h2>
<ul>
<li><a href="https://github.com/eslint/eslint/commit/f8a8a2d6b45c82f94a574623759b6e3d2af193f3"><code>f8a8a2d</code></a> chore: upgrade <code>@​eslint/js</code><a href="https://github.com/8"><code>@​8</code></a>.50.0 (<a href="https://redirect.github.com/eslint/eslint/issues/17599">#17599</a>) (Milos Djermanovic)</li>
<li><a href="https://github.com/eslint/eslint/commit/38ada6df8f4a0313b7d0739b28f0af6b4897b8ce"><code>38ada6d</code></a> chore: package.json update for <code>@​eslint/js</code> release (ESLint Jenkins)</li>
</ul>
</blockquote>
</details>
<details>
<summary>Changelog</summary>
<p><em>Sourced from <a href="https://github.com/eslint/eslint/blob/main/CHANGELOG.md">eslint's changelog</a>.</em></p>
<blockquote>
<p>v8.50.0 - September 22, 2023</p>
<ul>
<li><a href="https://github.com/eslint/eslint/commit/f8a8a2d6b45c82f94a574623759b6e3d2af193f3"><code>f8a8a2d</code></a> chore: upgrade <code>@​eslint/js</code><a href="https://github.com/8"><code>@​8</code></a>.50.0 (<a href="https://redirect.github.com/eslint/eslint/issues/17599">#17599</a>) (Milos Djermanovic)</li>
<li><a href="https://github.com/eslint/eslint/commit/38ada6df8f4a0313b7d0739b28f0af6b4897b8ce"><code>38ada6d</code></a> chore: package.json update for <code>@​eslint/js</code> release (ESLint Jenkins)</li>
<li><a href="https://github.com/eslint/eslint/commit/27d5a9e57ad347982a68fcd0e75eafee42d344f0"><code>27d5a9e</code></a> feat: add suggestions to array-callback-return (<a href="https://redirect.github.com/eslint/eslint/issues/17590">#17590</a>) (Tanuj Kanti)</li>
<li><a href="https://github.com/eslint/eslint/commit/f9082ff3f3956a0a5a7d7659de63640a21c4de0f"><code>f9082ff</code></a> feat: flat-rule-tester make sure default config always matches (<a href="https://redirect.github.com/eslint/eslint/issues/17585">#17585</a>) (fnx)</li>
<li><a href="https://github.com/eslint/eslint/commit/83914adbfd5fce7d11b33d095ba6d6a39be0dbbc"><code>83914ad</code></a> feat: Implement SourceCode#applyInlineConfig() (<a href="https://redirect.github.com/eslint/eslint/issues/17351">#17351</a>) (Nicholas C. Zakas)</li>
<li><a href="https://github.com/eslint/eslint/commit/cc4d26b5a59d510f2c878e973fd245e8eff27c2a"><code>cc4d26b</code></a> fix: Ensure deprecated context.parserServices warns (<a href="https://redirect.github.com/eslint/eslint/issues/17593">#17593</a>) (Nicholas C. Zakas)</li>
<li><a href="https://github.com/eslint/eslint/commit/1ea4cfb585dcb52ac3cb1522a32f25cfe507121b"><code>1ea4cfb</code></a> fix: Ensure all RuleTester tests all deprecated context methods (<a href="https://redirect.github.com/eslint/eslint/issues/17587">#17587</a>) (Nicholas C. Zakas)</li>
<li><a href="https://github.com/eslint/eslint/commit/180053759c6cf05a326c710353b4717fbf289ee0"><code>1800537</code></a> docs: Fix and standardize JSX code examples (<a href="https://redirect.github.com/eslint/eslint/issues/17591">#17591</a>) (Francesco Trotta)</li>
<li><a href="https://github.com/eslint/eslint/commit/22a558228ff98f478fa308c9ecde361acc4caf20"><code>22a5582</code></a> feat: add rule <code>no-object-constructor</code>, deprecate <code>no-new-object</code> (<a href="https://redirect.github.com/eslint/eslint/issues/17576">#17576</a>) (Francesco Trotta)</li>
<li><a href="https://github.com/eslint/eslint/commit/48a44a73ac456739bdee348bbaf1840d2b1e4830"><code>48a44a7</code></a> docs: Add correct/incorrect tags to <code>prefer-arrow-callback</code> (<a href="https://redirect.github.com/eslint/eslint/issues/17589">#17589</a>) (Francesco Trotta)</li>
<li><a href="https://github.com/eslint/eslint/commit/aa1b657a9febcd03e9298c03ae2888762795e322"><code>aa1b657</code></a> fix: wrong suggestion and message in <code>no-misleading-character-class</code> (<a href="https://redirect.github.com/eslint/eslint/issues/17571">#17571</a>) (Yosuke Ota)</li>
<li><a href="https://github.com/eslint/eslint/commit/20893d48b9012f2b61bbbfeac8bee70d68d90e5e"><code>20893d4</code></a> docs: fix incorrect tag's place (<a href="https://redirect.github.com/eslint/eslint/issues/17575">#17575</a>) (Tanuj Kanti)</li>
<li><a href="https://github.com/eslint/eslint/commit/85a3d9e967b19cb4a0189746499d81ef2f93e14e"><code>85a3d9e</code></a> feat: allowVoid option in array-callback-return (<a href="https://redirect.github.com/eslint/eslint/issues/17564">#17564</a>) (Tanuj Kanti)</li>
<li><a href="https://github.com/eslint/eslint/commit/bd7a71fd6b7efb0445393304e2d48c5c06d46a45"><code>bd7a71f</code></a> docs: Update README (GitHub Actions Bot)</li>
</ul>
</blockquote>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a href="https://github.com/eslint/eslint/commit/299bfae1254f22bd4b3bccd897d6355f63e0d3b6"><code>299bfae</code></a> 8.50.0</li>
<li><a href="https://github.com/eslint/eslint/commit/212687c36a9e2682b84f5de2b683b025182d9777"><code>212687c</code></a> Build: changelog update for 8.50.0</li>
<li><a href="https://github.com/eslint/eslint/commit/f8a8a2d6b45c82f94a574623759b6e3d2af193f3"><code>f8a8a2d</code></a> chore: upgrade <code>@​eslint/js</code><a href="https://github.com/8"><code>@​8</code></a>.50.0 (<a href="https://redirect.github.com/eslint/eslint/issues/17599">#17599</a>)</li>
<li><a href="https://github.com/eslint/eslint/commit/38ada6df8f4a0313b7d0739b28f0af6b4897b8ce"><code>38ada6d</code></a> chore: package.json update for <code>@​eslint/js</code> release</li>
<li><a href="https://github.com/eslint/eslint/commit/27d5a9e57ad347982a68fcd0e75eafee42d344f0"><code>27d5a9e</code></a> feat: add suggestions to array-callback-return (<a href="https://redirect.github.com/eslint/eslint/issues/17590">#17590</a>)</li>
<li><a href="https://github.com/eslint/eslint/commit/f9082ff3f3956a0a5a7d7659de63640a21c4de0f"><code>f9082ff</code></a> feat: flat-rule-tester make sure default config always matches (<a href="https://redirect.github.com/eslint/eslint/issues/17585">#17585</a>)</li>
<li><a href="https://github.com/eslint/eslint/commit/83914adbfd5fce7d11b33d095ba6d6a39be0dbbc"><code>83914ad</code></a> feat: Implement SourceCode#applyInlineConfig() (<a href="https://redirect.github.com/eslint/eslint/issues/17351">#17351</a>)</li>
<li><a href="https://github.com/eslint/eslint/commit/cc4d26b5a59d510f2c878e973fd245e8eff27c2a"><code>cc4d26b</code></a> fix: Ensure deprecated context.parserServices warns (<a href="https://redirect.github.com/eslint/eslint/issues/17593">#17593</a>)</li>
<li><a href="https://github.com/eslint/eslint/commit/1ea4cfb585dcb52ac3cb1522a32f25cfe507121b"><code>1ea4cfb</code></a> fix: Ensure all RuleTester tests all deprecated context methods (<a href="https://redirect.github.com/eslint/eslint/issues/17587">#17587</a>)</li>
<li><a href="https://github.com/eslint/eslint/commit/180053759c6cf05a326c710353b4717fbf289ee0"><code>1800537</code></a> docs: Fix and standardize JSX code examples (<a href="https://redirect.github.com/eslint/eslint/issues/17591">#17591</a>)</li>
<li>Additional commits viewable in <a href="https://github.com/eslint/eslint/compare/v8.49.0...v8.50.0">compare view</a></li>
</ul>
</details>
<br />


[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=eslint&package-manager=npm_and_yarn&previous-version=8.49.0&new-version=8.50.0)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores)

Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`.

[//]: # (dependabot-automerge-start)
[//]: # (dependabot-automerge-end)

---

<details>
<summary>Dependabot commands and options</summary>
<br />

You can trigger Dependabot actions by commenting on this PR:
- `@dependabot rebase` will rebase this PR
- `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it
- `@dependabot merge` will merge this PR after your CI passes on it
- `@dependabot squash and merge` will squash and merge this PR after your CI passes on it
- `@dependabot cancel merge` will cancel a previously requested merge and block automerging
- `@dependabot reopen` will reopen this PR if it is closed
- `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually
- `@dependabot show <dependency name> ignore conditions` will show all of the ignore conditions of the specified dependency
- `@dependabot ignore <dependency name> major version` will close this group update PR and stop Dependabot creating any more for the specific dependency's major version (unless you unignore this specific dependency's major version or upgrade to it yourself)
- `@dependabot ignore <dependency name> minor version` will close this group update PR and stop Dependabot creating any more for the specific dependency's minor version (unless you unignore this specific dependency's minor version or upgrade to it yourself)
- `@dependabot ignore <dependency name>` will close this group update PR and stop Dependabot creating any more for the specific dependency (unless you unignore this specific dependency or upgrade to it yourself)
- `@dependabot unignore <dependency name>` will remove all of the ignore conditions of the specified dependency
- `@dependabot unignore <dependency name> <ignore condition>` will remove the ignore condition of the specified dependency and ignore conditions


</details>
2023-10-02 08:53:55 +03:00
dependabot[bot] 8af28717a3 chore: bump eslint from 8.49.0 to 8.50.0 in /offlinedocs (#9970)
Bumps [eslint](https://github.com/eslint/eslint) from 8.49.0 to 8.50.0.
- [Release notes](https://github.com/eslint/eslint/releases)
- [Changelog](https://github.com/eslint/eslint/blob/main/CHANGELOG.md)
- [Commits](https://github.com/eslint/eslint/compare/v8.49.0...v8.50.0)

---
updated-dependencies:
- dependency-name: eslint
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-10-02 05:46:22 +00:00
dependabot[bot] d650cf9b8c chore: bump eslint-config-next from 13.4.10 to 13.5.3 in /offlinedocs (#9973)
Bumps [eslint-config-next](https://github.com/vercel/next.js/tree/HEAD/packages/eslint-config-next) from 13.4.10 to 13.5.3.
- [Release notes](https://github.com/vercel/next.js/releases)
- [Changelog](https://github.com/vercel/next.js/blob/canary/release.js)
- [Commits](https://github.com/vercel/next.js/commits/v13.5.3/packages/eslint-config-next)

---
updated-dependencies:
- dependency-name: eslint-config-next
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-10-02 08:42:11 +03:00
dependabot[bot] cac677b4ba chore: bump @octokit/types from 11.1.0 to 12.0.0 in /site (#9963)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-10-01 11:50:36 +00:00
dependabot[bot] 3dc478ad6b chore: bump ts-proto from 1.158.0 to 1.159.1 in /site (#9964)
Bumps [ts-proto](https://github.com/stephenh/ts-proto) from 1.158.0 to 1.159.1.
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a href="https://github.com/stephenh/ts-proto/releases">ts-proto's releases</a>.</em></p>
<blockquote>
<h2>v1.159.1</h2>
<h2><a href="https://github.com/stephenh/ts-proto/compare/v1.159.0...v1.159.1">1.159.1</a> (2023-09-30)</h2>
<h3>Bug Fixes</h3>
<ul>
<li>Use a Map when map keys are boolean. (<a href="https://redirect.github.com/stephenh/ts-proto/issues/933">#933</a>) (<a href="https://github.com/stephenh/ts-proto/commit/c1253a3761405d7a2ffe4d15f4c3ffb364697a02">c1253a3</a>), closes <a href="https://redirect.github.com/stephenh/ts-proto/issues/926">#926</a></li>
</ul>
<h2>v1.159.0</h2>
<h1><a href="https://github.com/stephenh/ts-proto/compare/v1.158.1...v1.159.0">1.159.0</a> (2023-09-30)</h1>
<h3>Features</h3>
<ul>
<li>Add globalThisPolyfill, defaults false. (<a href="https://redirect.github.com/stephenh/ts-proto/issues/931">#931</a>) (<a href="https://github.com/stephenh/ts-proto/commit/085fa21603a74544af192f404289c2e62ecfd8f6">085fa21</a>)</li>
</ul>
<h2>v1.158.1</h2>
<h2><a href="https://github.com/stephenh/ts-proto/compare/v1.158.0...v1.158.1">1.158.1</a> (2023-09-30)</h2>
<h3>Bug Fixes</h3>
<ul>
<li>Use globalThis for Array/String/Boolean (<a href="https://redirect.github.com/stephenh/ts-proto/issues/930">#930</a>) (<a href="https://github.com/stephenh/ts-proto/commit/9a252c3d4cf988496f6de17cc378dbb09a1baf92">9a252c3</a>)</li>
</ul>
</blockquote>
</details>
<details>
<summary>Changelog</summary>
<p><em>Sourced from <a href="https://github.com/stephenh/ts-proto/blob/main/CHANGELOG.md">ts-proto's changelog</a>.</em></p>
<blockquote>
<h2><a href="https://github.com/stephenh/ts-proto/compare/v1.159.0...v1.159.1">1.159.1</a> (2023-09-30)</h2>
<h3>Bug Fixes</h3>
<ul>
<li>Use a Map when map keys are boolean. (<a href="https://redirect.github.com/stephenh/ts-proto/issues/933">#933</a>) (<a href="https://github.com/stephenh/ts-proto/commit/c1253a3761405d7a2ffe4d15f4c3ffb364697a02">c1253a3</a>), closes <a href="https://redirect.github.com/stephenh/ts-proto/issues/926">#926</a></li>
</ul>
<h1><a href="https://github.com/stephenh/ts-proto/compare/v1.158.1...v1.159.0">1.159.0</a> (2023-09-30)</h1>
<h3>Features</h3>
<ul>
<li>Add globalThisPolyfill, defaults false. (<a href="https://redirect.github.com/stephenh/ts-proto/issues/931">#931</a>) (<a href="https://github.com/stephenh/ts-proto/commit/085fa21603a74544af192f404289c2e62ecfd8f6">085fa21</a>)</li>
</ul>
<h2><a href="https://github.com/stephenh/ts-proto/compare/v1.158.0...v1.158.1">1.158.1</a> (2023-09-30)</h2>
<h3>Bug Fixes</h3>
<ul>
<li>Use globalThis for Array/String/Boolean (<a href="https://redirect.github.com/stephenh/ts-proto/issues/930">#930</a>) (<a href="https://github.com/stephenh/ts-proto/commit/9a252c3d4cf988496f6de17cc378dbb09a1baf92">9a252c3</a>)</li>
</ul>
</blockquote>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a href="https://github.com/stephenh/ts-proto/commit/09e9fa2594431785253a2fc15e66d85e721003e9"><code>09e9fa2</code></a> chore(release): 1.159.1 [skip ci]</li>
<li><a href="https://github.com/stephenh/ts-proto/commit/c1253a3761405d7a2ffe4d15f4c3ffb364697a02"><code>c1253a3</code></a> fix: Use a Map when map keys are boolean. (<a href="https://redirect.github.com/stephenh/ts-proto/issues/933">#933</a>)</li>
<li><a href="https://github.com/stephenh/ts-proto/commit/ccf54be52d181c341ff310c68665a65fef3ed86d"><code>ccf54be</code></a> chore(release): 1.159.0 [skip ci]</li>
<li><a href="https://github.com/stephenh/ts-proto/commit/085fa21603a74544af192f404289c2e62ecfd8f6"><code>085fa21</code></a> feat: Add globalThisPolyfill, defaults false. (<a href="https://redirect.github.com/stephenh/ts-proto/issues/931">#931</a>)</li>
<li><a href="https://github.com/stephenh/ts-proto/commit/6f856376b103284e2694d3bb7d4471c6b43429f9"><code>6f85637</code></a> chore(release): 1.158.1 [skip ci]</li>
<li><a href="https://github.com/stephenh/ts-proto/commit/9a252c3d4cf988496f6de17cc378dbb09a1baf92"><code>9a252c3</code></a> fix: Use globalThis for Array/String/Boolean (<a href="https://redirect.github.com/stephenh/ts-proto/issues/930">#930</a>)</li>
<li>See full diff in <a href="https://github.com/stephenh/ts-proto/compare/v1.158.0...v1.159.1">compare view</a></li>
</ul>
</details>
<br />


[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=ts-proto&package-manager=npm_and_yarn&previous-version=1.158.0&new-version=1.159.1)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores)

Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`.

[//]: # (dependabot-automerge-start)
[//]: # (dependabot-automerge-end)

---

<details>
<summary>Dependabot commands and options</summary>
<br />

You can trigger Dependabot actions by commenting on this PR:
- `@dependabot rebase` will rebase this PR
- `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it
- `@dependabot merge` will merge this PR after your CI passes on it
- `@dependabot squash and merge` will squash and merge this PR after your CI passes on it
- `@dependabot cancel merge` will cancel a previously requested merge and block automerging
- `@dependabot reopen` will reopen this PR if it is closed
- `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually
- `@dependabot show <dependency name> ignore conditions` will show all of the ignore conditions of the specified dependency
- `@dependabot ignore <dependency name> major version` will close this group update PR and stop Dependabot creating any more for the specific dependency's major version (unless you unignore this specific dependency's major version or upgrade to it yourself)
- `@dependabot ignore <dependency name> minor version` will close this group update PR and stop Dependabot creating any more for the specific dependency's minor version (unless you unignore this specific dependency's minor version or upgrade to it yourself)
- `@dependabot ignore <dependency name>` will close this group update PR and stop Dependabot creating any more for the specific dependency (unless you unignore this specific dependency or upgrade to it yourself)
- `@dependabot unignore <dependency name>` will remove all of the ignore conditions of the specified dependency
- `@dependabot unignore <dependency name> <ignore condition>` will remove the ignore condition of the specified dependency and ignore conditions


</details>
2023-10-01 14:49:04 +03:00
dependabot[bot] b035c4d88a chore: bump chromatic from 7.1.0 to 7.2.0 in /site (#9966)
Bumps [chromatic](https://github.com/chromaui/chromatic-cli) from 7.1.0 to 7.2.0.
<details>
<summary>Commits</summary>
<ul>
<li><a href="https://github.com/chromaui/chromatic-cli/commit/5366e6b8a73f606cdf48bec69176c090bdaf58c4"><code>5366e6b</code></a> 7.2.0</li>
<li><a href="https://github.com/chromaui/chromatic-cli/commit/0749afb68e1da025de47af3204e6ea5062c9c571"><code>0749afb</code></a> Step package.json back</li>
<li><a href="https://github.com/chromaui/chromatic-cli/commit/788d8e96f72a95fc69f831fbceab862fd404a6ce"><code>788d8e9</code></a> Merge pull request <a href="https://redirect.github.com/chromaui/chromatic-cli/issues/819">#819</a> from chromaui/tom/drop-loggly</li>
<li><a href="https://github.com/chromaui/chromatic-cli/commit/0967fa81cc4358e3709e4468c5599e1797922c58"><code>0967fa8</code></a> 7.2.1-canary.0</li>
<li><a href="https://github.com/chromaui/chromatic-cli/commit/2f9484e733bd09300de76707d24815e08adbaca7"><code>2f9484e</code></a> No longer log to loggly</li>
<li><a href="https://github.com/chromaui/chromatic-cli/commit/6f614e64036e02bbb0cec3d9252718de7277acb0"><code>6f614e6</code></a> 7.2.0-next.1</li>
<li><a href="https://github.com/chromaui/chromatic-cli/commit/10bc2a32a1db2e5039e117e233f3aba3c6cfe51b"><code>10bc2a3</code></a> 7.2.0-next.0</li>
<li><a href="https://github.com/chromaui/chromatic-cli/commit/a0b14d8c45f8fc2c50cbb7b944bcddee3a9cf294"><code>a0b14d8</code></a> Merge pull request <a href="https://redirect.github.com/chromaui/chromatic-cli/issues/814">#814</a> from chromaui/tom/ap-3623-add-cli-support-for-a-chrom...</li>
<li><a href="https://github.com/chromaui/chromatic-cli/commit/a8acc0e8d33180a35846feb8c314d0fe0edfae97"><code>a8acc0e</code></a> Trying <code>xlarge</code></li>
<li><a href="https://github.com/chromaui/chromatic-cli/commit/5af4e277207621d0b379bc272a60972cf1c29eeb"><code>5af4e27</code></a> Try medium resource class</li>
<li>Additional commits viewable in <a href="https://github.com/chromaui/chromatic-cli/compare/v7.1.0...v7.2.0">compare view</a></li>
</ul>
</details>
<br />


[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=chromatic&package-manager=npm_and_yarn&previous-version=7.1.0&new-version=7.2.0)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores)

Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`.

[//]: # (dependabot-automerge-start)
[//]: # (dependabot-automerge-end)

---

<details>
<summary>Dependabot commands and options</summary>
<br />

You can trigger Dependabot actions by commenting on this PR:
- `@dependabot rebase` will rebase this PR
- `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it
- `@dependabot merge` will merge this PR after your CI passes on it
- `@dependabot squash and merge` will squash and merge this PR after your CI passes on it
- `@dependabot cancel merge` will cancel a previously requested merge and block automerging
- `@dependabot reopen` will reopen this PR if it is closed
- `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually
- `@dependabot show <dependency name> ignore conditions` will show all of the ignore conditions of the specified dependency
- `@dependabot ignore <dependency name> major version` will close this group update PR and stop Dependabot creating any more for the specific dependency's major version (unless you unignore this specific dependency's major version or upgrade to it yourself)
- `@dependabot ignore <dependency name> minor version` will close this group update PR and stop Dependabot creating any more for the specific dependency's minor version (unless you unignore this specific dependency's minor version or upgrade to it yourself)
- `@dependabot ignore <dependency name>` will close this group update PR and stop Dependabot creating any more for the specific dependency (unless you unignore this specific dependency or upgrade to it yourself)
- `@dependabot unignore <dependency name>` will remove all of the ignore conditions of the specified dependency
- `@dependabot unignore <dependency name> <ignore condition>` will remove the ignore condition of the specified dependency and ignore conditions


</details>
2023-10-01 14:42:35 +03:00
dependabot[bot] 3d71173e74 chore: bump yup from 1.2.0 to 1.3.2 in /site (#9968)
Bumps [yup](https://github.com/jquense/yup) from 1.2.0 to 1.3.2.
<details>
<summary>Changelog</summary>
<p><em>Sourced from <a href="https://github.com/jquense/yup/blob/master/CHANGELOG.md">yup's changelog</a>.</em></p>
<blockquote>
<h2><a href="https://github.com/jquense/yup/compare/v1.3.1...v1.3.2">1.3.2</a> (2023-09-29)</h2>
<h3>Bug Fixes</h3>
<ul>
<li>pick and omit with excluded edges (<a href="https://github.com/jquense/yup/commit/6956ee788369dff00e5ecadb506726af3598a87e">6956ee7</a>), closes <a href="https://redirect.github.com/jquense/yup/issues/2097">#2097</a></li>
</ul>
<h2><a href="https://github.com/jquense/yup/compare/v1.3.0...v1.3.1">1.3.1</a> (2023-09-26)</h2>
<h3>Bug Fixes</h3>
<ul>
<li>ValidationError extends Error (<a href="https://github.com/jquense/yup/commit/bc5121b92d8e16baf8fe9b83f0247a4e90e169b8">bc5121b</a>)</li>
</ul>
<h1><a href="https://github.com/jquense/yup/compare/v1.2.0...v1.3.0">1.3.0</a> (2023-09-23)</h1>
<h3>Bug Fixes</h3>
<ul>
<li>add tuple to locale object (<a href="https://redirect.github.com/jquense/yup/issues/2100">#2100</a>) (<a href="https://github.com/jquense/yup/commit/809b55a9c16e0cd567f4eced9b9ab02ad8b0bffa">809b55a</a>)</li>
<li>performance improvement (<a href="https://redirect.github.com/jquense/yup/issues/2043">#2043</a>) (<a href="https://redirect.github.com/jquense/yup/issues/2044">#2044</a>) (<a href="https://github.com/jquense/yup/commit/ee1b7317b0a9fc0e16a7d33064c3e5584bd7f2d5">ee1b731</a>)</li>
</ul>
<h3>Features</h3>
<ul>
<li>Allow schema metadata to be strongly typed (<a href="https://redirect.github.com/jquense/yup/issues/2021">#2021</a>) (<a href="https://github.com/jquense/yup/commit/e593f8f72e7195cf0ac48fa8e1cd82d95c1e6bb5">e593f8f</a>)</li>
</ul>
<h3>Reverts</h3>
<ul>
<li>Revert &quot;fix: performance improvement (<a href="https://redirect.github.com/jquense/yup/issues/2043">#2043</a>) (<a href="https://redirect.github.com/jquense/yup/issues/2044">#2044</a>)&quot; (<a href="https://redirect.github.com/jquense/yup/issues/2071">#2071</a>) (<a href="https://github.com/jquense/yup/commit/b940eef48eb7456622ae384d0ffa7363d4fbad25">b940eef</a>), closes <a href="https://redirect.github.com/jquense/yup/issues/2043">#2043</a> <a href="https://redirect.github.com/jquense/yup/issues/2044">#2044</a> <a href="https://redirect.github.com/jquense/yup/issues/2071">#2071</a></li>
</ul>
</blockquote>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a href="https://github.com/jquense/yup/commit/a58f02d2f6164c46a9757a818eebac582f7a441c"><code>a58f02d</code></a> Publish v1.3.2</li>
<li><a href="https://github.com/jquense/yup/commit/2f2c0aa9be6258b763f95e7de076c2dcfbe0cae3"><code>2f2c0aa</code></a> fix type</li>
<li><a href="https://github.com/jquense/yup/commit/020901fcf3cfb12a38afd90e4fe56e2e37c312a1"><code>020901f</code></a> Allow parent resolve before describe. (<a href="https://redirect.github.com/jquense/yup/issues/2051">#2051</a>)</li>
<li><a href="https://github.com/jquense/yup/commit/6956ee788369dff00e5ecadb506726af3598a87e"><code>6956ee7</code></a> fix: pick and omit with excluded edges</li>
<li><a href="https://github.com/jquense/yup/commit/e15297bb747552e4742bbaa2ecb95aad1c37f918"><code>e15297b</code></a> Publish v1.3.1</li>
<li><a href="https://github.com/jquense/yup/commit/bc5121b92d8e16baf8fe9b83f0247a4e90e169b8"><code>bc5121b</code></a> fix: ValidationError extends Error</li>
<li><a href="https://github.com/jquense/yup/commit/9c1208c0685a5a7571ef74c39a08d248100f793f"><code>9c1208c</code></a> Publish v1.3.0</li>
<li><a href="https://github.com/jquense/yup/commit/809b55a9c16e0cd567f4eced9b9ab02ad8b0bffa"><code>809b55a</code></a> fix: add tuple to locale object (<a href="https://redirect.github.com/jquense/yup/issues/2100">#2100</a>)</li>
<li><a href="https://github.com/jquense/yup/commit/13ce359c20be195794f22f16a64d633bc28db7f5"><code>13ce359</code></a> Update README.md (<a href="https://redirect.github.com/jquense/yup/issues/2101">#2101</a>)</li>
<li><a href="https://github.com/jquense/yup/commit/1ee9b21c994b4293f3ab338119dc17ab2f4e284c"><code>1ee9b21</code></a> Export Lazy and Reference types (<a href="https://redirect.github.com/jquense/yup/issues/2093">#2093</a>)</li>
<li>Additional commits viewable in <a href="https://github.com/jquense/yup/compare/v1.2.0...v1.3.2">compare view</a></li>
</ul>
</details>
<br />


[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=yup&package-manager=npm_and_yarn&previous-version=1.2.0&new-version=1.3.2)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores)

Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`.

[//]: # (dependabot-automerge-start)
[//]: # (dependabot-automerge-end)

---

<details>
<summary>Dependabot commands and options</summary>
<br />

You can trigger Dependabot actions by commenting on this PR:
- `@dependabot rebase` will rebase this PR
- `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it
- `@dependabot merge` will merge this PR after your CI passes on it
- `@dependabot squash and merge` will squash and merge this PR after your CI passes on it
- `@dependabot cancel merge` will cancel a previously requested merge and block automerging
- `@dependabot reopen` will reopen this PR if it is closed
- `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually
- `@dependabot show <dependency name> ignore conditions` will show all of the ignore conditions of the specified dependency
- `@dependabot ignore <dependency name> major version` will close this group update PR and stop Dependabot creating any more for the specific dependency's major version (unless you unignore this specific dependency's major version or upgrade to it yourself)
- `@dependabot ignore <dependency name> minor version` will close this group update PR and stop Dependabot creating any more for the specific dependency's minor version (unless you unignore this specific dependency's minor version or upgrade to it yourself)
- `@dependabot ignore <dependency name>` will close this group update PR and stop Dependabot creating any more for the specific dependency (unless you unignore this specific dependency or upgrade to it yourself)
- `@dependabot unignore <dependency name>` will remove all of the ignore conditions of the specified dependency
- `@dependabot unignore <dependency name> <ignore condition>` will remove the ignore condition of the specified dependency and ignore conditions


</details>
2023-10-01 14:41:38 +03:00
dependabot[bot] 5b18007311 chore: bump @vitejs/plugin-react from 4.0.1 to 4.1.0 in /site (#9969)
Bumps [@vitejs/plugin-react](https://github.com/vitejs/vite-plugin-react/tree/HEAD/packages/plugin-react) from 4.0.1 to 4.1.0.
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a href="https://github.com/vitejs/vite-plugin-react/releases"><code>@​vitejs/plugin-react</code>'s releases</a>.</em></p>
<blockquote>
<h2>v4.1.0</h2>
<ul>
<li>Add <code>@types/babel__cores</code> to dependencies (fix <a href="https://redirect.github.com/vitejs/vite-plugin-react/issues/211">#211</a>)</li>
<li>Improve build perf when not using Babel plugins by lazy loading <code>@babel/core</code> <a href="https://redirect.github.com/vitejs/vite-plugin-react/pull/212">#212</a></li>
<li>Better invalidation message when an export is added &amp; fix HMR for export of nullish values <a href="https://redirect.github.com/vitejs/vite-plugin-react/pull/215">#215</a></li>
<li>Include non-dev jsx runtime in optimizeDeps &amp; support HMR for JS files using the non dev runtime <a href="https://redirect.github.com/vitejs/vite-plugin-react/pull/224">#224</a></li>
<li>The build output now contains a <code>index.d.cts</code> file so you don't get types errors when setting <code>moduleResolution</code> to <code>node16</code> or <code>nodenext</code> in your tsconfig (we recommend using <code>bundler</code> which is more close to how Vite works)</li>
</ul>
<h2>v4.0.4</h2>
<ul>
<li>Fix <a href="https://github.com/vitejs/vite-plugin-react/discussions/198">#198</a>: Enable Babel if presets list is not empty</li>
</ul>
<h2>v4.0.3</h2>
<ul>
<li>Revert <a href="https://redirect.github.com/vitejs/vite-plugin-react/pull/108">#108</a>: Remove throw when refresh runtime is loaded twice to enable usage in micro frontend apps. This was added to help fix setup usage, and this is not worth an annoying warning for others or a config parameter.</li>
</ul>
<h2>v4.0.2</h2>
<ul>
<li>Fix fast-refresh for files that are transformed into jsx (<a href="https://redirect.github.com/vitejs/vite-plugin-react/pull/188">#188</a>)</li>
</ul>
</blockquote>
</details>
<details>
<summary>Changelog</summary>
<p><em>Sourced from <a href="https://github.com/vitejs/vite-plugin-react/blob/main/packages/plugin-react/CHANGELOG.md"><code>@​vitejs/plugin-react</code>'s changelog</a>.</em></p>
<blockquote>
<h2>4.1.0 (2023-09-24)</h2>
<ul>
<li>Add <code>@types/babel__cores</code> to dependencies (fix <a href="https://redirect.github.com/vitejs/vite-plugin-react/issues/211">#211</a>)</li>
<li>Improve build perf when not using Babel plugins by lazy loading <code>@babel/core</code> <a href="https://redirect.github.com/vitejs/vite-plugin-react/pull/212">#212</a></li>
<li>Better invalidation message when an export is added &amp; fix HMR for export of nullish values <a href="https://redirect.github.com/vitejs/vite-plugin-react/pull/215">#215</a></li>
<li>Include non-dev jsx runtime in optimizeDeps &amp; support HMR for JS files using the non dev runtime <a href="https://redirect.github.com/vitejs/vite-plugin-react/pull/224">#224</a></li>
<li>The build output now contains a <code>index.d.cts</code> file so you don't get types errors when setting <code>moduleResolution</code> to <code>node16</code> or <code>nodenext</code> in your tsconfig (we recommend using <code>bundler</code> which is more close to how Vite works)</li>
</ul>
<h2>4.0.4 (2023-07-31)</h2>
<ul>
<li>Fix <a href="https://github.com/vitejs/vite-plugin-react/discussions/198">#198</a>: Enable Babel if presets list is not empty</li>
</ul>
<h2>4.0.3 (2023-07-10)</h2>
<ul>
<li>Revert <a href="https://redirect.github.com/vitejs/vite-plugin-react/pull/108">#108</a>: Remove throw when refresh runtime is loaded twice to enable usage in micro frontend apps. This was added to help fix setup usage, and this is not worth an annoying warning for others or a config parameter.</li>
</ul>
<h2>4.0.2 (2023-07-06)</h2>
<ul>
<li>Fix fast-refresh for files that are transformed into jsx (<a href="https://redirect.github.com/vitejs/vite-plugin-react/pull/188">#188</a>)</li>
</ul>
</blockquote>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a href="https://github.com/vitejs/vite-plugin-react/commit/bf1453edac2d21f7fc06680aa66d178082b770df"><code>bf1453e</code></a> release: plugin-react@4.1.0</li>
<li><a href="https://github.com/vitejs/vite-plugin-react/commit/25fe88a02d3a718b81a3b1290ff4e46bfab427f9"><code>25fe88a</code></a> feat: add support for non-dev jsx runtime (<a href="https://github.com/vitejs/vite-plugin-react/tree/HEAD/packages/plugin-react/issues/224">#224</a>)</li>
<li><a href="https://github.com/vitejs/vite-plugin-react/commit/272c338a7c2927d6e673901bc52f25791d466a98"><code>272c338</code></a> fix(deps): update all non-major dependencies (<a href="https://github.com/vitejs/vite-plugin-react/tree/HEAD/packages/plugin-react/issues/206">#206</a>)</li>
<li><a href="https://github.com/vitejs/vite-plugin-react/commit/286360281992c425bf75cb0a18846f65fcdc5ef3"><code>2863602</code></a> fix: better invalidation message when an export is added &amp; fix HMR for export...</li>
<li><a href="https://github.com/vitejs/vite-plugin-react/commit/ccd25ddf1fe9d70d9486e8f07da95bcf3fd0b5d6"><code>ccd25dd</code></a> perf: lazy load <code>@babel/core</code> (<a href="https://github.com/vitejs/vite-plugin-react/tree/HEAD/packages/plugin-react/issues/212">#212</a>)</li>
<li><a href="https://github.com/vitejs/vite-plugin-react/commit/8413a1835e78a9d923bcc5a5723cb1e903c8fc0f"><code>8413a18</code></a> fix: add <code>@types/babel__cores</code> to dependencies (fix <a href="https://github.com/vitejs/vite-plugin-react/tree/HEAD/packages/plugin-react/issues/211">#211</a>)</li>
<li><a href="https://github.com/vitejs/vite-plugin-react/commit/90328ce92ecfdc9797aa58af67e46f9872b29118"><code>90328ce</code></a> release: plugin-react@4.0.4</li>
<li><a href="https://github.com/vitejs/vite-plugin-react/commit/9f9e2f66d699c47e8bf7b88175fdd55908a2bf35"><code>9f9e2f6</code></a> fix(deps): update all non-major dependencies (<a href="https://github.com/vitejs/vite-plugin-react/tree/HEAD/packages/plugin-react/issues/199">#199</a>)</li>
<li><a href="https://github.com/vitejs/vite-plugin-react/commit/6e2e0a406e8478002dc0ab4a5104d370d4afc7b3"><code>6e2e0a4</code></a> fix <a href="https://github.com/vitejs/vite-plugin-react/tree/HEAD/packages/plugin-react/issues/198">#198</a>: enable Babel if presets list is not empty</li>
<li><a href="https://github.com/vitejs/vite-plugin-react/commit/cbdf19f8f973fe78495336ca14247ddfc276f998"><code>cbdf19f</code></a> release: plugin-react@4.0.3</li>
<li>Additional commits viewable in <a href="https://github.com/vitejs/vite-plugin-react/commits/v4.1.0/packages/plugin-react">compare view</a></li>
</ul>
</details>
<br />


[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=@vitejs/plugin-react&package-manager=npm_and_yarn&previous-version=4.0.1&new-version=4.1.0)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores)

Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`.

[//]: # (dependabot-automerge-start)
[//]: # (dependabot-automerge-end)

---

<details>
<summary>Dependabot commands and options</summary>
<br />

You can trigger Dependabot actions by commenting on this PR:
- `@dependabot rebase` will rebase this PR
- `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it
- `@dependabot merge` will merge this PR after your CI passes on it
- `@dependabot squash and merge` will squash and merge this PR after your CI passes on it
- `@dependabot cancel merge` will cancel a previously requested merge and block automerging
- `@dependabot reopen` will reopen this PR if it is closed
- `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually
- `@dependabot show <dependency name> ignore conditions` will show all of the ignore conditions of the specified dependency
- `@dependabot ignore <dependency name> major version` will close this group update PR and stop Dependabot creating any more for the specific dependency's major version (unless you unignore this specific dependency's major version or upgrade to it yourself)
- `@dependabot ignore <dependency name> minor version` will close this group update PR and stop Dependabot creating any more for the specific dependency's minor version (unless you unignore this specific dependency's minor version or upgrade to it yourself)
- `@dependabot ignore <dependency name>` will close this group update PR and stop Dependabot creating any more for the specific dependency (unless you unignore this specific dependency or upgrade to it yourself)
- `@dependabot unignore <dependency name>` will remove all of the ignore conditions of the specified dependency
- `@dependabot unignore <dependency name> <ignore condition>` will remove the ignore condition of the specified dependency and ignore conditions


</details>
2023-10-01 14:41:02 +03:00
Kyle Carberry 5596fb20b5 chore: move /gitauth to /externalauth on the frontend (#9954)
* chore: move `/gitauth` to `/externalauth` on the frontend

This actually took a lot more jank than anticipated,
so I wanted to split this up before adding the ability
to embed new providers.

* Rename FE

* Fix em' up

* Fix linting error

* Fix e2e tests

* chore: update helm golden files
2023-09-30 14:30:01 -05:00
Muhammad Atif Ali 16a2d4d733 chore(dogfood): use coder modules in dogfood (#9890)
updates dogfood to use coder modules

---

<details open="true"><summary>Generated summary (powered by <a href="https://app.graphite.dev">Graphite</a>)</summary>

> # TL;DR
> This pull request removes the `dotfiles_url` and `jetbrains_ide` parameters, and the related code from the `main.tf` file. It also adds several new modules for `dotfiles`, `git-clone`, `personalize`, `code-server`, `jetbrains_gateway`, `vscode`, and `filebrowser`. The `startup_script` has been updated to remove the installation and launch of `filebrowser` and the `dotfiles` related code. 
> 
> # What changed
> - Removed `dotfiles_url` and `jetbrains_ide` parameters.
> - Removed related code for `dotfiles_url` and `jetbrains_ide`.
> - Added new modules for `dotfiles`, `git-clone`, `personalize`, `code-server`, `jetbrains_gateway`, `vscode`, and `filebrowser`.
> - Updated `startup_script` to remove the installation and launch of `filebrowser` and the `dotfiles` related code.
> 
> # How to test
> 1. Go to https://dev.coder.com/templates/coder/versions/dazzling_hugle0 and create a new workspace or change your dogfood workspace version to `dazzling_hugle0` .
> 2. Verify that the new modules are working as expected.
> 
> # Why make this change
> The `dotfiles_url` and `jetbrains_ide` parameters and related code were removed to simplify the configuration and make it easier to manage. The new modules were added to provide additional functionality and improve the overall user experience. The `startup_script` was updated to reflect these changes.
</details>
2023-09-30 22:22:14 +03:00
Kyle Carberry c1cd93da30 chore: update helm golden files (#9959) 2023-09-30 18:36:34 +00:00
Ammar Bandukwala 3d21872230 chore: set sessionAffinity to None in helm chart (#9918) 2023-09-30 12:33:20 -05:00
Steven Masley e9ccb8dc78 chore: change cli error message handling (#9952)
* chore: add command to easily visualize different errors

* chore: add verbose error printing in cli
2023-09-29 16:50:23 -05:00
Stephen Kirby fa297e1096 feat(site): add white coder icon (#9955)
* Added a white coder svg

* renamed svg

* rename icon
2023-09-29 15:25:44 -05:00
Mathias Fredriksson e6cb2c5a8e chore(go.mod): update cdr.dev/slog to include additional stackdriver field (#9938) 2023-09-29 20:22:37 +00:00
Eric Paulsen 710b170adf site(fix): add space characters to group display name (#9950) 2023-09-29 15:25:59 -04:00
Kyle Carberry 8abca9bea7 chore: rename git_auth to external_auth in our schema (#9935)
* chore: rename `git_auth` to `external_auth` in our schema

We're changing Git auth to be external auth. It will support
any OAuth2 or OIDC provider.

To split up the larger change I want to contribute the schema
changes first, and I'll add the feature itself in another PR.

* Fix names

* Fix outdated view

* Rename some additional places

* Fix sort order

* Fix template versions auth route

* Fix types

* Fix dbauthz
2023-09-29 19:13:20 +00:00
Kayla Washburn 2b5428e95f refactor: start using emotion for styling (#9909) 2023-09-29 13:08:17 -06:00
Colin Adler 4da1223a80 fix: pass OnSubscribe to HA MultiAgent (#9947)
Fixes https://github.com/coder/coder/issues/9929
2023-09-29 13:37:17 -05:00
Kayla Washburn 61154a6bb5 chore: update datadog (#9925) 2023-09-29 12:06:24 -06:00
Steven Masley 92308bec3b chore: color value_source for deployment values (#9922)
* chore: Return populated options vs a blank
* Strip secret values
2023-09-29 12:04:28 -05:00
Marcin Tojek 87ebe6c2c2 test: fix flaky TestPostWorkspacesByOrganization/Create (#9931) 2023-09-29 13:06:21 +00:00
Marcin Tojek c0705ec40e fix: flaky TestCreateValidateRichParameters/ValidateString (#9928) 2023-09-29 12:54:51 +02:00
Marcin Tojek 2dd49cc0a7 fix(site): double input box for logo url (#9926) 2023-09-29 07:27:47 +00:00
Steven Masley beac36027f chore: generate any interface as Deployment Option in TypeScript (#9917)
* chore: handle interfaces as "any" in typescript

Use generated Deployment Option
2023-09-28 16:14:28 -05:00
Colin Adler 885041a65b revert: downgrade alpine to v3.18.3 (#9916) 2023-09-28 20:27:47 +00:00
Steven Masley 8cff6237ba chore: show yaml option in deployment page (#9912) 2023-09-28 15:10:06 -05:00
Colin Adler 92c0237899 chore: upgrade alpine to v3.18.4 2023-09-28 19:47:48 +00:00
Colin Adler ed8ae2f123 chore: upgrade go to 1.20.8 2023-09-28 14:17:15 -05:00
Steven Masley 9e845213f5 chore: include organization id in workspace build audit log (#9905)
* chore: include organization id in workspace build audit log
* rename 'BuildAudit' to 'WorkspaceBuildAudit'
2023-09-28 11:29:12 -05:00
Marcin Tojek 305556f655 feat(site): use custom application name (#9902) 2023-09-28 18:23:27 +02:00
Kayla Washburn 0f946669c1 chore: simplify imports (#9896) 2023-09-28 09:21:36 -06:00
Marcin Tojek dae528f5e7 feat: expose application name and logo url via meta properties (#9900) 2023-09-28 10:50:40 +02:00
Steven Masley 2d1b35390e chore: relax wsproxy version checking (#9796) 2023-09-27 19:34:55 +00:00
Michael Smith dcad8fdc2f fix: add checks for preventing HSL colors from entering React state (#9893)
* fix: remove hsl color from initial form state

* chore: add extra color helpers

* chore: add extra runtime validation for colors

* chore: clean up comments for clarity

* chore: add tests for colors
2023-09-27 19:27:11 +00:00
Ben Potter 20a681af8d chore: add v2.2.0 changelog (#9889)
* chore: add v2.2.0 changelog

* add actual changelog
2023-09-27 17:38:43 +00:00
Kayla Washburn 066b25f710 chore: remove Maybe (#9880) 2023-09-27 10:45:12 -06:00
Cian Johnston 72e8f88af3 feat(scaletest/terraform): add cert-manager, otel, and TLS (#9894) 2023-09-27 17:41:07 +01:00
Mathias Fredriksson 0878381d0b fix(cli/cliui): avoid nil pointer deref when agent disconnects (#9892)
Fixes #9884
2023-09-27 19:10:15 +03:00
Kyle Carberry de6d0b9a1a fix: only specify vscode proxy uri if app subdomains enabled (#9891)
Otherwise this generates an invalid URI that breaks code-server!
2023-09-27 15:13:47 +00:00
Marcin Tojek cb5f8df4c2 feat: expose application name via Appearance API (#9886) 2023-09-27 17:02:18 +02:00
Mathias Fredriksson 68738771b9 feat(scaletest): create automated pprof dumps during scaletest (#9887) 2023-09-27 15:58:43 +03:00
Cian Johnston fad02081fc fix: avoid logging env in unit tests (#9885) 2023-09-27 13:34:40 +01:00
Mathias Fredriksson d8515f02af feat(scaletest): add grafana annotations and slack reporting (#9852)
Fixes #9575
Fixes #9576
2023-09-27 11:44:11 +00:00
Mathias Fredriksson 4e442040f7 feat(coderd/httpmw): log start timestamp for http requests (#9776) 2023-09-27 14:39:22 +03:00
Spike Curtis c67db6efb0 fix: wait for bash prompt before commands (#9882)
Signed-off-by: Spike Curtis <spike@coder.com>
2023-09-27 12:26:24 +04:00
Cian Johnston 399b428149 chore(scaletest): update scaletest terraform to match big.cdr.dev (#9860)
- Removes usage of null_resources as no longer required
- Updates terraform in both infra/ and k8s/ to match
- Updates provisionerd deployment to use helm chart
2023-09-27 09:02:35 +01:00
Kyle Carberry 726a4dadf2 feat: allow magic string to generate session token for external apps (#9878)
* fix: make non-http external app links open in the current window

* Allow magic string to be replaced with a session token for external apps

* Improve readibility
2023-09-26 16:04:24 -05:00
Kira Pilot 75366ec6b5 more renames (#9876) 2023-09-26 14:45:29 -04:00
Kayla Washburn 6f0e2a7968 refactor: poll for git auth updates when creating a workspace (#9804) 2023-09-26 11:39:07 -06:00
Marcin Tojek 4c3b579f58 feat: expose insights into user activity (#9807) 2023-09-26 18:42:16 +02:00
Cian Johnston 1f4335733c fix(coderd/workspaceapps/apptest): bump sleep in testReconnectingPTY to reduce test flakes (#9875) 2023-09-26 14:58:18 +01:00
Bruno Quaresma b0b9d32a2a chore(site): remove dead code (#9830) 2023-09-26 10:05:24 -03:00
Cian Johnston 93ef696b57 refactor(agent): add agenttest.New helper function (#9812)
* Adds agenttest.New() helper function
* Makes sure agent gets closed on test cleanup
* Makes sure you don't forget to set session token
* Sets the agent and client logger automatically
2023-09-26 12:05:19 +01:00
Cian Johnston 96c5076c69 fix(coderd): remove troublesome test case (#9874) 2023-09-26 11:33:21 +01:00
Kyle Carberry c4718fd747 fix: remove pinned version for dogfood (#9872) 2023-09-26 02:23:42 +00:00
Muhammad Atif Ali 04c85c3833 chore: add icons (#9871) 2023-09-26 00:46:07 +00:00
Kyle Carberry f7c89082d2 chore: swap dogfood to use modules (#9870) 2023-09-25 19:41:45 -05:00
Kyle Carberry 442fb105c9 chore: add git svg icon (#9869) 2023-09-26 00:15:55 +00:00
Kyle Carberry 20bfe6e9e5 fix: allow expansion from log_path for coder_script (#9868) 2023-09-25 23:45:55 +00:00
Colin Adler 89292264be feat(coderd): add simple healthcheck formatting option (#9864) 2023-09-25 22:55:50 +00:00
Kyle Carberry 6e6b808143 fix: add case for logs without a source (#9866)
This is to support legacy logs!
2023-09-25 22:19:51 +00:00
Kyle Carberry d3220c5db9 fix: resolve flake in log sender by checking context (#9865)
See: https://github.com/coder/coder/actions/runs/6305051172/job/17117693579
2023-09-25 22:19:27 +00:00
Kyle Carberry 1262eef2c0 feat: add support for coder_script (#9584)
* Add basic migrations

* Improve schema

* Refactor agent scripts into it's own package

* Support legacy start and stop script format

* Pipe the scripts!

* Finish the piping

* Fix context usage

* It works!

* Fix sql query

* Fix SQL query

* Rename `LogSourceID` -> `SourceID`

* Fix the FE

* fmt

* Rename migrations

* Fix log tests

* Fix lint err

* Fix gen

* Fix story type

* Rename source to script

* Fix schema jank

* Uncomment test

* Rename proto to TimeoutSeconds

* Fix comments

* Fix comments

* Fix legacy endpoint without specified log_source

* Fix non-blocking by default in agent

* Fix resources tests

* Fix dbfake

* Fix resources

* Fix linting I think

* Add fixtures

* fmt

* Fix startup script behavior

* Fix comments

* Fix context

* Fix cancel

* Fix SQL tests

* Fix e2e tests

* Interrupt on Windows

* Fix agent leaking script process

* Fix migrations

* Fix stories

* Fix duplicate logs appearing

* Gen

* Fix log location

* Fix tests

* Fix tests

* Fix log output

* Show display name in output

* Fix print

* Return timeout on start context

* Gen

* Fix fixture

* Fix the agent status

* Fix startup timeout msg

* Fix command using shared context

* Fix timeout draining

* Change signal type

* Add deterministic colors to startup script logs

---------

Co-authored-by: Muhammad Atif Ali <atif@coder.com>
2023-09-25 16:47:17 -05:00
Kayla Washburn dac1375880 feat: add &hellip; to actions that require confirmation (#9862) 2023-09-25 15:25:02 -06:00
Kayla Washburn ff3fc0971c feat: create a workspace from any template version (#9861) 2023-09-25 14:54:19 -06:00
Ammar Bandukwala 4adbf24a08 docs: fix typo (#9859) 2023-09-25 19:52:53 +00:00
Steven Masley b6c5e94ffa fix: consider all 'devel' builds as 'dev' builds (#9794)
* fix: all 'devel' builds should be considered 'dev' builds.

If CI needs to be distinguished from a dev build, we should add
a different pre-release tag for those builds.

* change CI version checking to be more strict
2023-09-25 13:59:49 -05:00
Kayla Washburn 47d3161b0b fix: give more room to lonely resource metadata items (#9832) 2023-09-25 09:40:51 -06:00
Michael Smith 3757005e82 feat: add middle click support for workspace rows (#9834)
* chore: add generic ref support for useClickable

* chore: update useClickable call sites to use type parameter

* chore: update useClickableTableRow implementation

* chore: update other components using useClickableTableRow

* feat: add middle-click and cmd-click support for rows

* refactor: rename variable for clarity

* docs: add comment for clarity

* chore: add more click logic and comments

* refactor: clean up useClickableTableRow

* docs: rewrite comments for clarity

* fix: update TimelineEntry to accept forwarded ref

* fix: fix keyboard event logic to respond to spaces properly
2023-09-25 11:32:33 -04:00
Marcin Tojek 415818035c test(site): e2e: use IPv4 address for web server (#9843) 2023-09-25 14:44:15 +02:00
Cian Johnston 4622ea2c10 chore: remove filebrowser.db (#9854)
* rm and gitignore filebrowser.db
2023-09-25 12:41:27 +00:00
Bruno Quaresma cb545bcc30 chore(site): move a few pages to lazy load (#9831) 2023-09-25 09:38:24 -03:00
Muhammad Atif Ali 63ea12e74c chore: remove terraform provider versions for pr-deployment template (#9853) 2023-09-25 12:33:01 +00:00
dependabot[bot] 7da3180036 chore: bump github.com/spf13/afero from 1.9.5 to 1.10.0 (#9850)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-09-25 15:32:21 +03:00
dependabot[bot] 9d5af5b483 chore: bump github.com/coder/terraform-provider-coder from 0.11.1 to 0.12.0 (#9849)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-09-25 15:23:19 +03:00
dependabot[bot] e649b7cefe chore: bump google.golang.org/api from 0.141.0 to 0.142.0 (#9848)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-09-25 15:22:54 +03:00
dependabot[bot] 5c1ee6990e chore: bump github.com/gohugoio/hugo from 0.118.2 to 0.119.0 (#9847)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-09-25 15:22:43 +03:00
dependabot[bot] 9358b3bd84 ci: bump the github-actions group with 2 updates (#9846)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-09-25 15:22:19 +03:00
Muhammad Atif Ali 26e0d7580c chore: avoid pushing .terraform.lock.hcl while creating the template (#9851) 2023-09-25 15:13:32 +03:00
Cian Johnston 382843dc5f chore(docs): add notice re enabling encryption (#9844) 2023-09-25 11:07:38 +01:00
Bruno Quaresma 85ab9c2d48 chore(site): replace agent log service (#9814) 2023-09-22 16:13:25 -03:00
Bruno Quaresma 7bb0061804 chore(site): remove workspace build machine (#9813) 2023-09-22 16:12:25 -03:00
Muhammad Atif Ali df0c597843 docs: update VS Code Web docs (#9811)
* docs: update VS Code Web docs

* add back folder
2023-09-22 18:49:20 +00:00
Colin Adler cc009fe121 ci: increase timeout for template build jobs (#9829) 2023-09-22 13:13:50 -05:00
Ammar Bandukwala 733171a93b revert: "ci: cache datadog-ci (#9702)" (#9828)
Original commit changeset: b104e0ec0c
2023-09-22 17:31:25 +00:00
Michael Smith c201fc2538 revert: remove localStorage sync for search params (#9827) 2023-09-22 12:43:08 -04:00
Bruno Quaresma f6ee08d100 chore(site): replace create user machine by react-query (#9810) 2023-09-22 13:28:56 -03:00
Jon Ayers 9216725698 chore: add alpha badges to workspace cleanup fields (#9802) 2023-09-22 10:41:17 -05:00
Cian Johnston 8d8402da00 fix(coderd/database): avoid clobbering workspace build state (#9826)
Fixes #9823.

- Decomposes UpdateWorkspaceBuildByID into UpdateWorkspaceBuildProvisionerStateByID and UpdateWorkspaceBuildDeadlineByID.
- Replaces existing invocations of UpdateWorkspaceBuildByID with the newer queries where applicable.
- Modifies GetActiveWorkspaceBuildsByTemplateID to not return incomplete workspace builds.
2023-09-22 16:22:07 +01:00
Cian Johnston a1f3a6b606 refactor(scaletest/terraform): break up infra creation and k8s resource provisioning (#9824)
Breaks up scaletest/terraform into {infra, k8s}.
2023-09-22 15:55:47 +01:00
Michael Smith 84999cb33d feat: add empty state for SSO auth methods (#9818)
* fix: remove needless undefined checks

* refactor: clean up button markup

* refactor: restrict access to full auth in oidc functions

* feat: add empty SSO state
2023-09-22 09:38:49 -04:00
Spike Curtis e9077f3bd2 fix: use AlwaysEnable for licenses with all features (#9808)
* fix: use AlwaysEnable for licenses with all features

Signed-off-by: Spike Curtis <spike@coder.com>

* use dbtime.Now() intead of time.Now()

Signed-off-by: Spike Curtis <spike@coder.com>

---------

Signed-off-by: Spike Curtis <spike@coder.com>
2023-09-22 05:02:28 +00:00
Dean Sheather 94a0612cd2 chore: update tailscale (#9817) 2023-09-22 07:21:38 +10:00
Colin Adler c900b5f8df feat: add single tailnet support to pgcoord (#9351) 2023-09-21 14:30:48 -05:00
Colin Adler fbad06f406 chore: bump wgtunnel (#9805) 2023-09-21 13:33:13 -05:00
Michael Smith 91a04c0132 chore: enhance tests for TemplateSchedulePage (#9801)
* chore: Add benchmark logs to test

* chore: Remove benchmark logic

* chore: add hard cutoff for waitFor calls

* refactor: clean up waitFor cut-off logic

* chore: add assertion that submit button is not disabled

* chore: Remove disabled check at the start of the test

* fix: extend cutoff for waitFor config
2023-09-21 14:25:26 -04:00
Muhammad Atif Ali 201a6c0c79 chore: remove extra condition from pr-deploy.yaml (#9788) 2023-09-21 17:58:46 +03:00
Bruno Quaresma 801c6c994b chore(site): replace setup machine by react-query (#9809) 2023-09-21 11:21:49 -03:00
Spike Curtis 866ba8ede5 fix: call agent directly in cli tests (#9789)
* fix: call agent directly in cli tests

Signed-off-by: Spike Curtis <spike@coder.com>

* log verbose in TestDERPHeaders

Signed-off-by: Spike Curtis <spike@coder.com>

---------

Signed-off-by: Spike Curtis <spike@coder.com>
2023-09-21 13:30:24 +04:00
Muhammad Atif Ali fa858531a8 feat: add nomad template (#9786) 2023-09-21 08:54:56 +00:00
Michael Smith b742661abd feat: make workspace search bar remember text (#9759)
* minor: Add useEffectEvent polyfill

* chore: update filter to have better callback support

* docs: Clean up comments

* fix: add localStorage to useWorkspacesFilter

* refactor: Centralize stable useSearchParams

* refactor: clean up filter to be fully pure on mount

* chore: add tests for useEffectEvent

* wip: commit progress for searchbar fix

* chore: clean up WorkspacesPage

* fix: add logic for syncing queries with search params

* chore: Rename initialValue to fallbackFilter

* chore: Remove todo comment

* refactor: update code to use useEffectEvent

* docs: clean up comments for clarity

* fix: update url check to use regex
2023-09-20 16:44:19 -04:00
Bruno Quaresma 92a90eb9ae test(site): fix terminal page test flakiness (#9798) 2023-09-20 15:19:27 -03:00
Bruno Quaresma 1cd0bea86e chore: make workspace batch actions enabled by default (#9797) 2023-09-20 14:10:01 -03:00
Eric Paulsen fae8a470df fix(cli): display pasted session token (#9710) 2023-09-20 12:41:59 -04:00
Steven Masley f89b68056d chore: add debug information to wsproxy errors (#9683)
* chore: add debug information to wsproxy errors
* Use codersdk.ReadBodyAsError
2023-09-20 10:05:14 -05:00
Cian Johnston ae1896f2dc chore(docs): replace numbering with bullets in admin/encryption.md (#9792) 2023-09-20 15:15:39 +01:00
Marcin Tojek 8e012e4e1a test(site): workaround for reattached xterm-rows (#9790) 2023-09-20 14:25:30 +02:00
Steven Masley a18bf73131 chore: display warnings on app share failure (#9783)
* chore: add warnings to app share failure
Warnings only appear if the app is misconfigured to the deployment
2023-09-19 21:54:51 +00:00
Kayla Washburn 1fd1c654a9 fix: hide empty update message box (#9784) 2023-09-19 13:11:22 -06:00
Dean Sheather eda32659a8 chore: fix flake in tunnel (#9746) 2023-09-19 18:54:56 +00:00
Spike Curtis 70e481e7a5 fix: use terminal emulator that keeps state in ReconnectingPTY tests (#9765)
* Add more pty diagnostics for terminal parsing

Signed-off-by: Spike Curtis <spike@coder.com>

* print escaped strings

Signed-off-by: Spike Curtis <spike@coder.com>

* Only log on failure - heisenbug?

Signed-off-by: Spike Curtis <spike@coder.com>

* use the terminal across matches to keep cursor & contents state

Signed-off-by: Spike Curtis <spike@coder.com>

* Only log bytes if we're not expecting EOF

Signed-off-by: Spike Curtis <spike@coder.com>

---------

Signed-off-by: Spike Curtis <spike@coder.com>
2023-09-19 17:57:30 +00:00
Kayla Washburn 269b1c59f1 refactor: get rid of templateVariablesXService (#9763) 2023-09-19 11:54:14 -06:00
Mathias Fredriksson 530dd9d247 fix(coderd): subscribe to workspace when streaming agent logs to detect outdated build (#9729)
Fixes #9721
2023-09-19 20:02:27 +03:00
Bruno Quaresma 87d50f17a2 chore(site): refactor groups to use react-query (#9701) 2023-09-19 13:37:17 -03:00
Mathias Fredriksson 161a3cfa26 fix(coderd/batchstats): use debug log on query cancellation in flush (#9778)
Fixes #9772
2023-09-19 18:16:07 +03:00
Marcin Tojek ceb52ac24a fix: user should always belong to an organization (#9781) 2023-09-19 16:22:37 +02:00
Mathias Fredriksson d6089ae0ad fix(coderd/batchstats): use debug log on context cancellation in flush (#9777) 2023-09-19 13:19:39 +00:00
Bruno Quaresma 7bc98c296b refactor(site): do not display error details as message (#9755) 2023-09-19 09:54:59 -03:00
Bruno Quaresma e26bb2d91b chore(site): rollback remark-gfm version (#9774) 2023-09-19 09:43:11 -03:00
Bruno Quaresma ffa77ba6ff feat(site): show CLI flags and env variables for the options (#9757) 2023-09-19 09:34:04 -03:00
Dr. Pi3cH 94cccd0a01 fix: make sure fly_app name is lower case (#9771)
fly_app does not support uppercase. Coder allows uppercase for username/owner.
2023-09-19 12:30:52 +00:00
Eric Paulsen e9c183d0dc feat: add envFrom value to Helm chart (#9587)
* feat: add envFrom value to Helm chart

* add envUseClusterAccessURL

* add tests

---------

Co-authored-by: Dean Sheather <dean@deansheather.com>
2023-09-19 16:03:13 +04:00
Marcin Tojek ceeb9987a5 test(cli): ensure first option selected with is expected (#9770) 2023-09-19 13:55:51 +02:00
Marcin Tojek b0e3daa120 feat(coderd): support weekly aggregated insights (#9684) 2023-09-19 13:06:19 +02:00
Muhammad Atif Ali b358e3d558 chore: fix permission for kubeconfig (#9768) 2023-09-19 08:36:00 +00:00
Spike Curtis 375c70d141 feat: integrate Acquirer for provisioner jobs (#9717)
* chore: add Acquirer to provisionerdserver pkg

Signed-off-by: Spike Curtis <spike@coder.com>

* code review improvements & fixes

Signed-off-by: Spike Curtis <spike@coder.com>

* feat: integrate Acquirer for provisioner jobs

Signed-off-by: Spike Curtis <spike@coder.com>

* Fix imports, whitespace

Signed-off-by: Spike Curtis <spike@coder.com>

* provisionerdserver always closes; remove poll interval from playwright

Signed-off-by: Spike Curtis <spike@coder.com>

* post jobs outside transactions

Signed-off-by: Spike Curtis <spike@coder.com>

* graceful shutdown in test

Signed-off-by: Spike Curtis <spike@coder.com>

* Mark AcquireJob deprecated

Signed-off-by: Spike Curtis <spike@coder.com>

* Graceful shutdown on all provisionerd tests

Signed-off-by: Spike Curtis <spike@coder.com>

* Deprecate, not remove CLI flags

Signed-off-by: Spike Curtis <spike@coder.com>

---------

Signed-off-by: Spike Curtis <spike@coder.com>
2023-09-19 10:25:57 +04:00
dependabot[bot] 6cf531bfef chore: bump typescript from 5.1.6 to 5.2.2 in /site (#9743)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-09-19 08:32:14 +03:00
dependabot[bot] 8fe4401e23 chore: bump github.com/klauspost/compress from 1.16.5 to 1.17.0 (#9735)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-09-19 05:30:04 +00:00
Cian Johnston aa8652c928 fix(dbtestutil): avoid truncating inserts that span multiple lines (#9756) 2023-09-18 19:46:22 +00:00
Kayla Washburn ed25f1449d refactor: use a line graph for DAUChart (#9758) 2023-09-18 12:28:30 -06:00
Kayla Washburn f85aa443dd feat: show version messages in version lists (#9708) 2023-09-18 11:17:07 -06:00
Jon Ayers 622442203d chore: fix test flake in TestProvisionerd (#9709) 2023-09-18 11:23:22 -05:00
Cian Johnston 45eadfc136 fix(cli): specify IgnoreErrors in slogtest options for scaletest cli tests (#9751)
* fix(cli): specify IgnoreErrors in slogtest options for scaletest cli tests
* bump test timeout
2023-09-18 16:39:28 +01:00
Asher 17f9991118 fix: reconnect terminal on non-modified key presses (#9686)
* Listen to web terminal keydown on capture

Instead of bubbling.  I think maybe what happens here is that xterm is
capturing key presses and preventing the event from bubbling?  So
setting the listener on the capture phase instead works around this.
Probably would also work to dipsose the terminal.

* Prevent issuing terminal reload when already reloading

I am not sure this actually causes any issues, but might as well.

* Ignore modifier keys for reconnecting terminal
2023-09-18 07:24:01 -08:00
Michael Smith 2caf7a7ceb fix: remove just-debounce-it (#9707)
* fix: Switch UserAutocomplete to useDebouncedFunction

* fix: switch UserOrGroupAutocomplete to useDebouncedFunction

* chore: remove just-debounce-it dependency

* docs: Clean up comments
2023-09-18 14:20:11 +00:00
Bruno Quaresma a2aff1f527 chore(site): replace xstate by react-query on update password (#9696) 2023-09-18 11:03:35 -03:00
Bruno Quaresma e74d8a7b21 chore(site): refactor starter templates to use react-query (#9697)
* Remove starter templates service

* Remove starter template service

* Remove template x service
2023-09-18 11:02:55 -03:00
dependabot[bot] e1bd6ddc25 chore: bump the otel group with 3 updates (#9731)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-09-18 16:55:38 +03:00
dependabot[bot] a989e8363b chore: bump google.golang.org/api from 0.140.0 to 0.141.0 (#9732)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-09-18 16:54:32 +03:00
dependabot[bot] 24bff1098d chore: bump gopkg.in/DataDog/dd-trace-go.v1 from 1.54.0 to 1.55.0 (#9734)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-09-18 16:53:40 +03:00
dependabot[bot] 1d8a4ed201 chore: bump jest-location-mock from 1.0.9 to 2.0.0 in /site (#9727)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-09-18 13:46:08 +00:00
Bruno Quaresma 2319486806 chore(site): replace deployment stats service by react-query (#9698) 2023-09-18 10:44:52 -03:00
dependabot[bot] 5a22f08f3f chore: bump @tanstack/react-query from 4.33.0 to 4.35.3 in /site (#9738)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-09-18 16:34:56 +03:00
dependabot[bot] d326f1b10c chore: bump remark-gfm from 3.0.1 to 4.0.0 in /site (#9726)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-09-18 16:32:57 +03:00
dependabot[bot] 972425e3d4 chore: bump @playwright/test from 1.37.1 to 1.38.0 in /site (#9739)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-09-18 16:32:42 +03:00
dependabot[bot] b76a430d22 chore: bump github.com/valyala/fasthttp from 1.49.0 to 1.50.0 (#9736)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-09-18 16:31:54 +03:00
dependabot[bot] ea93b4bbe4 chore: bump react-icons from 4.10.1 to 4.11.0 in /offlinedocs (#9740)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-09-18 16:31:48 +03:00
dependabot[bot] bd3f2f8c10 chore: bump eslint from 8.48.0 to 8.49.0 in /offlinedocs (#9742)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-09-18 16:31:16 +03:00
dependabot[bot] 010a13c654 chore: bump @testing-library/user-event from 14.4.3 to 14.5.1 in /site (#9730)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-09-18 16:24:05 +03:00
dependabot[bot] 9c8140270a chore: bump the react group in /site with 1 update (#9723)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-09-18 16:23:35 +03:00
dependabot[bot] c58e5bf09a chore: bump the eslint group in /site with 1 update (#9725)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-09-18 11:41:20 +00:00
Muhammad Atif Ali 3ed65de82e chore: increase dependabot open pr limit for site (#9728) 2023-09-18 11:24:49 +00:00
dependabot[bot] eb72866a29 ci: bump the github-actions group with 2 updates (#9722)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-09-18 11:15:56 +00:00
Cian Johnston 1df7589105 feat(coderd/database/dbtestutil): add ability to dump database on failure (#9704)
Adds dbtestutil.DumpOnFailure() to allow dumping the entire test database contents upon test failure.
This does nothing for dbfake currently.
2023-09-18 11:50:15 +01:00
Muhammad Atif Ali e6865e0df5 ci: remove example templates readme from docs filter (#9720) 2023-09-18 10:38:57 +00:00
Cian Johnston 9bcff30dee fix(coderd/database): migrate workspaces.last_used_at to timestamptz (#9699) 2023-09-18 11:07:54 +01:00
Cian Johnston 1f5eb088b5 fix(examples): fix typo in examples.gen.json (#9718) 2023-09-18 09:09:30 +00:00
Cian Johnston 653488e8ee fix(coderd): emit CollectedAt as UTC in convertWorkspaceAgentMetadata (#9700) 2023-09-18 09:17:18 +01:00
Ben Potter 5de5d20808 fix: remove broken fly.io template from starter templates (#9711)
Co-authored-by: Atif Ali <atif@coder.com>
2023-09-17 20:13:36 +03:00
sharkymark b2f84668c8 docs: document display_apps feature to hide/show built-in coder_app resources (#9714)
* docs: display_apps feature to hide/show terminal, vscode desktop, port-forwarding, etc.

* Update docs/templates/index.md

Co-authored-by: Muhammad Atif Ali <atif@coder.com>

* Update docs/templates/index.md

Co-authored-by: Muhammad Atif Ali <atif@coder.com>

---------

Co-authored-by: Muhammad Atif Ali <atif@coder.com>
2023-09-17 15:13:56 +00:00
kpoxo6op ab08b2c3e4 fix typo in README.md (#9715)
typo
2023-09-17 07:07:13 -05:00
Michael Smith fcc8b9ec92 fix: prevent workspace search bar text from getting garbled (#9703)
* chore: Reorganize hook calls for useWorkspacesFilter

* refactor: Clean up some filter logic

* refactor: Create debounce utility hooks

* docs: Clean up comments for clarity

* fix: Update focus logic to apply for any inner focus

* fix: Add onBlur behavior for state syncs

* chore: Add progress for debounce test

* chore: Finish tests for debounce hooks

* docs: Add file description and warning
2023-09-15 15:55:59 -04:00
Ammar Bandukwala b104e0ec0c ci: cache datadog-ci (#9702) 2023-09-15 19:22:38 +00:00
Kayla Washburn 9e053ce220 feat: show update messages on workspace page (#9705) 2023-09-15 13:09:29 -06:00
Kayla Washburn efe804498b feat: add quiet hours settings page (#9676) 2023-09-15 11:14:33 -06:00
Cian Johnston 72dff7f188 fix(enterprise/dbcrypt): do not skip deleted users when encrypting or deleting (#9694)
- Broadens scope of data generation in TestServerDBCrypt over all user login types, statuses, and deletion status.
- Adds support for specifying user status / user deletion status in dbgen
- Adds more comprehensive logging in TestServerDBCrypt upon test failure (to be generalized and expanded upon in a follow-up)
- Adds AllUserIDs query, updates dbcrypt to use this instead of GetUsers.
2023-09-15 15:09:40 +01:00
Mathias Fredriksson bc97eaa41b feat(scaletest): add scaletest-runner template (#9662)
Closes #9571
2023-09-15 13:23:37 +00:00
Marcin Tojek d0d64bbdca refactor: define insights interval (#9693) 2023-09-15 12:01:00 +00:00
Cian Johnston 65db7a71b7 feat(coderd/database/dbtestutil): set default database timezone to non-UTC in unit tests (#9672)
- Adds dbtestutil.WithTimezone(tz) to allow setting the timezone for a test database.
- Modifies our test database setup code to pick a consistently weird timezone for the database.
- Adds the facility randtz.Name() to pick a random timezone which is consistent across subtests (via sync.Once).
- Adds a linter rule to warn against setting the test database timezone to UTC.
2023-09-15 09:01:32 +01:00
Ammar Bandukwala 281faf9ccd ci: upgrade runners (#9689)
Per DataDog, I've doubled the resources of our slowest jobs.
2023-09-14 20:20:39 -05:00
Ammar Bandukwala b63dfe7b75 perf(cli): optimize CPU consumption of help pages (#9607)
This change reduces the CPU consumption of --help by ~50%.

Also, this change removes ANSI escape codes from our golden files. I
don't think those were worth the inability to parallelize golden file tests and
global state fragility.
2023-09-14 19:48:29 -05:00
Jon Ayers 7311ffbd9d feat: implement agent process management (#9461)
- An opt-in feature has been added to the agent to allow
   deprioritizing non coder-related processes for CPU by setting their
   niceness level to 10.
- Opting in to the feature requires setting CODER_PROC_PRIO_MGMT to a non-empty value.
2023-09-14 19:45:05 -05:00
Bruno Quaresma 79d4179123 chore(site): migrate a few services to react-query used in the DashboardProvider (#9667) 2023-09-14 19:35:03 -03:00
Bruno Quaresma 3b088a5cb8 chore(site): refactor deployment values service to react-query (#9669) 2023-09-14 18:49:23 -03:00
Marcin Tojek 225cf8acec chore: print page content on failed promise (#9681) 2023-09-14 13:30:46 +02:00
Marcin Tojek dcad0a437c fix: wait for build job (#9680) 2023-09-14 11:20:09 +02:00
Cian Johnston 8b6e2862fd refactor(coderd): collapse activityBumpWorkspace into a single query (#9652)
* Adds unit-style tests for activityBumpWorkspace
* Ports logic of activityBumpWorkspace to a SQL query
* Updates activityBumpWorkspace to call above query
2023-09-14 09:09:51 +01:00
Colin Adler 38560dd922 chore: remove coder trace telemetry (#9677) 2023-09-14 02:20:28 -04:00
Bruno Quaresma e7b0181519 feat(site): add support to .sh and .tpl files (#9674) 2023-09-13 16:27:02 -03:00
Steven Masley e0e6d7c9a6 fix: case insensitve agent ssh session env var (#9675) 2023-09-13 14:18:00 -05:00
Steven Masley 0e4d6896e3 test: fix cleanup order on provisioner daemon work dir (#9668)
* test: fix cleanup order on provisioner daemon work dir

* Reduce the test race condition
2023-09-13 13:13:08 -05:00
Kayla Washburn 53a985ff11 refactor: clean up workspace and template settings (#9654) 2023-09-13 11:55:27 -06:00
dependabot[bot] 6c409b8872 chore: bump chromatic from 6.24.1 to 7.1.0 in /site (#9629)
Bumps [chromatic](https://github.com/chromaui/chromatic-cli) from 6.24.1 to 7.1.0.
- [Changelog](https://github.com/chromaui/chromatic-cli/blob/main/CHANGELOG.md)
- [Commits](https://github.com/chromaui/chromatic-cli/compare/v6.24.1...v7.1.0)

---
updated-dependencies:
- dependency-name: chromatic
  dependency-type: direct:development
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-09-13 14:49:54 -03:00
Jon Ayers 3dc1e22d56 feat: add template_id and template_name to workspace data source (#9655) 2023-09-13 11:09:08 -05:00
Marcin Tojek d171b3611b fix: flaky: TestDeleteTemplate/NoWorkspaces (#9666) 2023-09-13 17:05:08 +02:00
Cian Johnston 3be783b319 fix(scaletest/workspacetraffic): wait for non-zero metrics before cancelling in TestRun (#9663) 2023-09-13 15:54:56 +01:00
Muhammad Atif Ali 254f459d69 chore(dogfood): add a coder_app for JetBrains gateway IDEs (#9644) 2023-09-13 17:49:36 +03:00
Marcin Tojek a229855e71 test(site): e2e: improve webTerminal test (#9659) 2023-09-13 16:18:10 +02:00
Spike Curtis 4ebf490d97 feat: add Acquirer to provisionerdserver pkg (#9658)
* chore: add Acquirer to provisionerdserver pkg

Signed-off-by: Spike Curtis <spike@coder.com>

* code review improvements & fixes

Signed-off-by: Spike Curtis <spike@coder.com>

---------

Signed-off-by: Spike Curtis <spike@coder.com>
2023-09-13 16:36:43 +04:00
Cian Johnston 2ac532982d feat(coderd/database): generate foreign key constraints and add database.IsForeignKeyViolation (#9657)
* feat(coderd/database): generate foreign key constraints, add database.IsForeignKeyViolation

* address PR comments
2023-09-13 13:28:46 +01:00
Cian Johnston a6f7f71808 chore(docs/admin): update encryption.md (#9660) 2023-09-13 12:56:20 +01:00
Marcin Tojek e2579e9440 test: fix flaky TestPatchTemplateMeta/Modified (#9656) 2023-09-13 11:34:53 +02:00
Steven Masley 18c34ee456 chore: support external types in typescript codegen (#9633)
* chore: support external types in typescript codegen
* fix enums on external packages
* Support clibase.struct
* Add regexp
* Make gen with updated generator
2023-09-12 18:21:09 -05:00
Bruno Quaresma 641bf272ed fix(site): fix renderer error (#9653) 2023-09-12 19:59:09 -03:00
Kayla Washburn 0726eb56bb fix: update autostart/autostop text (#9650) 2023-09-12 15:29:39 -06:00
Bruno Quaresma b3c98395ab chore(site): use react-query to fetch roles (#9630) 2023-09-12 15:07:56 -03:00
Bruno Quaresma b33cb0ef97 chore(site): refactor workspace quota to use react-query instead of XState (#9626) 2023-09-12 14:58:35 -03:00
Julio 64bc317cd4 Doc - Remove sysbox 16 pods max. (#9646) 2023-09-12 17:49:51 +00:00
Bruno Quaresma 5ca8c4287f chore(site): move ssh keys management to react-query (#9625) 2023-09-12 14:40:07 -03:00
Bruno Quaresma 6db89b0372 chore(site): move templates fetching to react-query (#9622) 2023-09-12 14:09:16 -03:00
Bruno Quaresma b7550bfda5 chore(site): remove unecessary types and move types to where they are used (#9621) 2023-09-12 13:54:05 -03:00
Marcin Tojek 0e28397c82 fix: use CRC32 to shorten app subdomain (#9645) 2023-09-12 17:11:45 +02:00
Marcin Tojek 898971b329 refactor: generate application URL on backend side (#9618) 2023-09-12 15:25:10 +02:00
dependabot[bot] 228d1cf361 chore: bump the eslint group in /site with 3 updates (#9639)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-09-12 10:25:04 +00:00
dependabot[bot] 531e1334af chore: bump monaco-editor from 0.41.0 to 0.43.0 in /site (#9642)
Bumps [monaco-editor](https://github.com/microsoft/monaco-editor) from 0.41.0 to 0.43.0.
- [Changelog](https://github.com/microsoft/monaco-editor/blob/main/CHANGELOG.md)
- [Commits](https://github.com/microsoft/monaco-editor/compare/v0.41.0...v0.43.0)

---
updated-dependencies:
- dependency-name: monaco-editor
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-09-12 12:56:43 +03:00
dependabot[bot] 7f126758a5 chore: bump jest-websocket-mock from 2.4.0 to 2.5.0 in /site (#9641)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-09-12 09:24:10 +00:00
dependabot[bot] d49bc2003b chore: bump msw from 1.2.2 to 1.3.0 in /site (#9640)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-09-12 12:16:16 +03:00
dependabot[bot] 8b08a78168 chore: bump google.golang.org/api from 0.138.0 to 0.140.0 (#9636)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-09-12 08:45:29 +00:00
Muhammad Atif Ali f1f522a9a7 revert: "chore: bump the eslint group in /site with 3 updates" (#9638) 2023-09-12 11:26:51 +03:00
dependabot[bot] 2c19995712 ci: bump the github-actions group with 2 updates (#9620)
Bumps the github-actions group with 2 updates: [actions/checkout](https://github.com/actions/checkout) and [crate-ci/typos](https://github.com/crate-ci/typos).


Updates `actions/checkout` from 3 to 4
- [Release notes](https://github.com/actions/checkout/releases)
- [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md)
- [Commits](https://github.com/actions/checkout/compare/v3...v4)

Updates `crate-ci/typos` from 1.16.10 to 1.16.11
- [Release notes](https://github.com/crate-ci/typos/releases)
- [Changelog](https://github.com/crate-ci/typos/blob/master/CHANGELOG.md)
- [Commits](https://github.com/crate-ci/typos/compare/v1.16.10...v1.16.11)

---
updated-dependencies:
- dependency-name: actions/checkout
  dependency-type: direct:production
  update-type: version-update:semver-major
  dependency-group: github-actions
- dependency-name: crate-ci/typos
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: github-actions
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-09-12 10:22:22 +03:00
dependabot[bot] e85981713d chore: bump the xterm group in /site with 6 updates (#9627)
Bumps the xterm group in /site with 6 updates:

| Package | From | To |
| --- | --- | --- |
| [xterm](https://github.com/xtermjs/xterm.js) | `5.2.1` | `5.3.0` |
| [xterm-addon-canvas](https://github.com/xtermjs/xterm.js) | `0.4.0` | `0.5.0` |
| [xterm-addon-fit](https://github.com/xtermjs/xterm.js) | `0.7.0` | `0.8.0` |
| [xterm-addon-unicode11](https://github.com/xtermjs/xterm.js) | `0.5.0` | `0.6.0` |
| [xterm-addon-web-links](https://github.com/xtermjs/xterm.js) | `0.8.0` | `0.9.0` |
| [xterm-addon-webgl](https://github.com/xtermjs/xterm.js) | `0.15.0` | `0.16.0` |


Updates `xterm` from 5.2.1 to 5.3.0
- [Release notes](https://github.com/xtermjs/xterm.js/releases)
- [Commits](https://github.com/xtermjs/xterm.js/compare/5.2.1...5.3.0)

Updates `xterm-addon-canvas` from 0.4.0 to 0.5.0
- [Release notes](https://github.com/xtermjs/xterm.js/releases)
- [Commits](https://github.com/xtermjs/xterm.js/compare/0.4...0.5)

Updates `xterm-addon-fit` from 0.7.0 to 0.8.0
- [Release notes](https://github.com/xtermjs/xterm.js/releases)
- [Commits](https://github.com/xtermjs/xterm.js/compare/0.7...0.8)

Updates `xterm-addon-unicode11` from 0.5.0 to 0.6.0
- [Release notes](https://github.com/xtermjs/xterm.js/releases)
- [Commits](https://github.com/xtermjs/xterm.js/compare/0.5...0.6)

Updates `xterm-addon-web-links` from 0.8.0 to 0.9.0
- [Release notes](https://github.com/xtermjs/xterm.js/releases)
- [Commits](https://github.com/xtermjs/xterm.js/compare/0.8...0.9)

Updates `xterm-addon-webgl` from 0.15.0 to 0.16.0
- [Release notes](https://github.com/xtermjs/xterm.js/releases)
- [Commits](https://github.com/xtermjs/xterm.js/compare/0.15...0.16)

---
updated-dependencies:
- dependency-name: xterm
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: xterm
- dependency-name: xterm-addon-canvas
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: xterm
- dependency-name: xterm-addon-fit
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: xterm
- dependency-name: xterm-addon-unicode11
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: xterm
- dependency-name: xterm-addon-web-links
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: xterm
- dependency-name: xterm-addon-webgl
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: xterm
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-09-12 10:21:59 +03:00
dependabot[bot] 140a7d2de2 chore: bump the eslint group in /site with 3 updates (#9628)
Bumps the eslint group in /site with 3 updates: [@typescript-eslint/eslint-plugin](https://github.com/typescript-eslint/typescript-eslint/tree/HEAD/packages/eslint-plugin), [@typescript-eslint/parser](https://github.com/typescript-eslint/typescript-eslint/tree/HEAD/packages/parser) and [eslint](https://github.com/eslint/eslint).


Updates `@typescript-eslint/eslint-plugin` from 6.5.0 to 6.7.0
- [Release notes](https://github.com/typescript-eslint/typescript-eslint/releases)
- [Changelog](https://github.com/typescript-eslint/typescript-eslint/blob/main/packages/eslint-plugin/CHANGELOG.md)
- [Commits](https://github.com/typescript-eslint/typescript-eslint/commits/v6.7.0/packages/eslint-plugin)

Updates `@typescript-eslint/parser` from 6.5.0 to 6.7.0
- [Release notes](https://github.com/typescript-eslint/typescript-eslint/releases)
- [Changelog](https://github.com/typescript-eslint/typescript-eslint/blob/main/packages/parser/CHANGELOG.md)
- [Commits](https://github.com/typescript-eslint/typescript-eslint/commits/v6.7.0/packages/parser)

Updates `eslint` from 8.48.0 to 8.49.0
- [Release notes](https://github.com/eslint/eslint/releases)
- [Changelog](https://github.com/eslint/eslint/blob/main/CHANGELOG.md)
- [Commits](https://github.com/eslint/eslint/compare/v8.48.0...v8.49.0)

---
updated-dependencies:
- dependency-name: "@typescript-eslint/eslint-plugin"
  dependency-type: direct:development
  update-type: version-update:semver-minor
  dependency-group: eslint
- dependency-name: "@typescript-eslint/parser"
  dependency-type: direct:development
  update-type: version-update:semver-minor
  dependency-group: eslint
- dependency-name: eslint
  dependency-type: direct:development
  update-type: version-update:semver-minor
  dependency-group: eslint
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-09-12 10:21:47 +03:00
dependabot[bot] 3e0969004d chore: bump ts-proto from 1.156.0 to 1.157.0 in /site (#9631)
Bumps [ts-proto](https://github.com/stephenh/ts-proto) from 1.156.0 to 1.157.0.
- [Release notes](https://github.com/stephenh/ts-proto/releases)
- [Changelog](https://github.com/stephenh/ts-proto/blob/main/CHANGELOG.md)
- [Commits](https://github.com/stephenh/ts-proto/compare/v1.156.0...v1.157.0)

---
updated-dependencies:
- dependency-name: ts-proto
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-09-12 10:21:09 +03:00
dependabot[bot] abbd780373 chore: bump cronstrue from 2.31.0 to 2.32.0 in /site (#9632)
Bumps [cronstrue](https://github.com/bradymholt/cronstrue) from 2.31.0 to 2.32.0.
- [Release notes](https://github.com/bradymholt/cronstrue/releases)
- [Changelog](https://github.com/bradymholt/cRonstrue/blob/main/CHANGELOG.md)
- [Commits](https://github.com/bradymholt/cronstrue/compare/v2.31.0...v2.32.0)

---
updated-dependencies:
- dependency-name: cronstrue
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-09-12 10:20:54 +03:00
dependabot[bot] d4bdb96883 chore: bump google.golang.org/grpc from 1.57.0 to 1.58.0 (#9563)
Bumps [google.golang.org/grpc](https://github.com/grpc/grpc-go) from 1.57.0 to 1.58.0.
- [Release notes](https://github.com/grpc/grpc-go/releases)
- [Commits](https://github.com/grpc/grpc-go/compare/v1.57.0...v1.58.0)

---
updated-dependencies:
- dependency-name: google.golang.org/grpc
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-09-12 10:18:21 +03:00
Kayla Washburn 13acf5976c chore: remove i18next (#9608) 2023-09-11 11:17:58 -06:00
Marcin Tojek 1a1c230534 fix(docs): skip >> character (#9616) 2023-09-11 12:23:40 +02:00
Marcin Tojek 67fe3ae8d6 feat: clean stale provisioner files (#9545) 2023-09-11 07:37:14 +00:00
sharkymark d055f93706 Docs coder apps web ides (#9613)
* chore: document external URLs, refresh web IDE images

* chore: coder_app external URL, updated images, file browser

* Update docs/ides/web-ides.md

---------

Co-authored-by: Muhammad Atif Ali <atif@coder.com>
2023-09-10 20:26:59 +00:00
Muhammad Atif Ali 84ede326e8 docs: add VS Code Web to web-ides (#9591) 2023-09-10 02:32:41 +00:00
Ammar Bandukwala f703a5b34e chore(cli): lighten flags on help page (#9606) 2023-09-08 13:43:56 -05:00
Ammar Bandukwala e361f1107b feat(cli): colorize help page (#9589) 2023-09-08 18:21:33 +00:00
Bruno Quaresma 11404af9ca chore(site): update files to use a more standard naming (#9605) 2023-09-08 15:14:41 -03:00
Bruno Quaresma 554ddb11cd chore(site): refactor stories and test from page components (#9603)
* Refactor AuditPage

* Refactor CliAuthPageView stories

* Refactor CreateTemplateForm stories

* Refactor CreateUserPage test

* Refactor CreateWorkspacePage tests

* Fix stories name

* Refactor AppereancePageView stories

* Refactor GitAuthSettingsPageView stories

* Refactor NetworkSettingsPageView stories

* Refactor SecuritySettingsPageView stories

* Refactor UserAuthSettingsPageView stories

* Refactor GroupsPage stories

* Refactor LoginPage tests

* Refactor SetupPage stories

* Refactor StarterTemplatePageView stories

* Refactor StarterTemplatesPage tests

* Refactor TemplatePage tests

* RefactorTemplateSettingsPage tests

* Refactor TemplatesPage tests

* Flat TemplateVersionEditorPage

* Refactor TemplateVersionPage stories

* Refactor UserSettingsPage stories

* Refactor UsersPage stories

* Simplify IndexPage

* Refactor WorkspaceSettingsPage stories

* Refactor WorkspacePage stories

* Refactor Conditionals stories

* Fix typo

* Fix imports

* Fix ChooseOne story

* Fix UserAuthSettingsPageView stories
2023-09-08 15:14:13 -03:00
David Morcillo 9e5a59e222 Update upgrade.md (#9569)
Fix wrong docker-compose update instructions.
2023-09-08 10:38:35 -04:00
Marcin Tojek ad23075e1b refactor: build application URL (#9601)
* refactor: build application URL

* fix
2023-09-08 14:01:57 +00:00
Cian Johnston 392b11272b fixup! fix(scripts): modify logic for determining terraform arch (#9595) (#9596) 2023-09-08 11:07:57 +00:00
Cian Johnston a3a16a1586 fix(scripts): modify logic for determining terraform arch (#9595)
Commit fb3616c used a build-arg to set the desired terrafomr
architeture to fetch. This is set in build_docker.sh but not
when building using depot.dev. Baking the logic into the
Dockerfile instead.
2023-09-08 10:47:51 +00:00
Spike Curtis 8d7eb1728c fix: stop inserting provisioner daemons into the database (#9108)
Signed-off-by: Spike Curtis <spike@coder.com>
2023-09-08 10:37:36 +00:00
Cian Johnston fb3616c37e fix(scripts): wget terraform directly from releases.hashicorp.com (#9594) 2023-09-08 10:02:18 +00:00
Spike Curtis 11b6068112 feat: add support for networked provisioners (#9593)
* Refactor provisionerd to use interface to connect to provisioners

Signed-off-by: Spike Curtis <spike@coder.com>

* feat: add support for networked provisioners

Signed-off-by: Spike Curtis <spike@coder.com>

* fix token length and linting

Signed-off-by: Spike Curtis <spike@coder.com>

---------

Signed-off-by: Spike Curtis <spike@coder.com>
2023-09-08 09:53:48 +00:00
Kayla Washburn 8b51a2f3c5 docs: mention the need for permission to read email addresses (#9588) 2023-09-07 16:40:22 -06:00
Ammar Bandukwala dd97fe2bce chore(cli): replace lipgloss with coder/pretty (#9564)
This change will improve over CLI performance and "snappiness" as well as
substantially reduce our test times. Preliminary benchmarks show
`coder server --help` times cut from 300ms to 120ms on my dogfood
instance.

The inefficiency of lipgloss disproportionately impacts our system, as all help
text for every command is generated whenever any command is invoked.

The `pretty` API could clean up a lot of the code (e.g., by replacing
complex string concatenations with Printf), but this commit is too
expansive as is so that work will be done in a follow up.
2023-09-07 16:28:22 -05:00
Kayla Washburn 8421f56137 refactor: bring back updated install.sh with patches (#9583) 2023-09-07 21:17:16 +00:00
Eric Paulsen ccda1c5c7d fix: rm tf provider versions in examples/ (#9586) 2023-09-07 18:53:23 +00:00
Cian Johnston 0306631518 fix(docs): fix broken link (#9585) 2023-09-07 18:36:26 +00:00
Bruno Quaresma 869d040cc6 chore(site): refactor stories and tests from components directory (#9578)
* Refactor Alert

* Refactor Avatar and its stories

* Refactor AvatarData and its stories

* Refactor CodeExample and its tests

* Refactor ServiceBanner stories

* Refactor Navbar and its tests

* Refactor ServiceBanner stories

* Refactor LicenseBannerView stories

* Refactor DeploymentBannerView stories

* Extract optionValue into a module

* Refactor DeleteDialog stories

* Refactor ConfirmDialog tests

* Refactor EmptyState tests

* Flat ErrorBoundaryState and refactor stories

* Refactor Expander stories

* Refactor FormFooter stories

* Refactor FullPageForm stories

* Refactor EnterpriseSnackbar stories

* Refactor GroupAvatar stories

* Refactor HelpTooltip stories and remove index

* Remove unecessary types module from IconField

* Refactor LoadingButton stories

* Refactor Margins stories

* Refactor Markdown stories

* Refactor PageHeader stories

* Refactor PageButton tests

* Refactor Pill stories

* Refactor Resources stories

* Refactor RichParameterInput stories and flat MultiTextField

* Remove unecessary Stack story

* Refactor TableRowMenu stories

* Refactor TemplateLayout stories

* Refactor Typography props

* Refactor UserAutocomplete

* Refactor WorkspaceBuildLogs components and tests

* Refactor WorkspaceStatusBadge stories

* Fix wrong imports

* Remove Example.args pattern

* Fix wrong import

* Refactor EmptyState stories

* Refactor HelpTooltip stories

* Remove not valid ErrorAlert story

* Fix AvatarData story

* Add border back to CodeExample

* Fix Navbar story

* Fix AgentRow proxy in the stories
2023-09-07 18:38:28 +02:00
Kayla Washburn 4f142fa959 feat: add minimal frontend for creating workspaces from specific template versions (#9475) 2023-09-07 10:33:42 -06:00
Mathias Fredriksson 40fcabfa0e chore(go.mod): update github.com/hashicorp/terraform-json to main (#9582) 2023-09-07 16:06:28 +00:00
Cian Johnston 7d7c84bb4d feat(coderd): connect dbcrypt package implementation (#9523)
See also: https://github.com/coder/coder/pull/9522

- Adds commands `server dbcrypt {rotate,decrypt,delete}` to re-encrypt, decrypt, or delete encrypted data, respectively.
- Plumbs through dbcrypt in enterprise/coderd (including unit tests).
- Adds documentation in admin/encryption.md.

This enables dbcrypt by default, but the feature is soft-enforced on supplying external token encryption keys. Without specifying any keys, encryption/decryption is a no-op.
2023-09-07 15:49:49 +01:00
Mathias Fredriksson ed7f682fd1 chore(go.mod): update github.com/hashicorp/terraform-json to v0.17.1 (#9570) 2023-09-07 14:55:39 +03:00
dependabot[bot] 5a6f6e5679 chore: bump the golang-x group with 4 updates (#9562)
Bumps the golang-x group with 4 updates: [golang.org/x/crypto](https://github.com/golang/crypto), [golang.org/x/net](https://github.com/golang/net), [golang.org/x/oauth2](https://github.com/golang/oauth2) and [golang.org/x/tools](https://github.com/golang/tools).


Updates `golang.org/x/crypto` from 0.12.0 to 0.13.0
- [Commits](https://github.com/golang/crypto/compare/v0.12.0...v0.13.0)

Updates `golang.org/x/net` from 0.14.0 to 0.15.0
- [Commits](https://github.com/golang/net/compare/v0.14.0...v0.15.0)

Updates `golang.org/x/oauth2` from 0.11.0 to 0.12.0
- [Commits](https://github.com/golang/oauth2/compare/v0.11.0...v0.12.0)

Updates `golang.org/x/tools` from 0.12.0 to 0.13.0
- [Release notes](https://github.com/golang/tools/releases)
- [Commits](https://github.com/golang/tools/compare/v0.12.0...v0.13.0)

---
updated-dependencies:
- dependency-name: golang.org/x/crypto
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: golang-x
- dependency-name: golang.org/x/net
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: golang-x
- dependency-name: golang.org/x/oauth2
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: golang-x
- dependency-name: golang.org/x/tools
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: golang-x
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-09-07 08:26:40 +00:00
Kayla Washburn fd565e0e0b chore: enable test-2e (#9567) 2023-09-07 05:49:40 +00:00
Kayla Washburn bfff88d2d3 revert: improve flag interpretation for install.sh (#9566) 2023-09-07 05:29:52 +00:00
Muhammad Atif Ali 2dae60038a fix(docs): fix manifest of gcp docs (#9559) 2023-09-06 22:21:00 +03:00
Kayla Washburn fd8a86808f chore: add #9555 to .git-blame-ignore-revs (#9557) 2023-09-06 13:10:58 -06:00
Kayla Washburn 988c9af015 chore: format code with semicolons when using prettier (#9555) 2023-09-06 12:59:26 -06:00
Muhammad Atif Ali bef38b8413 docs: update google-cloud-platform docs to use our marketplace image (#9549) 2023-09-06 21:58:14 +03:00
Kayla Washburn 4ed8dd0d6c refactor: improve flag interpretation for install.sh (#9554) 2023-09-06 12:57:28 -06:00
Bruno Quaresma b15bfa41c2 chore(site): move components close to where they are used (#9552)
* Move AppLink

* Move AuditLogRow

* Move UserDropdown

* Move BuildsTable

* Remove CodeBlock

* Move CreateUserForm

* Move DeploymentBanner

* Move ResetPassworDialog

* Move EditRolesButton

* Move EnterpriseSnackbar

* Move GitAuth

* Move LicenseBanner

* Move Logs

* Move MultiTextField

* Move Navbar

* Remove PasswordField

* Move RuntimeErrorState

* Remove Section

* Move SectionAction

* Move ServiceBanner

* Move SettingsAccountForm

* Move LicenseCard

* Move SettingsSecurityForm

* Move SignInForm

* Remove TabPanel and TabSidebar

* Move TemplateStats and TemplateVariableField

* Move TemplateEditor

* Move TerminalLink

* Move SSH Button

* Move many tooltips

* Move UsersTable

* Move VersionsTable

* Move VSCodeDesktopButton

* Remove WarningAlert

* Move Workspace

* Move WorkspaceActions

* Move WorkspaceBuildProgress

* Move WorkspaceDeletedBanner

* Move WorkspaceScheduleForm

* Move WorkspaceSection

* Move WorkspaceStats

* Fix imports

* Flat CreateUserForm

* Flat GitAuth

* Transform WorkspaceSection into ChartSection

* Flat AccountForm

* Flat ConfirmDeleteDialog

* Flat ResetPasswordDialog

* Flat BuildsTable
2023-09-06 18:06:08 +00:00
Kayla Washburn 75139d1d06 refactor(site): update versions table design (#9540) 2023-09-06 08:31:07 -06:00
Ben Potter 1bcc4152af chore: avoid formatting changelogs (#9548) 2023-09-06 14:26:50 +00:00
Eric Paulsen 4ec2fea66b docs: fix psk secret cmd (#9524) 2023-09-06 09:04:44 -04:00
Cian Johnston 7918e65510 feat(coderd): add dbcrypt package (#9522)
- Adds package enterprise/dbcrypt to implement database encryption/decryption
- Adds table dbcrypt_keys and associated queries
- Adds columns oauth_access_token_key_id and oauth_refresh_token_key_id
  to tables git_auth_links and user_links

Co-authored-by: Kyle Carberry <kyle@coder.com>
2023-09-06 12:06:26 +01:00
Spike Curtis 3bd0fd396c feat: add boringcrypto builds for linux (#9543)
This reverts commit da0ef92f77.
2023-09-06 12:48:27 +04:00
Kayla Washburn 2849895832 fix: use $coder_version instead of hardcoded version in release script (#9539) 2023-09-05 17:30:54 -06:00
Ben Potter 66019ef70a docs: add v2.1.6 changelog (#9538) 2023-09-05 21:44:12 +00:00
Alexis Emerson d85c354507 docs: add CODER_TLS_ADDRESS to documentation for TLS setup (#9503)
Co-authored-by: Muhammad Atif Ali <atif@coder.com>
2023-09-05 19:07:56 +00:00
Steven Masley 630d125286 chore: fix typo in OpenID on cli help (#9535) 2023-09-05 18:37:21 +00:00
Muhammad Atif Ali 2487e64d25 fix(docs): fix broken markdown links (#9534) 2023-09-05 18:12:04 +00:00
Kyle Carberry 82e238b0c6 chore: exclude generated files from vscode search by default (#9530)
Anyone can feel free to revert some of these, but they were constantly
annoying when searching for symbols in our code.
2023-09-05 15:05:46 +00:00
Steven Masley 58f7071569 fix: make 'NoRefresh' honor unlimited tokens in gitauth (#9472)
* chore: fix NoRefresh to honor unlimited tokens
* improve testing coverage of gitauth
* refactor rest of gitauth tests
2023-09-05 09:08:04 -05:00
Kyle Carberry da0ef92f77 Revert "feat: add boringcrypto builds for linux (#9528)" (#9529)
This reverts commit 79cd6047dc.
2023-09-05 08:37:07 -05:00
Spike Curtis 79cd6047dc feat: add boringcrypto builds for linux (#9528)
* feat: add boringcrypto builds for linux

Signed-off-by: Spike Curtis <spike@coder.com>

* strip debug symbols, add BoringCryto to buildinfo

Signed-off-by: Spike Curtis <spike@coder.com>

* Fix TestVersion

Signed-off-by: Spike Curtis <spike@coder.com>

---------

Signed-off-by: Spike Curtis <spike@coder.com>
2023-09-05 13:12:38 +00:00
dependabot[bot] ce08c47b8a chore: bump github.com/gohugoio/hugo from 0.117.0 to 0.118.2 (#9516)
Bumps [github.com/gohugoio/hugo](https://github.com/gohugoio/hugo) from 0.117.0 to 0.118.2.
- [Release notes](https://github.com/gohugoio/hugo/releases)
- [Changelog](https://github.com/gohugoio/hugo/blob/master/hugoreleaser.toml)
- [Commits](https://github.com/gohugoio/hugo/compare/v0.117.0...v0.118.2)

---
updated-dependencies:
- dependency-name: github.com/gohugoio/hugo
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-09-05 11:52:26 +03:00
Mathias Fredriksson 76ab22f539 chore(coderd/database): introduce compile-time guard against import in slim build (#9521)
This change introduces a compile-time error when `coderd/database` is
imported into the slim build. This is to guard against accidentally
growing the binary size via import.

Ref: #9380
2023-09-04 19:01:11 +00:00
Mathias Fredriksson adba421524 refactor(coderd/telemetry): move CLI telemetry to cli/telemetry (#9517)
This change removes an indirect import of `coderd/database` from the
slim binary.

No size change (yet).

Ref: #9380
2023-09-04 21:42:45 +03:00
Mathias Fredriksson b240799f47 refactor(cli): use codersdk for provisioner types (#9508)
This change removes one use of `coderd/database` from the slim binary
and more correctly uses codersdk instead of database or provisionerd
packages.

No size change (yet).

Ref: #9380
2023-09-04 21:42:15 +03:00
Mathias Fredriksson 39e3b049a5 refactor(coderd/healthcheck): move derp report to derphealth package (#9506)
This change helps remove one indirect use of coderd/database in the slim
CLI.

No size change (yet).

Ref: #9380
2023-09-04 21:41:50 +03:00
Mathias Fredriksson a1025f92af refactor(examples): pre-parse frontmatter via scripts/examplegen (#9514)
* refactor(examples): pre-parse frontmatter via scripts/examplegen

This removes 2 MB from the slim binary.

Ref: #9380
2023-09-04 20:15:29 +03:00
Mathias Fredriksson 6fc1f5276d refactor(coderd/httpapi): remove database, dbauthz and rbac imports (#9481)
Ref: #9380
2023-09-04 19:39:14 +03:00
Mathias Fredriksson d2115941b7 refactor(cli)!: remove reset-password from slim binary (#9520)
This is an alternative approach to #9519 and removes 2 MB instead of 1
MB (1.2 MB accounted for by embedded migration SQL files).

Combined with #9481, #9506, #9508, #9517, a total of 5 MB is removed.

Ref: #9380
2023-09-04 19:38:53 +03:00
Mathias Fredriksson ad23d33f28 refactor(coderd/schedule): move cron schedule to cron package (#9507)
This removes an indirect import of `coderd/database` from the CLI and
results in a logical separation between server related and generalized
schedule.

No size change (yet).

Ref: #9380
2023-09-04 16:48:25 +03:00
dependabot[bot] c31292abe8 ci: bump the github-actions group with 2 updates (#9509)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-09-04 16:29:56 +03:00
Muhammad Atif Ali 29b2eaa217 fix(cli/dotfiles): add an exception for .gitconfig (#9515)
* fix(cli/dotfiles): Only ignore .git directory 

Resolves #8306

* fix fmt

* add exception for .gitconfig

* Update dotfiles.go
2023-09-04 13:17:07 +00:00
Marcin Tojek aa94d89f97 test: improve E2E framework (#9469) 2023-09-04 14:46:48 +02:00
dependabot[bot] 91cb9c65f9 chore: bump github.com/hashicorp/hc-install from 0.5.2 to 0.6.0 (#9511)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-09-04 15:29:10 +03:00
dependabot[bot] c2be893b7f chore: bump github.com/open-policy-agent/opa from 0.55.0 to 0.56.0 (#9512)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-09-04 15:28:51 +03:00
dependabot[bot] c5714f2b47 chore: bump github.com/swaggo/swag from 1.8.6 to 1.16.2 (#9513)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-09-04 15:28:39 +03:00
dependabot[bot] cb5347bb12 chore: bump the golang-x group with 3 updates (#9510)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-09-04 15:27:03 +03:00
Bruno Quaresma b9f604c58d fix(site): fix workspace parameters update when having immutable parameters (#9500) 2023-09-03 21:56:25 -03:00
Ben Potter f5829d2be6 chore(dogfood): authenticate to coder CLI if unauthenticated (#9487) 2023-09-04 02:26:48 +03:00
Kyle Carberry 05439d2c1b fix: generate username with uuid to prevent collision (#9496)
See https://github.com/coder/coder/actions/runs/6052801777/job/16426982174
2023-09-03 18:02:28 +00:00
sharkymark 43ebf667f0 docs: explain why coder port-forward is more performant than dashboard and sshd (#9494) 2023-09-03 10:10:48 -05:00
Mathias Fredriksson 18c9f33dec chore: use tailscale extra small buildflags (#9490)
Ref: #9380
2023-09-01 19:14:56 +00:00
Mathias Fredriksson 27ab0d9a84 refactor(enterprise/cli): remove provisionerd from slim binary (#9488)
This change saves 8 MB in the slim binary.

Ref: #9380
2023-09-01 18:26:44 +00:00
Mathias Fredriksson 19d7da3d24 refactor(coderd/database): split Time and Now into dbtime package (#9482)
Ref: #9380
2023-09-01 16:50:12 +00:00
Mathias Fredriksson 702b064cac refactor: split coderd/gitauth into two, add cli/gitauth (#9479)
* refactor: split coderd/gitauth into two, add cli/gitauth

Ref: #9380
2023-09-01 15:41:22 +00:00
Mathias Fredriksson d8718c3818 chore: add ts_omit_aws tag to remove aws dependency pulled in by tailscale (#9486)
On Linux, this saves us 7 MB.

Ref: #9380
2023-09-01 18:37:49 +03:00
Mathias Fredriksson f1f9cb030d refactor(cli): avoid importing coderd in slim server (#9483)
This small change removes 11 MB from the slim binary size.

Ref: #9380
2023-09-01 13:32:21 +00:00
Marcin Tojek 5d7a77911e fix: use getProvisionerJobByIDNoLock (#9484) 2023-09-01 13:21:18 +00:00
Cian Johnston bc9fdd15f2 fix(enterprise/cli): correctly set default tags for PSK auth (#9436)
* provisionerd: unconditionally set tag scope to org for psk auth
* provisionerd: add unit tests for MutateTags
* cli: add some informational logging around provisionerd tags
* cli: respect CODER_VERBOSE when initializing logger
2023-09-01 10:37:09 +01:00
Colin Adler 8ee6178c66 chore(tailnet): fix MultiAgentConn mockgen (#9476) 2023-08-31 22:37:05 +00:00
Kayla Washburn eded7a4b88 feat: create a workspace from any template version (#9471) 2023-08-31 15:07:58 -06:00
Colin Adler 796a9754a9 feat(enterprise/audit): add user object to slog exporter (#9456) 2023-08-31 13:32:28 -05:00
Marcin Tojek 11d4b6f758 chore: move dormancy to enterprise package (#9468) 2023-08-31 17:59:53 +02:00
Marcin Tojek 7c4ce62a58 test(site): print agent logs (#9464) 2023-08-31 14:44:44 +02:00
Cian Johnston 22f31e721c fix(coderd/prometheusmetrics): close batcher to force flush before asserting agent stats (#9465) 2023-08-31 11:40:57 +01:00
Cian Johnston fd17857095 fix(cli): template pull tests: await template version job before exiting (#9430) 2023-08-31 11:40:24 +01:00
Spike Curtis ed50acaabf fix: don't log error on context cancel (#9463)
Signed-off-by: Spike Curtis <spike@coder.com>
2023-08-31 12:08:18 +04:00
Muhammad Atif Ali 73976dd076 fix: fix aws_linux template (#9349) 2023-08-31 04:24:10 +03:00
dependabot[bot] 2aa66ad7c3 chore: bump monaco-editor from 0.40.0 to 0.41.0 in /site (#9458)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-08-31 02:23:32 +03:00
dependabot[bot] 723bba98ff chore: bump jest-canvas-mock from 2.4.0 to 2.5.2 in /site (#9460)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-08-31 02:22:54 +03:00
dependabot[bot] 83cee77de0 chore: bump cronstrue from 2.28.0 to 2.31.0 in /site (#9459)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-08-31 02:22:39 +03:00
dependabot[bot] f4affda554 chore: bump cron-parser from 4.7.0 to 4.9.0 in /site (#9455)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-08-30 23:13:48 +00:00
dependabot[bot] 03052c2e64 chore: bump @testing-library/jest-dom (#9375)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Atif Ali <atif@coder.com>
2023-08-30 23:02:01 +00:00
dependabot[bot] e8047838b3 chore: bump chart.js from 4.3.3 to 4.4.0 in /site (#9454)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-08-30 22:45:59 +00:00
dependabot[bot] 8841e23065 chore: bump the eslint group in /site with 7 updates (#9450)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Atif Ali <atif@coder.com>
2023-08-31 01:42:48 +03:00
dependabot[bot] c6f0d5a6e0 chore: bump axios from 1.3.4 to 1.5.0 in /site (#9452)
Bumps [axios](https://github.com/axios/axios) from 1.3.4 to 1.5.0.
- [Release notes](https://github.com/axios/axios/releases)
- [Changelog](https://github.com/axios/axios/blob/v1.x/CHANGELOG.md)
- [Commits](https://github.com/axios/axios/compare/v1.3.4...v1.5.0)

---
updated-dependencies:
- dependency-name: axios
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-08-30 19:38:10 -03:00
dependabot[bot] a67bd2ce3b chore: bump @tanstack/react-query from 4.32.0 to 4.33.0 in /site (#9453)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-08-31 01:31:00 +03:00
Kayla Washburn 4c91146cb8 fix: hide OIDC and Github auth settings when they are disabled (#9447) 2023-08-30 15:56:18 -06:00
Ammar Bandukwala 8f3b4075c7 ci: enable nestif linter (#9363) 2023-08-30 21:50:43 +00:00
Bruno Quaresma d29696296f refactor(site): refactor rich parameter input and form initial data (#9440) 2023-08-30 18:42:36 -03:00
dependabot[bot] db93f17dab chore: bump eslint from 8.46.0 to 8.48.0 in /offlinedocs (#9366)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-08-31 00:31:11 +03:00
dependabot[bot] 6268904421 chore: bump the storybook group in /site with 7 updates (#9449)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-08-31 00:27:46 +03:00
Steven Masley e827278db7 feat: failed update refresh should redirect to login (#9442)
* chore: update refresh oauth token message
* chore: unauthorized -> forbidden for non authentication failures
* redirect to login on all 401 responses
* add unit test to verify 401 on expired refresh
2023-08-30 16:14:24 -05:00
dependabot[bot] b9fbc541c6 chore: bump framer-motion from 10.15.0 to 10.16.1 in /offlinedocs (#9369)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-08-31 00:14:02 +03:00
dependabot[bot] 2bc8ba251d chore: bump archiver from 5.3.1 to 6.0.0 in /offlinedocs (#9367)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-08-31 00:13:52 +03:00
dependabot[bot] 5b1da77291 chore: bump github.com/valyala/fasthttp from 1.48.0 to 1.49.0 (#9385)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-08-31 00:13:19 +03:00
dependabot[bot] e4543e0e14 chore: bump the otel group with 4 updates (#9413)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-08-31 00:12:42 +03:00
dependabot[bot] 2c1b92b1d2 chore: bump chromatic from 6.20.0 to 6.24.1 in /site (#9377)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-08-31 00:11:05 +03:00
dependabot[bot] bb478d4939 chore: bump @playwright/test from 1.36.0 to 1.37.1 in /site (#9378)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-08-31 00:10:31 +03:00
Dean Sheather 1de61246a3 feat: add experimental template autostop requirement template settings UI (#9417) 2023-08-30 20:41:27 +00:00
Kayla Washburn d2462e5b88 docs: add macOS installation page (#9443) 2023-08-30 14:37:51 -06:00
Denbeigh Stevens 53a5f18ba4 fix(examples): remove reference to non-existent local variable (#9448) 2023-08-30 20:14:11 +00:00
Jon Ayers ee24260614 feat: allow configuring display apps from template (#9100) 2023-08-30 14:53:42 -05:00
Kayla Washburn 9c9d035354 feat: automate updating homebrew tap formula (#9412) 2023-08-30 13:44:38 -06:00
Kayla Washburn c6f4f0f8ad feat: install from homebrew in install.sh (#9414) 2023-08-30 11:58:53 -06:00
Mathias Fredriksson 21f3282c82 chore(dogfood): fix code-server folder (#9437) 2023-08-30 20:08:06 +03:00
Bruno Quaresma a2516b5fc3 fix(site): remove checkbox from ws table loader (#9441) 2023-08-30 14:06:39 -03:00
Marcin Tojek 2377ab6624 test(site): improve E2E framework (#9438) 2023-08-30 15:34:45 +00:00
Steven Masley a910e934a4 chore: improve error message around gitaskpass failures (#9407) 2023-08-30 08:58:31 -05:00
Bruno Quaresma 2399063a56 feat(site): make workspace batch deletion GA (#9313) 2023-08-30 10:08:42 -03:00
Spike Curtis 90acf998bf fix: fix null pointer on external provisioner daemons with daily_cost (#9401)
* fix: fix null pointer on external provisioner daemons with daily_cost

Signed-off-by: Spike Curtis <spike@coder.com>

* Add logging for debounce and job acquire

Signed-off-by: Spike Curtis <spike@coder.com>

* Return error instead of panic

Signed-off-by: Spike Curtis <spike@coder.com>

* remove debounce on external provisioners to fix test flakes

Signed-off-by: Spike Curtis <spike@coder.com>

---------

Signed-off-by: Spike Curtis <spike@coder.com>
2023-08-30 10:48:35 +00:00
Spike Curtis a415395e9e fix: stop dropping error log on context canceled after heartbeat (#9427)
Signed-off-by: Spike Curtis <spike@coder.com>
2023-08-30 14:44:00 +04:00
Marcin Tojek 3e67d8fa6a docs: describe dynamic options and locals (#9429) 2023-08-30 12:30:24 +02:00
Ammar Bandukwala 16ef97a061 feat(cli): add DataDog Go tracer (#9411) 2023-08-29 22:14:28 +00:00
Eric Paulsen 9ceba20ea4 docs: add jetbrains offline mode config steps (#9388) 2023-08-29 17:04:49 -04:00
Colin Adler 64ef867b4f fix(tailnet): re-add keepalives (#9410) 2023-08-29 15:21:30 -05:00
Colin Adler 8443d3e0f8 fix(enterprise): ensure audit log json fields are formatted correctly (#9397) 2023-08-29 13:36:54 -05:00
Dean Sheather a572800d47 chore: rename template restart requirement to autostop requirement (#9295) 2023-08-29 18:35:05 +00:00
Bruno Quaresma fc4683d8b3 chore: support protobuf files in the UI (#9408) 2023-08-29 17:26:23 +00:00
Mathias Fredriksson 605d2b20e2 chore(go.mod): update github.com/fergusstrange/embedded-postgres to v1.24.0 (#9405) 2023-08-29 19:00:38 +03:00
Marcin Tojek f5d813c4fb test(site): e2e: update workspace with parameters (#9338) 2023-08-29 15:10:31 +02:00
Mathias Fredriksson 3557497ea4 test(coderd): fix workspace rename test (#9402)
Fixes #9400
2023-08-29 11:42:42 +00:00
Dean Sheather 5993f85ec9 fix: avoid redirect loop on workspace proxies (#9389)
* fix: avoid redirect loop on workspace proxies

---------

Co-authored-by: Steven Masley <stevenmasley@coder.com>
2023-08-28 20:34:52 -05:00
Ben Potter eb68684327 docs: add v2.1.4 changelog (#9398)
* docs: add v2.1.4 changelog

* fmt

* reorder

* clarify
2023-08-28 22:55:09 +00:00
Mathias Fredriksson be47cc58ff fix(enterprise/coderd): use websocketNetConn in workspaceProxyCoordinate to bind context (#9395) 2023-08-28 23:12:45 +03:00
Mathias Fredriksson 487bdc2e08 fix(coderd): allow workspaceAgentLogs follow to return on non-latest-build (#9382) 2023-08-28 19:46:42 +00:00
Steven Masley fea8813f13 chore: drop 'template plan' unused command (#9386) 2023-08-28 13:33:40 -05:00
Bruno Quaresma 2167fe16d6 chore: remove e2e workaround (#9393) 2023-08-28 15:24:01 -03:00
Bruno Quaresma d138ed7314 fix(coderd): send updated workspace data adter ws connection (#9392) 2023-08-28 15:14:17 -03:00
Dean Sheather a2be2f9838 fix: avoid derp-map updates endpoint leak (#9390) 2023-08-28 18:13:19 +00:00
Kayla Washburn ce9b048f06 feat(site): improve template publishing flow (#9346) 2023-08-28 11:27:51 -06:00
Marcin Tojek 80425c32bf fix(site): workaround: reload page every 3sec (#9387) 2023-08-28 16:22:39 +00:00
Muhammad Atif Ali 35d0809830 ci: prefix dependabot github-actions PRs with ci: (#9376) 2023-08-28 18:20:52 +03:00
dependabot[bot] b6e808d116 chore: bump github.com/charmbracelet/lipgloss from 0.7.1 to 0.8.0 (#9370)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-08-28 14:08:32 +03:00
dependabot[bot] 506b81adeb ci: bump crate-ci/typos@v1.16.6 to crate-ci/typos@v1.16.8 (#9372)
bumps crate-ci/typos@v1.16.6 to crate-ci/typos@v1.16.8
2023-08-28 09:41:05 +00:00
Muhammad Atif Ali 79aba1d5ff ci: remove redundant groups from dependabot.yaml (#9365) 2023-08-28 09:21:54 +00:00
Ammar Bandukwala 594a6aae19 chore: format oidctest (#9362) 2023-08-27 19:51:13 +00:00
Ammar Bandukwala 6ba92ef924 ci: enable gocognit (#9359)
And, bring the server under 300:

* Removed the undocumented "disable" STUN address in favor of the
--disable-direct flag.
2023-08-27 14:46:44 -05:00
Ben Potter 173aac959c fix(systemd): use more reasonable restart limit (#9355) 2023-08-27 14:35:06 -05:00
Ammar Bandukwala 4a140536e1 ci: lint against dupl (#9357)
This lint rule should help us keep Go code redundancy under control.
2023-08-27 11:42:51 -05:00
Kyle Carberry 61634d482f fix: truncate websocket close error (#9360)
Related #9324
2023-08-27 16:26:31 +00:00
Kyle Carberry c3ac55ff42 feat: add template_active_version_id to workspaces (#9226)
* feat: add `template_active_version_id` to workspaces

This reduces a fetch in the VS Code extension when getting the
active version update message!

* Fix entities.ts

* Fix golden gen
2023-08-27 16:26:20 +00:00
Muhammad Atif Ali 54032ccfe8 ci: update pr-cleanup.yaml to remove set -x (#9358) 2023-08-26 23:02:22 +00:00
Muhammad Atif Ali f97b497966 chore(dogfood): update docker tf provider and metadata (#9356) 2023-08-27 01:22:28 +03:00
Ammar Bandukwala 451ca042ce feat(site): show entity name in DeleteDialog (#9347) 2023-08-25 22:16:30 +00:00
Muhammad Atif Ali 7904d0b92f docs: list firewall exceptions for restricted internet installations (#8936)
* docs: add firewall exceptions for restricted internet installtions

closes #7542

* fix link

* fmt
2023-08-25 23:48:35 +03:00
Bruno Quaresma 1de1e3b98a fix(site): make right panel scrollable on template editor (#9344) 2023-08-25 13:52:10 -06:00
Steven Masley d9d4d74f99 test: add full OIDC fake IDP (#9317)
* test: implement fake OIDC provider with full functionality
* Refactor existing tests
2023-08-25 14:34:07 -05:00
Bruno Quaresma 0a213a6ac3 refactor(site): improve the overall user table design (#9342) 2023-08-25 17:59:41 +00:00
Ammar Bandukwala 14f769d229 fix(site): use WebGL renderer for terminal (#9320) 2023-08-25 12:46:14 -05:00
Ammar Bandukwala e5c64a8ea9 fix(site): render variable width unicode characters in terminal (#9259)
Previously, characters such as 🟢 were given insufficient space, leading
to mangled output.
2023-08-25 17:45:36 +00:00
Eric Paulsen 91f900ec64 docs: expand on TTL flags (#9286)
* docs: expand on TTL flags

* make: gen

* Discard changes to site/src/api/api.ts

* Discard changes to site/src/xServices/templateVersion/templateVersionXService.ts

---------

Co-authored-by: Muhammad Atif Ali <matifali@live.com>
Co-authored-by: Muhammad Atif Ali <atif@coder.com>
2023-08-25 13:39:12 -04:00
Ammar Bandukwala f149db6ca6 fix(cli): add --max-ttl to template create (#9319)
It was just in template edit by mistake.
2023-08-25 11:00:38 -05:00
Muhammad Atif Ali 3b1ecd3c2f chore: update aws_linux template (#9325) 2023-08-25 13:50:03 +00:00
Marcin Tojek d7a788d89d test(site): e2e: restart workspace with ephemeral parameters (#9304) 2023-08-25 14:50:38 +02:00
Spike Curtis aed891b4ff fix: fix coder template pull on Windows (#9327)
* fix: fix coder template pull on Windows

Signed-off-by: Spike Curtis <spike@coder.com>

* appease linter

Signed-off-by: Spike Curtis <spike@coder.com>

* improvements from code review

Signed-off-by: Spike Curtis <spike@coder.com>

---------

Signed-off-by: Spike Curtis <spike@coder.com>
2023-08-25 10:58:13 +00:00
Spike Curtis e7a231e44f fix: fix test flake introduced by #9264 (#9330)
* Fix test flake introduced by #9264

Signed-off-by: Spike Curtis <spike@coder.com>

* change check to match suffix

Signed-off-by: Spike Curtis <spike@coder.com>

---------

Signed-off-by: Spike Curtis <spike@coder.com>
2023-08-25 10:48:42 +00:00
Bruno Quaresma 058fb2ecf0 fix(site): fix default ephemeral parameter value on parameters page (#9314) 2023-08-25 12:28:18 +02:00
Spike Curtis 60d5002eb6 refactor: change template archive extraction to be on provisioner (#9264)
* refactor provisionersdk protocol

Signed-off-by: Spike Curtis <spike@coder.com>

* refactor provisioners to use new protocol

Signed-off-by: Spike Curtis <spike@coder.com>

* refactor provisionerd to use new protocol

Signed-off-by: Spike Curtis <spike@coder.com>

* refactor tests & proto renames

* Fixes from self-review

Signed-off-by: Spike Curtis <spike@coder.com>

* appease fmt & link

Signed-off-by: Spike Curtis <spike@coder.com>

* code review fixes & e2e fixes

Signed-off-by: Spike Curtis <spike@coder.com>

* More fmt

Signed-off-by: Spike Curtis <spike@coder.com>

* Code review fixes

Signed-off-by: Spike Curtis <spike@coder.com>

* new gen; use uuid for session workdir

Signed-off-by: Spike Curtis <spike@coder.com>

* Revert nix-based gen CI task until dogfood is on nix

Signed-off-by: Spike Curtis <spike@coder.com>

* revert deleting dogfood Docker stuff

Signed-off-by: Spike Curtis <spike@coder.com>

* Revert "revert deleting dogfood Docker stuff"

This reverts commit 9762158167.

---------

Signed-off-by: Spike Curtis <spike@coder.com>
2023-08-25 06:10:15 +00:00
sharkymark 4bed492012 docs: ui option for adding licenses (#9322) 2023-08-24 22:23:59 -05:00
Jon Ayers 7ddb216d87 chore: revert nix-related CI changes (#9321)
* chore: revert nix-related CI changes

- Reverts using nix to run CI-dependencies.
- Running 'make gen' in a dogfood workspace resulted in inconsistent
  results for protobuf-related files making it difficult to pass CI.
  This PR imports the minimum changes necessary to make CI compatible
  with dogfood.
2023-08-24 21:26:30 -05:00
Ammar Bandukwala 630ec55c48 fix(coderd): remove rate limits from agent metadata (#9308)
Include the full update message in the PubSub notification so that
we don't have to refresh metadata from the DB and can avoid rate
limiting.
2023-08-24 15:18:42 -05:00
Jon Ayers 7f14b50dbe chore: rename locked to dormant (#9290)
* chore: rename locked to dormant

- The following columns have been updated:
  - workspace.locked_at -> dormant_at
  - template.inactivity_ttl -> time_til_dormant
  - template.locked_ttl -> time_til_dormant_autodelete

This change has also been reflected in the SDK.

A route has also been updated from /workspaces/<id>/lock to /workspaces/<id>/dormant
2023-08-24 13:25:54 -05:00
Ben Potter ebd878b6b5 chore: v2.1.3 changelog (#9311) 2023-08-24 17:35:00 +00:00
Dean Sheather 64df076328 feat: add server flag to force DERP to use always websockets (#9238) 2023-08-24 17:22:31 +00:00
Mathias Fredriksson 9cb913fb1a fix(go.mod): upgrade cdr.dev/slog to fix isTTY race (#9305) 2023-08-24 18:08:52 +03:00
Mathias Fredriksson af939d1e94 fix(coderd): optimize template app insights query for speed and decrease intervals (#9302) 2023-08-24 14:34:38 +00:00
Bruno Quaresma 67c8635543 fix(site): only show workspace actions if user has permission (#9303) 2023-08-24 11:28:59 -03:00
Bruno Quaresma 14aa1af45f refactor(site): remove as many 100vh units as possible(#9272) 2023-08-24 09:25:27 -03:00
Mathias Fredriksson 04d5e3f54f fix(coderd): rewrite template insights query for speed and fix intervals (#9300) 2023-08-24 14:38:32 +03:00
Mathias Fredriksson d00817ea4a perf(coderd): simplify insights queries to speed them up (#9299) 2023-08-24 10:52:20 +00:00
Mathias Fredriksson 6b69abfec7 fix(coderd): use stable sorting for insights and improve test coverage (#9250)
Fixes #9213
2023-08-24 13:36:40 +03:00
Cian Johnston 970072f61d chore(docs): add example scenario for parameter updates (#9298) 2023-08-24 10:35:20 +01:00
Marcin Tojek 52ea23355a docs: incompatibility in parameter options for workspace builds (#9297) 2023-08-24 11:05:31 +02:00
coryb 113894c045 fix(coderd): prevent oidc refresh being ignored (#9293) 2023-08-24 00:42:20 -05:00
Ben Potter f96622f192 chore: add exempt users to CLAbot allowlist (#9292) 2023-08-23 23:17:22 +00:00
Bruno Quaresma 6c93687095 fix(site): fix vertical scroll in the bottom bar (#9270) 2023-08-23 17:24:47 -03:00
Cian Johnston 2fa6a50de6 chore(docs): update scaling table (#9279) 2023-08-23 20:18:42 +00:00
Ben Potter e0ba80c872 chore: write v2.1.2 changelog (#9288) 2023-08-23 19:51:29 +00:00
Reuben Ellis 868ae06d4e chore: add a base directory for TurboSnap (#9258)
* Add base dir for TurboSnap

* updated main workflow as well

* Add vite configuration

* remove the mergeConfig and return config
2023-08-23 15:12:00 -03:00
dependabot[bot] 69b5c9cc27 chore: bump the react group in /site with 1 update (#9164)
Bumps the react group in /site with 1 update: [react-router-dom](https://github.com/remix-run/react-router/tree/HEAD/packages/react-router-dom).

- [Release notes](https://github.com/remix-run/react-router/releases)
- [Changelog](https://github.com/remix-run/react-router/blob/main/packages/react-router-dom/CHANGELOG.md)
- [Commits](https://github.com/remix-run/react-router/commits/react-router-dom@6.15.0/packages/react-router-dom)

---
updated-dependencies:
- dependency-name: react-router-dom
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: react
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-08-23 15:11:02 -03:00
Kyle Carberry 707a0a2d95 fix: resolve deadlock when fetching everyone group for in-memory db (#9277) 2023-08-23 16:54:16 +00:00
Marcin Tojek e845deaa89 fix: prompt when parameter options are incompatible (#9247) 2023-08-23 18:18:38 +02:00
Mathias Fredriksson 8bfa312905 fix(coderd): parallelize queries to improve template insights performance (#9275) 2023-08-23 15:31:23 +00:00
dependabot[bot] d180df1fd5 chore: bump google.golang.org/api from 0.137.0 to 0.138.0 (#9216)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-08-23 18:04:20 +03:00
dependabot[bot] cff33c2326 chore: bump the github-actions group with 1 update (#9218)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-08-23 18:03:59 +03:00
Kayla Washburn 72cb42b8e0 feat(site): add descriptions for each auth method to the selection menu (#9252) 2023-08-23 08:58:49 -06:00
Bruno Quaresma b6aedb9f1d refactor(site): improve how string values are displayed (#9273) 2023-08-23 11:32:55 -03:00
Dean Sheather f35423c041 fix: update conn derpmap every 5s in single tailnet (#9176) 2023-08-23 11:20:31 +00:00
Dean Sheather 53de47d4c8 chore: fix flake in TestDERPHeaders (#9262) 2023-08-23 21:03:39 +10:00
Marcin Tojek a3d31268a3 fix(cli): do not ask for immutables on update (#9266) 2023-08-23 12:46:52 +02:00
Marcin Tojek e6d90bd4fe fix: rewrite onlyDataResources (#9263) 2023-08-23 10:17:16 +00:00
Muhammad Atif Ali d37f6d80f7 chore(docs): update docs for correct use of shell and console and enforce linewidth (#9245) 2023-08-23 12:27:57 +03:00
Mathias Fredriksson ed2b1236c0 fix(coderd/batchstats): fix init race and close flush (#9248) 2023-08-23 11:58:25 +03:00
Kayla Washburn 31ffb566d0 fix: disable setup page once setup has been completed (#9198) 2023-08-22 14:57:46 -06:00
Jon Ayers 6e41cd1eda feat: add activity bumping to template scheduling (#9040) 2023-08-22 15:15:13 -05:00
Ammar Bandukwala 6214117d3d fix: pull agent metadata even when rate is high (#9251)
This commit fixes a bug where when the rate of metadata updates was
too high, the debounce caused a new update to get indefinitely delayed.
2023-08-22 13:55:00 -05:00
Kayla Washburn 697b0283c5 chore: fix low hanging lint issues (#9253) 2023-08-22 12:32:37 -06:00
Ben Potter 306615c674 docs: add v2.1.1 changelog (#9249)
* add WPL to manifest

* docs: add v2.1.1 changelog
2023-08-22 16:09:33 +00:00
Steven Masley 262d7692b6 feat: add force refresh of license entitlements (#9155)
* feat: add force refresh of license entitlements
* send "going away" mesasge on licenses pubsub on close
* Add manual refresh to licenses page
2023-08-22 09:26:43 -05:00
Steven Masley 37a3b42c55 feat: add last_used search params to workspaces (#9230)
* feat: add last_used search params to workspaces
2023-08-22 08:41:58 -05:00
Cian Johnston e57d635739 feat: add script to run a local keycloak instance (#9242) 2023-08-22 14:32:03 +01:00
Marcin Tojek 8a1da743cc test(site): e2e: create workspace with rich parameters (#9185) 2023-08-22 14:21:32 +02:00
Ammar Bandukwala 545a256b57 fix: correctly reject quota-violating builds (#9233)
Due to a logical error in CommitQuota, all workspace Stop->Start operations
were being accepted, regardless of the Quota limit. This issue only
appeared after #9201, so this was a minor regression in main for about
3 days. This PR adds a test to make sure this kind of bug doesn't recur.

To make the new test possible, we give the echo provisioner the ability
to simulate responses to specific transitions.
2023-08-22 02:55:39 +00:00
Ammar Bandukwala 69ec8d774b fix(cli/server): apply log filter to log message as well as name (#9232) 2023-08-21 17:53:26 -05:00
Kayla Washburn 2a263b9534 fix: always show add user button (#9229)
Fixes #9172

There is always at least one authentication method enabled (none), so we should remove the authMethod check to make sure that the button is always shown.
2023-08-21 15:44:20 -06:00
Ammar Bandukwala 4a9c7733d8 chore(dogfood): revert to pre-nix image (#9231) 2023-08-21 20:30:09 +00:00
Kyle Carberry 2a04d15c6d chore: downgrade dogfood image to postgres 13 (#9228) 2023-08-21 19:26:31 +00:00
Bruno Quaresma f6e02068e7 fix(site): fix ports update (#9221) 2023-08-21 14:32:59 -03:00
Bruno Quaresma 92445cf52e fix(site): fix locale dates in timeline component (#9223) 2023-08-21 14:24:54 -03:00
Cian Johnston 5c1ecfbd5f feat(scripts/develop.sh): provide an easy way to specify access url (#9222)
Allows `develop.sh --access-url="http://host:port"`
2023-08-21 17:23:07 +00:00
Steven Masley b2ca3ebaa3 fix: add workspace_proxy type to auditlog friendly strings (#9194)
* fix: add workspace_proxy type to auditlog friendly strings
* add unit test and organization type
2023-08-21 10:53:41 -05:00
Kyle Carberry 07188b123a chore: add dependencies for js-test to our nix flake (#9224) 2023-08-21 15:03:33 +00:00
Cian Johnston 5d4a17717f refactor(coderd): fetch owner information when authorizing workspace agent (#9123)
* Refactors the existing httpmw tests to use dbtestutil so that we can test them against a real database if desired,
* Modifies the GetWorkspaceAgentByAuthToken to return the owner and associated roles, removing the need for additional queries
2023-08-21 15:49:26 +01:00
Ammar Bandukwala 6d939b726c fix: correctly assess quota for stopped resources (#9201) 2023-08-21 09:01:16 -05:00
Mathias Fredriksson 509411f87c chore(flake.nix): add kubectx (#9219) 2023-08-21 15:54:22 +03:00
Mathias Fredriksson 03453b1e02 feat(coderd): add template app usage to insights (#9138)
Fixes #8658
2023-08-21 15:08:58 +03:00
Cian Johnston 4de7de420e fix(flake.nix): add gcloud auth plugin (#9215) 2023-08-21 10:58:34 +00:00
Kyle Carberry 7404ee9b21 chore: add name to top-level package.json to allow importing (#9209) 2023-08-20 00:35:38 +00:00
Kyle Carberry 4d85d56327 chore: add version to top-level package.json to allow importing (#9208) 2023-08-20 00:10:53 +00:00
Kyle Carberry 2c83bfdfa5 fix: set the location of locale_archive (#9207)
See https://nixos.wiki/wiki/Locales
2023-08-19 22:37:44 +00:00
Ammar Bandukwala 6b8102cf4c feat(cli): add daily_cost to coder ls (#9200) 2023-08-19 12:56:08 -05:00
Vaibhav Kumar e95557890a docs: remove <> and use shell for code blocks in azure docs (#9078) 2023-08-19 13:52:24 +00:00
Kyle Carberry 40ef9ff779 fix: add sapling to the nix flake (#9202) 2023-08-18 16:41:03 -05:00
Kyle Carberry 22e781eced chore: add /v2 to import module path (#9072)
* chore: add /v2 to import module path

go mod requires semantic versioning with versions greater than 1.x

This was a mechanical update by running:
```
go install github.com/marwan-at-work/mod/cmd/mod@latest
mod upgrade
```

Migrate generated files to import /v2

* Fix gen
2023-08-18 18:55:43 +00:00
Cian Johnston 0d40e7fe24 chore(flake.nix): add gcloud and kubectl to flake (#9197) 2023-08-18 18:29:24 +00:00
Kyle Carberry 9e9c79dbd3 fix: remove nix bash from the dogfood image (#9195)
This was unnecessary.
2023-08-18 17:59:25 +00:00
Mathias Fredriksson bbaa057e15 fix(agent): log correct script timeout for startup script (#9190) 2023-08-18 17:35:49 +00:00
Kyle Carberry 4c133e7058 fix: add yarn to the dogfood image (#9193) 2023-08-18 17:15:33 +00:00
Ben Potter 36fcee50b6 fix: use proper link to workspace proxies page (#9183)
we changed the route in #9070
2023-08-18 11:49:14 -05:00
Kyle Carberry c93782aba6 fix: allow chsh in dev image (#9191) 2023-08-18 16:15:05 +00:00
Kyle Carberry 9725ec0713 fix: separate dev shell and dev image nix deps (#9189)
* fix: separate dev shell and dev image nix deps

* Add less
2023-08-18 15:58:52 +00:00
Kyle Carberry e94ebea5e9 fix: add gh cli to the dogfood image (#9184) 2023-08-18 14:49:54 +00:00
Kyle Carberry 88de63f891 fix: add locale to dogfood image (#9181)
* fix: add locale to dogfood image

* Update flake.nix

Co-authored-by: Mathias Fredriksson <mafredri@gmail.com>

* Add gcc

---------

Co-authored-by: Mathias Fredriksson <mafredri@gmail.com>
2023-08-18 09:16:16 -05:00
Cian Johnston 95458ac8a5 chore(scripts/develop.sh): restore original access url setting (#9174) 2023-08-18 13:24:17 +00:00
Bruno Quaresma 8db3869415 chore: add zsh to dogfood (#9178) 2023-08-18 13:05:02 +00:00
Dean Sheather f4f3132120 docs: add workspace process logging doc (#9002) 2023-08-18 23:02:01 +10:00
Bruno Quaresma 531f740070 fix(site): remove mock data from port forward button (#9177) 2023-08-18 12:59:20 +00:00
Marcin Tojek 669ae9d4d3 fix(cli): remove prompt for immutable parameters on start and restart (#9173) 2023-08-18 14:06:46 +02:00
phorcys420 376352eeb3 fix(ci): add github token to chocolatey workflow (#9166) 2023-08-18 13:16:56 +03:00
Marcin Tojek ea34ec7538 chore(site): regenerate provisioner stub (#9151) 2023-08-18 10:50:43 +02:00
Marcin Tojek 04810cb42e fix: do not install strace on OSX (#9167) 2023-08-18 10:07:11 +02:00
Spike Curtis 2f46f2315c fix: fix race in PGCoord at startup (#9144)
Signed-off-by: Spike Curtis <spike@coder.com>
2023-08-18 09:53:03 +04:00
Kyle Carberry c0a78533bf chore: reduce build time by converting docker image to build with nix (#9099)
* Add Docker image

* Try building the container in CI

* Uncomment testing lines

* Trim image step

* Hit 'em with a Docker load

* Oopsie!

* Add a tag and push!

* Fix image name 🤦

* Fix sudo

* Fix target name

* Build and push

* Fix login to docker hub

* Revert to Docker push

* Fix PATH

* Fix SHA

* Fix ca certs

* Fix ca certs

* Fix coping files in

* Fix docker init

* Fix Docker group and init

* Add comments to our Nix

* Fix build stage

* Add some more comments

* Remove old dogfood image files

* Tag and push with branch name

* Fix tag passing

* Fix tag passing

* Remove old pull triggers

* Convert gen to use Nix

* Add protobuf to the flake

* Add prettier to the dev shell

* Swap to the faster Nix cache action

* Add the correct yq

* Fix gen

* Add make to the flake

* Update extensions
2023-08-17 21:19:36 -05:00
Kayla Washburn 5b165d5cb9 fix: make displayName primary in ParameterLabel component (#9158) 2023-08-17 19:07:57 -06:00
Ben Potter 71d5882341 chore: 2.1.0 changelog (#9160) 2023-08-17 23:02:54 +00:00
Bruno Quaresma 9caa4cfde0 feat(site): display build logs history in the build log page (#9150) 2023-08-17 18:59:26 -03:00
Ammar Bandukwala be40dc85ab chore: cleanup extraneous logging (#9156)
* The batchstats warning went out on every Ctrl+C in my development

Rule of silence:

The provisioner and connect messages messages were sent out on every startup
without a corresponding user event, making them annoying and more-so
debug messages.
2023-08-17 21:01:55 +00:00
Kayla Washburn 9710bada06 fix: redirect to login upon authentication error (#9134) 2023-08-17 13:54:20 -06:00
Ammar Bandukwala 720ad9a653 fix(site): avoid showing disabled fields in group settings page (#9154)
Previously we allowed interaction with the icon setter and showed
confusing help text under the disabled "Display Name" field.
2023-08-17 14:21:36 -05:00
Jon Ayers 2f6687a475 feat: expose Everyone group through UI (#9117)
- Allows setting quota allowances on the 'Everyone' group.
2023-08-17 13:25:16 -05:00
Steven Masley 8910f05172 fix: /workspaces should work even if missing template perms (#9152)
If a user is missing template perms to a workspace, just block reading
that workspace. This is to keep the api consistent, it is not a rbac
enforcement.

This should ublock users reporting this bug that /workspaces returns
nothing when 1 workspace cannot be fully read. We might want to be
able to return missing or unknown fields in our api to account
for this.
2023-08-17 13:22:03 -05:00
Kayla Washburn e39402f1c9 fix: don't navigate away from editor after publishing (#9153) 2023-08-17 10:49:16 -06:00
Reuben Ellis 94cbc2ae7f chore: update storybook build script (#9140) 2023-08-17 09:58:52 -03:00
Oleg Kovalov c639674b39 chore: replace chi with chi/v5 (#9143) 2023-08-17 07:46:56 -05:00
Spike Curtis c66befb548 fix(scaletest): change IP range to non-reserved in GCP (#9146)
Signed-off-by: Spike Curtis <spike@coder.com>
2023-08-17 13:11:02 +04:00
Spike Curtis c7a6d626b4 fix: make PGCoordinator close connections when unhealthy (#9125)
Signed-off-by: Spike Curtis <spike@coder.com>
2023-08-17 09:36:47 +04:00
Eric Paulsen c217a0d819 fix!: remove jq from image (#8979)
* fix: remove jq from base and add jq ext image

* Delete Dockerfile.ext-jq

---------

Co-authored-by: Muhammad Atif Ali <atif@coder.com>
2023-08-16 21:20:33 -04:00
Kayla Washburn 5c7780015b chore: rename UsersDropdown.tsx component file to UserDropdown.tsx (#9137) 2023-08-16 17:36:51 -06:00
Ben Potter fa8e103b0e docs: last seen before & after (#9096) 2023-08-16 23:20:03 +00:00
Asher 02ee724d9f fix: do terminal emulation in reconnecting pty tests (#9114)
It looks like it is possible for screen to use control sequences instead
of literal newlines which fails the tests.

This reuses the existing readUntil function used in other pty tests.
2023-08-16 13:02:03 -08:00
Steven Masley 74999305b6 fix: change oauth convert oidc cookie to SameSite=Lax (#9129)
The strict mode was blocking the cookie from being sent on the
redirect flow. This worked on localhost because cookies
behave differently on localhost
2023-08-16 12:50:44 -05:00
Bruno Quaresma b05293572f refactor(site): remove template parameters insights out of experimental (#9126) 2023-08-16 12:29:42 -03:00
Muhammad Atif Ali 8646f7c00d chore: add JFrog VS Code extension to jfrog template (#9128) 2023-08-16 10:03:42 -05:00
Bruno Quaresma 752070baf5 refactor(site): use bar chart for DAUs (#9127) 2023-08-16 10:59:15 -03:00
Spike Curtis ff9252c706 feat: add provisioner chart to release and docs (#9050)
* Add provisioner chart to release and docs

Signed-off-by: Spike Curtis <spike@coder.com>

* Update docs/admin/provisioners.md

Co-authored-by: Muhammad Atif Ali <atif@coder.com>

* Prettier

Signed-off-by: Spike Curtis <spike@coder.com>

* spell out PSK first time per section

Co-authored-by: Cian Johnston <cian@coder.com>

---------

Signed-off-by: Spike Curtis <spike@coder.com>
Co-authored-by: Muhammad Atif Ali <atif@coder.com>
Co-authored-by: Cian Johnston <cian@coder.com>
2023-08-16 16:26:38 +04:00
Mathias Fredriksson 6fd9975aed feat(coderd): add coder_app usage stats (#9001)
Updates #8658
2023-08-16 15:22:00 +03:00
phorcys420 f3c707648c ci: publsh Chocolatey package (#8921) 2023-08-16 15:21:28 +03:00
Ammar Bandukwala 95d66ac385 docs: explain using Artifactory as a template store (#9071) 2023-08-15 16:46:56 -05:00
sharkymark 7261f0a9d4 docs: add bpmct template repo to community markdown (#9113) 2023-08-15 21:13:51 +00:00
Cian Johnston 6cdf1c73c0 chore: update sqlc to version 1.20.0 (#9111) 2023-08-15 20:06:03 +00:00
Colin Adler 5b2ea2e94f fix(tailnet): disable wireguard trimming (#9098)
Co-authored-by: Spike Curtis <spike@coder.com>
2023-08-15 14:26:56 -05:00
Eric Paulsen e4c24e05f8 fix: rename group GET request (#9097)
* fix: group GET req naming

* make: gen
2023-08-15 14:47:08 -04:00
dependabot[bot] 279d9f71f9 chore: bump github.com/gohugoio/hugo from 0.116.0 to 0.117.0 (#9084)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-08-15 13:40:03 -05:00
Ben Potter ee9deb0a6e docs: add conditional example to optional vs required parameters (#9115) 2023-08-15 18:24:05 +00:00
dependabot[bot] 65d84827cd chore: Bump the github-actions group with 1 update (#9086)
Bumps the github-actions group with 1 update: [crate-ci/typos](https://github.com/crate-ci/typos).

- [Release notes](https://github.com/crate-ci/typos/releases)
- [Changelog](https://github.com/crate-ci/typos/blob/master/CHANGELOG.md)
- [Commits](https://github.com/crate-ci/typos/compare/v1.16.2...v1.16.4)

---
updated-dependencies:
- dependency-name: crate-ci/typos
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: github-actions
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-08-15 19:33:34 +03:00
Bruno Quaresma c5d4a4d85d docs: update FE stack (#9112) 2023-08-15 16:03:14 +00:00
Spike Curtis 63278ab88f Reword latency docs for HA (#8860)
Signed-off-by: Spike Curtis <spike@coder.com>
2023-08-15 19:58:04 +04:00
Bruno Quaresma 4058f049af feat(site): add batch actions to the workspaces page (#9091) 2023-08-15 12:57:39 -03:00
dependabot[bot] c2c9da7db0 chore: bump google.golang.org/api from 0.134.0 to 0.137.0 (#9093)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-08-15 10:50:10 -05:00
Colin Adler 9d9b330b16 chore: add request body to patch groups openapi spec (#9101) 2023-08-15 15:29:15 +00:00
Spike Curtis 41433cd1ec feat: add terminationGracePeriodSeconds to provisioner chart (#9048)
* feat: add terminationGracePeriodSeconds to provisioner chart

Signed-off-by: Spike Curtis <spike@coder.com>

* Remove hardcoded 1 minute graceful timeout

Signed-off-by: Spike Curtis <spike@coder.com>

---------

Signed-off-by: Spike Curtis <spike@coder.com>
2023-08-15 08:38:58 +00:00
Spike Curtis e893ab232c chore: enables debug logging on TestTemplateInsights (#9103)
Signed-off-by: Spike Curtis <spike@coder.com>
2023-08-15 12:35:51 +04:00
Muhammad Atif Ali 86fcd4503f Revert "ci: run tests intelligently based on changes between consecutive commits (#9017)" (#9104) 2023-08-15 08:22:49 +00:00
Muhammad Atif Ali 9a1f845553 docs: expand jfrog platform and example template (#9073) 2023-08-15 07:04:07 +00:00
Spike Curtis d54b387e34 fix: fix deadlock on tailnet close (#9079)
* fix: fix deadlock in tailnet close

Signed-off-by: Spike Curtis <spike@coder.com>

* close another tailscale race

Signed-off-by: Spike Curtis <spike@coder.com>

* Close another race

Signed-off-by: Spike Curtis <spike@coder.com>

* HACK - run go tests

Signed-off-by: Spike Curtis <spike@coder.com>

* Revert "HACK - run go tests"

This reverts commit d2729f36b4.

* tailscale to tip of coder/tailscale/main

Signed-off-by: Spike Curtis <spike@coder.com>

---------

Signed-off-by: Spike Curtis <spike@coder.com>
2023-08-15 06:54:06 +00:00
Colin Adler 344d32b2f1 feat(coderd): expire agents from server tailnet (#9092) 2023-08-14 20:38:37 -05:00
Asher a08f7b8fb9 fix: catch missing output with reconnecting PTY (#9094)
I forgot that waiting on the cond releases the lock so it was possible
to get pty output after writing the buffer but before adding the pty to
the map.  To fix, add the pty to the map while under the same lock where
we read from the buffer.

The rest does not need to be behind the lock so I moved it out of
doAttach, and that also means we no longer need
waitForStateOrContextLocked.

Also, this can hit a logger error saying the attach failed which fails
the tests however it is not that the attach failed, just that the
process already ran and exited, so when the process exits do not
set an error, instead for now assume this is an expected close.
2023-08-14 15:54:23 -08:00
Steven Masley 6ea82c5ae7 chore: add oidc sequence diagram image to docs (#9089)
* chore: add oidc sequence diagram image to docs

* Change wording

* Direct link to the sequence diagram
2023-08-14 17:35:43 -05:00
Steven Masley 25ce30df36 feat: add azure oidc PKI auth instead of client secret (#9054)
* feat: add azure oidc PKI auth instead of client secret
* add client cert and key as deployment options
* Custom token refresher to handle pki auth
2023-08-14 17:33:13 -05:00
dependabot[bot] 4e36f91ea2 chore: bump the golang-x group with 1 update (#9083)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-08-14 16:59:28 -05:00
Dean Sheather 47b8bf6585 feat: update workspace deadline when template policy changes (#8964) 2023-08-14 21:16:47 +00:00
Asher 37f9d4b783 feat: add --header-command flag (#9059)
This allows specifying a command to run that can output headers for
cases where users require dynamic headers (like to authenticate to their
VPN).

The primary use case is to add this flag in SSH configs created by the
VS Code plugin, although maybe config-ssh should do the same.
2023-08-14 12:12:17 -08:00
Asher b993cab49a fix: use screen for reconnecting terminal sessions on Linux if available (#8640)
* Add screen backend for reconnecting ptys

The screen portion is a port from wsep.  There is an interface that lets
you choose between screen and the previous method.  By default it will
choose screen if it is installed but this can be overidden (mostly for
tests).

The tests use a scanner instead of a reader now because the reader will
loop infinitely at the end of a stream.

Replace /bin/bash with bash since bash is not always in /bin.

* Remove connection_id from reconnecting PTY logger

This serves multiple connections so it makes no sense to scope it to a
single connection.

Also lets us use "connection_id" when logging write errors instead of
"other_conn_id".

* Use PATH to test buffered reconnecting pty
2023-08-14 11:19:13 -08:00
Muhammad Atif Ali 878315dcaf fix: fix CI concurrency (#9088) 2023-08-14 18:48:14 +03:00
Cian Johnston ef9d84c723 fix(scaletest): cleanup: attempt to cancel in-progress jobs (#9080)
This change modifies the cleanup behaviour to make a best-effort attempt to cancel the in-progress scaletest workspace build jobs before deleting them.
2023-08-14 12:43:45 +01:00
Cian Johnston 72575cc462 chore(docs): fix indentation in install/kubernetes.md (#8906)
* chore(docs): fix indentation in install/kubernetes.md

* fmt
2023-08-14 09:41:00 +01:00
Kyle Carberry 594b9797dd fix: change dashboard route /settings/deployment to /deployment (#9070)
It felt unnecessary to nest this.
2023-08-13 16:58:04 +00:00
Kyle Carberry 0d01d022f7 fix: remove unnecessary newlines from the end of cli output (#9068)
`Infof` already adds a newline, so we don't need to as well!
2023-08-13 11:48:11 -05:00
Kyle Carberry 9a13814b46 fix: remove duplication from language of query param error (#9069) 2023-08-13 11:47:44 -05:00
Muhammad Atif Ali 1629a2a4ee chore: sort DERP regions by latencies on workspace page (#9063) 2023-08-13 18:52:14 +03:00
Kyle Carberry abe17b1164 chore: update speakeasy to fix stty path bug on nixos (#9022)
Prompts failed on NixOS due to /bin/stty being hardcoded for turning
off echo in the terminal prompt. See:
https://github.com/bgentry/speakeasy/commit/760eaf8b681647364e7a400b856e0921248728a5
2023-08-13 15:10:58 +00:00
Muhammad Atif Ali 984f7ce045 fix: update BUILD condition in pr-deploy.yaml (#9064)
This makes the build condition more understandable and fixes an issue where we could not deploy a new PR as the build condition was constantly evaluating false.
2023-08-13 11:18:17 +03:00
Eric Paulsen 6af6e85fe3 docs: add coder login to CI docs (#9038)
* docs: add coder login to CI docs

* add CODER_URL

* add --url flag to login cmd
2023-08-11 20:55:55 +00:00
Eric Paulsen d2a9049fd7 docs: add offline docs for JetBrains Gateway (#9039) 2023-08-11 14:56:35 -05:00
Steven Masley 320de18be7 fix: correct github oauth2 callback url (#9052)
* fix: correct github oauth2 callback url
2023-08-11 09:25:05 -05:00
Steven Masley 47ca84be47 chore: return queried user on failure to help debug (#9051) 2023-08-11 14:02:19 +00:00
Steven Masley 1c7bd57da8 chore: clarify region selection behavior (#9021)
* chore: clarify region selection behavior

* Update site/src/components/Navbar/NavbarView.tsx

Co-authored-by: Kyle Carberry <kyle@coder.com>

---------

Co-authored-by: Kyle Carberry <kyle@coder.com>
2023-08-11 08:26:01 -05:00
Muhammad Atif Ali 59fd4e86c9 ci: remove deleting comments section from pr-cleanup.yaml (#9047) 2023-08-11 15:43:37 +03:00
Muhammad Atif Ali a13c8c88d5 fix: prevent unrequested PR deployments (#9049) 2023-08-11 12:32:42 +00:00
Muhammad Atif Ali 7fb9197860 ci: do not run deploy-pr on main (#9046) 2023-08-11 10:54:55 +00:00
Muhammad Atif Ali 114ad4624e ci: upgrade pr deployments workflow (#8924) 2023-08-11 13:49:23 +03:00
Muhammad Atif Ali 4d8152d543 ci: run tests intelligently based on changes between consecutive commits (#9017) 2023-08-11 13:48:24 +03:00
Steven Masley 40f3fc3a1c feat: allow creating manual oidc/github based users (#9000)
* feat: allow creating manual oidc/github based users
* Add unit test for oidc and no login type create
2023-08-10 20:04:35 -05:00
ffais 6fd5344d0a feat: add support for NodePort service type in Helm chart (#8993)
* add support for NodePort service type in Helm chart

* fix nodeport values

* formatting & make update-golden-files

* update-golden-files

---------

Co-authored-by: Eric <ericpaulsen@coder.com>
2023-08-10 20:57:59 -04:00
timquinlan a2d64c08c1 docs: update helm values.yaml code snippet, put quote around boolean value (#9026)
* updated helm values.yaml code snippet, put quote around boolean values and added comments showing that CODER_OAUTH2_GITHUB_ALLOW_EVERYONE and CODER_OAUTH2_GITHUB_ALLOW_EVERYONE are mutually exclusive

* Update auth.md

spotted and fixed minor typo
2023-08-10 17:06:10 -04:00
Dean Sheather d2f22b063a fix: move STUN servers into their own regions (#9030) 2023-08-11 05:04:17 +10:00
Dean Sheather 25c6832772 chore: update tailscale (#9027) 2023-08-11 04:26:28 +10:00
Bruno Quaresma 175aed1685 feat(site): add tooltip showing the error in the failure badge (#9029) 2023-08-10 15:23:31 -03:00
Bruno Quaresma 83061bef7e refactor(site): add minor improvements to the port button (#9028) 2023-08-10 14:47:56 -03:00
Ben Potter 76ad116e12 docs: write 2.0.2 changelog (#9025)
* mention provisioner authentication

* add changelog for 2.1.0

* rename to 2.0.2
2023-08-10 17:02:02 +00:00
Marcin Tojek 967a4b0c7c feat: add example template using rich parameters (#9020) 2023-08-10 16:36:18 +02:00
Muhammad Atif Ali 091c00bd70 fix: make preferred region the first in list (#9014) 2023-08-10 12:59:39 +00:00
Bruno Quaresma 834ce41013 refactor(site): add default background color to html and body (#9009) 2023-08-10 09:41:35 -03:00
Marcin Tojek 9d9814c6b0 refactor(cli): adjust parameter resolver (#9019) 2023-08-10 12:08:00 +02:00
Spike Curtis 21af020386 feat: add external provisioner daemon helm chart (#8939)
* Refactor helm to extract common templates to libcoder

Signed-off-by: Spike Curtis <spike@coder.com>

* Remove comment from libcoder Chart.yaml

Signed-off-by: Spike Curtis <spike@coder.com>

* Add provisioner helm chart

* Fix prettier, linting, docs

Signed-off-by: Spike Curtis <spike@coder.com>

* Log at INFO when provisionerd connects to coderd

Signed-off-by: Spike Curtis <spike@coder.com>

* remove unnecessary exports in helm tests

Signed-off-by: Spike Curtis <spike@coder.com>

---------

Signed-off-by: Spike Curtis <spike@coder.com>
2023-08-10 13:59:43 +04:00
Steven Masley cdb089049e chore: add docs for creating missing groups on oidc sync (#8983) 2023-08-09 22:43:44 -05:00
Colin Adler 370bdd6a03 fix(cli): only init clistat.Client when calling coder stat (#9013) 2023-08-09 19:17:57 -05:00
Bruno Quaresma c0d1cacc49 fix(site): fix storybook error and inconsistent snapshots (#9010) 2023-08-09 21:22:13 +00:00
Eric Paulsen fb5e0c4bba docs: add TLS config steps for K8s (#9011)
* docs: add TLS config steps for K8s

* add note on wildcard cert
2023-08-09 17:00:22 -04:00
Bruno Quaresma 3245e91a32 fix(site): set default color and display error on appearance form (#9004) 2023-08-09 16:53:32 -03:00
Colin Adler bc862fa493 chore: upgrade tailscale to v1.46.1 (#8913) 2023-08-09 19:50:26 +00:00
Bruno Quaresma 5b9dc2ee8b fix(site): add search params to auth redirect (#9005) 2023-08-09 16:31:12 -03:00
phorcys420 53f26b313d fix(scripts): check if PR list is empty (#8805)
Co-authored-by: Mathias Fredriksson <mafredri@gmail.com>
2023-08-09 19:22:46 +00:00
Colin Adler 612f1c6a55 chore: use echo provisioners in logging tests (#9008) 2023-08-09 19:03:02 +00:00
Steven Masley f334b66178 chore: do not allow resetting password of non password users (#9003) 2023-08-09 13:56:13 -05:00
Colin Adler 919f5c6fe9 chore: increase e2e timeout to 60s (#9007) 2023-08-09 18:50:27 +00:00
Colin Adler a9e01bf3f1 chore: fix terraform tests (#9006) 2023-08-09 18:11:03 +00:00
Bruno Quaresma 7b35f3b3ad fix(site): add horizontal scroll when having many tabs (#8998) 2023-08-09 14:28:25 +00:00
Bruno Quaresma 7fceb9aaff fix(site): make stats bar scrollable on smaller viewports (#8996) 2023-08-09 11:26:56 -03:00
Bruno Quaresma d73e3ad3f3 fix(site): show user avatar on group page (#8997) 2023-08-09 11:26:43 -03:00
dependabot[bot] a6716ca829 chore: bump chart.js from 3.9.1 to 4.3.3 in /site (#8874)
* chore: bump chart.js from 3.9.1 to 4.3.3 in /site

Bumps [chart.js](https://github.com/chartjs/Chart.js) from 3.9.1 to 4.3.3.
- [Release notes](https://github.com/chartjs/Chart.js/releases)
- [Commits](https://github.com/chartjs/Chart.js/compare/v3.9.1...v4.3.3)

---
updated-dependencies:
- dependency-name: chart.js
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>

* Remove timescale

* Fix step size

---------

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Muhammad Atif Ali <atif@coder.com>
Co-authored-by: BrunoQuaresma <bruno_nonato_quaresma@hotmail.com>
2023-08-09 09:54:03 -03:00
Bruno Quaresma 73e518b0fb refactor(site): remove last 7 days label (#8986) 2023-08-09 09:46:14 -03:00
Spike Curtis e0f644c598 test(coderd): fix TestWorkspaceWatcher hang waiting for update (#8992)
Signed-off-by: Spike Curtis <spike@coder.com>
2023-08-09 16:09:25 +04:00
Marcin Tojek 0d382d1e05 feat(cli): provide parameter values via command line (#8898) 2023-08-09 13:00:25 +02:00
Ben Potter 1730d35467 Revert "fix: hide experiment CTA from OIDC copy (#8695)" (#8825)
This reverts commit adbabe4e09.
2023-08-09 10:05:46 +00:00
Dean Sheather 9941f49056 fix: remove stun nodes from workspace proxy regions (#8990) 2023-08-09 09:31:25 +00:00
Dean Sheather 00a8221e51 fix: rename duplicate migration (#8989) 2023-08-09 05:49:13 +00:00
Dean Sheather 07fd73c4a0 chore: allow multiple agent subsystems, add exectrace (#8933) 2023-08-08 22:10:28 -07:00
Bruno Quaresma 70bd23a40a refactor(site): add default title (#8985) 2023-08-08 18:48:53 -03:00
Steven Masley d4e115d267 chore: show basic experiment set value (#8984)
This value is pre-parsed, meaning the experiments listed may not
be valid. This is a very basic display for helping debuging purposes.
2023-08-08 15:33:08 -05:00
Dean Sheather f7a35e0559 chore: add workspace proxies to telemetry (#8963) 2023-08-08 18:29:35 +00:00
Dean Sheather 3c52b01850 chore: add tailscale magicsock debug logging controls (#8982) 2023-08-08 17:56:08 +00:00
Colin Adler a5c59b9934 chore: upgrade to alpine 3.18.3 (#8980) 2023-08-08 12:21:38 -05:00
Bruno Quaresma 76b1594670 feat(site): add date range picker for the template insights (#8976) 2023-08-08 13:43:21 -03:00
Steven Masley f4122fa9f5 feat: add auto group create from OIDC (#8884)
* add flag for auto create groups
* fixup! add flag for auto create groups
* sync missing groups
Also added a regex filter to filter out groups that are not
important
2023-08-08 11:37:49 -05:00
Bruno Quaresma 4a987e9917 feat(site): add parameters usage to insights (#8886) 2023-08-08 13:09:31 -03:00
Steven Masley 5339a31532 fix: remove refresh oauth logic on OIDC login (#8950)
* fix: do not do oauth refresh logic on oidc login
2023-08-08 10:05:12 -05:00
Cem 1d4a72f43f perf(coderd/util/slice): refactor unique method for large lists (#8925) 2023-08-08 10:02:52 -05:00
Muhammad Atif Ali 05054c6a0a ci: make test-e2e a required check (#8977) 2023-08-08 14:57:57 +00:00
Kyle Carberry 4d3230c9ad fix: default to executing e2e ssh without args (#8975)
This was causing the test to fail consistently!
2023-08-08 14:35:34 +00:00
Muhammad Atif Ali c20c4faa7c docs: format CONTRIBUTING.md (#8973) 2023-08-08 17:12:51 +03:00
Dean Sheather b2a84462ab chore: fix ruleguard xerrors rules (#8967) 2023-08-08 12:32:41 +00:00
Muhammad Atif Ali 31b7de6a3e chore: upgrade go to 1.20.7 (#8923)
* chore: upgrade go to 1.20.7

* remove unused env
2023-08-08 09:20:36 +03:00
Kyle Carberry bac3a588b3 chore: add e2e test for backwards client ssh compatibility (#8958)
* chore: add e2e test for backwards client ssh compatibility

This was discussed as part of our regression review for outdated
agents, so here is the reverse with an extremely old client.

* fmt
2023-08-08 05:36:46 +00:00
Kyle Carberry 73b136e3f0 fix: add exp backoff to validate fresh git auth tokens (#8956)
A customer using GitHub in Australia reported that validating immediately
after refreshing the token would intermittently fail with a 401. Waiting
a few milliseconds with the exact same token on the exact same request
would resolve the issue. It seems likely that the write is not propagating
to the read replica in time.
2023-08-08 04:29:35 +00:00
Colin Adler 694729b4f7 chore: disable goleak in windows cli tests (#8955) 2023-08-07 22:23:00 -05:00
Colin Adler 7e3ff5b66e chore: fix TestBatchStats flake (#8952) 2023-08-07 21:55:31 -05:00
Colin Adler 758c368222 chore: fix TestTailnet/ForcesWebSockets flake (#8953) 2023-08-07 21:17:39 -05:00
dependabot[bot] 827de08007 chore: bump the golang-x group with 3 updates (#8940)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-08-07 14:30:14 -05:00
dependabot[bot] b2dc8897ff chore: bump github.com/go-playground/validator/v10 from 10.14.0 to 10.15.0 (#8941)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-08-07 14:16:03 -05:00
Ben Potter 3b16e7112d fix: improve formatting in Gateway docs (#8949)
* fix: image formatting for gateway docs

* chore: fix some more spots

* more

* fmt

* space things out more
2023-08-07 17:34:41 +00:00
Ben Potter b67ece1cbc fix: image formatting for gateway docs (#8947) 2023-08-07 11:45:15 -05:00
sharkymark 9f76381fc1 chore: add install more providers step in jetbrains docs; update images (#8943) 2023-08-07 16:31:43 +00:00
Marcin Tojek e8627195a2 feat(coderd): expose parameter description and type (#8944) 2023-08-07 16:11:44 +00:00
dependabot[bot] 00be8ab875 chore: bump the github-actions group with 1 update (#8942)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-08-07 18:54:20 +03:00
Dean Sheather 67ff2077a6 feat: add derp only text to proxies list in dashboard (#8932) 2023-08-08 01:52:06 +10:00
Cian Johnston 82e0e2e43c fix(cli): clistat: accept positional arg for stat disk cmd (#8911) 2023-08-07 16:26:16 +01:00
Muhammad Atif Ali 6ded748989 fix: update tag name for coder-preview image in ci.yaml (#8945) 2023-08-07 14:35:28 +00:00
Steven Masley 71ea5ace07 feat: add login type to users page (#8912) 2023-08-07 09:34:39 -05:00
Muhammad Atif Ali 90c1647fcf ci: change ghcr.io/coder/coder-preview:main tag to use version names (#8938) 2023-08-07 16:41:20 +03:00
Muhammad Atif Ali e7047726d8 docs: fix a broken link in docs.changelogs/README.md (#8937) 2023-08-07 13:00:05 +03:00
Ammar Bandukwala 81752d1b84 fix(cli/delete): prompt for confirmation after workspace is found (#8579) 2023-08-05 11:25:37 -05:00
Colin Adler eddaa7781d fix: don't close cached tailnet on pty close (#8917) 2023-08-04 22:54:27 +00:00
Colin Adler 0c7ff4fb8a fix(enterprise): ensure SCIM create user can unsuspend (#8916) 2023-08-04 22:03:21 +00:00
Bruno Quaresma 8f7b6a2936 fix(site): fix date range on template insights (#8914) 2023-08-04 18:00:13 +00:00
Cian Johnston 7224ff2af8 fix(enterprise/replicasync): fix data race in Manager.Regional (#8910) 2023-08-04 17:33:05 +01:00
Muhammad Atif Ali 9f5ac4d15d ci: publish main commit tag to ghcr.io/coder/coder-preview (#8897)
* wip

* push new tag and delete old tag

* prune by filtering

* fix permission

* fix filter

* keep last 2 versions

* use first 7 characters of sha for tag

* do not use gh cli

* test

* typo

* use gh cli again

* reduce days to 3

* fixup

* typo

* keep-last 5

* ready to merge

* retain tags from last 7 days

* test

* ready
2023-08-04 19:27:12 +03:00
Cian Johnston 9fb18f3ae5 feat(coderd): batch agent stats inserts (#8875)
This PR adds support for batching inserts to the workspace_agents_stats table.
Up to 1024 stats are batched, and flushed every second in a batch.
2023-08-04 17:00:42 +01:00
Cian Johnston ae88b79fd7 fix(cli): stat: set --host arg in TestStatCPUCmd to avoid test flakes in containers (#8806) 2023-08-04 15:15:33 +00:00
Cian Johnston 607cd11724 fix(cli): address race condition in scaletest_test output (#8902) 2023-08-04 15:06:28 +00:00
Bruno Quaresma 5106dfde52 refactor(site): refactor the ports button design (#8879)
* Refactor button

* Move component to where it is used

* Add base state of port forward component

* Add stories and empty state

* Add listening ports to handlers

* Add review suggestions

* Fix minor thing
2023-08-04 09:55:33 -05:00
Eric Paulsen 1c3ec8743c docs: clean up k8s install steps and order (#8869) 2023-08-04 08:40:48 -04:00
Ammar Bandukwala eae15c0789 chore(examples): bump envbuilder version (#8893) 2023-08-04 06:47:15 -05:00
Cian Johnston aff025e78c chore(docs): fix link to helm values highlighting affinity (#8901) 2023-08-04 10:25:24 +00:00
Spike Curtis cb4989cd8d feat: add PSK for external provisionerd auth (#8877)
Signed-off-by: Spike Curtis <spike@coder.com>
2023-08-04 12:32:28 +04:00
Muhammad Atif Ali b77d6b2c84 ci: delete comments by github-action[bot] (#8896) 2023-08-04 06:55:38 +00:00
Eric Paulsen 2e45a0ffd7 fix(helm): set correct prom port in helm notes (#8888) 2023-08-04 07:52:59 +03:00
Jon Ayers e43608395c feat: add frontend for locked workspaces (#8655)
- Fix workspaces query for locked workspaces.
2023-08-03 19:46:02 -05:00
Colin Adler 502c7680a2 chore: fix release and security pipelines (#8891) 2023-08-03 18:40:47 -05:00
2359 changed files with 144397 additions and 72064 deletions
+5
View File
@@ -0,0 +1,5 @@
# If you would like `git blame` to ignore commits from this file, run...
# git config blame.ignoreRevsFile .git-blame-ignore-revs
# chore: format code with semicolons when using prettier (#9555)
988c9af0153561397686c119da9d1336d2433fdd
+1 -1
View File
@@ -4,7 +4,7 @@ description: |
inputs:
version:
description: "The Go version to use."
default: "1.20.6"
default: "1.20.10"
runs:
using: "composite"
steps:
+2 -2
View File
@@ -5,6 +5,6 @@ runs:
using: "composite"
steps:
- name: Setup sqlc
uses: sqlc-dev/setup-sqlc@v3
uses: sqlc-dev/setup-sqlc@v4
with:
sqlc-version: "1.19.1"
sqlc-version: "1.20.0"
+1 -1
View File
@@ -7,5 +7,5 @@ runs:
- name: Install Terraform
uses: hashicorp/setup-terraform@v2
with:
terraform_version: ~1.5
terraform_version: 1.5.5
terraform_wrapper: false
+1 -1
View File
@@ -20,7 +20,7 @@ runs:
echo "No API key provided, skipping..."
exit 0
fi
npm install -g @datadog/datadog-ci@2.10.0
npm install -g @datadog/datadog-ci@2.21.0
datadog-ci junit upload --service coder ./gotests.xml \
--tags os:${{runner.os}} --tags runner_name:${{runner.name}}
env:
+2 -20
View File
@@ -8,7 +8,7 @@ updates:
timezone: "America/Chicago"
labels: []
commit-message:
prefix: "chore"
prefix: "ci"
ignore:
# These actions deliver the latest versions by updating the major
# release tag, so ignore minor and patch versions
@@ -92,6 +92,7 @@ updates:
- dependency-name: "@types/node"
update-types:
- version-update:semver-major
open-pull-requests-limit: 15
groups:
react:
patterns:
@@ -117,11 +118,6 @@ updates:
- "@eslint*"
- "@typescript-eslint/eslint-plugin"
- "@typescript-eslint/parser"
jest:
patterns:
- "jest*"
- "@swc/jest"
- "@types/jest"
- package-ecosystem: "npm"
directory: "/offlinedocs/"
@@ -146,20 +142,6 @@ updates:
- version-update:semver-major
# Update dogfood.
- package-ecosystem: "docker"
directory: "/dogfood/"
schedule:
interval: "weekly"
time: "06:00"
timezone: "America/Chicago"
commit-message:
prefix: "chore"
labels: []
groups:
dogfood-docker:
patterns:
- "*"
- package-ecosystem: "terraform"
directory: "/dogfood/"
schedule:
+13
View File
@@ -0,0 +1,13 @@
apiVersion: cert-manager.io/v1
kind: Certificate
metadata:
name: pr${PR_NUMBER}-tls
namespace: pr-deployment-certs
spec:
secretName: pr${PR_NUMBER}-tls
issuerRef:
name: letsencrypt
kind: ClusterIssuer
dnsNames:
- "${PR_HOSTNAME}"
- "*.${PR_HOSTNAME}"
+31
View File
@@ -0,0 +1,31 @@
apiVersion: v1
kind: ServiceAccount
metadata:
name: coder-workspace-pr${PR_NUMBER}
namespace: pr${PR_NUMBER}
---
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
name: coder-workspace-pr${PR_NUMBER}
namespace: pr${PR_NUMBER}
rules:
- apiGroups: ["*"]
resources: ["*"]
verbs: ["*"]
---
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
name: coder-workspace-pr${PR_NUMBER}
namespace: pr${PR_NUMBER}
subjects:
- kind: ServiceAccount
name: coder-workspace-pr${PR_NUMBER}
namespace: pr${PR_NUMBER}
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: Role
name: coder-workspace-pr${PR_NUMBER}
+314
View File
@@ -0,0 +1,314 @@
terraform {
required_providers {
coder = {
source = "coder/coder"
}
kubernetes = {
source = "hashicorp/kubernetes"
}
}
}
provider "coder" {
}
variable "namespace" {
type = string
description = "The Kubernetes namespace to create workspaces in (must exist prior to creating workspaces)"
}
data "coder_parameter" "cpu" {
name = "cpu"
display_name = "CPU"
description = "The number of CPU cores"
default = "2"
icon = "/icon/memory.svg"
mutable = true
option {
name = "2 Cores"
value = "2"
}
option {
name = "4 Cores"
value = "4"
}
option {
name = "6 Cores"
value = "6"
}
option {
name = "8 Cores"
value = "8"
}
}
data "coder_parameter" "memory" {
name = "memory"
display_name = "Memory"
description = "The amount of memory in GB"
default = "2"
icon = "/icon/memory.svg"
mutable = true
option {
name = "2 GB"
value = "2"
}
option {
name = "4 GB"
value = "4"
}
option {
name = "6 GB"
value = "6"
}
option {
name = "8 GB"
value = "8"
}
}
data "coder_parameter" "home_disk_size" {
name = "home_disk_size"
display_name = "Home disk size"
description = "The size of the home disk in GB"
default = "10"
type = "number"
icon = "/emojis/1f4be.png"
mutable = false
validation {
min = 1
max = 99999
}
}
provider "kubernetes" {
config_path = null
}
data "coder_workspace" "me" {}
resource "coder_agent" "main" {
os = "linux"
arch = "amd64"
startup_script_timeout = 180
startup_script = <<-EOT
set -e
# install and start code-server
curl -fsSL https://code-server.dev/install.sh | sh -s -- --method=standalone --prefix=/tmp/code-server
/tmp/code-server/bin/code-server --auth none --port 13337 >/tmp/code-server.log 2>&1 &
EOT
# The following metadata blocks are optional. They are used to display
# information about your workspace in the dashboard. You can remove them
# if you don't want to display any information.
# For basic resources, you can use the `coder stat` command.
# If you need more control, you can write your own script.
metadata {
display_name = "CPU Usage"
key = "0_cpu_usage"
script = "coder stat cpu"
interval = 10
timeout = 1
}
metadata {
display_name = "RAM Usage"
key = "1_ram_usage"
script = "coder stat mem"
interval = 10
timeout = 1
}
metadata {
display_name = "Home Disk"
key = "3_home_disk"
script = "coder stat disk --path $${HOME}"
interval = 60
timeout = 1
}
metadata {
display_name = "CPU Usage (Host)"
key = "4_cpu_usage_host"
script = "coder stat cpu --host"
interval = 10
timeout = 1
}
metadata {
display_name = "Memory Usage (Host)"
key = "5_mem_usage_host"
script = "coder stat mem --host"
interval = 10
timeout = 1
}
metadata {
display_name = "Load Average (Host)"
key = "6_load_host"
# get load avg scaled by number of cores
script = <<EOT
echo "`cat /proc/loadavg | awk '{ print $1 }'` `nproc`" | awk '{ printf "%0.2f", $1/$2 }'
EOT
interval = 60
timeout = 1
}
}
# code-server
resource "coder_app" "code-server" {
agent_id = coder_agent.main.id
slug = "code-server"
display_name = "code-server"
icon = "/icon/code.svg"
url = "http://localhost:13337?folder=/home/coder"
subdomain = false
share = "owner"
healthcheck {
url = "http://localhost:13337/healthz"
interval = 3
threshold = 10
}
}
resource "kubernetes_persistent_volume_claim" "home" {
metadata {
name = "coder-${lower(data.coder_workspace.me.owner)}-${lower(data.coder_workspace.me.name)}-home"
namespace = var.namespace
labels = {
"app.kubernetes.io/name" = "coder-pvc"
"app.kubernetes.io/instance" = "coder-pvc-${lower(data.coder_workspace.me.owner)}-${lower(data.coder_workspace.me.name)}"
"app.kubernetes.io/part-of" = "coder"
//Coder-specific labels.
"com.coder.resource" = "true"
"com.coder.workspace.id" = data.coder_workspace.me.id
"com.coder.workspace.name" = data.coder_workspace.me.name
"com.coder.user.id" = data.coder_workspace.me.owner_id
"com.coder.user.username" = data.coder_workspace.me.owner
}
annotations = {
"com.coder.user.email" = data.coder_workspace.me.owner_email
}
}
wait_until_bound = false
spec {
access_modes = ["ReadWriteOnce"]
resources {
requests = {
storage = "${data.coder_parameter.home_disk_size.value}Gi"
}
}
}
}
resource "kubernetes_deployment" "main" {
count = data.coder_workspace.me.start_count
depends_on = [
kubernetes_persistent_volume_claim.home
]
wait_for_rollout = false
metadata {
name = "coder-${lower(data.coder_workspace.me.owner)}-${lower(data.coder_workspace.me.name)}"
namespace = var.namespace
labels = {
"app.kubernetes.io/name" = "coder-workspace"
"app.kubernetes.io/instance" = "coder-workspace-${lower(data.coder_workspace.me.owner)}-${lower(data.coder_workspace.me.name)}"
"app.kubernetes.io/part-of" = "coder"
"com.coder.resource" = "true"
"com.coder.workspace.id" = data.coder_workspace.me.id
"com.coder.workspace.name" = data.coder_workspace.me.name
"com.coder.user.id" = data.coder_workspace.me.owner_id
"com.coder.user.username" = data.coder_workspace.me.owner
}
annotations = {
"com.coder.user.email" = data.coder_workspace.me.owner_email
}
}
spec {
replicas = 1
selector {
match_labels = {
"app.kubernetes.io/name" = "coder-workspace"
}
}
strategy {
type = "Recreate"
}
template {
metadata {
labels = {
"app.kubernetes.io/name" = "coder-workspace"
}
}
spec {
security_context {
run_as_user = 1000
fs_group = 1000
}
service_account_name = "coder-workspace-${var.namespace}"
container {
name = "dev"
image = "bencdr/devops-tools"
image_pull_policy = "Always"
command = ["sh", "-c", coder_agent.main.init_script]
security_context {
run_as_user = "1000"
}
env {
name = "CODER_AGENT_TOKEN"
value = coder_agent.main.token
}
resources {
requests = {
"cpu" = "250m"
"memory" = "512Mi"
}
limits = {
"cpu" = "${data.coder_parameter.cpu.value}"
"memory" = "${data.coder_parameter.memory.value}Gi"
}
}
volume_mount {
mount_path = "/home/coder"
name = "home"
read_only = false
}
}
volume {
name = "home"
persistent_volume_claim {
claim_name = kubernetes_persistent_volume_claim.home.metadata.0.name
read_only = false
}
}
affinity {
// This affinity attempts to spread out all workspace pods evenly across
// nodes.
pod_anti_affinity {
preferred_during_scheduling_ignored_during_execution {
weight = 1
pod_affinity_term {
topology_key = "kubernetes.io/hostname"
label_selector {
match_expressions {
key = "app.kubernetes.io/name"
operator = "In"
values = ["coder-workspace"]
}
}
}
}
}
}
}
}
}
}
+38
View File
@@ -0,0 +1,38 @@
coder:
image:
repo: "${REPO}"
tag: "pr${PR_NUMBER}"
pullPolicy: Always
service:
type: ClusterIP
ingress:
enable: true
className: traefik
host: "${PR_HOSTNAME}"
wildcardHost: "*.${PR_HOSTNAME}"
tls:
enable: true
secretName: "pr${PR_NUMBER}-tls"
wildcardSecretName: "pr${PR_NUMBER}-tls"
env:
- name: "CODER_ACCESS_URL"
value: "https://${PR_HOSTNAME}"
- name: "CODER_WILDCARD_ACCESS_URL"
value: "*.${PR_HOSTNAME}"
- name: "CODER_EXPERIMENTS"
value: "${EXPERIMENTS}"
- name: CODER_PG_CONNECTION_URL
valueFrom:
secretKeyRef:
name: coder-db-url
key: url
- name: "CODER_OAUTH2_GITHUB_ALLOW_SIGNUPS"
value: "true"
- name: "CODER_OAUTH2_GITHUB_CLIENT_ID"
value: "${PR_DEPLOYMENTS_GITHUB_OAUTH_CLIENT_ID}"
- name: "CODER_OAUTH2_GITHUB_CLIENT_SECRET"
value: "${PR_DEPLOYMENTS_GITHUB_OAUTH_CLIENT_SECRET}"
- name: "CODER_OAUTH2_GITHUB_ALLOWED_ORGS"
value: "coder"
- name: "CODER_DERP_CONFIG_URL"
value: "https://controlplane.tailscale.com/derpmap/default"
+95 -51
View File
@@ -24,7 +24,7 @@ permissions:
# additional changes
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: ${{ github.event_name == 'pull_request' }}
cancel-in-progress: ${{ github.ref != 'refs/heads/main' }}
jobs:
changes:
@@ -39,7 +39,7 @@ jobs:
offlinedocs: ${{ steps.filter.outputs.offlinedocs }}
steps:
- name: Checkout
uses: actions/checkout@v3
uses: actions/checkout@v4
with:
fetch-depth: 1
# For pull requests it's not necessary to checkout the code
@@ -53,7 +53,6 @@ jobs:
docs:
- "docs/**"
- "README.md"
- "examples/templates/**"
- "examples/web-server/**"
- "examples/monitoring/**"
- "examples/lima/**"
@@ -110,7 +109,7 @@ jobs:
runs-on: ${{ github.repository_owner == 'coder' && 'buildjet-8vcpu-ubuntu-2204' || 'ubuntu-latest' }}
steps:
- name: Checkout
uses: actions/checkout@v3
uses: actions/checkout@v4
with:
fetch-depth: 1
@@ -137,7 +136,7 @@ jobs:
# Check for any typos
- name: Check for typos
uses: crate-ci/typos@v1.16.1
uses: crate-ci/typos@v1.16.19
with:
config: .github/workflows/typos.toml
@@ -165,7 +164,7 @@ jobs:
if: needs.changes.outputs.docs-only == 'false' || needs.changes.outputs.ci == 'true' || github.ref == 'refs/heads/main'
steps:
- name: Checkout
uses: actions/checkout@v3
uses: actions/checkout@v4
with:
fetch-depth: 1
@@ -188,16 +187,13 @@ jobs:
- name: Install Protoc
run: |
# protoc must be in lockstep with our dogfood Dockerfile or the
# version in the comments will differ. This is also defined in
# security.yaml
set -x
cd dogfood
DOCKER_BUILDKIT=1 docker build . --target proto -t protoc
protoc_path=/usr/local/bin/protoc
docker run --rm --entrypoint cat protoc /tmp/bin/protoc > $protoc_path
chmod +x $protoc_path
protoc --version
mkdir -p /tmp/proto
pushd /tmp/proto
curl -L -o protoc.zip https://github.com/protocolbuffers/protobuf/releases/download/v23.3/protoc-23.3-linux-x86_64.zip
unzip protoc.zip
cp -r ./bin/* /usr/local/bin
cp -r ./include /usr/local/bin/include
popd
- name: make gen
run: "make --output-sync -j -B gen"
@@ -212,7 +208,7 @@ jobs:
timeout-minutes: 7
steps:
- name: Checkout
uses: actions/checkout@v3
uses: actions/checkout@v4
with:
fetch-depth: 1
@@ -224,10 +220,10 @@ jobs:
with:
# This doesn't need caching. It's super fast anyways!
cache: false
go-version: 1.20.6
go-version: 1.20.10
- name: Install shfmt
run: go install mvdan.cc/sh/v3/cmd/shfmt@v3.5.0
run: go install mvdan.cc/sh/v3/cmd/shfmt@v3.7.0
- name: make fmt
run: |
@@ -238,7 +234,7 @@ jobs:
run: ./scripts/check_unstaged.sh
test-go:
runs-on: ${{ matrix.os == 'ubuntu-latest' && github.repository_owner == 'coder' && 'buildjet-4vcpu-ubuntu-2204' || matrix.os == 'macos-latest' && github.repository_owner == 'coder' && 'macos-latest-xl' || matrix.os == 'windows-2019' && github.repository_owner == 'coder' && 'windows-latest-8-cores' || matrix.os }}
runs-on: ${{ matrix.os == 'ubuntu-latest' && github.repository_owner == 'coder' && 'buildjet-4vcpu-ubuntu-2204' || matrix.os == 'macos-latest' && github.repository_owner == 'coder' && 'macos-latest-xlarge' || matrix.os == 'windows-2022' && github.repository_owner == 'coder' && 'windows-latest-16-cores' || matrix.os }}
needs: changes
if: needs.changes.outputs.go == 'true' || needs.changes.outputs.ci == 'true' || github.ref == 'refs/heads/main'
timeout-minutes: 20
@@ -248,10 +244,10 @@ jobs:
os:
- ubuntu-latest
- macos-latest
- windows-2019
- windows-2022
steps:
- name: Checkout
uses: actions/checkout@v3
uses: actions/checkout@v4
with:
fetch-depth: 1
@@ -275,22 +271,29 @@ jobs:
echo "cover=false" >> $GITHUB_OUTPUT
fi
# if macOS, install google-chrome for scaletests. As another concern,
# should we really have this kind of external dependency requirement
# on standard CI?
if [ "${{ matrix.os }}" == "macos-latest" ]; then
brew install google-chrome
fi
# By default Go will use the number of logical CPUs, which
# is a fine default.
PARALLEL_FLAG=""
# macOS will output "The default interactive shell is now zsh"
# intermittently in CI...
if [ "${{ matrix.os }}" == "macos-latest" ]; then
touch ~/.bash_profile && echo "export BASH_SILENCE_DEPRECATION_WARNING=1" >> ~/.bash_profile
fi
export TS_DEBUG_DISCO=true
gotestsum --junitfile="gotests.xml" --jsonfile="gotests.json" \
--packages="./..." -- $PARALLEL_FLAG -short -failfast $COVERAGE_FLAGS
- name: Print test stats
if: success() || failure()
run: |
# Artifacts are not available after rerunning a job,
# so we need to print the test stats to the log.
go run ./scripts/ci-report/main.go gotests.json | tee gotests_stats.json
- name: Upload test stats to Datadog
timeout-minutes: 1
continue-on-error: true
uses: ./.github/actions/upload-datadog
if: success() || failure()
with:
@@ -320,7 +323,7 @@ jobs:
timeout-minutes: 25
steps:
- name: Checkout
uses: actions/checkout@v3
uses: actions/checkout@v4
with:
fetch-depth: 1
@@ -335,14 +338,9 @@ jobs:
export TS_DEBUG_DISCO=true
make test-postgres
- name: Print test stats
if: success() || failure()
run: |
# Artifacts are not available after rerunning a job,
# so we need to print the test stats to the log.
go run ./scripts/ci-report/main.go gotests.json | tee gotests_stats.json
- name: Upload test stats to Datadog
timeout-minutes: 1
continue-on-error: true
uses: ./.github/actions/upload-datadog
if: success() || failure()
with:
@@ -368,7 +366,7 @@ jobs:
timeout-minutes: 25
steps:
- name: Checkout
uses: actions/checkout@v3
uses: actions/checkout@v4
with:
fetch-depth: 1
@@ -383,6 +381,8 @@ jobs:
gotestsum --junitfile="gotests.xml" -- -race ./...
- name: Upload test stats to Datadog
timeout-minutes: 1
continue-on-error: true
uses: ./.github/actions/upload-datadog
if: always()
with:
@@ -390,7 +390,7 @@ jobs:
deploy:
name: "deploy"
runs-on: ${{ github.repository_owner == 'coder' && 'buildjet-8vcpu-ubuntu-2204' || 'ubuntu-latest' }}
runs-on: ${{ github.repository_owner == 'coder' && 'buildjet-16vcpu-ubuntu-2204' || 'ubuntu-latest' }}
timeout-minutes: 30
needs: changes
if: |
@@ -401,7 +401,7 @@ jobs:
id-token: write
steps:
- name: Checkout
uses: actions/checkout@v3
uses: actions/checkout@v4
with:
fetch-depth: 0
@@ -489,7 +489,7 @@ jobs:
timeout-minutes: 20
steps:
- name: Checkout
uses: actions/checkout@v3
uses: actions/checkout@v4
with:
fetch-depth: 1
@@ -513,13 +513,13 @@ jobs:
flags: unittest-js
test-e2e:
runs-on: ${{ github.repository_owner == 'coder' && 'buildjet-8vcpu-ubuntu-2204' || 'ubuntu-latest' }}
runs-on: ${{ github.repository_owner == 'coder' && 'buildjet-16vcpu-ubuntu-2204' || 'ubuntu-latest' }}
needs: changes
if: needs.changes.outputs.go == 'true' || needs.changes.outputs.ts == 'true' || needs.changes.outputs.ci == 'true' || github.ref == 'refs/heads/main'
timeout-minutes: 20
steps:
- name: Checkout
uses: actions/checkout@v3
uses: actions/checkout@v4
with:
fetch-depth: 1
@@ -532,6 +532,24 @@ jobs:
- name: Setup Terraform
uses: ./.github/actions/setup-tf
- name: go install tools
run: |
go install google.golang.org/protobuf/cmd/protoc-gen-go@v1.30
go install storj.io/drpc/cmd/protoc-gen-go-drpc@v0.0.33
go install golang.org/x/tools/cmd/goimports@latest
go install github.com/mikefarah/yq/v4@v4.30.6
go install github.com/golang/mock/mockgen@v1.6.0
- name: Install Protoc
run: |
mkdir -p /tmp/proto
pushd /tmp/proto
curl -L -o protoc.zip https://github.com/protocolbuffers/protobuf/releases/download/v23.3/protoc-23.3-linux-x86_64.zip
unzip protoc.zip
cp -r ./bin/* /usr/local/bin
cp -r ./include /usr/local/bin/include
popd
- name: Build
run: |
make -B site/out/index.html
@@ -539,7 +557,7 @@ jobs:
- run: pnpm playwright:install
working-directory: site
- run: pnpm playwright:test
- run: pnpm playwright:test --workers 1
env:
DEBUG: pw:api
working-directory: site
@@ -552,6 +570,14 @@ jobs:
path: ./site/test-results/**/*.webm
retention-days: 7
- name: Upload pprof dumps
if: always() && github.actor != 'dependabot[bot]' && runner.os == 'Linux' && !github.event.pull_request.head.repo.fork
uses: actions/upload-artifact@v3
with:
name: debug-pprof-dumps
path: ./site/test-results/**/debug-pprof-*.txt
retention-days: 7
chromatic:
# REMARK: this is only used to build storybook and deploy it to Chromatic.
runs-on: ubuntu-latest
@@ -559,7 +585,7 @@ jobs:
if: needs.changes.outputs.ts == 'true' || needs.changes.outputs.ci == 'true'
steps:
- name: Checkout
uses: actions/checkout@v3
uses: actions/checkout@v4
with:
# Required by Chromatic for build-over-build history, otherwise we
# only get 1 commit on shallow checkout.
@@ -586,6 +612,7 @@ jobs:
# https://www.chromatic.com/docs/github-actions#forked-repositories
projectToken: 695c25b6cb65
workingDir: "./site"
storybookBaseDir: "./site"
# Prevent excessive build runs on minor version changes
skip: "@(renovate/**|dependabot/**)"
# Run TurboSnap to trace file dependencies to related stories
@@ -611,6 +638,7 @@ jobs:
buildScriptName: "storybook:build"
projectToken: 695c25b6cb65
workingDir: "./site"
storybookBaseDir: "./site"
# Run TurboSnap to trace file dependencies to related stories
# and tell chromatic to only take snapshots of relevent stories
onlyChanged: true
@@ -622,7 +650,7 @@ jobs:
if: needs.changes.outputs.offlinedocs == 'true' || needs.changes.outputs.ci == 'true'
steps:
- name: Checkout
uses: actions/checkout@v3
uses: actions/checkout@v4
with:
# 0 is required here for version.sh to work.
fetch-depth: 0
@@ -640,9 +668,7 @@ jobs:
go install github.com/golang/mock/mockgen@v1.6.0
- name: Setup sqlc
uses: sqlc-dev/setup-sqlc@v3
with:
sqlc-version: "1.19.1"
uses: ./.github/actions/setup-sqlc
- name: Format
run: |
@@ -668,6 +694,7 @@ jobs:
- test-go-pg
- test-go-race
- test-js
- test-e2e
- offlinedocs
# Allow this job to run even if the needed jobs fail, are skipped or
# cancelled.
@@ -703,7 +730,7 @@ jobs:
DOCKER_CLI_EXPERIMENTAL: "enabled"
steps:
- name: Checkout
uses: actions/checkout@v3
uses: actions/checkout@v4
with:
fetch-depth: 0
@@ -717,13 +744,14 @@ jobs:
uses: ./.github/actions/setup-sqlc
- name: GHCR Login
uses: docker/login-action@v2
uses: docker/login-action@v3
with:
registry: ghcr.io
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Build and push Linux amd64 Docker image
id: build_and_push
run: |
set -euxo pipefail
go mod download
@@ -738,3 +766,19 @@ jobs:
--version $version \
--push \
build/coder_linux_amd64
# Tag image with new package tag and push
tag=$(echo "$version" | sed 's/+/-/g')
docker tag ghcr.io/coder/coder-preview:main ghcr.io/coder/coder-preview:main-$tag
docker push ghcr.io/coder/coder-preview:main-$tag
- name: Prune old images
uses: vlaurin/action-ghcr-prune@v0.5.0
with:
token: ${{ secrets.GITHUB_TOKEN }}
organization: coder
container: coder-preview
keep-younger-than: 7 # days
keep-tags-regexes: ^pr
prune-tags-regexes: ^main-
prune-untagged: true
+3 -2
View File
@@ -34,7 +34,7 @@ jobs:
steps:
- name: cla
if: (github.event.comment.body == 'recheck' || github.event.comment.body == 'I have read the CLA Document and I hereby sign the CLA') || github.event_name == 'pull_request_target'
uses: contributor-assistant/github-action@v2.3.0
uses: contributor-assistant/github-action@v2.3.1
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
# the below token should have repo scope and must be manually added by you in the repository's secret
@@ -46,7 +46,8 @@ jobs:
path-to-document: "https://github.com/coder/cla/blob/main/README.md"
# branch should not be protected
branch: "main"
allowlist: dependabot*
# Some users have signed a corporate CLA with Coder so are exempt from signing our community one.
allowlist: "coryb,aaronlehmann,dependabot*"
release-labels:
runs-on: ubuntu-latest
+2 -2
View File
@@ -32,10 +32,10 @@ jobs:
if: github.repository_owner == 'coder'
steps:
- name: Checkout
uses: actions/checkout@v3
uses: actions/checkout@v4
- name: Docker login
uses: docker/login-action@v2
uses: docker/login-action@v3
with:
registry: ghcr.io
username: ${{ github.actor }}
+19 -15
View File
@@ -5,11 +5,15 @@ on:
branches:
- main
paths:
- "flake.nix"
- "flake.lock"
- "dogfood/**"
- ".github/workflows/dogfood.yaml"
# Uncomment these lines when testing with CI.
# pull_request:
# paths:
# - "flake.nix"
# - "flake.lock"
# - "dogfood/**"
# - ".github/workflows/dogfood.yaml"
workflow_dispatch:
@@ -18,6 +22,9 @@ jobs:
deploy_image:
runs-on: buildjet-4vcpu-ubuntu-2204
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Get branch name
id: branch-name
uses: tj-actions/branch-names@v6.5
@@ -30,34 +37,31 @@ jobs:
tag=${tag//\//--}
echo "tag=${tag}" >> $GITHUB_OUTPUT
- name: Set up QEMU
uses: docker/setup-qemu-action@v2
- name: Install Nix
uses: DeterminateSystems/nix-installer-action@v6
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v2
- name: Run the Magic Nix Cache
uses: DeterminateSystems/magic-nix-cache-action@v2
- run: nix build .#devEnvImage && ./result | docker load
- name: Login to DockerHub
uses: docker/login-action@v2
uses: docker/login-action@v3
with:
username: ${{ secrets.DOCKERHUB_USERNAME }}
password: ${{ secrets.DOCKERHUB_PASSWORD }}
- name: Build and push
uses: docker/build-push-action@v4
with:
context: "{{defaultContext}}:dogfood"
pull: true
push: true
tags: "codercom/oss-dogfood:${{ steps.docker-tag-name.outputs.tag }},codercom/oss-dogfood:latest"
cache-from: type=registry,ref=codercom/oss-dogfood:latest
cache-to: type=inline
- name: Tag and Push
run: |
docker tag codercom/oss-dogfood:latest codercom/oss-dogfood:${{ steps.docker-tag-name.outputs.tag }}
docker push codercom/oss-dogfood -a
deploy_template:
needs: deploy_image
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v3
uses: actions/checkout@v4
- name: Get short commit SHA
id: vars
+2 -2
View File
@@ -17,7 +17,7 @@ jobs:
timeout-minutes: 240
steps:
- name: Checkout
uses: actions/checkout@v3
uses: actions/checkout@v4
- name: Setup Go
uses: ./.github/actions/setup-go
@@ -44,7 +44,7 @@ jobs:
timeout-minutes: 10
steps:
- name: Checkout
uses: actions/checkout@v3
uses: actions/checkout@v4
- name: Setup Go
uses: ./.github/actions/setup-go
+1 -1
View File
@@ -14,4 +14,4 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Assign author
uses: toshimaru/auto-author-assign@v1.6.2
uses: toshimaru/auto-author-assign@v2.0.1
+4 -4
View File
@@ -1,4 +1,4 @@
name: Cleanup PR deployment and image
name: pr-cleanup
on:
pull_request:
types: closed
@@ -35,14 +35,14 @@ jobs:
- name: Set up kubeconfig
run: |
set -euxo pipefail
set -euo pipefail
mkdir -p ~/.kube
echo "${{ secrets.PR_DEPLOYMENTS_KUBECONFIG }}" > ~/.kube/config
export KUBECONFIG=~/.kube/config
- name: Delete helm release
run: |
set -euxo pipefail
set -euo pipefail
helm delete --namespace "pr${{ steps.pr_number.outputs.PR_NUMBER }}" "pr${{ steps.pr_number.outputs.PR_NUMBER }}" || echo "helm release not found"
- name: "Remove PR namespace"
@@ -51,7 +51,7 @@ jobs:
- name: "Remove DNS records"
run: |
set -euxo pipefail
set -euo pipefail
# Get identifier for the record
record_id=$(curl -X GET "https://api.cloudflare.com/client/v4/zones/${{ secrets.PR_DEPLOYMENTS_ZONE_ID }}/dns_records?name=%2A.pr${{ steps.pr_number.outputs.PR_NUMBER }}.${{ secrets.PR_DEPLOYMENTS_DOMAIN }}" \
-H "Authorization: Bearer ${{ secrets.PR_DEPLOYMENTS_CLOUDFLARE_API_TOKEN }}" \
+166 -190
View File
@@ -4,24 +4,30 @@
# 3. when a PR is updated
name: Deploy PR
on:
pull_request:
types: synchronize
push:
branches-ignore:
- main
workflow_dispatch:
inputs:
pr_number:
description: "PR number"
type: number
required: true
skip_build:
description: "Skip build job"
required: false
type: boolean
default: false
experiments:
description: "Experiments to enable"
required: false
type: string
default: "*"
build:
description: "Force new build"
required: false
type: boolean
default: false
deploy:
description: "Force new deployment"
required: false
type: boolean
default: false
env:
REPO: ghcr.io/coder/coder-preview
@@ -29,43 +35,66 @@ env:
permissions:
contents: read
packages: write
pull-requests: write
concurrency:
group: ${{ github.workflow }}-PR-${{ github.event.pull_request.number || github.event.inputs.pr_number }}
cancel-in-progress: true
pull-requests: write # needed for commenting on PRs
jobs:
check_pr:
runs-on: ubuntu-latest
outputs:
PR_OPEN: ${{ steps.check_pr.outputs.pr_open }}
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Check if PR is open
id: check_pr
run: |
set -euo pipefail
pr_open=true
if [[ "$(gh pr view --json state | jq -r '.state')" != "OPEN" ]]; then
echo "PR doesn't exist or is closed."
pr_open=false
fi
echo "pr_open=$pr_open" >> $GITHUB_OUTPUT
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
get_info:
if: github.event_name == 'workflow_dispatch' || github.event_name == 'pull_request'
needs: check_pr
if: ${{ needs.check_pr.outputs.PR_OPEN == 'true' }}
outputs:
PR_NUMBER: ${{ steps.pr_info.outputs.PR_NUMBER }}
PR_TITLE: ${{ steps.pr_info.outputs.PR_TITLE }}
PR_URL: ${{ steps.pr_info.outputs.PR_URL }}
PR_BRANCH: ${{ steps.pr_info.outputs.PR_BRANCH }}
CODER_BASE_IMAGE_TAG: ${{ steps.set_tags.outputs.CODER_BASE_IMAGE_TAG }}
CODER_IMAGE_TAG: ${{ steps.set_tags.outputs.CODER_IMAGE_TAG }}
NEW: ${{ steps.check_deployment.outputs.new }}
BUILD: ${{ steps.filter.outputs.all_count > steps.filter.outputs.ignored_count || steps.check_deployment.outputs.new }}
NEW: ${{ steps.check_deployment.outputs.NEW }}
BUILD: ${{ steps.build_conditionals.outputs.first_or_force_build == 'true' || steps.build_conditionals.outputs.automatic_rebuild == 'true' }}
runs-on: "ubuntu-latest"
steps:
- name: Checkout
uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Get PR number, title, and branch name
id: pr_info
run: |
set -euxo pipefail
PR_NUMBER=${{ github.event.inputs.pr_number || github.event.pull_request.number }}
PR_TITLE=$(curl -s -H "Authorization: token ${{ secrets.GITHUB_TOKEN }}" https://api.github.com/repos/coder/coder/pulls/$PR_NUMBER | jq -r '.title')
PR_BRANCH=$(curl -s -H "Authorization: token ${{ secrets.GITHUB_TOKEN }}" https://api.github.com/repos/coder/coder/pulls/$PR_NUMBER | jq -r '.head.ref')
echo "PR_URL=https://github.com/coder/coder/pull/$PR_NUMBER" >> $GITHUB_OUTPUT
set -euo pipefail
PR_NUMBER=$(gh pr view --json number | jq -r '.number')
PR_TITLE=$(gh pr view --json title | jq -r '.title')
PR_URL=$(gh pr view --json url | jq -r '.url')
echo "PR_URL=$PR_URL" >> $GITHUB_OUTPUT
echo "PR_NUMBER=$PR_NUMBER" >> $GITHUB_OUTPUT
echo "PR_TITLE=$PR_TITLE" >> $GITHUB_OUTPUT
echo "PR_BRANCH=$PR_BRANCH" >> $GITHUB_OUTPUT
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- name: Set required tags
id: set_tags
run: |
set -euxo pipefail
set -euo pipefail
echo "CODER_BASE_IMAGE_TAG=$CODER_BASE_IMAGE_TAG" >> $GITHUB_OUTPUT
echo "CODER_IMAGE_TAG=$CODER_IMAGE_TAG" >> $GITHUB_OUTPUT
env:
@@ -74,61 +103,30 @@ jobs:
- name: Set up kubeconfig
run: |
set -euxo pipefail
set -euo pipefail
mkdir -p ~/.kube
echo "${{ secrets.PR_DEPLOYMENTS_KUBECONFIG }}" > ~/.kube/config
chmod 644 ~/.kube/config
export KUBECONFIG=~/.kube/config
- name: Check if the helm deployment already exists
id: check_deployment
run: |
set -euxo pipefail
set -euo pipefail
if helm status "pr${{ steps.pr_info.outputs.PR_NUMBER }}" --namespace "pr${{ steps.pr_info.outputs.PR_NUMBER }}" > /dev/null 2>&1; then
echo "Deployment already exists. Skipping deployment."
new=false
NEW=false
else
echo "Deployment doesn't exist."
new=true
NEW=true
fi
echo "new=$new" >> $GITHUB_OUTPUT
- name: Find Comment
uses: peter-evans/find-comment@v2
if: github.event_name == 'workflow_dispatch' || steps.check_deployment.outputs.NEW == 'false'
id: fc
with:
issue-number: ${{ steps.pr_info.outputs.PR_NUMBER }}
comment-author: "github-actions[bot]"
body-includes: ":rocket:"
direction: last
- name: Comment on PR
id: comment_id
if: github.event_name == 'workflow_dispatch' || steps.check_deployment.outputs.NEW == 'false'
uses: peter-evans/create-or-update-comment@v3
with:
comment-id: ${{ steps.fc.outputs.comment-id }}
issue-number: ${{ steps.pr_info.outputs.PR_NUMBER }}
edit-mode: replace
body: |
---
:rocket: Deploying PR ${{ steps.pr_info.outputs.PR_NUMBER }} ...
---
reactions: eyes
reactions-edit-mode: replace
- name: Checkout
if: github.event_name == 'workflow_dispatch' || steps.check_deployment.outputs.NEW == 'false'
uses: actions/checkout@v3
with:
ref: ${{ steps.pr_info.outputs.PR_BRANCH }}
fetch-depth: 0
echo "NEW=$NEW" >> $GITHUB_OUTPUT
- name: Check changed files
if: github.event_name == 'workflow_dispatch' || steps.check_deployment.outputs.NEW == 'false'
uses: dorny/paths-filter@v2
id: filter
with:
base: ${{ github.ref }}
filters: |
all:
- "**"
@@ -149,57 +147,85 @@ jobs:
- "scripts/**/*[^D][^o][^c][^k][^e][^r][^f][^i][^l][^e][.][b][^a][^s][^e]*"
- name: Print number of changed files
if: github.event_name == 'workflow_dispatch' || steps.check_deployment.outputs.NEW == 'false'
run: |
set -euxo pipefail
set -euo pipefail
echo "Total number of changed files: ${{ steps.filter.outputs.all_count }}"
echo "Number of ignored files: ${{ steps.filter.outputs.ignored_count }}"
- name: Build conditionals
id: build_conditionals
run: |
set -euo pipefail
# build if the workflow is manually triggered and the deployment doesn't exist (first build or force rebuild)
echo "first_or_force_build=${{ (github.event_name == 'workflow_dispatch' && steps.check_deployment.outputs.NEW == 'true') || github.event.inputs.build == 'true' }}" >> $GITHUB_OUTPUT
# build if the deployment alreday exist and there are changes in the files that we care about (automatic updates)
echo "automatic_rebuild=${{ steps.check_deployment.outputs.NEW == 'false' && steps.filter.outputs.all_count > steps.filter.outputs.ignored_count }}" >> $GITHUB_OUTPUT
comment-pr:
needs: get_info
if: needs.get_info.outputs.BUILD == 'true' || github.event.inputs.deploy == 'true'
runs-on: "ubuntu-latest"
steps:
- name: Find Comment
uses: peter-evans/find-comment@v2
id: fc
with:
issue-number: ${{ needs.get_info.outputs.PR_NUMBER }}
comment-author: "github-actions[bot]"
body-includes: ":rocket:"
direction: last
- name: Comment on PR
id: comment_id
uses: peter-evans/create-or-update-comment@v3
with:
comment-id: ${{ steps.fc.outputs.comment-id }}
issue-number: ${{ needs.get_info.outputs.PR_NUMBER }}
edit-mode: replace
body: |
---
:rocket: Deploying PR ${{ needs.get_info.outputs.PR_NUMBER }} ...
---
reactions: eyes
reactions-edit-mode: replace
build:
needs: get_info
# Skips the build job if the workflow was triggered by a workflow_dispatch event and the skip_build input is set to true
# or if the workflow was triggered by an issue_comment event and the comment body contains --skip-build
# always run the build job if a pull_request event triggered the workflow
if: |
(github.event_name == 'workflow_dispatch' && github.event.inputs.skip_build == 'false') ||
(github.event_name == 'pull_request' && needs.get_info.result == 'success' && needs.get_info.outputs.NEW == 'false')
# Run build job only if there are changes in the files that we care about or if the workflow is manually triggered with --build flag
if: needs.get_info.outputs.BUILD == 'true'
runs-on: ${{ github.repository_owner == 'coder' && 'buildjet-8vcpu-ubuntu-2204' || 'ubuntu-latest' }}
# This concurrency only cancels build jobs if a new build is triggred. It will avoid cancelling the current deployemtn in case of docs chnages.
concurrency:
group: build-${{ github.workflow }}-${{ github.ref }}-${{ needs.get_info.outputs.BUILD }}
cancel-in-progress: true
env:
DOCKER_CLI_EXPERIMENTAL: "enabled"
CODER_IMAGE_TAG: ${{ needs.get_info.outputs.CODER_IMAGE_TAG }}
PR_NUMBER: ${{ needs.get_info.outputs.PR_NUMBER }}
PR_BRANCH: ${{ needs.get_info.outputs.PR_BRANCH }}
steps:
- name: Checkout
uses: actions/checkout@v3
uses: actions/checkout@v4
with:
ref: ${{ env.PR_BRANCH }}
fetch-depth: 0
- name: Setup Node
if: needs.get_info.outputs.BUILD == 'true'
uses: ./.github/actions/setup-node
- name: Setup Go
if: needs.get_info.outputs.BUILD == 'true'
uses: ./.github/actions/setup-go
- name: Setup sqlc
if: needs.get_info.outputs.BUILD == 'true'
uses: ./.github/actions/setup-sqlc
- name: GHCR Login
if: needs.get_info.outputs.BUILD == 'true'
uses: docker/login-action@v2
uses: docker/login-action@v3
with:
registry: ghcr.io
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Build and push Linux amd64 Docker image
if: needs.get_info.outputs.BUILD == 'true'
run: |
set -euxo pipefail
set -euo pipefail
go mod download
make gen/mark-fresh
export DOCKER_IMAGE_NO_PREREQUISITES=true
@@ -217,35 +243,43 @@ jobs:
needs: [build, get_info]
# Run deploy job only if build job was successful or skipped
if: |
always() && (needs.build.result == 'success' || needs.build.result == 'skipped') &&
(github.event_name == 'workflow_dispatch' || needs.get_info.outputs.NEW == 'false')
always() && (needs.build.result == 'success' || needs.build.result == 'skipped') &&
(needs.get_info.outputs.BUILD == 'true' || github.event.inputs.deploy == 'true')
runs-on: "ubuntu-latest"
env:
CODER_IMAGE_TAG: ${{ needs.get_info.outputs.CODER_IMAGE_TAG }}
PR_NUMBER: ${{ needs.get_info.outputs.PR_NUMBER }}
PR_TITLE: ${{ needs.get_info.outputs.PR_TITLE }}
PR_URL: ${{ needs.get_info.outputs.PR_URL }}
PR_BRANCH: ${{ needs.get_info.outputs.PR_BRANCH }}
PR_DEPLOYMENT_ACCESS_URL: "pr${{ needs.get_info.outputs.PR_NUMBER }}.${{ secrets.PR_DEPLOYMENTS_DOMAIN }}"
PR_HOSTNAME: "pr${{ needs.get_info.outputs.PR_NUMBER }}.${{ secrets.PR_DEPLOYMENTS_DOMAIN }}"
steps:
- name: Set up kubeconfig
run: |
set -euxo pipefail
set -euo pipefail
mkdir -p ~/.kube
echo "${{ secrets.PR_DEPLOYMENTS_KUBECONFIG }}" > ~/.kube/config
chmod 644 ~/.kube/config
export KUBECONFIG=~/.kube/config
- name: Check if image exists
if: needs.get_info.outputs.NEW == 'true'
run: |
set -euxo pipefail
foundTag=$(curl -fsSL https://github.com/coder/coder/pkgs/container/coder-preview | grep -o ${{ env.CODER_IMAGE_TAG }} | head -n 1)
set -euo pipefail
foundTag=$(
gh api /orgs/coder/packages/container/coder-preview/versions |
jq -r --arg tag "pr${{ env.PR_NUMBER }}" '.[] |
select(.metadata.container.tags == [$tag]) |
.metadata.container.tags[0]'
)
if [ -z "$foundTag" ]; then
echo "Image not found"
echo "${{ env.CODER_IMAGE_TAG }} not found in ghcr.io/coder/coder-preview"
echo "Please remove --skip-build from the comment and try again"
exit 1
else
echo "Image found"
echo "$foundTag tag found in ghcr.io/coder/coder-preview"
fi
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- name: Add DNS record to Cloudflare
if: needs.get_info.outputs.NEW == 'true'
@@ -253,43 +287,27 @@ jobs:
curl -X POST "https://api.cloudflare.com/client/v4/zones/${{ secrets.PR_DEPLOYMENTS_ZONE_ID }}/dns_records" \
-H "Authorization: Bearer ${{ secrets.PR_DEPLOYMENTS_CLOUDFLARE_API_TOKEN }}" \
-H "Content-Type:application/json" \
--data '{"type":"CNAME","name":"*.${{ env.PR_DEPLOYMENT_ACCESS_URL }}","content":"${{ env.PR_DEPLOYMENT_ACCESS_URL }}","ttl":1,"proxied":false}'
- name: Checkout
uses: actions/checkout@v3
with:
ref: ${{ env.PR_BRANCH }}
--data '{"type":"CNAME","name":"*.${{ env.PR_HOSTNAME }}","content":"${{ env.PR_HOSTNAME }}","ttl":1,"proxied":false}'
- name: Create PR namespace
if: needs.get_info.outputs.NEW == 'true'
if: needs.get_info.outputs.NEW == 'true' || github.event.inputs.deploy == 'true'
run: |
set -euxo pipefail
set -euo pipefail
# try to delete the namespace, but don't fail if it doesn't exist
kubectl delete namespace "pr${{ env.PR_NUMBER }}" || true
kubectl create namespace "pr${{ env.PR_NUMBER }}"
- name: Checkout
uses: actions/checkout@v4
- name: Check and Create Certificate
if: needs.get_info.outputs.NEW == 'true'
if: needs.get_info.outputs.NEW == 'true' || github.event.inputs.deploy == 'true'
run: |
# Using kubectl to check if a Certificate resource already exists
# we are doing this to avoid letsenrypt rate limits
if ! kubectl get certificate pr${{ env.PR_NUMBER }}-tls -n pr-deployment-certs > /dev/null 2>&1; then
echo "Certificate doesn't exist. Creating a new one."
cat <<EOF | kubectl apply -f -
apiVersion: cert-manager.io/v1
kind: Certificate
metadata:
name: pr${{ env.PR_NUMBER }}-tls
namespace: pr-deployment-certs
spec:
secretName: pr${{ env.PR_NUMBER }}-tls
issuerRef:
name: letsencrypt
kind: ClusterIssuer
dnsNames:
- "${{ env.PR_DEPLOYMENT_ACCESS_URL }}"
- "*.${{ env.PR_DEPLOYMENT_ACCESS_URL }}"
EOF
envsubst < ./.github/pr-deployments/certificate.yaml | kubectl apply -f -
else
echo "Certificate exists. Skipping certificate creation."
fi
@@ -306,7 +324,7 @@ jobs:
)
- name: Set up PostgreSQL database
if: needs.get_info.outputs.NEW == 'true'
if: needs.get_info.outputs.NEW == 'true' || github.event.inputs.deploy == 'true'
run: |
helm repo add bitnami https://charts.bitnami.com/bitnami
helm install coder-db bitnami/postgresql \
@@ -318,82 +336,45 @@ jobs:
kubectl create secret generic coder-db-url -n pr${{ env.PR_NUMBER }} \
--from-literal=url="postgres://coder:coder@coder-db-postgresql.pr${{ env.PR_NUMBER }}.svc.cluster.local:5432/coder?sslmode=disable"
- name: Create values.yaml
if: github.event_name == 'workflow_dispatch'
- name: Create a service account, role, and rolebinding for the PR namespace
if: needs.get_info.outputs.NEW == 'true' || github.event.inputs.deploy == 'true'
run: |
cat <<EOF > pr-deploy-values.yaml
coder:
image:
repo: ${{ env.REPO }}
tag: pr${{ env.PR_NUMBER }}
pullPolicy: Always
service:
type: ClusterIP
ingress:
enable: true
className: traefik
host: ${{ env.PR_DEPLOYMENT_ACCESS_URL }}
wildcardHost: "*.${{ env.PR_DEPLOYMENT_ACCESS_URL }}"
tls:
enable: true
secretName: pr${{ env.PR_NUMBER }}-tls
wildcardSecretName: pr${{ env.PR_NUMBER }}-tls
env:
- name: "CODER_ACCESS_URL"
value: "https://${{ env.PR_DEPLOYMENT_ACCESS_URL }}"
- name: "CODER_WILDCARD_ACCESS_URL"
value: "*.${{ env.PR_DEPLOYMENT_ACCESS_URL }}"
- name: "CODER_EXPERIMENTS"
value: "${{ github.event.inputs.experiments }}"
- name: CODER_PG_CONNECTION_URL
valueFrom:
secretKeyRef:
name: coder-db-url
key: url
- name: "CODER_OAUTH2_GITHUB_ALLOW_SIGNUPS"
value: "true"
- name: "CODER_OAUTH2_GITHUB_CLIENT_ID"
value: "${{ secrets.PR_DEPLOYMENTS_GITHUB_OAUTH_CLIENT_ID }}"
- name: "CODER_OAUTH2_GITHUB_CLIENT_SECRET"
value: "${{ secrets.PR_DEPLOYMENTS_GITHUB_OAUTH_CLIENT_SECRET }}"
- name: "CODER_OAUTH2_GITHUB_ALLOWED_ORGS"
value: "coder"
EOF
set -euo pipefail
# Create service account, role, rolebinding
envsubst < ./.github/pr-deployments/rbac.yaml | kubectl apply -f -
- name: Create values.yaml
env:
EXPERIMENTS: ${{ github.event.inputs.experiments }}
PR_DEPLOYMENTS_GITHUB_OAUTH_CLIENT_ID: ${{ secrets.PR_DEPLOYMENTS_GITHUB_OAUTH_CLIENT_ID }}
PR_DEPLOYMENTS_GITHUB_OAUTH_CLIENT_SECRET: ${{ secrets.PR_DEPLOYMENTS_GITHUB_OAUTH_CLIENT_SECRET }}
run: |
set -euo pipefail
envsubst < ./.github/pr-deployments/values.yaml > ./pr-deploy-values.yaml
- name: Install/Upgrade Helm chart
run: |
set -euxo pipefail
if [[ ${{ github.event_name }} == "workflow_dispatch" ]]; then
helm upgrade --install "pr${{ env.PR_NUMBER }}" ./helm \
--namespace "pr${{ env.PR_NUMBER }}" \
--values ./pr-deploy-values.yaml \
--force
else
if [[ ${{ needs.get_info.outputs.BUILD }} == "true" ]]; then
helm upgrade --install "pr${{ env.PR_NUMBER }}" ./helm \
--namespace "pr${{ env.PR_NUMBER }}" \
--reuse-values \
--force
else
echo "Skipping helm upgrade, as there is no new image to deploy"
fi
fi
set -euo pipefail
helm upgrade --install "pr${{ env.PR_NUMBER }}" ./helm/coder \
--namespace "pr${{ env.PR_NUMBER }}" \
--values ./pr-deploy-values.yaml \
--force
- name: Install coder-logstream-kube
if: needs.get_info.outputs.NEW == 'true'
if: needs.get_info.outputs.NEW == 'true' || github.event.inputs.deploy == 'true'
run: |
helm repo add coder-logstream-kube https://helm.coder.com/logstream-kube
helm upgrade --install coder-logstream-kube coder-logstream-kube/coder-logstream-kube \
--namespace "pr${{ env.PR_NUMBER }}" \
--set url="https://pr${{ env.PR_NUMBER }}.${{ secrets.PR_DEPLOYMENTS_DOMAIN }}"
--set url="https://${{ env.PR_HOSTNAME }}"
- name: Get Coder binary
if: needs.get_info.outputs.NEW == 'true'
if: needs.get_info.outputs.NEW == 'true' || github.event.inputs.deploy == 'true'
run: |
set -euxo pipefail
set -euo pipefail
DEST="${HOME}/coder"
URL="https://${{ env.PR_DEPLOYMENT_ACCESS_URL }}/bin/coder-linux-amd64"
URL="https://${{ env.PR_HOSTNAME }}/bin/coder-linux-amd64"
mkdir -p "$(dirname ${DEST})"
@@ -414,10 +395,10 @@ jobs:
mv "${DEST}" /usr/local/bin/coder
- name: Create first user, template and workspace
if: needs.get_info.outputs.NEW == 'true'
if: needs.get_info.outputs.NEW == 'true' || github.event.inputs.deploy == 'true'
id: setup_deployment
run: |
set -euxo pipefail
set -euo pipefail
# Create first user
@@ -429,28 +410,23 @@ jobs:
echo "password=$password" >> $GITHUB_OUTPUT
coder login \
--first-user-username test \
--first-user-username coder \
--first-user-email pr${{ env.PR_NUMBER }}@coder.com \
--first-user-password $password \
--first-user-trial \
--use-token-as-session \
https://${{ env.PR_DEPLOYMENT_ACCESS_URL }}
https://${{ env.PR_HOSTNAME }}
# Create template
coder templates init --id kubernetes && cd ./kubernetes/ && coder templates create -y --variable namespace=pr${{ env.PR_NUMBER }}
cd ./.github/pr-deployments/template
coder templates create -y --variable namespace=pr${{ env.PR_NUMBER }} kubernetes
# Create workspace
cat <<EOF > workspace.yaml
cpu: "2"
memory: "4"
home_disk_size: "2"
EOF
coder create --template="kubernetes" test --rich-parameter-file ./workspace.yaml -y
coder stop test -y
coder create --template="kubernetes" kube --parameter cpu=2 --parameter memory=4 --parameter home_disk_size=2 -y
coder stop kube -y
- name: Send Slack notification
if: needs.get_info.outputs.NEW == 'true'
if: needs.get_info.outputs.NEW == 'true' || github.event.inputs.deploy == 'true'
run: |
curl -s -o /dev/null -X POST -H 'Content-type: application/json' \
-d \
@@ -458,7 +434,7 @@ jobs:
"pr_number": "'"${{ env.PR_NUMBER }}"'",
"pr_url": "'"${{ env.PR_URL }}"'",
"pr_title": "'"${{ env.PR_TITLE }}"'",
"pr_access_url": "'"https://${{ env.PR_DEPLOYMENT_ACCESS_URL }}"'",
"pr_access_url": "'"https://${{ env.PR_HOSTNAME }}"'",
"pr_username": "'"test"'",
"pr_email": "'"pr${{ env.PR_NUMBER }}@coder.com"'",
"pr_password": "'"${{ steps.setup_deployment.outputs.password }}"'",
+145 -15
View File
@@ -28,10 +28,6 @@ env:
# https://github.blog/changelog/2022-06-10-github-actions-inputs-unified-across-manual-and-reusable-workflows/
CODER_RELEASE: ${{ !inputs.dry_run }}
CODER_DRY_RUN: ${{ inputs.dry_run }}
# For some reason, setup-go won't actually pick up a new patch version if
# it has an old one cached. We need to manually specify the versions so we
# can get the latest release. Never use "~1.xx" here!
CODER_GO_VERSION: "1.20.6"
jobs:
release:
@@ -44,7 +40,7 @@ jobs:
version: ${{ steps.version.outputs.version }}
steps:
- name: Checkout
uses: actions/checkout@v3
uses: actions/checkout@v4
with:
fetch-depth: 0
@@ -89,7 +85,7 @@ jobs:
cat "$CODER_RELEASE_NOTES_FILE"
- name: Docker Login
uses: docker/login-action@v2
uses: docker/login-action@v3
with:
registry: ghcr.io
username: ${{ github.actor }}
@@ -145,7 +141,8 @@ jobs:
build/coder_"$version"_linux_{amd64,armv7,arm64}.{tar.gz,apk,deb,rpm} \
build/coder_"$version"_{darwin,windows}_{amd64,arm64}.zip \
build/coder_"$version"_windows_amd64_installer.exe \
build/coder_helm_"$version".tgz
build/coder_helm_"$version".tgz \
build/provisioner_helm_"$version".tgz
env:
CODER_SIGN_DARWIN: "1"
AC_CERTIFICATE_FILE: /tmp/apple_cert.p12
@@ -299,9 +296,11 @@ jobs:
version="$(./scripts/version.sh)"
mkdir -p build/helm
cp "build/coder_helm_${version}.tgz" build/helm
cp "build/provisioner_helm_${version}.tgz" build/helm
gsutil cp gs://helm.coder.com/v2/index.yaml build/helm/index.yaml
helm repo index build/helm --url https://helm.coder.com/v2 --merge build/helm/index.yaml
gsutil -h "Cache-Control:no-cache,max-age=0" cp build/helm/coder_helm_${version}.tgz gs://helm.coder.com/v2
gsutil -h "Cache-Control:no-cache,max-age=0" cp build/helm/provisioner_helm_${version}.tgz gs://helm.coder.com/v2
gsutil -h "Cache-Control:no-cache,max-age=0" cp build/helm/index.yaml gs://helm.coder.com/v2
gsutil -h "Cache-Control:no-cache,max-age=0" cp helm/artifacthub-repo.yml gs://helm.coder.com/v2
@@ -329,13 +328,88 @@ jobs:
event-type: coder-release
client-payload: '{"coder_version": "${{ steps.version.outputs.version }}"}'
publish-homebrew:
name: Publish to Homebrew tap
runs-on: ubuntu-latest
needs: release
if: ${{ !inputs.dry_run }}
steps:
# TODO: skip this if it's not a new release (i.e. a backport). This is
# fine right now because it just makes a PR that we can close.
- name: Update homebrew
env:
# Variables used by the `gh` command
GH_REPO: coder/homebrew-coder
GH_TOKEN: ${{ secrets.CDRCI_GITHUB_TOKEN }}
run: |
# Keep version number around for reference, removing any potential leading v
coder_version="$(echo "${{ needs.release.outputs.version }}" | tr -d v)"
set -euxo pipefail
# Setup Git
git config --global user.email "ci@coder.com"
git config --global user.name "Coder CI"
git config --global credential.helper "store"
temp_dir="$(mktemp -d)"
cd "$temp_dir"
# Download checksums
checksums_url="$(gh release view --repo coder/coder "v$coder_version" --json assets \
| jq -r ".assets | map(.url) | .[]" \
| grep -e ".checksums.txt\$")"
wget "$checksums_url" -O checksums.txt
# Get the SHAs
darwin_arm_sha="$(cat checksums.txt | grep "darwin_arm64.zip" | awk '{ print $1 }')"
darwin_intel_sha="$(cat checksums.txt | grep "darwin_amd64.zip" | awk '{ print $1 }')"
linux_sha="$(cat checksums.txt | grep "linux_amd64.tar.gz" | awk '{ print $1 }')"
echo "macOS arm64: $darwin_arm_sha"
echo "macOS amd64: $darwin_intel_sha"
echo "Linux amd64: $linux_sha"
# Check out the homebrew repo
git clone "https://github.com/$GH_REPO" homebrew-coder
brew_branch="auto-release/$coder_version"
cd homebrew-coder
# Check if a PR already exists.
pr_count="$(gh pr list --search "head:$brew_branch" --json id,closed | jq -r ".[] | select(.closed == false) | .id" | wc -l)"
if [[ "$pr_count" > 0 ]]; then
echo "Bailing out as PR already exists" 2>&1
exit 0
fi
# Set up cdrci credentials for pushing to homebrew-coder
echo "https://x-access-token:$GH_TOKEN@github.com" >> ~/.git-credentials
# Update the formulae and push
git checkout -b "$brew_branch"
./scripts/update-v2.sh "$coder_version" "$darwin_arm_sha" "$darwin_intel_sha" "$linux_sha"
git add .
git commit -m "coder $coder_version"
git push -u origin -f "$brew_branch"
# Create PR
gh pr create \
-B master -H "$brew_branch" \
-t "coder $coder_version" \
-b "" \
-r "${{ github.actor }}" \
-a "${{ github.actor }}" \
-b "This automatic PR was triggered by the release of Coder v$coder_version"
publish-winget:
name: Publish to winget-pkgs
runs-on: windows-latest
needs: release
if: ${{ !inputs.dry_run }}
steps:
- name: Checkout
uses: actions/checkout@v3
uses: actions/checkout@v4
with:
fetch-depth: 0
@@ -368,12 +442,6 @@ jobs:
echo "Installer URL: ${installer_url}"
echo "Package version: ${version}"
# Bail if dry-run.
if ($env:CODER_DRY_RUN -match "t") {
echo "Skipping submission due to dry-run."
exit 0
}
# The URL "|X64" suffix forces the architecture as it cannot be
# sniffed properly from the URL. wingetcreate checks both the URL and
# binary magic bytes for the architecture and they need to both match,
@@ -397,7 +465,6 @@ jobs:
WINGET_GH_TOKEN: ${{ secrets.CDRCI_GITHUB_TOKEN }}
- name: Comment on PR
if: ${{ !inputs.dry_run }}
run: |
# wait 30 seconds
Start-Sleep -Seconds 30.0
@@ -413,3 +480,66 @@ jobs:
# For gh CLI. We need a real token since we're commenting on a PR in a
# different repo.
GH_TOKEN: ${{ secrets.CDRCI_GITHUB_TOKEN }}
publish-chocolatey:
name: Publish to Chocolatey
runs-on: windows-latest
needs: release
if: ${{ !inputs.dry_run }}
steps:
- name: Checkout
uses: actions/checkout@v4
with:
fetch-depth: 0
# Same reason as for release.
- name: Fetch git tags
run: git fetch --tags --force
# From https://chocolatey.org
- name: Install Chocolatey
run: |
Set-ExecutionPolicy Bypass -Scope Process -Force
[System.Net.ServicePointManager]::SecurityProtocol = [System.Net.ServicePointManager]::SecurityProtocol -bor 3072
iex ((New-Object System.Net.WebClient).DownloadString('https://community.chocolatey.org/install.ps1'))
- name: Build chocolatey package
run: |
cd scripts/chocolatey
# The package version is the same as the tag minus the leading "v".
# The version in this output already has the leading "v" removed but
# we do it again to be safe.
$version = "${{ needs.release.outputs.version }}".Trim('v')
$release_assets = gh release view --repo coder/coder "v${version}" --json assets | `
ConvertFrom-Json
# Get the URL for the Windows ZIP from the release assets.
$zip_url = $release_assets.assets | `
Where-Object name -Match ".*_windows_amd64.zip$" | `
Select -ExpandProperty url
echo "ZIP URL: ${zip_url}"
echo "Package version: ${version}"
echo "Downloading ZIP..."
Invoke-WebRequest $zip_url -OutFile assets.zip
echo "Extracting ZIP..."
Expand-Archive assets.zip -DestinationPath assets/
# No need to specify nuspec if there's only one in the directory.
choco pack --version=$version binary_path=assets/coder.exe
choco apikey --api-key $env:CHOCO_API_KEY --source https://push.chocolatey.org/
# No need to specify nupkg if there's only one in the directory.
choco push --source https://push.chocolatey.org/
env:
CHOCO_API_KEY: ${{ secrets.CHOCO_API_KEY }}
# We need a GitHub token for the gh CLI to function under GitHub Actions
GH_TOKEN: ${{ secrets.CDRCI_GITHUB_TOKEN }}
+3 -6
View File
@@ -21,15 +21,12 @@ concurrency:
group: ${{ github.workflow }}-${{ github.ref }}-security
cancel-in-progress: ${{ github.event_name == 'pull_request' }}
env:
CODER_GO_VERSION: "1.20.6"
jobs:
codeql:
runs-on: ${{ github.repository_owner == 'coder' && 'buildjet-8vcpu-ubuntu-2204' || 'ubuntu-latest' }}
steps:
- name: Checkout
uses: actions/checkout@v3
uses: actions/checkout@v4
- name: Initialize CodeQL
uses: github/codeql-action/init@v2
@@ -62,7 +59,7 @@ jobs:
runs-on: ${{ github.repository_owner == 'coder' && 'buildjet-8vcpu-ubuntu-2204' || 'ubuntu-latest' }}
steps:
- name: Checkout
uses: actions/checkout@v3
uses: actions/checkout@v4
with:
fetch-depth: 0
@@ -125,7 +122,7 @@ jobs:
image_name: ${{ steps.build.outputs.image }}
- name: Run Trivy vulnerability scanner
uses: aquasecurity/trivy-action@41f05d9ecffa2ed3f1580af306000f734b733e54
uses: aquasecurity/trivy-action@fbd16365eb88e12433951383f5e99bd901fc618f
with:
image-ref: ${{ steps.build.outputs.image }}
format: sarif
+1 -1
View File
@@ -34,7 +34,7 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@v3
uses: actions/checkout@v4
- name: Run delete-old-branches-action
uses: beatlabs/delete-old-branches-action@v0.0.10
with:
+12 -4
View File
@@ -30,15 +30,14 @@ site/e2e/states/*.json
site/e2e/.auth.json
site/playwright-report/*
site/.swc
site/dist/
# Make target for updating golden files (any dir).
.gen-golden
# Build
/build/
/dist/
site/out/
build/
dist/
out/
# Bundle analysis
site/stats/
@@ -61,3 +60,12 @@ site/stats/
./scaletest/terraform/.terraform.lock.hcl
scaletest/terraform/secrets.tfvars
.terraform.tfstate.*
# Nix
result
# Data dumps from unit tests
**/*.test.sql
# Filebrowser.db
**/filebrowser.db
+18 -7
View File
@@ -2,12 +2,19 @@
# Over time we should try tightening some of these.
linters-settings:
dupl:
# goal: 100
threshold: 412
exhaustruct:
include:
# Gradually extend to cover more of the codebase.
- 'httpmw\.\w+'
# We want to enforce all values are specified when inserting or updating
# a database row. Ref: #9936
- 'github.com/coder/coder/v2/coderd/database\.[^G][^e][^t]\w+Params'
gocognit:
min-complexity: 46 # Min code complexity (def 30).
min-complexity: 300
goconst:
min-len: 4 # Min length of string consts (def 3).
@@ -118,10 +125,6 @@ linters-settings:
goimports:
local-prefixes: coder.com,cdr.dev,go.coder.com,github.com/cdr,github.com/coder
gocyclo:
# goal: 30
min-complexity: 47
importas:
no-unaliased: true
@@ -131,7 +134,8 @@ linters-settings:
- trialer
nestif:
min-complexity: 4 # Min complexity of if statements (def 5, goal 4)
# goal: 10
min-complexity: 20
revive:
# see https://github.com/mgechev/revive#available-rules for details.
@@ -211,6 +215,7 @@ issues:
run:
skip-dirs:
- node_modules
- .git
skip-files:
- scripts/rules.go
timeout: 10m
@@ -231,7 +236,12 @@ linters:
- exportloopref
- forcetypeassert
- gocritic
- gocyclo
# gocyclo is may be useful in the future when we start caring
# about testing complexity, but for the time being we should
# create a good culture around cognitive complexity.
# - gocyclo
- gocognit
- nestif
- goimports
- gomodguard
- gosec
@@ -267,3 +277,4 @@ linters:
- typecheck
- unconvert
- unused
- dupl
+16 -5
View File
@@ -33,15 +33,14 @@ site/e2e/states/*.json
site/e2e/.auth.json
site/playwright-report/*
site/.swc
site/dist/
# Make target for updating golden files (any dir).
.gen-golden
# Build
/build/
/dist/
site/out/
build/
dist/
out/
# Bundle analysis
site/stats/
@@ -64,10 +63,19 @@ site/stats/
./scaletest/terraform/.terraform.lock.hcl
scaletest/terraform/secrets.tfvars
.terraform.tfstate.*
# Nix
result
# Data dumps from unit tests
**/*.test.sql
# Filebrowser.db
**/filebrowser.db
# .prettierignore.include:
# Helm templates contain variables that are invalid YAML and can't be formatted
# by Prettier.
helm/templates/*.yaml
helm/**/templates/*.yaml
# Terraform state files used in tests, these are automatically generated.
# Example: provisioner/terraform/testdata/instance-id/instance-id.tfstate.json
@@ -80,3 +88,6 @@ scripts/apitypings/testdata/**/*.ts
site/e2e/provisionerGenerated.ts
**/pnpm-lock.yaml
# Ignore generated JSON (e.g. examples/examples.gen.json).
**/*.gen.json
+4 -1
View File
@@ -1,6 +1,6 @@
# Helm templates contain variables that are invalid YAML and can't be formatted
# by Prettier.
helm/templates/*.yaml
helm/**/templates/*.yaml
# Terraform state files used in tests, these are automatically generated.
# Example: provisioner/terraform/testdata/instance-id/instance-id.tfstate.json
@@ -13,3 +13,6 @@ scripts/apitypings/testdata/**/*.ts
site/e2e/provisionerGenerated.ts
**/pnpm-lock.yaml
# Ignore generated JSON (e.g. examples/examples.gen.json).
**/*.gen.json
+7 -7
View File
@@ -1,18 +1,18 @@
# This config file is used in conjunction with `.editorconfig` to specify
# formatting for prettier-supported files. See `.editorconfig` and
# `site/.editorconfig`for whitespace formatting options.
# `site/.editorconfig` for whitespace formatting options.
printWidth: 80
semi: false
proseWrap: always
trailingComma: all
useTabs: false
tabWidth: 2
overrides:
- files:
- README.md
- docs/api/**/*.md
- docs/cli/**/*.md
- docs/changelogs/*.md
- .github/**/*.{yaml,yml,toml}
- scripts/**/*.{yaml,yml,toml}
options:
proseWrap: preserve
- files:
- "site/**/*.yaml"
- "site/**/*.yml"
options:
proseWrap: always
+2 -2
View File
@@ -1,8 +1,8 @@
// Replace all NullTime with string
replace github.com/coder/coder/codersdk.NullTime string
replace github.com/coder/coder/v2/codersdk.NullTime string
// Prevent swaggo from rendering enums for time.Duration
replace time.Duration int64
// Do not expose "echo" provider
replace github.com/coder/coder/codersdk.ProvisionerType string
replace github.com/coder/coder/v2/codersdk.ProvisionerType string
// Do not render netip.Addr
replace netip.Addr string
+13 -4
View File
@@ -39,6 +39,7 @@
"enterprisemeta",
"errgroup",
"eventsourcemock",
"externalauth",
"Failf",
"fatih",
"Formik",
@@ -186,12 +187,20 @@
]
},
"eslint.workingDirectories": ["./site"],
"files.exclude": {
"**/node_modules": true
},
"search.exclude": {
"**.pb.go": true,
"**/*.gen.json": true,
"**/testdata/*": true,
"**Generated.ts": true,
"coderd/apidoc/**": true,
"docs/api/*.md": true,
"docs/templates/*.md": true,
"LICENSE": true,
"scripts/metricsdocgen/metrics": true,
"docs/api/*.md": true
"site/out/**": true,
"site/storybook-static/**": true,
"**.map": true,
"pnpm-lock.yaml": true
},
// Ensure files always have a newline.
"files.insertFinalNewline": true,
+54 -20
View File
@@ -107,9 +107,9 @@ endif
clean:
rm -rf build site/out
mkdir -p build site/out/bin
git restore site/out
rm -rf build/ site/build/ site/out/
mkdir -p build/ site/out/bin/
git restore site/out/
.PHONY: clean
build-slim: $(CODER_SLIM_BINARIES)
@@ -344,15 +344,19 @@ push/$(CODER_MAIN_IMAGE): $(CODER_MAIN_IMAGE)
docker manifest push "$$image_tag"
.PHONY: push/$(CODER_MAIN_IMAGE)
# Helm charts that are available
charts = coder provisioner
# Shortcut for Helm chart package.
build/coder_helm.tgz: build/coder_helm_$(VERSION).tgz
$(foreach chart,$(charts),build/$(chart)_helm.tgz): build/%_helm.tgz: build/%_helm_$(VERSION).tgz
rm -f "$@"
ln "$<" "$@"
# Helm chart package.
build/coder_helm_$(VERSION).tgz:
$(foreach chart,$(charts),build/$(chart)_helm_$(VERSION).tgz): build/%_helm_$(VERSION).tgz:
./scripts/helm.sh \
--version "$(VERSION)" \
--chart $* \
--output "$@"
site/out/index.html: site/package.json $(shell find ./site $(FIND_EXCLUSIONS) -type f \( -name '*.ts' -o -name '*.tsx' \))
@@ -415,7 +419,6 @@ lint: lint/shellcheck lint/go lint/ts lint/helm lint/site-icons
lint/site-icons:
./scripts/check_site_icons.sh
.PHONY: lint/site-icons
lint/ts:
@@ -452,10 +455,10 @@ DB_GEN_FILES := \
# all gen targets should be added here and to gen/mark-fresh
gen: \
coderd/database/dump.sql \
$(DB_GEN_FILES) \
provisionersdk/proto/provisioner.pb.go \
provisionerd/proto/provisionerd.pb.go \
coderd/database/dump.sql \
$(DB_GEN_FILES) \
site/src/api/typesGenerated.ts \
coderd/rbac/object_gen.go \
docs/admin/prometheus.md \
@@ -466,17 +469,20 @@ gen: \
.prettierignore \
site/.prettierrc.yaml \
site/.prettierignore \
site/.eslintignore
site/.eslintignore \
site/e2e/provisionerGenerated.ts \
site/src/theme/icons.json \
examples/examples.gen.json
.PHONY: gen
# Mark all generated files as fresh so make thinks they're up-to-date. This is
# used during releases so we don't run generation scripts.
gen/mark-fresh:
files="\
coderd/database/dump.sql \
$(DB_GEN_FILES) \
provisionersdk/proto/provisioner.pb.go \
provisionerd/proto/provisionerd.pb.go \
coderd/database/dump.sql \
$(DB_GEN_FILES) \
site/src/api/typesGenerated.ts \
coderd/rbac/object_gen.go \
docs/admin/prometheus.md \
@@ -488,6 +494,9 @@ gen/mark-fresh:
site/.prettierrc.yaml \
site/.prettierignore \
site/.eslintignore \
site/e2e/provisionerGenerated.ts \
site/src/theme/icons.json \
examples/examples.gen.json \
"
for file in $$files; do
echo "$$file"
@@ -507,6 +516,8 @@ coderd/database/dump.sql: coderd/database/gen/dump/main.go $(wildcard coderd/dat
go run ./coderd/database/gen/dump/main.go
# Generates Go code for querying the database.
# coderd/database/queries.sql.go
# coderd/database/models.go
coderd/database/querier.go: coderd/database/sqlc.yaml coderd/database/dump.sql $(wildcard coderd/database/queries/*.sql)
./coderd/database/generate.sh
@@ -529,10 +540,21 @@ provisionerd/proto/provisionerd.pb.go: provisionerd/proto/provisionerd.proto
--go-drpc_opt=paths=source_relative \
./provisionerd/proto/provisionerd.proto
site/src/api/typesGenerated.ts: scripts/apitypings/main.go $(shell find ./codersdk $(FIND_EXCLUSIONS) -type f -name '*.go')
go run scripts/apitypings/main.go > site/src/api/typesGenerated.ts
site/src/api/typesGenerated.ts: $(wildcard scripts/apitypings/*) $(shell find ./codersdk $(FIND_EXCLUSIONS) -type f -name '*.go')
go run ./scripts/apitypings/ > $@
pnpm run format:write:only "$@"
site/e2e/provisionerGenerated.ts: provisionerd/proto/provisionerd.pb.go provisionersdk/proto/provisioner.pb.go
cd site
pnpm run format:types
../scripts/pnpm_install.sh
pnpm run gen:provisioner
site/src/theme/icons.json: $(wildcard scripts/gensite/*) $(wildcard site/static/icon/*)
go run ./scripts/gensite/ -icons "$@"
pnpm run format:write:only "$@"
examples/examples.gen.json: scripts/examplegen/main.go examples/examples.go $(shell find ./examples/templates)
go run ./scripts/examplegen/main.go > examples/examples.gen.json
coderd/rbac/object_gen.go: scripts/rbacgen/main.go coderd/rbac/object.go
go run scripts/rbacgen/main.go ./coderd/rbac > coderd/rbac/object_gen.go
@@ -541,8 +563,8 @@ docs/admin/prometheus.md: scripts/metricsdocgen/main.go scripts/metricsdocgen/me
go run scripts/metricsdocgen/main.go
pnpm run format:write:only ./docs/admin/prometheus.md
docs/cli.md: scripts/clidocgen/main.go $(GO_SRC_FILES)
BASE_PATH="." go run ./scripts/clidocgen
docs/cli.md: scripts/clidocgen/main.go examples/examples.gen.json $(GO_SRC_FILES)
CI=true BASE_PATH="." go run ./scripts/clidocgen
pnpm run format:write:only ./docs/cli.md ./docs/cli/*.md ./docs/manifest.json
docs/admin/audit-logs.md: scripts/auditdocgen/main.go enterprise/audit/table.go coderd/rbac/object_gen.go
@@ -553,7 +575,7 @@ coderd/apidoc/swagger.json: $(shell find ./scripts/apidocgen $(FIND_EXCLUSIONS)
./scripts/apidocgen/generate.sh
pnpm run format:write:only ./docs/api ./docs/manifest.json ./coderd/apidoc/swagger.json
update-golden-files: cli/testdata/.gen-golden helm/tests/testdata/.gen-golden scripts/ci-report/testdata/.gen-golden enterprise/cli/testdata/.gen-golden
update-golden-files: cli/testdata/.gen-golden helm/coder/tests/testdata/.gen-golden helm/provisioner/tests/testdata/.gen-golden scripts/ci-report/testdata/.gen-golden enterprise/cli/testdata/.gen-golden coderd/.gen-golden provisioner/terraform/testdata/.gen-golden
.PHONY: update-golden-files
cli/testdata/.gen-golden: $(wildcard cli/testdata/*.golden) $(wildcard cli/*.tpl) $(GO_SRC_FILES) $(wildcard cli/*_test.go)
@@ -564,8 +586,20 @@ enterprise/cli/testdata/.gen-golden: $(wildcard enterprise/cli/testdata/*.golden
go test ./enterprise/cli -run="TestEnterpriseCommandHelp" -update
touch "$@"
helm/tests/testdata/.gen-golden: $(wildcard helm/tests/testdata/*.yaml) $(wildcard helm/tests/testdata/*.golden) $(GO_SRC_FILES) $(wildcard helm/tests/*_test.go)
go test ./helm/tests -run=TestUpdateGoldenFiles -update
helm/coder/tests/testdata/.gen-golden: $(wildcard helm/coder/tests/testdata/*.yaml) $(wildcard helm/coder/tests/testdata/*.golden) $(GO_SRC_FILES) $(wildcard helm/coder/tests/*_test.go)
go test ./helm/coder/tests -run=TestUpdateGoldenFiles -update
touch "$@"
helm/provisioner/tests/testdata/.gen-golden: $(wildcard helm/provisioner/tests/testdata/*.yaml) $(wildcard helm/provisioner/tests/testdata/*.golden) $(GO_SRC_FILES) $(wildcard helm/provisioner/tests/*_test.go)
go test ./helm/provisioner/tests -run=TestUpdateGoldenFiles -update
touch "$@"
coderd/.gen-golden: $(wildcard coderd/testdata/*/*.golden) $(GO_SRC_FILES) $(wildcard coderd/*_test.go)
go test ./coderd -run="Test.*Golden$$" -update
touch "$@"
provisioner/terraform/testdata/.gen-golden: $(wildcard provisioner/terraform/testdata/*/*.golden) $(GO_SRC_FILES) $(wildcard provisioner/terraform/*_test.go)
go test ./provisioner/terraform -run="Test.*Golden$$" -update
touch "$@"
scripts/ci-report/testdata/.gen-golden: $(wildcard scripts/ci-report/testdata/*) $(wildcard scripts/ci-report/*.go)
@@ -586,7 +620,7 @@ site/.prettierrc.yaml: .prettierrc.yaml
# - ./ -> ../
# - ./site -> ./
yq \
'.overrides[].files |= map(. | sub("^./"; "") | sub("^"; "../") | sub("../site/"; "./"))' \
'.overrides[].files |= map(. | sub("^./"; "") | sub("^"; "../") | sub("../site/"; "./") | sub("../!"; "!../"))' \
"$<" >> "$@"
# Combine .gitignore with .prettierignore.include to generate .prettierignore.
+1 -1
View File
@@ -74,7 +74,7 @@ You can run the install script with `--dry-run` to see the commands that will be
Once installed, you can start a production deployment<sup>1</sup> with a single command:
```console
```shell
# Automatically sets up an external access URL on *.try.coder.app
coder server
+47 -39
View File
@@ -1,7 +1,7 @@
# Coder Security
Coder welcomes feedback from security researchers and the general public
to help improve our security. If you believe you have discovered a vulnerability,
Coder welcomes feedback from security researchers and the general public to help
improve our security. If you believe you have discovered a vulnerability,
privacy issue, exposed data, or other security issues in any of our assets, we
want to hear from you. This policy outlines steps for reporting vulnerabilities
to us, what we expect, what you can expect from us.
@@ -10,64 +10,72 @@ You can see the pretty version [here](https://coder.com/security/policy)
# Why Coder's security matters
If an attacker could fully compromise a Coder installation, they could spin
up expensive workstations, steal valuable credentials, or steal proprietary
source code. We take this risk very seriously and employ routine pen testing,
vulnerability scanning, and code reviews. We also welcome the contributions
from the community that helped make this product possible.
If an attacker could fully compromise a Coder installation, they could spin up
expensive workstations, steal valuable credentials, or steal proprietary source
code. We take this risk very seriously and employ routine pen testing,
vulnerability scanning, and code reviews. We also welcome the contributions from
the community that helped make this product possible.
# Where should I report security issues?
Please report security issues to security@coder.com, providing
all relevant information. The more details you provide, the easier it will be
for us to triage and fix the issue.
Please report security issues to security@coder.com, providing all relevant
information. The more details you provide, the easier it will be for us to
triage and fix the issue.
# Out of Scope
Our primary concern is around an abuse of the Coder application that allows
an attacker to gain access to another users workspace, or spin up unwanted
Our primary concern is around an abuse of the Coder application that allows an
attacker to gain access to another users workspace, or spin up unwanted
workspaces.
- DOS/DDOS attacks affecting availability --> While we do support rate limiting
of requests, we primarily leave this to the owner of the Coder installation. Our
rationale is that a DOS attack only affecting availability is not a valuable
target for attackers.
of requests, we primarily leave this to the owner of the Coder installation.
Our rationale is that a DOS attack only affecting availability is not a
valuable target for attackers.
- Abuse of a compromised user credential --> If a user credential is compromised
outside of the Coder ecosystem, then we consider it beyond the scope of our application.
However, if an unprivileged user could escalate their permissions or gain access
to another workspace, that is a cause for concern.
outside of the Coder ecosystem, then we consider it beyond the scope of our
application. However, if an unprivileged user could escalate their permissions
or gain access to another workspace, that is a cause for concern.
- Vulnerabilities in third party systems --> Vulnerabilities discovered in
out-of-scope systems should be reported to the appropriate vendor or applicable authority.
out-of-scope systems should be reported to the appropriate vendor or
applicable authority.
# Our Commitments
When working with us, according to this policy, you can expect us to:
- Respond to your report promptly, and work with you to understand and validate your report;
- Strive to keep you informed about the progress of a vulnerability as it is processed;
- Work to remediate discovered vulnerabilities in a timely manner, within our operational constraints; and
- Extend Safe Harbor for your vulnerability research that is related to this policy.
- Respond to your report promptly, and work with you to understand and validate
your report;
- Strive to keep you informed about the progress of a vulnerability as it is
processed;
- Work to remediate discovered vulnerabilities in a timely manner, within our
operational constraints; and
- Extend Safe Harbor for your vulnerability research that is related to this
policy.
# Our Expectations
In participating in our vulnerability disclosure program in good faith, we ask that you:
In participating in our vulnerability disclosure program in good faith, we ask
that you:
- Play by the rules, including following this policy and any other relevant agreements.
If there is any inconsistency between this policy and any other applicable terms, the
terms of this policy will prevail;
- Play by the rules, including following this policy and any other relevant
agreements. If there is any inconsistency between this policy and any other
applicable terms, the terms of this policy will prevail;
- Report any vulnerability youve discovered promptly;
- Avoid violating the privacy of others, disrupting our systems, destroying data, and/or
harming user experience;
- Avoid violating the privacy of others, disrupting our systems, destroying
data, and/or harming user experience;
- Use only the Official Channels to discuss vulnerability information with us;
- Provide us a reasonable amount of time (at least 90 days from the initial report) to
resolve the issue before you disclose it publicly;
- Perform testing only on in-scope systems, and respect systems and activities which
are out-of-scope;
- If a vulnerability provides unintended access to data: Limit the amount of data you
access to the minimum required for effectively demonstrating a Proof of Concept; and
cease testing and submit a report immediately if you encounter any user data during testing,
such as Personally Identifiable Information (PII), Personal Healthcare Information (PHI),
credit card data, or proprietary information;
- You should only interact with test accounts you own or with explicit permission from
- Provide us a reasonable amount of time (at least 90 days from the initial
report) to resolve the issue before you disclose it publicly;
- Perform testing only on in-scope systems, and respect systems and activities
which are out-of-scope;
- If a vulnerability provides unintended access to data: Limit the amount of
data you access to the minimum required for effectively demonstrating a Proof
of Concept; and cease testing and submit a report immediately if you encounter
any user data during testing, such as Personally Identifiable Information
(PII), Personal Healthcare Information (PHI), credit card data, or proprietary
information;
- You should only interact with test accounts you own or with explicit
permission from
- the account holder; and
- Do not engage in extortion.
+463 -490
View File
File diff suppressed because it is too large Load Diff
+481 -183
View File
@@ -1,7 +1,6 @@
package agent_test
import (
"bufio"
"bytes"
"context"
"encoding/json"
@@ -12,6 +11,7 @@ import (
"net/http/httptest"
"net/netip"
"os"
"os/exec"
"os/user"
"path"
"path/filepath"
@@ -21,10 +21,12 @@ import (
"strings"
"sync"
"sync/atomic"
"syscall"
"testing"
"time"
scp "github.com/bramvdbogaerde/go-scp"
"github.com/golang/mock/gomock"
"github.com/google/uuid"
"github.com/pion/udp"
"github.com/pkg/sftp"
@@ -41,18 +43,20 @@ import (
"tailscale.com/tailcfg"
"cdr.dev/slog"
"cdr.dev/slog/sloggers/sloghuman"
"cdr.dev/slog/sloggers/slogtest"
"github.com/coder/coder/agent"
"github.com/coder/coder/agent/agentssh"
"github.com/coder/coder/agent/agenttest"
"github.com/coder/coder/coderd/httpapi"
"github.com/coder/coder/codersdk"
"github.com/coder/coder/codersdk/agentsdk"
"github.com/coder/coder/pty"
"github.com/coder/coder/pty/ptytest"
"github.com/coder/coder/tailnet"
"github.com/coder/coder/tailnet/tailnettest"
"github.com/coder/coder/testutil"
"github.com/coder/coder/v2/agent"
"github.com/coder/coder/v2/agent/agentproc"
"github.com/coder/coder/v2/agent/agentproc/agentproctest"
"github.com/coder/coder/v2/agent/agentssh"
"github.com/coder/coder/v2/agent/agenttest"
"github.com/coder/coder/v2/codersdk"
"github.com/coder/coder/v2/codersdk/agentsdk"
"github.com/coder/coder/v2/pty"
"github.com/coder/coder/v2/pty/ptytest"
"github.com/coder/coder/v2/tailnet"
"github.com/coder/coder/v2/tailnet/tailnettest"
"github.com/coder/coder/v2/testutil"
)
func TestMain(m *testing.M) {
@@ -102,7 +106,7 @@ func TestAgent_Stats_ReconnectingPTY(t *testing.T) {
//nolint:dogsled
conn, _, stats, _, _ := setupAgent(t, agentsdk.Manifest{}, 0)
ptyConn, err := conn.ReconnectingPTY(ctx, uuid.New(), 128, 128, "/bin/bash")
ptyConn, err := conn.ReconnectingPTY(ctx, uuid.New(), 128, 128, "bash")
require.NoError(t, err)
defer ptyConn.Close()
@@ -352,7 +356,7 @@ func TestAgent_Session_TTY_MOTD(t *testing.T) {
Enabled: true,
Message: "\n\n\n\n\n\nbanner\n\n\n\n\n\n",
},
expectedRe: regexp.MustCompile("([^\n\r]|^)banner\r\n\r\n[^\r\n]"),
expectedRe: regexp.MustCompile(`([^\n\r]|^)banner\r\n\r\n[^\r\n]`),
},
}
@@ -1055,84 +1059,6 @@ func TestAgent_SSHConnectionEnvVars(t *testing.T) {
}
}
func TestAgent_StartupScript(t *testing.T) {
t.Parallel()
output := "something"
command := "sh -c 'echo " + output + "'"
if runtime.GOOS == "windows" {
command = "cmd.exe /c echo " + output
}
t.Run("Success", func(t *testing.T) {
t.Parallel()
logger := slogtest.Make(t, nil).Leveled(slog.LevelDebug)
client := agenttest.NewClient(t,
logger,
uuid.New(),
agentsdk.Manifest{
StartupScript: command,
DERPMap: &tailcfg.DERPMap{},
},
make(chan *agentsdk.Stats),
tailnet.NewCoordinator(logger),
)
closer := agent.New(agent.Options{
Client: client,
Filesystem: afero.NewMemMapFs(),
Logger: logger.Named("agent"),
ReconnectingPTYTimeout: 0,
})
t.Cleanup(func() {
_ = closer.Close()
})
assert.Eventually(t, func() bool {
got := client.GetLifecycleStates()
return len(got) > 0 && got[len(got)-1] == codersdk.WorkspaceAgentLifecycleReady
}, testutil.WaitShort, testutil.IntervalMedium)
require.Len(t, client.GetStartupLogs(), 1)
require.Equal(t, output, client.GetStartupLogs()[0].Output)
})
// This ensures that even when coderd sends back that the startup
// script has written too many lines it will still succeed!
t.Run("OverflowsAndSkips", func(t *testing.T) {
t.Parallel()
logger := slogtest.Make(t, nil).Leveled(slog.LevelDebug)
client := agenttest.NewClient(t,
logger,
uuid.New(),
agentsdk.Manifest{
StartupScript: command,
DERPMap: &tailcfg.DERPMap{},
},
make(chan *agentsdk.Stats, 50),
tailnet.NewCoordinator(logger),
)
client.PatchWorkspaceLogs = func() error {
resp := httptest.NewRecorder()
httpapi.Write(context.Background(), resp, http.StatusRequestEntityTooLarge, codersdk.Response{
Message: "Too many lines!",
})
res := resp.Result()
defer res.Body.Close()
return codersdk.ReadBodyAsError(res)
}
closer := agent.New(agent.Options{
Client: client,
Filesystem: afero.NewMemMapFs(),
Logger: logger.Named("agent"),
ReconnectingPTYTimeout: 0,
})
t.Cleanup(func() {
_ = closer.Close()
})
assert.Eventually(t, func() bool {
got := client.GetLifecycleStates()
return len(got) > 0 && got[len(got)-1] == codersdk.WorkspaceAgentLifecycleReady
}, testutil.WaitShort, testutil.IntervalMedium)
require.Len(t, client.GetStartupLogs(), 0)
})
}
func TestAgent_Metadata(t *testing.T) {
t.Parallel()
@@ -1140,34 +1066,43 @@ func TestAgent_Metadata(t *testing.T) {
t.Run("Once", func(t *testing.T) {
t.Parallel()
//nolint:dogsled
_, client, _, _, _ := setupAgent(t, agentsdk.Manifest{
Metadata: []codersdk.WorkspaceAgentMetadataDescription{
{
Key: "greeting",
Key: "greeting1",
Interval: 0,
Script: echoHello,
},
{
Key: "greeting2",
Interval: 1,
Script: echoHello,
},
},
}, 0, func(_ *agenttest.Client, opts *agent.Options) {
opts.ReportMetadataInterval = 100 * time.Millisecond
opts.ReportMetadataInterval = testutil.IntervalFast
})
var gotMd map[string]agentsdk.PostMetadataRequest
var gotMd map[string]agentsdk.Metadata
require.Eventually(t, func() bool {
gotMd = client.GetMetadata()
return len(gotMd) == 1
}, testutil.WaitShort, testutil.IntervalMedium)
return len(gotMd) == 2
}, testutil.WaitShort, testutil.IntervalFast/2)
collectedAt := gotMd["greeting"].CollectedAt
collectedAt1 := gotMd["greeting1"].CollectedAt
collectedAt2 := gotMd["greeting2"].CollectedAt
require.Never(t, func() bool {
require.Eventually(t, func() bool {
gotMd = client.GetMetadata()
if len(gotMd) != 1 {
if len(gotMd) != 2 {
panic("unexpected number of metadata")
}
return !gotMd["greeting"].CollectedAt.Equal(collectedAt)
}, testutil.WaitShort, testutil.IntervalMedium)
return !gotMd["greeting2"].CollectedAt.Equal(collectedAt2)
}, testutil.WaitShort, testutil.IntervalFast/2)
require.Equal(t, gotMd["greeting1"].CollectedAt, collectedAt1, "metadata should not be collected again")
})
t.Run("Many", func(t *testing.T) {
@@ -1186,7 +1121,7 @@ func TestAgent_Metadata(t *testing.T) {
opts.ReportMetadataInterval = testutil.IntervalFast
})
var gotMd map[string]agentsdk.PostMetadataRequest
var gotMd map[string]agentsdk.Metadata
require.Eventually(t, func() bool {
gotMd = client.GetMetadata()
return len(gotMd) == 1
@@ -1287,8 +1222,11 @@ func TestAgent_Lifecycle(t *testing.T) {
t.Parallel()
_, client, _, _, _ := setupAgent(t, agentsdk.Manifest{
StartupScript: "sleep 3",
StartupScriptTimeout: time.Nanosecond,
Scripts: []codersdk.WorkspaceAgentScript{{
Script: "sleep 3",
Timeout: time.Millisecond,
RunOnStart: true,
}},
}, 0)
want := []codersdk.WorkspaceAgentLifecycle{
@@ -1309,8 +1247,11 @@ func TestAgent_Lifecycle(t *testing.T) {
t.Parallel()
_, client, _, _, _ := setupAgent(t, agentsdk.Manifest{
StartupScript: "false",
StartupScriptTimeout: 30 * time.Second,
Scripts: []codersdk.WorkspaceAgentScript{{
Script: "false",
Timeout: 30 * time.Second,
RunOnStart: true,
}},
}, 0)
want := []codersdk.WorkspaceAgentLifecycle{
@@ -1331,8 +1272,11 @@ func TestAgent_Lifecycle(t *testing.T) {
t.Parallel()
_, client, _, _, _ := setupAgent(t, agentsdk.Manifest{
StartupScript: "true",
StartupScriptTimeout: 30 * time.Second,
Scripts: []codersdk.WorkspaceAgentScript{{
Script: "true",
Timeout: 30 * time.Second,
RunOnStart: true,
}},
}, 0)
want := []codersdk.WorkspaceAgentLifecycle{
@@ -1353,8 +1297,11 @@ func TestAgent_Lifecycle(t *testing.T) {
t.Parallel()
_, client, _, _, closer := setupAgent(t, agentsdk.Manifest{
ShutdownScript: "sleep 3",
StartupScriptTimeout: 30 * time.Second,
Scripts: []codersdk.WorkspaceAgentScript{{
Script: "sleep 3",
Timeout: 30 * time.Second,
RunOnStop: true,
}},
}, 0)
assert.Eventually(t, func() bool {
@@ -1391,8 +1338,11 @@ func TestAgent_Lifecycle(t *testing.T) {
t.Parallel()
_, client, _, _, closer := setupAgent(t, agentsdk.Manifest{
ShutdownScript: "sleep 3",
ShutdownScriptTimeout: time.Nanosecond,
Scripts: []codersdk.WorkspaceAgentScript{{
Script: "sleep 3",
Timeout: time.Millisecond,
RunOnStop: true,
}},
}, 0)
assert.Eventually(t, func() bool {
@@ -1430,8 +1380,11 @@ func TestAgent_Lifecycle(t *testing.T) {
t.Parallel()
_, client, _, _, closer := setupAgent(t, agentsdk.Manifest{
ShutdownScript: "false",
ShutdownScriptTimeout: 30 * time.Second,
Scripts: []codersdk.WorkspaceAgentScript{{
Script: "false",
Timeout: 30 * time.Second,
RunOnStop: true,
}},
}, 0)
assert.Eventually(t, func() bool {
@@ -1475,9 +1428,16 @@ func TestAgent_Lifecycle(t *testing.T) {
logger,
uuid.New(),
agentsdk.Manifest{
DERPMap: derpMap,
StartupScript: "echo 1",
ShutdownScript: "echo " + expected,
DERPMap: derpMap,
Scripts: []codersdk.WorkspaceAgentScript{{
LogPath: "coder-startup-script.log",
Script: "echo 1",
RunOnStart: true,
}, {
LogPath: "coder-shutdown-script.log",
Script: "echo " + expected,
RunOnStop: true,
}},
},
make(chan *agentsdk.Stats, 50),
tailnet.NewCoordinator(logger),
@@ -1528,9 +1488,7 @@ func TestAgent_Startup(t *testing.T) {
t.Parallel()
_, client, _, _, _ := setupAgent(t, agentsdk.Manifest{
StartupScript: "true",
StartupScriptTimeout: 30 * time.Second,
Directory: "",
Directory: "",
}, 0)
assert.Eventually(t, func() bool {
return client.GetStartup().Version != ""
@@ -1542,9 +1500,7 @@ func TestAgent_Startup(t *testing.T) {
t.Parallel()
_, client, _, _, _ := setupAgent(t, agentsdk.Manifest{
StartupScript: "true",
StartupScriptTimeout: 30 * time.Second,
Directory: "~",
Directory: "~",
}, 0)
assert.Eventually(t, func() bool {
return client.GetStartup().Version != ""
@@ -1558,9 +1514,7 @@ func TestAgent_Startup(t *testing.T) {
t.Parallel()
_, client, _, _, _ := setupAgent(t, agentsdk.Manifest{
StartupScript: "true",
StartupScriptTimeout: 30 * time.Second,
Directory: "coder/coder",
Directory: "coder/coder",
}, 0)
assert.Eventually(t, func() bool {
return client.GetStartup().Version != ""
@@ -1574,9 +1528,7 @@ func TestAgent_Startup(t *testing.T) {
t.Parallel()
_, client, _, _, _ := setupAgent(t, agentsdk.Manifest{
StartupScript: "true",
StartupScriptTimeout: 30 * time.Second,
Directory: "$HOME",
Directory: "$HOME",
}, 0)
assert.Eventually(t, func() bool {
return client.GetStartup().Version != ""
@@ -1587,8 +1539,8 @@ func TestAgent_Startup(t *testing.T) {
})
}
//nolint:paralleltest // This test sets an environment variable.
func TestAgent_ReconnectingPTY(t *testing.T) {
t.Parallel()
if runtime.GOOS == "windows" {
// This might be our implementation, or ConPTY itself.
// It's difficult to find extensive tests for it, so
@@ -1596,61 +1548,136 @@ func TestAgent_ReconnectingPTY(t *testing.T) {
t.Skip("ConPTY appears to be inconsistent on Windows.")
}
ctx, cancel := context.WithTimeout(context.Background(), testutil.WaitLong)
defer cancel()
backends := []string{"Buffered", "Screen"}
//nolint:dogsled
conn, _, _, _, _ := setupAgent(t, agentsdk.Manifest{}, 0)
id := uuid.New()
netConn, err := conn.ReconnectingPTY(ctx, id, 100, 100, "/bin/bash")
require.NoError(t, err)
defer netConn.Close()
_, err := exec.LookPath("screen")
hasScreen := err == nil
bufRead := bufio.NewReader(netConn)
// Make sure UTF-8 works even with LANG set to something like C.
t.Setenv("LANG", "C")
// Brief pause to reduce the likelihood that we send keystrokes while
// the shell is simultaneously sending a prompt.
time.Sleep(100 * time.Millisecond)
data, err := json.Marshal(codersdk.ReconnectingPTYRequest{
Data: "echo test\r\n",
})
require.NoError(t, err)
_, err = netConn.Write(data)
require.NoError(t, err)
expectLine := func(matcher func(string) bool) {
for {
line, err := bufRead.ReadString('\n')
require.NoError(t, err)
if matcher(line) {
break
for _, backendType := range backends {
backendType := backendType
t.Run(backendType, func(t *testing.T) {
if backendType == "Screen" {
if runtime.GOOS != "linux" {
t.Skipf("`screen` is not supported on %s", runtime.GOOS)
} else if !hasScreen {
t.Skip("`screen` not found")
}
} else if hasScreen && runtime.GOOS == "linux" {
// Set up a PATH that does not have screen in it.
bashPath, err := exec.LookPath("bash")
require.NoError(t, err)
dir, err := os.MkdirTemp("/tmp", "coder-test-reconnecting-pty-PATH")
require.NoError(t, err, "create temp dir for reconnecting pty PATH")
err = os.Symlink(bashPath, filepath.Join(dir, "bash"))
require.NoError(t, err, "symlink bash into reconnecting pty PATH")
t.Setenv("PATH", dir)
}
}
ctx, cancel := context.WithTimeout(context.Background(), testutil.WaitLong)
defer cancel()
//nolint:dogsled
conn, _, _, _, _ := setupAgent(t, agentsdk.Manifest{}, 0)
id := uuid.New()
// --norc disables executing .bashrc, which is often used to customize the bash prompt
netConn1, err := conn.ReconnectingPTY(ctx, id, 80, 80, "bash --norc")
require.NoError(t, err)
defer netConn1.Close()
tr1 := testutil.NewTerminalReader(t, netConn1)
// A second simultaneous connection.
netConn2, err := conn.ReconnectingPTY(ctx, id, 80, 80, "bash --norc")
require.NoError(t, err)
defer netConn2.Close()
tr2 := testutil.NewTerminalReader(t, netConn2)
matchPrompt := func(line string) bool {
return strings.Contains(line, "$ ") || strings.Contains(line, "# ")
}
matchEchoCommand := func(line string) bool {
return strings.Contains(line, "echo test")
}
matchEchoOutput := func(line string) bool {
return strings.Contains(line, "test") && !strings.Contains(line, "echo")
}
matchExitCommand := func(line string) bool {
return strings.Contains(line, "exit")
}
matchExitOutput := func(line string) bool {
return strings.Contains(line, "exit") || strings.Contains(line, "logout")
}
// Wait for the prompt before writing commands. If the command arrives before the prompt is written, screen
// will sometimes put the command output on the same line as the command and the test will flake
require.NoError(t, tr1.ReadUntil(ctx, matchPrompt), "find prompt")
require.NoError(t, tr2.ReadUntil(ctx, matchPrompt), "find prompt")
data, err := json.Marshal(codersdk.ReconnectingPTYRequest{
Data: "echo test\r",
})
require.NoError(t, err)
_, err = netConn1.Write(data)
require.NoError(t, err)
// Once for typing the command...
require.NoError(t, tr1.ReadUntil(ctx, matchEchoCommand), "find echo command")
// And another time for the actual output.
require.NoError(t, tr1.ReadUntil(ctx, matchEchoOutput), "find echo output")
// Same for the other connection.
require.NoError(t, tr2.ReadUntil(ctx, matchEchoCommand), "find echo command")
require.NoError(t, tr2.ReadUntil(ctx, matchEchoOutput), "find echo output")
_ = netConn1.Close()
_ = netConn2.Close()
netConn3, err := conn.ReconnectingPTY(ctx, id, 80, 80, "bash --norc")
require.NoError(t, err)
defer netConn3.Close()
tr3 := testutil.NewTerminalReader(t, netConn3)
// Same output again!
require.NoError(t, tr3.ReadUntil(ctx, matchEchoCommand), "find echo command")
require.NoError(t, tr3.ReadUntil(ctx, matchEchoOutput), "find echo output")
// Exit should cause the connection to close.
data, err = json.Marshal(codersdk.ReconnectingPTYRequest{
Data: "exit\r",
})
require.NoError(t, err)
_, err = netConn3.Write(data)
require.NoError(t, err)
// Once for the input and again for the output.
require.NoError(t, tr3.ReadUntil(ctx, matchExitCommand), "find exit command")
require.NoError(t, tr3.ReadUntil(ctx, matchExitOutput), "find exit output")
// Wait for the connection to close.
require.ErrorIs(t, tr3.ReadUntil(ctx, nil), io.EOF)
// Try a non-shell command. It should output then immediately exit.
netConn4, err := conn.ReconnectingPTY(ctx, uuid.New(), 80, 80, "echo test")
require.NoError(t, err)
defer netConn4.Close()
tr4 := testutil.NewTerminalReader(t, netConn4)
require.NoError(t, tr4.ReadUntil(ctx, matchEchoOutput), "find echo output")
require.ErrorIs(t, tr4.ReadUntil(ctx, nil), io.EOF)
// Ensure that UTF-8 is supported. Avoid the terminal emulator because it
// does not appear to support UTF-8, just make sure the bytes that come
// back have the character in it.
netConn5, err := conn.ReconnectingPTY(ctx, uuid.New(), 80, 80, "echo ")
require.NoError(t, err)
defer netConn5.Close()
bytes, err := io.ReadAll(netConn5)
require.NoError(t, err)
require.Contains(t, string(bytes), "")
})
}
matchEchoCommand := func(line string) bool {
return strings.Contains(line, "echo test")
}
matchEchoOutput := func(line string) bool {
return strings.Contains(line, "test") && !strings.Contains(line, "echo")
}
// Once for typing the command...
expectLine(matchEchoCommand)
// And another time for the actual output.
expectLine(matchEchoOutput)
_ = netConn.Close()
netConn, err = conn.ReconnectingPTY(ctx, id, 100, 100, "/bin/bash")
require.NoError(t, err)
defer netConn.Close()
bufRead = bufio.NewReader(netConn)
// Same output again!
expectLine(matchEchoCommand)
expectLine(matchEchoOutput)
}
func TestAgent_Dial(t *testing.T) {
@@ -1843,13 +1870,16 @@ func TestAgent_UpdatedDERP(t *testing.T) {
func TestAgent_Speedtest(t *testing.T) {
t.Parallel()
t.Skip("This test is relatively flakey because of Tailscale's speedtest code...")
logger := slogtest.Make(t, &slogtest.Options{IgnoreErrors: true}).Leveled(slog.LevelDebug)
ctx, cancel := context.WithTimeout(context.Background(), testutil.WaitLong)
defer cancel()
derpMap, _ := tailnettest.RunDERPAndSTUN(t)
//nolint:dogsled
conn, _, _, _, _ := setupAgent(t, agentsdk.Manifest{
DERPMap: derpMap,
}, 0)
}, 0, func(client *agenttest.Client, options *agent.Options) {
options.Logger = logger.Named("agent")
})
defer conn.Close()
res, err := conn.Speedtest(ctx, speedtest.Upload, 250*time.Millisecond)
require.NoError(t, err)
@@ -1932,6 +1962,96 @@ func TestAgent_WriteVSCodeConfigs(t *testing.T) {
}, testutil.WaitShort, testutil.IntervalFast)
}
func TestAgent_DebugServer(t *testing.T) {
t.Parallel()
derpMap, _ := tailnettest.RunDERPAndSTUN(t)
//nolint:dogsled
conn, _, _, _, agnt := setupAgent(t, agentsdk.Manifest{
DERPMap: derpMap,
}, 0)
awaitReachableCtx := testutil.Context(t, testutil.WaitLong)
ok := conn.AwaitReachable(awaitReachableCtx)
require.True(t, ok)
_ = conn.Close()
srv := httptest.NewServer(agnt.HTTPDebug())
t.Cleanup(srv.Close)
t.Run("MagicsockDebug", func(t *testing.T) {
t.Parallel()
ctx := testutil.Context(t, testutil.WaitLong)
req, err := http.NewRequestWithContext(ctx, http.MethodGet, srv.URL+"/debug/magicsock", nil)
require.NoError(t, err)
res, err := srv.Client().Do(req)
require.NoError(t, err)
defer res.Body.Close()
require.Equal(t, http.StatusOK, res.StatusCode)
resBody, err := io.ReadAll(res.Body)
require.NoError(t, err)
require.Contains(t, string(resBody), "<h1>magicsock</h1>")
})
t.Run("MagicsockDebugLogging", func(t *testing.T) {
t.Parallel()
t.Run("Enable", func(t *testing.T) {
t.Parallel()
ctx := testutil.Context(t, testutil.WaitLong)
req, err := http.NewRequestWithContext(ctx, http.MethodGet, srv.URL+"/debug/magicsock/debug-logging/t", nil)
require.NoError(t, err)
res, err := srv.Client().Do(req)
require.NoError(t, err)
defer res.Body.Close()
require.Equal(t, http.StatusOK, res.StatusCode)
resBody, err := io.ReadAll(res.Body)
require.NoError(t, err)
require.Contains(t, string(resBody), "updated magicsock debug logging to true")
})
t.Run("Disable", func(t *testing.T) {
t.Parallel()
ctx := testutil.Context(t, testutil.WaitLong)
req, err := http.NewRequestWithContext(ctx, http.MethodGet, srv.URL+"/debug/magicsock/debug-logging/0", nil)
require.NoError(t, err)
res, err := srv.Client().Do(req)
require.NoError(t, err)
defer res.Body.Close()
require.Equal(t, http.StatusOK, res.StatusCode)
resBody, err := io.ReadAll(res.Body)
require.NoError(t, err)
require.Contains(t, string(resBody), "updated magicsock debug logging to false")
})
t.Run("Invalid", func(t *testing.T) {
t.Parallel()
ctx := testutil.Context(t, testutil.WaitLong)
req, err := http.NewRequestWithContext(ctx, http.MethodGet, srv.URL+"/debug/magicsock/debug-logging/blah", nil)
require.NoError(t, err)
res, err := srv.Client().Do(req)
require.NoError(t, err)
defer res.Body.Close()
require.Equal(t, http.StatusBadRequest, res.StatusCode)
resBody, err := io.ReadAll(res.Body)
require.NoError(t, err)
require.Contains(t, string(resBody), `invalid state "blah", must be a boolean`)
})
})
}
func setupSSHCommand(t *testing.T, beforeArgs []string, afterArgs []string) (*ptytest.PTYCmd, pty.Process) {
//nolint:dogsled
agentConn, _, _, _, _ := setupAgent(t, agentsdk.Manifest{}, 0)
@@ -2013,7 +2133,7 @@ func setupAgent(t *testing.T, metadata agentsdk.Manifest, ptyTimeout time.Durati
*agenttest.Client,
<-chan *agentsdk.Stats,
afero.Fs,
io.Closer,
agent.Agent,
) {
logger := slogtest.Make(t, nil).Leveled(slog.LevelDebug)
if metadata.DERPMap == nil {
@@ -2250,6 +2370,173 @@ func TestAgent_Metrics_SSH(t *testing.T) {
require.NoError(t, err)
}
func TestAgent_ManageProcessPriority(t *testing.T) {
t.Parallel()
t.Run("OK", func(t *testing.T) {
t.Parallel()
if runtime.GOOS != "linux" {
t.Skip("Skipping non-linux environment")
}
var (
expectedProcs = map[int32]agentproc.Process{}
fs = afero.NewMemMapFs()
syscaller = agentproctest.NewMockSyscaller(gomock.NewController(t))
ticker = make(chan time.Time)
modProcs = make(chan []*agentproc.Process)
logger = slog.Make(sloghuman.Sink(io.Discard))
)
// Create some processes.
for i := 0; i < 4; i++ {
// Create a prioritized process. This process should
// have it's oom_score_adj set to -500 and its nice
// score should be untouched.
var proc agentproc.Process
if i == 0 {
proc = agentproctest.GenerateProcess(t, fs,
func(p *agentproc.Process) {
p.CmdLine = "./coder\x00agent\x00--no-reap"
p.PID = int32(i)
},
)
} else {
proc = agentproctest.GenerateProcess(t, fs,
func(p *agentproc.Process) {
// Make the cmd something similar to a prioritized
// process but differentiate the arguments.
p.CmdLine = "./coder\x00stat"
},
)
syscaller.EXPECT().SetPriority(proc.PID, 10).Return(nil)
syscaller.EXPECT().GetPriority(proc.PID).Return(20, nil)
}
syscaller.EXPECT().
Kill(proc.PID, syscall.Signal(0)).
Return(nil)
expectedProcs[proc.PID] = proc
}
_, _, _, _, _ = setupAgent(t, agentsdk.Manifest{}, 0, func(c *agenttest.Client, o *agent.Options) {
o.Syscaller = syscaller
o.ModifiedProcesses = modProcs
o.EnvironmentVariables = map[string]string{agent.EnvProcPrioMgmt: "1"}
o.Filesystem = fs
o.Logger = logger
o.ProcessManagementTick = ticker
})
actualProcs := <-modProcs
require.Len(t, actualProcs, len(expectedProcs)-1)
})
t.Run("IgnoreCustomNice", func(t *testing.T) {
t.Parallel()
if runtime.GOOS != "linux" {
t.Skip("Skipping non-linux environment")
}
var (
expectedProcs = map[int32]agentproc.Process{}
fs = afero.NewMemMapFs()
ticker = make(chan time.Time)
syscaller = agentproctest.NewMockSyscaller(gomock.NewController(t))
modProcs = make(chan []*agentproc.Process)
logger = slog.Make(sloghuman.Sink(io.Discard))
)
// Create some processes.
for i := 0; i < 2; i++ {
proc := agentproctest.GenerateProcess(t, fs)
syscaller.EXPECT().
Kill(proc.PID, syscall.Signal(0)).
Return(nil)
if i == 0 {
// Set a random nice score. This one should not be adjusted by
// our management loop.
syscaller.EXPECT().GetPriority(proc.PID).Return(25, nil)
} else {
syscaller.EXPECT().GetPriority(proc.PID).Return(20, nil)
syscaller.EXPECT().SetPriority(proc.PID, 10).Return(nil)
}
expectedProcs[proc.PID] = proc
}
_, _, _, _, _ = setupAgent(t, agentsdk.Manifest{}, 0, func(c *agenttest.Client, o *agent.Options) {
o.Syscaller = syscaller
o.ModifiedProcesses = modProcs
o.EnvironmentVariables = map[string]string{agent.EnvProcPrioMgmt: "1"}
o.Filesystem = fs
o.Logger = logger
o.ProcessManagementTick = ticker
})
actualProcs := <-modProcs
// We should ignore the process with a custom nice score.
require.Len(t, actualProcs, 1)
})
t.Run("DisabledByDefault", func(t *testing.T) {
t.Parallel()
if runtime.GOOS != "linux" {
t.Skip("Skipping non-linux environment")
}
var (
buf bytes.Buffer
wr = &syncWriter{
w: &buf,
}
)
log := slog.Make(sloghuman.Sink(wr)).Leveled(slog.LevelDebug)
_, _, _, _, _ = setupAgent(t, agentsdk.Manifest{}, 0, func(c *agenttest.Client, o *agent.Options) {
o.Logger = log
})
require.Eventually(t, func() bool {
wr.mu.Lock()
defer wr.mu.Unlock()
return strings.Contains(buf.String(), "process priority not enabled")
}, testutil.WaitLong, testutil.IntervalFast)
})
t.Run("DisabledForNonLinux", func(t *testing.T) {
t.Parallel()
if runtime.GOOS == "linux" {
t.Skip("Skipping linux environment")
}
var (
buf bytes.Buffer
wr = &syncWriter{
w: &buf,
}
)
log := slog.Make(sloghuman.Sink(wr)).Leveled(slog.LevelDebug)
_, _, _, _, _ = setupAgent(t, agentsdk.Manifest{}, 0, func(c *agenttest.Client, o *agent.Options) {
o.Logger = log
// Try to enable it so that we can assert that non-linux
// environments are truly disabled.
o.EnvironmentVariables = map[string]string{agent.EnvProcPrioMgmt: "1"}
})
require.Eventually(t, func() bool {
wr.mu.Lock()
defer wr.mu.Unlock()
return strings.Contains(buf.String(), "process priority not enabled")
}, testutil.WaitLong, testutil.IntervalFast)
})
}
func verifyCollectedMetrics(t *testing.T, expected []agentsdk.AgentMetric, actual []*promgo.MetricFamily) bool {
t.Helper()
@@ -2271,3 +2558,14 @@ func verifyCollectedMetrics(t *testing.T, expected []agentsdk.AgentMetric, actua
}
return true
}
type syncWriter struct {
mu sync.Mutex
w io.Writer
}
func (s *syncWriter) Write(p []byte) (int, error) {
s.mu.Lock()
defer s.mu.Unlock()
return s.w.Write(p)
}
+5
View File
@@ -0,0 +1,5 @@
// Package agentproctest contains utility functions
// for testing process management in the agent.
package agentproctest
//go:generate mockgen -destination ./syscallermock.go -package agentproctest github.com/coder/coder/v2/agent/agentproc Syscaller
+49
View File
@@ -0,0 +1,49 @@
package agentproctest
import (
"fmt"
"testing"
"github.com/spf13/afero"
"github.com/stretchr/testify/require"
"github.com/coder/coder/v2/agent/agentproc"
"github.com/coder/coder/v2/cryptorand"
)
func GenerateProcess(t *testing.T, fs afero.Fs, muts ...func(*agentproc.Process)) agentproc.Process {
t.Helper()
pid, err := cryptorand.Intn(1<<31 - 1)
require.NoError(t, err)
arg1, err := cryptorand.String(5)
require.NoError(t, err)
arg2, err := cryptorand.String(5)
require.NoError(t, err)
arg3, err := cryptorand.String(5)
require.NoError(t, err)
cmdline := fmt.Sprintf("%s\x00%s\x00%s", arg1, arg2, arg3)
process := agentproc.Process{
CmdLine: cmdline,
PID: int32(pid),
}
for _, mut := range muts {
mut(&process)
}
process.Dir = fmt.Sprintf("%s/%d", "/proc", process.PID)
err = fs.MkdirAll(process.Dir, 0o555)
require.NoError(t, err)
err = afero.WriteFile(fs, fmt.Sprintf("%s/cmdline", process.Dir), []byte(process.CmdLine), 0o444)
require.NoError(t, err)
return process
}
@@ -0,0 +1,78 @@
// Code generated by MockGen. DO NOT EDIT.
// Source: github.com/coder/coder/v2/agent/agentproc (interfaces: Syscaller)
// Package agentproctest is a generated GoMock package.
package agentproctest
import (
reflect "reflect"
syscall "syscall"
gomock "github.com/golang/mock/gomock"
)
// MockSyscaller is a mock of Syscaller interface.
type MockSyscaller struct {
ctrl *gomock.Controller
recorder *MockSyscallerMockRecorder
}
// MockSyscallerMockRecorder is the mock recorder for MockSyscaller.
type MockSyscallerMockRecorder struct {
mock *MockSyscaller
}
// NewMockSyscaller creates a new mock instance.
func NewMockSyscaller(ctrl *gomock.Controller) *MockSyscaller {
mock := &MockSyscaller{ctrl: ctrl}
mock.recorder = &MockSyscallerMockRecorder{mock}
return mock
}
// EXPECT returns an object that allows the caller to indicate expected use.
func (m *MockSyscaller) EXPECT() *MockSyscallerMockRecorder {
return m.recorder
}
// GetPriority mocks base method.
func (m *MockSyscaller) GetPriority(arg0 int32) (int, error) {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "GetPriority", arg0)
ret0, _ := ret[0].(int)
ret1, _ := ret[1].(error)
return ret0, ret1
}
// GetPriority indicates an expected call of GetPriority.
func (mr *MockSyscallerMockRecorder) GetPriority(arg0 interface{}) *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetPriority", reflect.TypeOf((*MockSyscaller)(nil).GetPriority), arg0)
}
// Kill mocks base method.
func (m *MockSyscaller) Kill(arg0 int32, arg1 syscall.Signal) error {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "Kill", arg0, arg1)
ret0, _ := ret[0].(error)
return ret0
}
// Kill indicates an expected call of Kill.
func (mr *MockSyscallerMockRecorder) Kill(arg0, arg1 interface{}) *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Kill", reflect.TypeOf((*MockSyscaller)(nil).Kill), arg0, arg1)
}
// SetPriority mocks base method.
func (m *MockSyscaller) SetPriority(arg0 int32, arg1 int) error {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "SetPriority", arg0, arg1)
ret0, _ := ret[0].(error)
return ret0
}
// SetPriority indicates an expected call of SetPriority.
func (mr *MockSyscallerMockRecorder) SetPriority(arg0, arg1 interface{}) *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SetPriority", reflect.TypeOf((*MockSyscaller)(nil).SetPriority), arg0, arg1)
}
+3
View File
@@ -0,0 +1,3 @@
// Package agentproc contains logic for interfacing with local
// processes running in the same context as the agent.
package agentproc
+24
View File
@@ -0,0 +1,24 @@
//go:build !linux
// +build !linux
package agentproc
import (
"github.com/spf13/afero"
)
func (p *Process) Niceness(sc Syscaller) (int, error) {
return 0, errUnimplemented
}
func (p *Process) SetNiceness(sc Syscaller, score int) error {
return errUnimplemented
}
func (p *Process) Cmd() string {
return ""
}
func List(fs afero.Fs, syscaller Syscaller) ([]*Process, error) {
return nil, errUnimplemented
}
+166
View File
@@ -0,0 +1,166 @@
package agentproc_test
import (
"runtime"
"syscall"
"testing"
"github.com/golang/mock/gomock"
"github.com/spf13/afero"
"github.com/stretchr/testify/require"
"golang.org/x/xerrors"
"github.com/coder/coder/v2/agent/agentproc"
"github.com/coder/coder/v2/agent/agentproc/agentproctest"
)
func TestList(t *testing.T) {
t.Parallel()
if runtime.GOOS != "linux" {
t.Skipf("skipping non-linux environment")
}
t.Run("OK", func(t *testing.T) {
t.Parallel()
var (
fs = afero.NewMemMapFs()
sc = agentproctest.NewMockSyscaller(gomock.NewController(t))
expectedProcs = make(map[int32]agentproc.Process)
)
for i := 0; i < 4; i++ {
proc := agentproctest.GenerateProcess(t, fs)
expectedProcs[proc.PID] = proc
sc.EXPECT().
Kill(proc.PID, syscall.Signal(0)).
Return(nil)
}
actualProcs, err := agentproc.List(fs, sc)
require.NoError(t, err)
require.Len(t, actualProcs, len(expectedProcs))
for _, proc := range actualProcs {
expected, ok := expectedProcs[proc.PID]
require.True(t, ok)
require.Equal(t, expected.PID, proc.PID)
require.Equal(t, expected.CmdLine, proc.CmdLine)
require.Equal(t, expected.Dir, proc.Dir)
}
})
t.Run("FinishedProcess", func(t *testing.T) {
t.Parallel()
var (
fs = afero.NewMemMapFs()
sc = agentproctest.NewMockSyscaller(gomock.NewController(t))
expectedProcs = make(map[int32]agentproc.Process)
)
for i := 0; i < 3; i++ {
proc := agentproctest.GenerateProcess(t, fs)
expectedProcs[proc.PID] = proc
sc.EXPECT().
Kill(proc.PID, syscall.Signal(0)).
Return(nil)
}
// Create a process that's already finished. We're not adding
// it to the map because it should be skipped over.
proc := agentproctest.GenerateProcess(t, fs)
sc.EXPECT().
Kill(proc.PID, syscall.Signal(0)).
Return(xerrors.New("os: process already finished"))
actualProcs, err := agentproc.List(fs, sc)
require.NoError(t, err)
require.Len(t, actualProcs, len(expectedProcs))
for _, proc := range actualProcs {
expected, ok := expectedProcs[proc.PID]
require.True(t, ok)
require.Equal(t, expected.PID, proc.PID)
require.Equal(t, expected.CmdLine, proc.CmdLine)
require.Equal(t, expected.Dir, proc.Dir)
}
})
t.Run("NoSuchProcess", func(t *testing.T) {
t.Parallel()
var (
fs = afero.NewMemMapFs()
sc = agentproctest.NewMockSyscaller(gomock.NewController(t))
expectedProcs = make(map[int32]agentproc.Process)
)
for i := 0; i < 3; i++ {
proc := agentproctest.GenerateProcess(t, fs)
expectedProcs[proc.PID] = proc
sc.EXPECT().
Kill(proc.PID, syscall.Signal(0)).
Return(nil)
}
// Create a process that doesn't exist. We're not adding
// it to the map because it should be skipped over.
proc := agentproctest.GenerateProcess(t, fs)
sc.EXPECT().
Kill(proc.PID, syscall.Signal(0)).
Return(syscall.ESRCH)
actualProcs, err := agentproc.List(fs, sc)
require.NoError(t, err)
require.Len(t, actualProcs, len(expectedProcs))
for _, proc := range actualProcs {
expected, ok := expectedProcs[proc.PID]
require.True(t, ok)
require.Equal(t, expected.PID, proc.PID)
require.Equal(t, expected.CmdLine, proc.CmdLine)
require.Equal(t, expected.Dir, proc.Dir)
}
})
}
// These tests are not very interesting but they provide some modicum of
// confidence.
func TestProcess(t *testing.T) {
t.Parallel()
if runtime.GOOS != "linux" {
t.Skipf("skipping non-linux environment")
}
t.Run("SetNiceness", func(t *testing.T) {
t.Parallel()
var (
sc = agentproctest.NewMockSyscaller(gomock.NewController(t))
proc = &agentproc.Process{
PID: 32,
}
score = 20
)
sc.EXPECT().SetPriority(proc.PID, score).Return(nil)
err := proc.SetNiceness(sc, score)
require.NoError(t, err)
})
t.Run("Cmd", func(t *testing.T) {
t.Parallel()
var (
proc = &agentproc.Process{
CmdLine: "helloworld\x00--arg1\x00--arg2",
}
expectedName = "helloworld --arg1 --arg2"
)
require.Equal(t, expectedName, proc.Cmd())
})
}
+109
View File
@@ -0,0 +1,109 @@
//go:build linux
// +build linux
package agentproc
import (
"errors"
"path/filepath"
"strconv"
"strings"
"syscall"
"github.com/spf13/afero"
"golang.org/x/xerrors"
)
func List(fs afero.Fs, syscaller Syscaller) ([]*Process, error) {
d, err := fs.Open(defaultProcDir)
if err != nil {
return nil, xerrors.Errorf("open dir %q: %w", defaultProcDir, err)
}
defer d.Close()
entries, err := d.Readdirnames(0)
if err != nil {
return nil, xerrors.Errorf("readdirnames: %w", err)
}
processes := make([]*Process, 0, len(entries))
for _, entry := range entries {
pid, err := strconv.ParseInt(entry, 10, 32)
if err != nil {
continue
}
// Check that the process still exists.
exists, err := isProcessExist(syscaller, int32(pid))
if err != nil {
return nil, xerrors.Errorf("check process exists: %w", err)
}
if !exists {
continue
}
cmdline, err := afero.ReadFile(fs, filepath.Join(defaultProcDir, entry, "cmdline"))
if err != nil {
var errNo syscall.Errno
if xerrors.As(err, &errNo) && errNo == syscall.EPERM {
continue
}
return nil, xerrors.Errorf("read cmdline: %w", err)
}
processes = append(processes, &Process{
PID: int32(pid),
CmdLine: string(cmdline),
Dir: filepath.Join(defaultProcDir, entry),
})
}
return processes, nil
}
func isProcessExist(syscaller Syscaller, pid int32) (bool, error) {
err := syscaller.Kill(pid, syscall.Signal(0))
if err == nil {
return true, nil
}
if err.Error() == "os: process already finished" {
return false, nil
}
var errno syscall.Errno
if !errors.As(err, &errno) {
return false, err
}
switch errno {
case syscall.ESRCH:
return false, nil
case syscall.EPERM:
return true, nil
}
return false, xerrors.Errorf("kill: %w", err)
}
func (p *Process) Niceness(sc Syscaller) (int, error) {
nice, err := sc.GetPriority(p.PID)
if err != nil {
return 0, xerrors.Errorf("get priority for %q: %w", p.CmdLine, err)
}
return nice, nil
}
func (p *Process) SetNiceness(sc Syscaller, score int) error {
err := sc.SetPriority(p.PID, score)
if err != nil {
return xerrors.Errorf("set priority for %q: %w", p.CmdLine, err)
}
return nil
}
func (p *Process) Cmd() string {
return strings.Join(p.cmdLine(), " ")
}
func (p *Process) cmdLine() []string {
return strings.Split(p.CmdLine, "\x00")
}
+19
View File
@@ -0,0 +1,19 @@
package agentproc
import (
"syscall"
)
type Syscaller interface {
SetPriority(pid int32, priority int) error
GetPriority(pid int32) (int, error)
Kill(pid int32, sig syscall.Signal) error
}
const defaultProcDir = "/proc"
type Process struct {
Dir string
CmdLine string
PID int32
}
+30
View File
@@ -0,0 +1,30 @@
//go:build !linux
// +build !linux
package agentproc
import (
"syscall"
"golang.org/x/xerrors"
)
func NewSyscaller() Syscaller {
return nopSyscaller{}
}
var errUnimplemented = xerrors.New("unimplemented")
type nopSyscaller struct{}
func (nopSyscaller) SetPriority(pid int32, priority int) error {
return errUnimplemented
}
func (nopSyscaller) GetPriority(pid int32) (int, error) {
return 0, errUnimplemented
}
func (nopSyscaller) Kill(pid int32, sig syscall.Signal) error {
return errUnimplemented
}
+42
View File
@@ -0,0 +1,42 @@
//go:build linux
// +build linux
package agentproc
import (
"syscall"
"golang.org/x/sys/unix"
"golang.org/x/xerrors"
)
func NewSyscaller() Syscaller {
return UnixSyscaller{}
}
type UnixSyscaller struct{}
func (UnixSyscaller) SetPriority(pid int32, nice int) error {
err := unix.Setpriority(unix.PRIO_PROCESS, int(pid), nice)
if err != nil {
return xerrors.Errorf("set priority: %w", err)
}
return nil
}
func (UnixSyscaller) GetPriority(pid int32) (int, error) {
nice, err := unix.Getpriority(0, int(pid))
if err != nil {
return 0, xerrors.Errorf("get priority: %w", err)
}
return nice, nil
}
func (UnixSyscaller) Kill(pid int32, sig syscall.Signal) error {
err := syscall.Kill(int(pid), sig)
if err != nil {
return xerrors.Errorf("kill: %w", err)
}
return nil
}
+283
View File
@@ -0,0 +1,283 @@
package agentscripts
import (
"context"
"errors"
"fmt"
"io"
"os"
"os/exec"
"os/user"
"path/filepath"
"sync"
"sync/atomic"
"time"
"github.com/robfig/cron/v3"
"github.com/spf13/afero"
"golang.org/x/sync/errgroup"
"golang.org/x/xerrors"
"cdr.dev/slog"
"github.com/coder/coder/v2/agent/agentssh"
"github.com/coder/coder/v2/codersdk"
"github.com/coder/coder/v2/codersdk/agentsdk"
)
var (
// ErrTimeout is returned when a script times out.
ErrTimeout = xerrors.New("script timed out")
parser = cron.NewParser(cron.Second | cron.Minute | cron.Hour | cron.Dom | cron.Month | cron.DowOptional)
)
// Options are a set of options for the runner.
type Options struct {
LogDir string
Logger slog.Logger
SSHServer *agentssh.Server
Filesystem afero.Fs
PatchLogs func(ctx context.Context, req agentsdk.PatchLogs) error
}
// New creates a runner for the provided scripts.
func New(opts Options) *Runner {
cronCtx, cronCtxCancel := context.WithCancel(context.Background())
return &Runner{
Options: opts,
cronCtx: cronCtx,
cronCtxCancel: cronCtxCancel,
cron: cron.New(cron.WithParser(parser)),
closed: make(chan struct{}),
}
}
type Runner struct {
Options
cronCtx context.Context
cronCtxCancel context.CancelFunc
cmdCloseWait sync.WaitGroup
closed chan struct{}
closeMutex sync.Mutex
cron *cron.Cron
initialized atomic.Bool
scripts []codersdk.WorkspaceAgentScript
}
// Init initializes the runner with the provided scripts.
// It also schedules any scripts that have a schedule.
// This function must be called before Execute.
func (r *Runner) Init(scripts []codersdk.WorkspaceAgentScript) error {
if r.initialized.Load() {
return xerrors.New("init: already initialized")
}
r.initialized.Store(true)
r.scripts = scripts
r.Logger.Info(r.cronCtx, "initializing agent scripts", slog.F("script_count", len(scripts)), slog.F("log_dir", r.LogDir))
for _, script := range scripts {
if script.Cron == "" {
continue
}
script := script
_, err := r.cron.AddFunc(script.Cron, func() {
err := r.run(r.cronCtx, script)
if err != nil {
r.Logger.Warn(context.Background(), "run agent script on schedule", slog.Error(err))
}
})
if err != nil {
return xerrors.Errorf("add schedule: %w", err)
}
}
return nil
}
// StartCron starts the cron scheduler.
// This is done async to allow for the caller to execute scripts prior.
func (r *Runner) StartCron() {
r.cron.Start()
}
// Execute runs a set of scripts according to a filter.
func (r *Runner) Execute(ctx context.Context, filter func(script codersdk.WorkspaceAgentScript) bool) error {
if filter == nil {
// Execute em' all!
filter = func(script codersdk.WorkspaceAgentScript) bool {
return true
}
}
var eg errgroup.Group
for _, script := range r.scripts {
if !filter(script) {
continue
}
script := script
eg.Go(func() error {
err := r.run(ctx, script)
if err != nil {
return xerrors.Errorf("run agent script %q: %w", script.LogSourceID, err)
}
return nil
})
}
return eg.Wait()
}
// run executes the provided script with the timeout.
// If the timeout is exceeded, the process is sent an interrupt signal.
// If the process does not exit after a few seconds, it is forcefully killed.
// This function immediately returns after a timeout, and does not wait for the process to exit.
func (r *Runner) run(ctx context.Context, script codersdk.WorkspaceAgentScript) error {
logPath := script.LogPath
if logPath == "" {
logPath = fmt.Sprintf("coder-script-%s.log", script.LogSourceID)
}
if logPath[0] == '~' {
// First we check the environment.
homeDir, err := os.UserHomeDir()
if err != nil {
u, err := user.Current()
if err != nil {
return xerrors.Errorf("current user: %w", err)
}
homeDir = u.HomeDir
}
logPath = filepath.Join(homeDir, logPath[1:])
}
logPath = os.ExpandEnv(logPath)
if !filepath.IsAbs(logPath) {
logPath = filepath.Join(r.LogDir, logPath)
}
logger := r.Logger.With(slog.F("log_path", logPath))
logger.Info(ctx, "running agent script", slog.F("script", script.Script))
fileWriter, err := r.Filesystem.OpenFile(logPath, os.O_CREATE|os.O_RDWR, 0o600)
if err != nil {
return xerrors.Errorf("open %s script log file: %w", logPath, err)
}
defer func() {
err := fileWriter.Close()
if err != nil {
logger.Warn(ctx, fmt.Sprintf("close %s script log file", logPath), slog.Error(err))
}
}()
var cmd *exec.Cmd
cmdCtx := ctx
if script.Timeout > 0 {
var ctxCancel context.CancelFunc
cmdCtx, ctxCancel = context.WithTimeout(ctx, script.Timeout)
defer ctxCancel()
}
cmdPty, err := r.SSHServer.CreateCommand(cmdCtx, script.Script, nil)
if err != nil {
return xerrors.Errorf("%s script: create command: %w", logPath, err)
}
cmd = cmdPty.AsExec()
cmd.SysProcAttr = cmdSysProcAttr()
cmd.WaitDelay = 10 * time.Second
cmd.Cancel = cmdCancel(cmd)
send, flushAndClose := agentsdk.LogsSender(script.LogSourceID, r.PatchLogs, logger)
// If ctx is canceled here (or in a writer below), we may be
// discarding logs, but that's okay because we're shutting down
// anyway. We could consider creating a new context here if we
// want better control over flush during shutdown.
defer func() {
if err := flushAndClose(ctx); err != nil {
logger.Warn(ctx, "flush startup logs failed", slog.Error(err))
}
}()
infoW := agentsdk.LogsWriter(ctx, send, script.LogSourceID, codersdk.LogLevelInfo)
defer infoW.Close()
errW := agentsdk.LogsWriter(ctx, send, script.LogSourceID, codersdk.LogLevelError)
defer errW.Close()
cmd.Stdout = io.MultiWriter(fileWriter, infoW)
cmd.Stderr = io.MultiWriter(fileWriter, errW)
start := time.Now()
defer func() {
end := time.Now()
execTime := end.Sub(start)
exitCode := 0
if err != nil {
exitCode = 255 // Unknown status.
var exitError *exec.ExitError
if xerrors.As(err, &exitError) {
exitCode = exitError.ExitCode()
}
logger.Warn(ctx, fmt.Sprintf("%s script failed", logPath), slog.F("execution_time", execTime), slog.F("exit_code", exitCode), slog.Error(err))
} else {
logger.Info(ctx, fmt.Sprintf("%s script completed", logPath), slog.F("execution_time", execTime), slog.F("exit_code", exitCode))
}
}()
err = cmd.Start()
if err != nil {
if errors.Is(err, context.DeadlineExceeded) {
return ErrTimeout
}
return xerrors.Errorf("%s script: start command: %w", logPath, err)
}
cmdDone := make(chan error, 1)
err = r.trackCommandGoroutine(func() {
cmdDone <- cmd.Wait()
})
if err != nil {
return xerrors.Errorf("%s script: track command goroutine: %w", logPath, err)
}
select {
case <-cmdCtx.Done():
// Wait for the command to drain!
select {
case <-cmdDone:
case <-time.After(10 * time.Second):
}
err = cmdCtx.Err()
case err = <-cmdDone:
}
if errors.Is(err, context.DeadlineExceeded) {
err = ErrTimeout
}
return err
}
func (r *Runner) Close() error {
r.closeMutex.Lock()
defer r.closeMutex.Unlock()
if r.isClosed() {
return nil
}
close(r.closed)
r.cronCtxCancel()
r.cron.Stop()
r.cmdCloseWait.Wait()
return nil
}
func (r *Runner) trackCommandGoroutine(fn func()) error {
r.closeMutex.Lock()
defer r.closeMutex.Unlock()
if r.isClosed() {
return xerrors.New("track command goroutine: closed")
}
r.cmdCloseWait.Add(1)
go func() {
defer r.cmdCloseWait.Done()
fn()
}()
return nil
}
func (r *Runner) isClosed() bool {
select {
case <-r.closed:
return true
default:
return false
}
}
+20
View File
@@ -0,0 +1,20 @@
//go:build !windows
package agentscripts
import (
"os/exec"
"syscall"
)
func cmdSysProcAttr() *syscall.SysProcAttr {
return &syscall.SysProcAttr{
Setsid: true,
}
}
func cmdCancel(cmd *exec.Cmd) func() error {
return func() error {
return syscall.Kill(-cmd.Process.Pid, syscall.SIGHUP)
}
}
+80
View File
@@ -0,0 +1,80 @@
package agentscripts_test
import (
"context"
"testing"
"time"
"github.com/prometheus/client_golang/prometheus"
"github.com/spf13/afero"
"github.com/stretchr/testify/require"
"go.uber.org/atomic"
"go.uber.org/goleak"
"cdr.dev/slog/sloggers/slogtest"
"github.com/coder/coder/v2/agent/agentscripts"
"github.com/coder/coder/v2/agent/agentssh"
"github.com/coder/coder/v2/codersdk"
"github.com/coder/coder/v2/codersdk/agentsdk"
)
func TestMain(m *testing.M) {
goleak.VerifyTestMain(m)
}
func TestExecuteBasic(t *testing.T) {
t.Parallel()
logs := make(chan agentsdk.PatchLogs, 1)
runner := setup(t, func(ctx context.Context, req agentsdk.PatchLogs) error {
logs <- req
return nil
})
defer runner.Close()
err := runner.Init([]codersdk.WorkspaceAgentScript{{
Script: "echo hello",
}})
require.NoError(t, err)
require.NoError(t, runner.Execute(context.Background(), func(script codersdk.WorkspaceAgentScript) bool {
return true
}))
log := <-logs
require.Equal(t, "hello", log.Logs[0].Output)
}
func TestTimeout(t *testing.T) {
t.Parallel()
runner := setup(t, nil)
defer runner.Close()
err := runner.Init([]codersdk.WorkspaceAgentScript{{
Script: "sleep infinity",
Timeout: time.Millisecond,
}})
require.NoError(t, err)
require.ErrorIs(t, runner.Execute(context.Background(), nil), agentscripts.ErrTimeout)
}
func setup(t *testing.T, patchLogs func(ctx context.Context, req agentsdk.PatchLogs) error) *agentscripts.Runner {
t.Helper()
if patchLogs == nil {
// noop
patchLogs = func(ctx context.Context, req agentsdk.PatchLogs) error {
return nil
}
}
fs := afero.NewMemMapFs()
logger := slogtest.Make(t, nil)
s, err := agentssh.NewServer(context.Background(), logger, prometheus.NewRegistry(), fs, 0, "")
require.NoError(t, err)
s.AgentToken = func() string { return "" }
s.Manifest = atomic.NewPointer(&agentsdk.Manifest{})
t.Cleanup(func() {
_ = s.Close()
})
return agentscripts.New(agentscripts.Options{
LogDir: t.TempDir(),
Logger: logger,
SSHServer: s,
Filesystem: fs,
PatchLogs: patchLogs,
})
}
@@ -0,0 +1,17 @@
package agentscripts
import (
"os"
"os/exec"
"syscall"
)
func cmdSysProcAttr() *syscall.SysProcAttr {
return &syscall.SysProcAttr{}
}
func cmdCancel(cmd *exec.Cmd) func() error {
return func() error {
return cmd.Process.Signal(os.Interrupt)
}
}
+35 -8
View File
@@ -19,6 +19,7 @@ import (
"time"
"github.com/gliderlabs/ssh"
"github.com/kballard/go-shellquote"
"github.com/pkg/sftp"
"github.com/prometheus/client_golang/prometheus"
"github.com/spf13/afero"
@@ -28,10 +29,10 @@ import (
"cdr.dev/slog"
"github.com/coder/coder/agent/usershell"
"github.com/coder/coder/codersdk"
"github.com/coder/coder/codersdk/agentsdk"
"github.com/coder/coder/pty"
"github.com/coder/coder/v2/agent/usershell"
"github.com/coder/coder/v2/codersdk"
"github.com/coder/coder/v2/codersdk/agentsdk"
"github.com/coder/coder/v2/pty"
)
const (
@@ -254,11 +255,13 @@ func (s *Server) sessionStart(session ssh.Session, extraEnv []string) (retErr er
magicType = strings.TrimPrefix(kv, MagicSessionTypeEnvironmentVariable+"=")
env = append(env[:index], env[index+1:]...)
}
switch magicType {
case MagicSessionTypeVSCode:
// Always force lowercase checking to be case-insensitive.
switch strings.ToLower(magicType) {
case strings.ToLower(MagicSessionTypeVSCode):
s.connCountVSCode.Add(1)
defer s.connCountVSCode.Add(-1)
case MagicSessionTypeJetBrains:
case strings.ToLower(MagicSessionTypeJetBrains):
s.connCountJetBrains.Add(1)
defer s.connCountJetBrains.Add(-1)
case "":
@@ -513,8 +516,32 @@ func (s *Server) CreateCommand(ctx context.Context, script string, env []string)
if runtime.GOOS == "windows" {
caller = "/c"
}
name := shell
args := []string{caller, script}
// A preceding space is generally not idiomatic for a shebang,
// but in Terraform it's quite standard to use <<EOF for a multi-line
// string which would indent with spaces, so we accept it for user-ease.
if strings.HasPrefix(strings.TrimSpace(script), "#!") {
// If the script starts with a shebang, we should
// execute it directly. This is useful for running
// scripts that aren't executable.
shebang := strings.SplitN(strings.TrimSpace(script), "\n", 2)[0]
shebang = strings.TrimSpace(shebang)
shebang = strings.TrimPrefix(shebang, "#!")
words, err := shellquote.Split(shebang)
if err != nil {
return nil, xerrors.Errorf("split shebang: %w", err)
}
name = words[0]
if len(words) > 1 {
args = words[1:]
} else {
args = []string{}
}
args = append(args, caller, script)
}
// gliderlabs/ssh returns a command slice of zero
// when a shell is requested.
if len(script) == 0 {
@@ -526,7 +553,7 @@ func (s *Server) CreateCommand(ctx context.Context, script string, env []string)
}
}
cmd := pty.CommandContext(ctx, shell, args...)
cmd := pty.CommandContext(ctx, name, args...)
cmd.Dir = manifest.Directory
// If the metadata directory doesn't exist, we run the command
+2 -2
View File
@@ -15,8 +15,8 @@ import (
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"github.com/coder/coder/pty"
"github.com/coder/coder/testutil"
"github.com/coder/coder/v2/pty"
"github.com/coder/coder/v2/testutil"
"cdr.dev/slog/sloggers/slogtest"
)
+40 -3
View File
@@ -6,6 +6,7 @@ import (
"bytes"
"context"
"net"
"runtime"
"strings"
"sync"
"testing"
@@ -20,9 +21,9 @@ import (
"cdr.dev/slog/sloggers/slogtest"
"github.com/coder/coder/agent/agentssh"
"github.com/coder/coder/codersdk/agentsdk"
"github.com/coder/coder/pty/ptytest"
"github.com/coder/coder/v2/agent/agentssh"
"github.com/coder/coder/v2/codersdk/agentsdk"
"github.com/coder/coder/v2/pty/ptytest"
)
func TestMain(m *testing.M) {
@@ -71,6 +72,42 @@ func TestNewServer_ServeClient(t *testing.T) {
<-done
}
func TestNewServer_ExecuteShebang(t *testing.T) {
t.Parallel()
if runtime.GOOS == "windows" {
t.Skip("bash doesn't exist on Windows")
}
ctx := context.Background()
logger := slogtest.Make(t, nil)
s, err := agentssh.NewServer(ctx, logger, prometheus.NewRegistry(), afero.NewMemMapFs(), 0, "")
require.NoError(t, err)
t.Cleanup(func() {
_ = s.Close()
})
s.AgentToken = func() string { return "" }
s.Manifest = atomic.NewPointer(&agentsdk.Manifest{})
t.Run("Basic", func(t *testing.T) {
t.Parallel()
cmd, err := s.CreateCommand(ctx, `#!/bin/bash
echo test`, nil)
require.NoError(t, err)
output, err := cmd.AsExec().CombinedOutput()
require.NoError(t, err)
require.Equal(t, "test\n", string(output))
})
t.Run("Args", func(t *testing.T) {
t.Parallel()
cmd, err := s.CreateCommand(ctx, `#!/usr/bin/env bash
echo test`, nil)
require.NoError(t, err)
output, err := cmd.AsExec().CombinedOutput()
require.NoError(t, err)
require.Equal(t, "test\n", string(output))
})
}
func TestNewServer_CloseActiveConnections(t *testing.T) {
t.Parallel()
+4 -1
View File
@@ -1,6 +1,8 @@
package agentssh
import (
"strings"
"github.com/prometheus/client_golang/prometheus"
)
@@ -78,5 +80,6 @@ func magicTypeMetricLabel(magicType string) string {
default:
magicType = "unknown"
}
return magicType
// Always be case insensitive
return strings.ToLower(magicType)
}
+3 -3
View File
@@ -19,9 +19,9 @@ import (
"cdr.dev/slog"
"cdr.dev/slog/sloggers/slogtest"
"github.com/coder/coder/agent/agentssh"
"github.com/coder/coder/codersdk/agentsdk"
"github.com/coder/coder/testutil"
"github.com/coder/coder/v2/agent/agentssh"
"github.com/coder/coder/v2/codersdk/agentsdk"
"github.com/coder/coder/v2/testutil"
)
func TestServer_X11(t *testing.T) {
+57
View File
@@ -0,0 +1,57 @@
package agenttest
import (
"context"
"net/url"
"testing"
"github.com/stretchr/testify/assert"
"cdr.dev/slog"
"cdr.dev/slog/sloggers/slogtest"
"github.com/coder/coder/v2/agent"
"github.com/coder/coder/v2/codersdk/agentsdk"
)
// New starts a new agent for use in tests.
// The agent will use the provided coder URL and session token.
// The options passed to agent.New() can be modified by passing an optional
// variadic func(*agent.Options).
// Returns the agent. Closing the agent is handled by the test cleanup.
// It is the responsibility of the caller to call coderdtest.AwaitWorkspaceAgents
// to ensure agent is connected.
func New(t testing.TB, coderURL *url.URL, agentToken string, opts ...func(*agent.Options)) agent.Agent {
t.Helper()
var o agent.Options
log := slogtest.Make(t, nil).Leveled(slog.LevelDebug).Named("agent")
o.Logger = log
for _, opt := range opts {
opt(&o)
}
if o.Client == nil {
agentClient := agentsdk.New(coderURL)
agentClient.SetSessionToken(agentToken)
agentClient.SDK.SetLogger(log)
o.Client = agentClient
}
if o.ExchangeToken == nil {
o.ExchangeToken = func(_ context.Context) (string, error) {
return agentToken, nil
}
}
if o.LogDir == "" {
o.LogDir = t.TempDir()
}
agt := agent.New(o)
t.Cleanup(func() {
assert.NoError(t, agt.Close(), "failed to close agent during cleanup")
})
return agt
}
+12 -10
View File
@@ -13,10 +13,10 @@ import (
"golang.org/x/xerrors"
"cdr.dev/slog"
"github.com/coder/coder/codersdk"
"github.com/coder/coder/codersdk/agentsdk"
"github.com/coder/coder/tailnet"
"github.com/coder/coder/testutil"
"github.com/coder/coder/v2/codersdk"
"github.com/coder/coder/v2/codersdk/agentsdk"
"github.com/coder/coder/v2/tailnet"
"github.com/coder/coder/v2/testutil"
)
func NewClient(t testing.TB,
@@ -45,7 +45,7 @@ type Client struct {
logger slog.Logger
agentID uuid.UUID
manifest agentsdk.Manifest
metadata map[string]agentsdk.PostMetadataRequest
metadata map[string]agentsdk.Metadata
statsChan chan *agentsdk.Stats
coordinator tailnet.Coordinator
LastWorkspaceAgent func()
@@ -136,20 +136,22 @@ func (c *Client) GetStartup() agentsdk.PostStartupRequest {
return c.startup
}
func (c *Client) GetMetadata() map[string]agentsdk.PostMetadataRequest {
func (c *Client) GetMetadata() map[string]agentsdk.Metadata {
c.mu.Lock()
defer c.mu.Unlock()
return maps.Clone(c.metadata)
}
func (c *Client) PostMetadata(ctx context.Context, key string, req agentsdk.PostMetadataRequest) error {
func (c *Client) PostMetadata(ctx context.Context, req agentsdk.PostMetadataRequest) error {
c.mu.Lock()
defer c.mu.Unlock()
if c.metadata == nil {
c.metadata = make(map[string]agentsdk.PostMetadataRequest)
c.metadata = make(map[string]agentsdk.Metadata)
}
for _, md := range req.Metadata {
c.metadata[md.Key] = md
c.logger.Debug(ctx, "post metadata", slog.F("key", md.Key), slog.F("md", md))
}
c.metadata[key] = req
c.logger.Debug(ctx, "post metadata", slog.F("key", key), slog.F("req", req))
return nil
}
+3 -3
View File
@@ -5,10 +5,10 @@ import (
"sync"
"time"
"github.com/go-chi/chi"
"github.com/go-chi/chi/v5"
"github.com/coder/coder/coderd/httpapi"
"github.com/coder/coder/codersdk"
"github.com/coder/coder/v2/coderd/httpapi"
"github.com/coder/coder/v2/codersdk"
)
func (a *agent) apiHandler() http.Handler {
+2 -2
View File
@@ -10,8 +10,8 @@ import (
"golang.org/x/xerrors"
"cdr.dev/slog"
"github.com/coder/coder/codersdk"
"github.com/coder/coder/codersdk/agentsdk"
"github.com/coder/coder/v2/codersdk"
"github.com/coder/coder/v2/codersdk/agentsdk"
"github.com/coder/retry"
)
+5 -5
View File
@@ -13,11 +13,11 @@ import (
"cdr.dev/slog"
"cdr.dev/slog/sloggers/slogtest"
"github.com/coder/coder/agent"
"github.com/coder/coder/coderd/httpapi"
"github.com/coder/coder/codersdk"
"github.com/coder/coder/codersdk/agentsdk"
"github.com/coder/coder/testutil"
"github.com/coder/coder/v2/agent"
"github.com/coder/coder/v2/coderd/httpapi"
"github.com/coder/coder/v2/codersdk"
"github.com/coder/coder/v2/codersdk/agentsdk"
"github.com/coder/coder/v2/testutil"
)
func TestAppHealth_Healthy(t *testing.T) {
+1 -1
View File
@@ -11,7 +11,7 @@ import (
"cdr.dev/slog"
"github.com/coder/coder/codersdk/agentsdk"
"github.com/coder/coder/v2/codersdk/agentsdk"
)
type agentMetrics struct {
+1 -1
View File
@@ -8,7 +8,7 @@ import (
"github.com/cakturk/go-netstat/netstat"
"golang.org/x/xerrors"
"github.com/coder/coder/codersdk"
"github.com/coder/coder/v2/codersdk"
)
func (lp *listeningPortsHandler) getListeningPorts() ([]codersdk.WorkspaceAgentListeningPort, error) {
+1 -1
View File
@@ -2,7 +2,7 @@
package agent
import "github.com/coder/coder/codersdk"
import "github.com/coder/coder/v2/codersdk"
func (lp *listeningPortsHandler) getListeningPorts() ([]codersdk.WorkspaceAgentListeningPort, error) {
// Can't scan for ports on non-linux or non-windows_amd64 systems at the
+2 -2
View File
@@ -14,8 +14,8 @@ import (
"github.com/hashicorp/go-reap"
"github.com/stretchr/testify/require"
"github.com/coder/coder/agent/reaper"
"github.com/coder/coder/testutil"
"github.com/coder/coder/v2/agent/reaper"
"github.com/coder/coder/v2/testutil"
)
// TestReap checks that's the reaper is successfully reaping
+241
View File
@@ -0,0 +1,241 @@
package reconnectingpty
import (
"context"
"errors"
"io"
"net"
"time"
"github.com/armon/circbuf"
"github.com/prometheus/client_golang/prometheus"
"golang.org/x/exp/slices"
"golang.org/x/xerrors"
"cdr.dev/slog"
"github.com/coder/coder/v2/pty"
)
// bufferedReconnectingPTY provides a reconnectable PTY by using a ring buffer to store
// scrollback.
type bufferedReconnectingPTY struct {
command *pty.Cmd
activeConns map[string]net.Conn
circularBuffer *circbuf.Buffer
ptty pty.PTYCmd
process pty.Process
metrics *prometheus.CounterVec
state *ptyState
// timer will close the reconnecting pty when it expires. The timer will be
// reset as long as there are active connections.
timer *time.Timer
timeout time.Duration
}
// newBuffered starts the buffered pty. If the context ends the process will be
// killed.
func newBuffered(ctx context.Context, cmd *pty.Cmd, options *Options, logger slog.Logger) *bufferedReconnectingPTY {
rpty := &bufferedReconnectingPTY{
activeConns: map[string]net.Conn{},
command: cmd,
metrics: options.Metrics,
state: newState(),
timeout: options.Timeout,
}
// Default to buffer 64KiB.
circularBuffer, err := circbuf.NewBuffer(64 << 10)
if err != nil {
rpty.state.setState(StateDone, xerrors.Errorf("create circular buffer: %w", err))
return rpty
}
rpty.circularBuffer = circularBuffer
// Add TERM then start the command with a pty. pty.Cmd duplicates Path as the
// first argument so remove it.
cmdWithEnv := pty.CommandContext(ctx, cmd.Path, cmd.Args[1:]...)
cmdWithEnv.Env = append(rpty.command.Env, "TERM=xterm-256color")
cmdWithEnv.Dir = rpty.command.Dir
ptty, process, err := pty.Start(cmdWithEnv)
if err != nil {
rpty.state.setState(StateDone, xerrors.Errorf("start pty: %w", err))
return rpty
}
rpty.ptty = ptty
rpty.process = process
go rpty.lifecycle(ctx, logger)
// Multiplex the output onto the circular buffer and each active connection.
// We do not need to separately monitor for the process exiting. When it
// exits, our ptty.OutputReader() will return EOF after reading all process
// output.
go func() {
buffer := make([]byte, 1024)
for {
read, err := ptty.OutputReader().Read(buffer)
if err != nil {
// When the PTY is closed, this is triggered.
// Error is typically a benign EOF, so only log for debugging.
if errors.Is(err, io.EOF) {
logger.Debug(ctx, "unable to read pty output, command might have exited", slog.Error(err))
} else {
logger.Warn(ctx, "unable to read pty output, command might have exited", slog.Error(err))
rpty.metrics.WithLabelValues("output_reader").Add(1)
}
// Could have been killed externally or failed to start at all (command
// not found for example).
// TODO: Should we check the process's exit code in case the command was
// invalid?
rpty.Close(nil)
break
}
part := buffer[:read]
rpty.state.cond.L.Lock()
_, err = rpty.circularBuffer.Write(part)
if err != nil {
logger.Error(ctx, "write to circular buffer", slog.Error(err))
rpty.metrics.WithLabelValues("write_buffer").Add(1)
}
// TODO: Instead of ranging over a map, could we send the output to a
// channel and have each individual Attach read from that?
for cid, conn := range rpty.activeConns {
_, err = conn.Write(part)
if err != nil {
logger.Warn(ctx,
"error writing to active connection",
slog.F("connection_id", cid),
slog.Error(err),
)
rpty.metrics.WithLabelValues("write").Add(1)
}
}
rpty.state.cond.L.Unlock()
}
}()
return rpty
}
// lifecycle manages the lifecycle of the reconnecting pty. If the context ends
// or the reconnecting pty closes the pty will be shut down.
func (rpty *bufferedReconnectingPTY) lifecycle(ctx context.Context, logger slog.Logger) {
rpty.timer = time.AfterFunc(attachTimeout, func() {
rpty.Close(xerrors.New("reconnecting pty timeout"))
})
logger.Debug(ctx, "reconnecting pty ready")
rpty.state.setState(StateReady, nil)
state, reasonErr := rpty.state.waitForStateOrContext(ctx, StateClosing)
if state < StateClosing {
// If we have not closed yet then the context is what unblocked us (which
// means the agent is shutting down) so move into the closing phase.
rpty.Close(reasonErr)
}
rpty.timer.Stop()
rpty.state.cond.L.Lock()
// Log these closes only for debugging since the connections or processes
// might have already closed on their own.
for _, conn := range rpty.activeConns {
err := conn.Close()
if err != nil {
logger.Debug(ctx, "closed conn with error", slog.Error(err))
}
}
// Connections get removed once they close but it is possible there is still
// some data that will be written before that happens so clear the map now to
// avoid writing to closed connections.
rpty.activeConns = map[string]net.Conn{}
rpty.state.cond.L.Unlock()
// Log close/kill only for debugging since the process might have already
// closed on its own.
err := rpty.ptty.Close()
if err != nil {
logger.Debug(ctx, "closed ptty with error", slog.Error(err))
}
err = rpty.process.Kill()
if err != nil {
logger.Debug(ctx, "killed process with error", slog.Error(err))
}
logger.Info(ctx, "closed reconnecting pty")
rpty.state.setState(StateDone, reasonErr)
}
func (rpty *bufferedReconnectingPTY) Attach(ctx context.Context, connID string, conn net.Conn, height, width uint16, logger slog.Logger) error {
logger.Info(ctx, "attach to reconnecting pty")
// This will kill the heartbeat once we hit EOF or an error.
ctx, cancel := context.WithCancel(ctx)
defer cancel()
err := rpty.doAttach(connID, conn)
if err != nil {
return err
}
defer func() {
rpty.state.cond.L.Lock()
defer rpty.state.cond.L.Unlock()
delete(rpty.activeConns, connID)
}()
state, err := rpty.state.waitForStateOrContext(ctx, StateReady)
if state != StateReady {
return err
}
go heartbeat(ctx, rpty.timer, rpty.timeout)
// Resize the PTY to initial height + width.
err = rpty.ptty.Resize(height, width)
if err != nil {
// We can continue after this, it's not fatal!
logger.Warn(ctx, "reconnecting PTY initial resize failed, but will continue", slog.Error(err))
rpty.metrics.WithLabelValues("resize").Add(1)
}
// Pipe conn -> pty and block. pty -> conn is handled in newBuffered().
readConnLoop(ctx, conn, rpty.ptty, rpty.metrics, logger)
return nil
}
// doAttach adds the connection to the map and replays the buffer. It exists
// separately only for convenience to defer the mutex unlock which is not
// possible in Attach since it blocks.
func (rpty *bufferedReconnectingPTY) doAttach(connID string, conn net.Conn) error {
rpty.state.cond.L.Lock()
defer rpty.state.cond.L.Unlock()
// Write any previously stored data for the TTY. Since the command might be
// short-lived and have already exited, make sure we always at least output
// the buffer before returning, mostly just so tests pass.
prevBuf := slices.Clone(rpty.circularBuffer.Bytes())
_, err := conn.Write(prevBuf)
if err != nil {
rpty.metrics.WithLabelValues("write").Add(1)
return xerrors.Errorf("write buffer to conn: %w", err)
}
rpty.activeConns[connID] = conn
return nil
}
func (rpty *bufferedReconnectingPTY) Wait() {
_, _ = rpty.state.waitForState(StateClosing)
}
func (rpty *bufferedReconnectingPTY) Close(error error) {
// The closing state change will be handled by the lifecycle.
rpty.state.setState(StateClosing, error)
}
+226
View File
@@ -0,0 +1,226 @@
package reconnectingpty
import (
"context"
"encoding/json"
"io"
"net"
"os/exec"
"runtime"
"sync"
"time"
"github.com/prometheus/client_golang/prometheus"
"golang.org/x/xerrors"
"cdr.dev/slog"
"github.com/coder/coder/v2/codersdk"
"github.com/coder/coder/v2/pty"
)
// attachTimeout is the initial timeout for attaching and will probably be far
// shorter than the reconnect timeout in most cases; in tests it might be
// longer. It should be at least long enough for the first screen attach to be
// able to start up the daemon and for the buffered pty to start.
const attachTimeout = 30 * time.Second
// Options allows configuring the reconnecting pty.
type Options struct {
// Timeout describes how long to keep the pty alive without any connections.
// Once elapsed the pty will be killed.
Timeout time.Duration
// Metrics tracks various error counters.
Metrics *prometheus.CounterVec
}
// ReconnectingPTY is a pty that can be reconnected within a timeout and to
// simultaneous connections. The reconnecting pty can be backed by screen if
// installed or a (buggy) buffer replay fallback.
type ReconnectingPTY interface {
// Attach pipes the connection and pty, spawning it if necessary, replays
// history, then blocks until EOF, an error, or the context's end. The
// connection is expected to send JSON-encoded messages and accept raw output
// from the ptty. If the context ends or the process dies the connection will
// be detached.
Attach(ctx context.Context, connID string, conn net.Conn, height, width uint16, logger slog.Logger) error
// Wait waits for the reconnecting pty to close. The underlying process might
// still be exiting.
Wait()
// Close kills the reconnecting pty process.
Close(err error)
}
// New sets up a new reconnecting pty that wraps the provided command. Any
// errors with starting are returned on Attach(). The reconnecting pty will
// close itself (and all connections to it) if nothing is attached for the
// duration of the timeout, if the context ends, or the process exits (buffered
// backend only).
func New(ctx context.Context, cmd *pty.Cmd, options *Options, logger slog.Logger) ReconnectingPTY {
if options.Timeout == 0 {
options.Timeout = 5 * time.Minute
}
// Screen seems flaky on Darwin. Locally the tests pass 100% of the time (100
// runs) but in CI screen often incorrectly claims the session name does not
// exist even though screen -list shows it. For now, restrict screen to
// Linux.
backendType := "buffered"
if runtime.GOOS == "linux" {
_, err := exec.LookPath("screen")
if err == nil {
backendType = "screen"
}
}
logger.Info(ctx, "start reconnecting pty", slog.F("backend_type", backendType))
switch backendType {
case "screen":
return newScreen(ctx, cmd, options, logger)
default:
return newBuffered(ctx, cmd, options, logger)
}
}
// heartbeat resets timer before timeout elapses and blocks until ctx ends.
func heartbeat(ctx context.Context, timer *time.Timer, timeout time.Duration) {
// Reset now in case it is near the end.
timer.Reset(timeout)
// Reset when the context ends to ensure the pty stays up for the full
// timeout.
defer timer.Reset(timeout)
heartbeat := time.NewTicker(timeout / 2)
defer heartbeat.Stop()
for {
select {
case <-ctx.Done():
return
case <-heartbeat.C:
timer.Reset(timeout)
}
}
}
// State represents the current state of the reconnecting pty. States are
// sequential and will only move forward.
type State int
const (
// StateStarting is the default/start state. Attaching will block until the
// reconnecting pty becomes ready.
StateStarting = iota
// StateReady means the reconnecting pty is ready to be attached.
StateReady
// StateClosing means the reconnecting pty has begun closing. The underlying
// process may still be exiting. Attaching will result in an error.
StateClosing
// StateDone means the reconnecting pty has completely shut down and the
// process has exited. Attaching will result in an error.
StateDone
)
// ptyState is a helper for tracking the reconnecting PTY's state.
type ptyState struct {
// cond broadcasts state changes and any accompanying errors.
cond *sync.Cond
// error describes the error that caused the state change, if there was one.
// It is not safe to access outside of cond.L.
error error
// state holds the current reconnecting pty state. It is not safe to access
// this outside of cond.L.
state State
}
func newState() *ptyState {
return &ptyState{
cond: sync.NewCond(&sync.Mutex{}),
state: StateStarting,
}
}
// setState sets and broadcasts the provided state if it is greater than the
// current state and the error if one has not already been set.
func (s *ptyState) setState(state State, err error) {
s.cond.L.Lock()
defer s.cond.L.Unlock()
// Cannot regress states. For example, trying to close after the process is
// done should leave us in the done state and not the closing state.
if state <= s.state {
return
}
s.error = err
s.state = state
s.cond.Broadcast()
}
// waitForState blocks until the state or a greater one is reached.
func (s *ptyState) waitForState(state State) (State, error) {
s.cond.L.Lock()
defer s.cond.L.Unlock()
for state > s.state {
s.cond.Wait()
}
return s.state, s.error
}
// waitForStateOrContext blocks until the state or a greater one is reached or
// the provided context ends.
func (s *ptyState) waitForStateOrContext(ctx context.Context, state State) (State, error) {
s.cond.L.Lock()
defer s.cond.L.Unlock()
nevermind := make(chan struct{})
defer close(nevermind)
go func() {
select {
case <-ctx.Done():
// Wake up when the context ends.
s.cond.Broadcast()
case <-nevermind:
}
}()
for ctx.Err() == nil && state > s.state {
s.cond.Wait()
}
if ctx.Err() != nil {
return s.state, ctx.Err()
}
return s.state, s.error
}
// readConnLoop reads messages from conn and writes to ptty as needed. Blocks
// until EOF or an error writing to ptty or reading from conn.
func readConnLoop(ctx context.Context, conn net.Conn, ptty pty.PTYCmd, metrics *prometheus.CounterVec, logger slog.Logger) {
decoder := json.NewDecoder(conn)
var req codersdk.ReconnectingPTYRequest
for {
err := decoder.Decode(&req)
if xerrors.Is(err, io.EOF) {
return
}
if err != nil {
logger.Warn(ctx, "reconnecting pty failed with read error", slog.Error(err))
return
}
_, err = ptty.InputWriter().Write([]byte(req.Data))
if err != nil {
logger.Warn(ctx, "reconnecting pty failed with write error", slog.Error(err))
metrics.WithLabelValues("input_writer").Add(1)
return
}
// Check if a resize needs to happen!
if req.Height == 0 || req.Width == 0 {
continue
}
err = ptty.Resize(req.Height, req.Width)
if err != nil {
// We can continue after this, it's not fatal!
logger.Warn(ctx, "reconnecting pty resize failed, but will continue", slog.Error(err))
metrics.WithLabelValues("resize").Add(1)
}
}
}
+389
View File
@@ -0,0 +1,389 @@
package reconnectingpty
import (
"bytes"
"context"
"crypto/rand"
"encoding/hex"
"errors"
"io"
"net"
"os"
"os/exec"
"path/filepath"
"strings"
"sync"
"time"
"github.com/gliderlabs/ssh"
"github.com/prometheus/client_golang/prometheus"
"golang.org/x/xerrors"
"cdr.dev/slog"
"github.com/coder/coder/v2/pty"
)
// screenReconnectingPTY provides a reconnectable PTY via `screen`.
type screenReconnectingPTY struct {
command *pty.Cmd
// id holds the id of the session for both creating and attaching. This will
// be generated uniquely for each session because without control of the
// screen daemon we do not have its PID and without the PID screen will do
// partial matching. Enforcing a unique ID should guarantee we match on the
// right session.
id string
// mutex prevents concurrent attaches to the session. Screen will happily
// spawn two separate sessions with the same name if multiple attaches happen
// in a close enough interval. We are not able to control the screen daemon
// ourselves to prevent this because the daemon will spawn with a hardcoded
// 24x80 size which results in confusing padding above the prompt once the
// attach comes in and resizes.
mutex sync.Mutex
configFile string
metrics *prometheus.CounterVec
state *ptyState
// timer will close the reconnecting pty when it expires. The timer will be
// reset as long as there are active connections.
timer *time.Timer
timeout time.Duration
}
// newScreen creates a new screen-backed reconnecting PTY. It writes config
// settings and creates the socket directory. If we could, we would want to
// spawn the daemon here and attach each connection to it but since doing that
// spawns the daemon with a hardcoded 24x80 size it is not a very good user
// experience. Instead we will let the attach command spawn the daemon on its
// own which causes it to spawn with the specified size.
func newScreen(ctx context.Context, cmd *pty.Cmd, options *Options, logger slog.Logger) *screenReconnectingPTY {
rpty := &screenReconnectingPTY{
command: cmd,
metrics: options.Metrics,
state: newState(),
timeout: options.Timeout,
}
go rpty.lifecycle(ctx, logger)
// Socket paths are limited to around 100 characters on Linux and macOS which
// depending on the temporary directory can be a problem. To give more leeway
// use a short ID.
buf := make([]byte, 4)
_, err := rand.Read(buf)
if err != nil {
rpty.state.setState(StateDone, xerrors.Errorf("generate screen id: %w", err))
return rpty
}
rpty.id = hex.EncodeToString(buf)
settings := []string{
// Tell screen not to handle motion for xterm* terminals which allows
// scrolling the terminal via the mouse wheel or scroll bar (by default
// screen uses it to cycle through the command history). There does not
// seem to be a way to make screen itself scroll on mouse wheel. tmux can
// do it but then there is no scroll bar and it kicks you into copy mode
// where keys stop working until you exit copy mode which seems like it
// could be confusing.
"termcapinfo xterm* ti@:te@",
// Enable alternate screen emulation otherwise applications get rendered in
// the current window which wipes out visible output resulting in missing
// output when scrolling back with the mouse wheel (copy mode still works
// since that is screen itself scrolling).
"altscreen on",
// Remap the control key to C-s since C-a may be used in applications. C-s
// is chosen because it cannot actually be used because by default it will
// pause and C-q to resume will just kill the browser window. We may not
// want people using the control key anyway since it will not be obvious
// they are in screen and doing things like switching windows makes mouse
// wheel scroll wonky due to the terminal doing the scrolling rather than
// screen itself (but again copy mode will work just fine).
"escape ^Ss",
}
rpty.configFile = filepath.Join(os.TempDir(), "coder-screen", "config")
err = os.MkdirAll(filepath.Dir(rpty.configFile), 0o700)
if err != nil {
rpty.state.setState(StateDone, xerrors.Errorf("make screen config dir: %w", err))
return rpty
}
err = os.WriteFile(rpty.configFile, []byte(strings.Join(settings, "\n")), 0o600)
if err != nil {
rpty.state.setState(StateDone, xerrors.Errorf("create config file: %w", err))
return rpty
}
return rpty
}
// lifecycle manages the lifecycle of the reconnecting pty. If the context ends
// the reconnecting pty will be closed.
func (rpty *screenReconnectingPTY) lifecycle(ctx context.Context, logger slog.Logger) {
rpty.timer = time.AfterFunc(attachTimeout, func() {
rpty.Close(xerrors.New("reconnecting pty timeout"))
})
logger.Debug(ctx, "reconnecting pty ready")
rpty.state.setState(StateReady, nil)
state, reasonErr := rpty.state.waitForStateOrContext(ctx, StateClosing)
if state < StateClosing {
// If we have not closed yet then the context is what unblocked us (which
// means the agent is shutting down) so move into the closing phase.
rpty.Close(reasonErr)
}
rpty.timer.Stop()
// If the command errors that the session is already gone that is fine.
err := rpty.sendCommand(context.Background(), "quit", []string{"No screen session found"})
if err != nil {
logger.Error(ctx, "close screen session", slog.Error(err))
}
logger.Info(ctx, "closed reconnecting pty")
rpty.state.setState(StateDone, reasonErr)
}
func (rpty *screenReconnectingPTY) Attach(ctx context.Context, _ string, conn net.Conn, height, width uint16, logger slog.Logger) error {
logger.Info(ctx, "attach to reconnecting pty")
// This will kill the heartbeat once we hit EOF or an error.
ctx, cancel := context.WithCancel(ctx)
defer cancel()
state, err := rpty.state.waitForStateOrContext(ctx, StateReady)
if state != StateReady {
return err
}
go heartbeat(ctx, rpty.timer, rpty.timeout)
ptty, process, err := rpty.doAttach(ctx, conn, height, width, logger)
if err != nil {
if errors.Is(err, context.Canceled) {
// Likely the process was too short-lived and canceled the version command.
// TODO: Is it worth distinguishing between that and a cancel from the
// Attach() caller? Additionally, since this could also happen if
// the command was invalid, should we check the process's exit code?
return nil
}
return err
}
defer func() {
// Log only for debugging since the process might have already exited on its
// own.
err := ptty.Close()
if err != nil {
logger.Debug(ctx, "closed ptty with error", slog.Error(err))
}
err = process.Kill()
if err != nil {
logger.Debug(ctx, "killed process with error", slog.Error(err))
}
}()
// Pipe conn -> pty and block.
readConnLoop(ctx, conn, ptty, rpty.metrics, logger)
return nil
}
// doAttach spawns the screen client and starts the heartbeat. It exists
// separately only so we can defer the mutex unlock which is not possible in
// Attach since it blocks.
func (rpty *screenReconnectingPTY) doAttach(ctx context.Context, conn net.Conn, height, width uint16, logger slog.Logger) (pty.PTYCmd, pty.Process, error) {
// Ensure another attach does not come in and spawn a duplicate session.
rpty.mutex.Lock()
defer rpty.mutex.Unlock()
logger.Debug(ctx, "spawning screen client", slog.F("screen_id", rpty.id))
// Wrap the command with screen and tie it to the connection's context.
cmd := pty.CommandContext(ctx, "screen", append([]string{
// -S is for setting the session's name.
"-S", rpty.id,
// -U tells screen to use UTF-8 encoding.
// -x allows attaching to an already attached session.
// -RR reattaches to the daemon or creates the session daemon if missing.
// -q disables the "New screen..." message that appears for five seconds
// when creating a new session with -RR.
// -c is the flag for the config file.
"-UxRRqc", rpty.configFile,
rpty.command.Path,
// pty.Cmd duplicates Path as the first argument so remove it.
}, rpty.command.Args[1:]...)...)
cmd.Env = append(rpty.command.Env, "TERM=xterm-256color")
cmd.Dir = rpty.command.Dir
ptty, process, err := pty.Start(cmd, pty.WithPTYOption(
pty.WithSSHRequest(ssh.Pty{
Window: ssh.Window{
// Make sure to spawn at the right size because if we resize afterward it
// leaves confusing padding (screen will resize such that the screen
// contents are aligned to the bottom).
Height: int(height),
Width: int(width),
},
}),
))
if err != nil {
rpty.metrics.WithLabelValues("screen_spawn").Add(1)
return nil, nil, err
}
// This context lets us abort the version command if the process dies.
versionCtx, versionCancel := context.WithCancel(ctx)
defer versionCancel()
// Pipe pty -> conn and close the connection when the process exits.
// We do not need to separately monitor for the process exiting. When it
// exits, our ptty.OutputReader() will return EOF after reading all process
// output.
go func() {
defer versionCancel()
defer func() {
err := conn.Close()
if err != nil {
// Log only for debugging since the connection might have already closed
// on its own.
logger.Debug(ctx, "closed connection with error", slog.Error(err))
}
}()
buffer := make([]byte, 1024)
for {
read, err := ptty.OutputReader().Read(buffer)
if err != nil {
// When the PTY is closed, this is triggered.
// Error is typically a benign EOF, so only log for debugging.
if errors.Is(err, io.EOF) {
logger.Debug(ctx, "unable to read pty output; screen might have exited", slog.Error(err))
} else {
logger.Warn(ctx, "unable to read pty output; screen might have exited", slog.Error(err))
rpty.metrics.WithLabelValues("screen_output_reader").Add(1)
}
// The process might have died because the session itself died or it
// might have been separately killed and the session is still up (for
// example `exit` or we killed it when the connection closed). If the
// session is still up we might leave the reconnecting pty in memory
// around longer than it needs to be but it will eventually clean up
// with the timer or context, or the next attach will respawn the screen
// daemon which is fine too.
break
}
part := buffer[:read]
_, err = conn.Write(part)
if err != nil {
// Connection might have been closed.
if errors.Unwrap(err).Error() != "endpoint is closed for send" {
logger.Warn(ctx, "error writing to active conn", slog.Error(err))
rpty.metrics.WithLabelValues("screen_write").Add(1)
}
break
}
}
}()
// Version seems to be the only command without a side effect (other than
// making the version pop up briefly) so use it to wait for the session to
// come up. If we do not wait we could end up spawning multiple sessions with
// the same name.
err = rpty.sendCommand(versionCtx, "version", nil)
if err != nil {
// Log only for debugging since the process might already have closed.
closeErr := ptty.Close()
if closeErr != nil {
logger.Debug(ctx, "closed ptty with error", slog.Error(closeErr))
}
closeErr = process.Kill()
if closeErr != nil {
logger.Debug(ctx, "killed process with error", slog.Error(closeErr))
}
rpty.metrics.WithLabelValues("screen_wait").Add(1)
return nil, nil, err
}
return ptty, process, nil
}
// sendCommand runs a screen command against a running screen session. If the
// command fails with an error matching anything in successErrors it will be
// considered a success state (for example "no session" when quitting and the
// session is already dead). The command will be retried until successful, the
// timeout is reached, or the context ends. A canceled context will return the
// canceled context's error as-is while a timed-out context returns together
// with the last error from the command.
func (rpty *screenReconnectingPTY) sendCommand(ctx context.Context, command string, successErrors []string) error {
ctx, cancel := context.WithTimeout(ctx, attachTimeout)
defer cancel()
var lastErr error
run := func() bool {
var stdout bytes.Buffer
//nolint:gosec
cmd := exec.CommandContext(ctx, "screen",
// -x targets an attached session.
"-x", rpty.id,
// -c is the flag for the config file.
"-c", rpty.configFile,
// -X runs a command in the matching session.
"-X", command,
)
cmd.Env = append(rpty.command.Env, "TERM=xterm-256color")
cmd.Dir = rpty.command.Dir
cmd.Stdout = &stdout
err := cmd.Run()
if err == nil {
return true
}
stdoutStr := stdout.String()
for _, se := range successErrors {
if strings.Contains(stdoutStr, se) {
return true
}
}
// Things like "exit status 1" are imprecise so include stdout as it may
// contain more information ("no screen session found" for example).
if !errors.Is(err, context.Canceled) && !errors.Is(err, context.DeadlineExceeded) {
lastErr = xerrors.Errorf("`screen -x %s -X %s`: %w: %s", rpty.id, command, err, stdoutStr)
}
return false
}
// Run immediately.
if done := run(); done {
return nil
}
// Then run on an interval.
ticker := time.NewTicker(250 * time.Millisecond)
defer ticker.Stop()
for {
select {
case <-ctx.Done():
if errors.Is(ctx.Err(), context.Canceled) {
return ctx.Err()
}
return errors.Join(ctx.Err(), lastErr)
case <-ticker.C:
if done := run(); done {
return nil
}
}
}
}
func (rpty *screenReconnectingPTY) Wait() {
_, _ = rpty.state.waitForState(StateClosing)
}
func (rpty *screenReconnectingPTY) Close(err error) {
// The closing state change will be handled by the lifecycle.
rpty.state.setState(StateClosing, err)
}
+1 -1
View File
@@ -7,7 +7,7 @@ import (
"github.com/stretchr/testify/require"
"github.com/coder/coder/agent/usershell"
"github.com/coder/coder/v2/agent/usershell"
)
//nolint:paralleltest,tparallel // This test sets an environment variable.
+7
View File
@@ -0,0 +1,7 @@
//go:build boringcrypto
package buildinfo
import "crypto/boring"
var boringcrypto = boring.Enabled()
+24 -7
View File
@@ -30,8 +30,15 @@ var (
)
const (
// develPrefix is prefixed to developer versions of the application.
develPrefix = "v0.0.0-devel"
// noVersion is the reported version when the version cannot be determined.
// Usually because `go build` is run instead of `make build`.
noVersion = "v0.0.0"
// develPreRelease is the pre-release tag for developer versions of the
// application. This includes CI builds. The pre-release tag should be appended
// to the version with a "-".
// Example: v0.0.0-devel
develPreRelease = "devel"
)
// Version returns the semantic version of the build.
@@ -45,7 +52,8 @@ func Version() string {
if tag == "" {
// This occurs when the tag hasn't been injected,
// like when using "go run".
version = develPrefix + revision
// <version>-<pre-release>+<revision>
version = fmt.Sprintf("%s-%s%s", noVersion, develPreRelease, revision)
return
}
version = "v" + tag
@@ -63,18 +71,23 @@ func Version() string {
// disregarded. If it detects that either version is a developer build it
// returns true.
func VersionsMatch(v1, v2 string) bool {
// Developer versions are disregarded...hopefully they know what they are
// doing.
if strings.HasPrefix(v1, develPrefix) || strings.HasPrefix(v2, develPrefix) {
// If no version is attached, then it is a dev build outside of CI. The version
// will be disregarded... hopefully they know what they are doing.
if strings.Contains(v1, noVersion) || strings.Contains(v2, noVersion) {
return true
}
return semver.MajorMinor(v1) == semver.MajorMinor(v2)
}
func IsDevVersion(v string) bool {
return strings.Contains(v, "-"+develPreRelease)
}
// IsDev returns true if this is a development build.
// CI builds are also considered development builds.
func IsDev() bool {
return strings.HasPrefix(Version(), develPrefix)
return IsDevVersion(Version())
}
// IsSlim returns true if this is a slim build.
@@ -87,6 +100,10 @@ func IsAGPL() bool {
return strings.Contains(agpl, "t")
}
func IsBoringCrypto() bool {
return boringcrypto
}
// ExternalURL returns a URL referencing the current Coder version.
// For production builds, this will link directly to a release.
// For development builds, this will link to a commit.
+9 -3
View File
@@ -7,7 +7,7 @@ import (
"github.com/stretchr/testify/require"
"golang.org/x/mod/semver"
"github.com/coder/coder/buildinfo"
"github.com/coder/coder/v2/buildinfo"
)
func TestBuildInfo(t *testing.T) {
@@ -57,13 +57,19 @@ func TestBuildInfo(t *testing.T) {
expectMatch: true,
},
// Our CI instance uses a "-devel" prerelease
// flag. This is not the same as a developer WIP build.
// flag.
{
name: "DevelPreleaseNotIgnored",
name: "DevelPreleaseMajor",
v1: "v1.1.1-devel+123abac",
v2: "v1.2.3",
expectMatch: false,
},
{
name: "DevelPreleaseSame",
v1: "v1.1.1-devel+123abac",
v2: "v1.1.9",
expectMatch: true,
},
{
name: "MajorMismatch",
v1: "v1.2.3",
+5
View File
@@ -0,0 +1,5 @@
//go:build !boringcrypto
package buildinfo
var boringcrypto = false
+43 -12
View File
@@ -12,6 +12,7 @@ import (
"path/filepath"
"runtime"
"strconv"
"strings"
"sync"
"time"
@@ -27,12 +28,13 @@ import (
"cdr.dev/slog/sloggers/sloghuman"
"cdr.dev/slog/sloggers/slogjson"
"cdr.dev/slog/sloggers/slogstackdriver"
"github.com/coder/coder/agent"
"github.com/coder/coder/agent/reaper"
"github.com/coder/coder/buildinfo"
"github.com/coder/coder/cli/clibase"
"github.com/coder/coder/codersdk"
"github.com/coder/coder/codersdk/agentsdk"
"github.com/coder/coder/v2/agent"
"github.com/coder/coder/v2/agent/agentproc"
"github.com/coder/coder/v2/agent/reaper"
"github.com/coder/coder/v2/buildinfo"
"github.com/coder/coder/v2/cli/clibase"
"github.com/coder/coder/v2/codersdk"
"github.com/coder/coder/v2/codersdk/agentsdk"
)
func (r *RootCmd) workspaceAgent() *clibase.Cmd {
@@ -197,9 +199,19 @@ func (r *RootCmd) workspaceAgent() *clibase.Cmd {
var exchangeToken func(context.Context) (agentsdk.AuthenticateResponse, error)
switch auth {
case "token":
token, err := inv.ParsedFlags().GetString(varAgentToken)
if err != nil {
return xerrors.Errorf("CODER_AGENT_TOKEN must be set for token auth: %w", err)
token, _ := inv.ParsedFlags().GetString(varAgentToken)
if token == "" {
tokenFile, _ := inv.ParsedFlags().GetString(varAgentTokenFile)
if tokenFile != "" {
tokenBytes, err := os.ReadFile(tokenFile)
if err != nil {
return xerrors.Errorf("read token file %q: %w", tokenFile, err)
}
token = strings.TrimSpace(string(tokenBytes))
}
}
if token == "" {
return xerrors.Errorf("CODER_AGENT_TOKEN or CODER_AGENT_TOKEN_FILE must be set for token auth")
}
client.SetSessionToken(token)
case "google-instance-identity":
@@ -253,7 +265,21 @@ func (r *RootCmd) workspaceAgent() *clibase.Cmd {
}
prometheusRegistry := prometheus.NewRegistry()
subsystem := inv.Environ.Get(agent.EnvAgentSubsystem)
subsystemsRaw := inv.Environ.Get(agent.EnvAgentSubsystem)
subsystems := []codersdk.AgentSubsystem{}
for _, s := range strings.Split(subsystemsRaw, ",") {
subsystem := codersdk.AgentSubsystem(strings.TrimSpace(s))
if subsystem == "" {
continue
}
if !subsystem.Valid() {
return xerrors.Errorf("invalid subsystem %q", subsystem)
}
subsystems = append(subsystems, subsystem)
}
procTicker := time.NewTicker(time.Second)
defer procTicker.Stop()
agnt := agent.New(agent.Options{
Client: client,
Logger: logger,
@@ -271,13 +297,18 @@ func (r *RootCmd) workspaceAgent() *clibase.Cmd {
return resp.SessionToken, nil
},
EnvironmentVariables: map[string]string{
"GIT_ASKPASS": executablePath,
"GIT_ASKPASS": executablePath,
agent.EnvProcPrioMgmt: os.Getenv(agent.EnvProcPrioMgmt),
},
IgnorePorts: ignorePorts,
SSHMaxTimeout: sshMaxTimeout,
Subsystem: codersdk.AgentSubsystem(subsystem),
Subsystems: subsystems,
PrometheusRegistry: prometheusRegistry,
Syscaller: agentproc.NewSyscaller(),
// Intentionally set this to nil. It's mainly used
// for testing.
ModifiedProcesses: nil,
})
prometheusSrvClose := ServeHandler(ctx, logger, prometheusMetricsHandler(prometheusRegistry, logger), prometheusAddress, "prometheus")
+39 -34
View File
@@ -2,6 +2,7 @@ package cli_test
import (
"context"
"fmt"
"os"
"path/filepath"
"runtime"
@@ -12,13 +13,13 @@ import (
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"github.com/coder/coder/agent"
"github.com/coder/coder/cli/clitest"
"github.com/coder/coder/coderd/coderdtest"
"github.com/coder/coder/codersdk"
"github.com/coder/coder/provisioner/echo"
"github.com/coder/coder/provisionersdk/proto"
"github.com/coder/coder/pty/ptytest"
"github.com/coder/coder/v2/agent"
"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/provisioner/echo"
"github.com/coder/coder/v2/provisionersdk/proto"
"github.com/coder/coder/v2/pty/ptytest"
)
func TestWorkspaceAgent(t *testing.T) {
@@ -37,9 +38,9 @@ func TestWorkspaceAgent(t *testing.T) {
ProvisionApply: echo.ProvisionApplyWithAgent(authToken),
})
template := coderdtest.CreateTemplate(t, client, user.OrganizationID, version.ID)
coderdtest.AwaitTemplateVersionJob(t, client, version.ID)
coderdtest.AwaitTemplateVersionJobCompleted(t, client, version.ID)
workspace := coderdtest.CreateWorkspace(t, client, user.OrganizationID, template.ID)
coderdtest.AwaitWorkspaceBuildJob(t, client, workspace.LatestBuild.ID)
coderdtest.AwaitWorkspaceBuildJobCompleted(t, client, workspace.LatestBuild.ID)
logDir := t.TempDir()
inv, _ := clitest.New(t,
@@ -74,9 +75,9 @@ func TestWorkspaceAgent(t *testing.T) {
user := coderdtest.CreateFirstUser(t, client)
version := coderdtest.CreateTemplateVersion(t, client, user.OrganizationID, &echo.Responses{
Parse: echo.ParseComplete,
ProvisionApply: []*proto.Provision_Response{{
Type: &proto.Provision_Response_Complete{
Complete: &proto.Provision_Complete{
ProvisionApply: []*proto.Response{{
Type: &proto.Response_Apply{
Apply: &proto.ApplyComplete{
Resources: []*proto.Resource{{
Name: "somename",
Type: "someinstance",
@@ -91,9 +92,9 @@ func TestWorkspaceAgent(t *testing.T) {
}},
})
template := coderdtest.CreateTemplate(t, client, user.OrganizationID, version.ID)
coderdtest.AwaitTemplateVersionJob(t, client, version.ID)
coderdtest.AwaitTemplateVersionJobCompleted(t, client, version.ID)
workspace := coderdtest.CreateWorkspace(t, client, user.OrganizationID, template.ID)
coderdtest.AwaitWorkspaceBuildJob(t, client, workspace.LatestBuild.ID)
coderdtest.AwaitWorkspaceBuildJobCompleted(t, client, workspace.LatestBuild.ID)
inv, _ := clitest.New(t, "agent", "--auth", "azure-instance-identity", "--agent-url", client.URL.String())
inv = inv.WithContext(
@@ -126,9 +127,9 @@ func TestWorkspaceAgent(t *testing.T) {
user := coderdtest.CreateFirstUser(t, client)
version := coderdtest.CreateTemplateVersion(t, client, user.OrganizationID, &echo.Responses{
Parse: echo.ParseComplete,
ProvisionApply: []*proto.Provision_Response{{
Type: &proto.Provision_Response_Complete{
Complete: &proto.Provision_Complete{
ProvisionApply: []*proto.Response{{
Type: &proto.Response_Apply{
Apply: &proto.ApplyComplete{
Resources: []*proto.Resource{{
Name: "somename",
Type: "someinstance",
@@ -143,9 +144,9 @@ func TestWorkspaceAgent(t *testing.T) {
}},
})
template := coderdtest.CreateTemplate(t, client, user.OrganizationID, version.ID)
coderdtest.AwaitTemplateVersionJob(t, client, version.ID)
coderdtest.AwaitTemplateVersionJobCompleted(t, client, version.ID)
workspace := coderdtest.CreateWorkspace(t, client, user.OrganizationID, template.ID)
coderdtest.AwaitWorkspaceBuildJob(t, client, workspace.LatestBuild.ID)
coderdtest.AwaitWorkspaceBuildJobCompleted(t, client, workspace.LatestBuild.ID)
inv, _ := clitest.New(t, "agent", "--auth", "aws-instance-identity", "--agent-url", client.URL.String())
inv = inv.WithContext(
@@ -175,12 +176,13 @@ func TestWorkspaceAgent(t *testing.T) {
GoogleTokenValidator: validator,
IncludeProvisionerDaemon: true,
})
user := coderdtest.CreateFirstUser(t, client)
version := coderdtest.CreateTemplateVersion(t, client, user.OrganizationID, &echo.Responses{
owner := coderdtest.CreateFirstUser(t, client)
member, _ := coderdtest.CreateAnotherUser(t, client, owner.OrganizationID)
version := coderdtest.CreateTemplateVersion(t, client, owner.OrganizationID, &echo.Responses{
Parse: echo.ParseComplete,
ProvisionApply: []*proto.Provision_Response{{
Type: &proto.Provision_Response_Complete{
Complete: &proto.Provision_Complete{
ProvisionApply: []*proto.Response{{
Type: &proto.Response_Apply{
Apply: &proto.ApplyComplete{
Resources: []*proto.Resource{{
Name: "somename",
Type: "someinstance",
@@ -194,14 +196,14 @@ func TestWorkspaceAgent(t *testing.T) {
},
}},
})
template := coderdtest.CreateTemplate(t, client, user.OrganizationID, version.ID)
coderdtest.AwaitTemplateVersionJob(t, client, version.ID)
workspace := coderdtest.CreateWorkspace(t, client, user.OrganizationID, template.ID)
coderdtest.AwaitWorkspaceBuildJob(t, client, workspace.LatestBuild.ID)
template := coderdtest.CreateTemplate(t, client, owner.OrganizationID, version.ID)
coderdtest.AwaitTemplateVersionJobCompleted(t, client, version.ID)
workspace := coderdtest.CreateWorkspace(t, member, owner.OrganizationID, template.ID)
coderdtest.AwaitWorkspaceBuildJobCompleted(t, client, workspace.LatestBuild.ID)
inv, cfg := clitest.New(t, "agent", "--auth", "google-instance-identity", "--agent-url", client.URL.String())
ptytest.New(t).Attach(inv)
clitest.SetupConfig(t, client, cfg)
clitest.SetupConfig(t, member, cfg)
clitest.Start(t,
inv.WithContext(
//nolint:revive,staticcheck
@@ -252,9 +254,9 @@ func TestWorkspaceAgent(t *testing.T) {
ProvisionApply: echo.ProvisionApplyWithAgent(authToken),
})
template := coderdtest.CreateTemplate(t, client, user.OrganizationID, version.ID)
coderdtest.AwaitTemplateVersionJob(t, client, version.ID)
coderdtest.AwaitTemplateVersionJobCompleted(t, client, version.ID)
workspace := coderdtest.CreateWorkspace(t, client, user.OrganizationID, template.ID)
coderdtest.AwaitWorkspaceBuildJob(t, client, workspace.LatestBuild.ID)
coderdtest.AwaitWorkspaceBuildJobCompleted(t, client, workspace.LatestBuild.ID)
logDir := t.TempDir()
inv, _ := clitest.New(t,
@@ -264,8 +266,8 @@ func TestWorkspaceAgent(t *testing.T) {
"--agent-url", client.URL.String(),
"--log-dir", logDir,
)
// Set the subsystem for the agent.
inv.Environ.Set(agent.EnvAgentSubsystem, string(codersdk.AgentSubsystemEnvbox))
// Set the subsystems for the agent.
inv.Environ.Set(agent.EnvAgentSubsystem, fmt.Sprintf("%s,%s", codersdk.AgentSubsystemExectrace, codersdk.AgentSubsystemEnvbox))
pty := ptytest.New(t).Attach(inv)
@@ -275,6 +277,9 @@ func TestWorkspaceAgent(t *testing.T) {
resources := coderdtest.AwaitWorkspaceAgents(t, client, workspace.ID)
require.Len(t, resources, 1)
require.Len(t, resources[0].Agents, 1)
require.Equal(t, codersdk.AgentSubsystemEnvbox, resources[0].Agents[0].Subsystem)
require.Len(t, resources[0].Agents[0].Subsystems, 2)
// Sorted
require.Equal(t, codersdk.AgentSubsystemEnvbox, resources[0].Agents[0].Subsystems[0])
require.Equal(t, codersdk.AgentSubsystemExectrace, resources[0].Agents[0].Subsystems[1])
})
}
+6 -4
View File
@@ -14,6 +14,8 @@ import (
"golang.org/x/exp/slices"
"golang.org/x/xerrors"
"gopkg.in/yaml.v3"
"github.com/coder/coder/v2/coderd/util/slice"
)
// Cmd describes an executable command.
@@ -102,11 +104,11 @@ func (c *Cmd) PrepareAll() error {
}
}
slices.SortFunc(c.Options, func(a, b Option) bool {
return a.Name < b.Name
slices.SortFunc(c.Options, func(a, b Option) int {
return slice.Ascending(a.Name, b.Name)
})
slices.SortFunc(c.Children, func(a, b *Cmd) bool {
return a.Name() < b.Name()
slices.SortFunc(c.Children, func(a, b *Cmd) int {
return slice.Ascending(a.Name(), b.Name())
})
for _, child := range c.Children {
child.Parent = c
+1 -1
View File
@@ -11,7 +11,7 @@ import (
"github.com/stretchr/testify/require"
"golang.org/x/xerrors"
"github.com/coder/coder/cli/clibase"
"github.com/coder/coder/v2/cli/clibase"
)
// ioBufs is the standard input, output, and error for a command.
+1 -1
View File
@@ -4,7 +4,7 @@ import (
"reflect"
"testing"
"github.com/coder/coder/cli/clibase"
"github.com/coder/coder/v2/cli/clibase"
)
func TestFilterNamePrefix(t *testing.T) {
+129 -18
View File
@@ -1,6 +1,8 @@
package clibase
import (
"bytes"
"encoding/json"
"os"
"strings"
@@ -65,6 +67,20 @@ type Option struct {
ValueSource ValueSource `json:"value_source,omitempty"`
}
// optionNoMethods is just a wrapper around Option so we can defer to the
// default json.Unmarshaler behavior.
type optionNoMethods Option
func (o *Option) UnmarshalJSON(data []byte) error {
// If an option has no values, we have no idea how to unmarshal it.
// So just discard the json data.
if o.Value == nil {
o.Value = &DiscardValue
}
return json.Unmarshal(data, (*optionNoMethods)(o))
}
func (o Option) YAMLPath() string {
if o.YAML == "" {
return ""
@@ -79,15 +95,101 @@ func (o Option) YAMLPath() string {
// OptionSet is a group of options that can be applied to a command.
type OptionSet []Option
// UnmarshalJSON implements json.Unmarshaler for OptionSets. Options have an
// interface Value type that cannot handle unmarshalling because the types cannot
// be inferred. Since it is a slice, instantiating the Options first does not
// help.
//
// However, we typically do instantiate the slice to have the correct types.
// So this unmarshaller will attempt to find the named option in the existing
// set, if it cannot, the value is discarded. If the option exists, the value
// is unmarshalled into the existing option, and replaces the existing option.
//
// The value is discarded if it's type cannot be inferred. This behavior just
// feels "safer", although it should never happen if the correct option set
// is passed in. The situation where this could occur is if a client and server
// are on different versions with different options.
func (optSet *OptionSet) UnmarshalJSON(data []byte) error {
dec := json.NewDecoder(bytes.NewBuffer(data))
// Should be a json array, so consume the starting open bracket.
t, err := dec.Token()
if err != nil {
return xerrors.Errorf("read array open bracket: %w", err)
}
if t != json.Delim('[') {
return xerrors.Errorf("expected array open bracket, got %q", t)
}
// As long as json elements exist, consume them. The counter is used for
// better errors.
var i int
OptionSetDecodeLoop:
for dec.More() {
var opt Option
// jValue is a placeholder value that allows us to capture the
// raw json for the value to attempt to unmarshal later.
var jValue jsonValue
opt.Value = &jValue
err := dec.Decode(&opt)
if err != nil {
return xerrors.Errorf("decode %d option: %w", i, err)
}
// This counter is used to contextualize errors to show which element of
// the array we failed to decode. It is only used in the error above, as
// if the above works, we can instead use the Option.Name which is more
// descriptive and useful. So increment here for the next decode.
i++
// Try to see if the option already exists in the option set.
// If it does, just update the existing option.
for optIndex, have := range *optSet {
if have.Name == opt.Name {
if jValue != nil {
err := json.Unmarshal(jValue, &(*optSet)[optIndex].Value)
if err != nil {
return xerrors.Errorf("decode option %q value: %w", have.Name, err)
}
// Set the opt's value
opt.Value = (*optSet)[optIndex].Value
} else {
// Hopefully the user passed empty values in the option set. There is no easy way
// to tell, and if we do not do this, it breaks json.Marshal if we do it again on
// this new option set.
opt.Value = (*optSet)[optIndex].Value
}
// Override the existing.
(*optSet)[optIndex] = opt
// Go to the next option to decode.
continue OptionSetDecodeLoop
}
}
// If the option doesn't exist, the value will be discarded.
// We do this because we cannot infer the type of the value.
opt.Value = DiscardValue
*optSet = append(*optSet, opt)
}
t, err = dec.Token()
if err != nil {
return xerrors.Errorf("read array close bracket: %w", err)
}
if t != json.Delim(']') {
return xerrors.Errorf("expected array close bracket, got %q", t)
}
return nil
}
// Add adds the given Options to the OptionSet.
func (s *OptionSet) Add(opts ...Option) {
*s = append(*s, opts...)
func (optSet *OptionSet) Add(opts ...Option) {
*optSet = append(*optSet, opts...)
}
// Filter will only return options that match the given filter. (return true)
func (s OptionSet) Filter(filter func(opt Option) bool) OptionSet {
func (optSet OptionSet) Filter(filter func(opt Option) bool) OptionSet {
cpy := make(OptionSet, 0)
for _, opt := range s {
for _, opt := range optSet {
if filter(opt) {
cpy = append(cpy, opt)
}
@@ -96,13 +198,13 @@ func (s OptionSet) Filter(filter func(opt Option) bool) OptionSet {
}
// FlagSet returns a pflag.FlagSet for the OptionSet.
func (s *OptionSet) FlagSet() *pflag.FlagSet {
if s == nil {
func (optSet *OptionSet) FlagSet() *pflag.FlagSet {
if optSet == nil {
return &pflag.FlagSet{}
}
fs := pflag.NewFlagSet("", pflag.ContinueOnError)
for _, opt := range *s {
for _, opt := range *optSet {
if opt.Flag == "" {
continue
}
@@ -139,8 +241,8 @@ func (s *OptionSet) FlagSet() *pflag.FlagSet {
// ParseEnv parses the given environment variables into the OptionSet.
// Use EnvsWithPrefix to filter out prefixes.
func (s *OptionSet) ParseEnv(vs []EnvVar) error {
if s == nil {
func (optSet *OptionSet) ParseEnv(vs []EnvVar) error {
if optSet == nil {
return nil
}
@@ -154,12 +256,21 @@ func (s *OptionSet) ParseEnv(vs []EnvVar) error {
envs[v.Name] = v.Value
}
for i, opt := range *s {
for i, opt := range *optSet {
if opt.Env == "" {
continue
}
envVal, ok := envs[opt.Env]
if !ok {
// Homebrew strips all environment variables that do not start with `HOMEBREW_`.
// This prevented using brew to invoke the Coder agent, because the environment
// variables to not get passed down.
//
// A customer wanted to use their custom tap inside a workspace, which was failing
// because the agent lacked the environment variables to authenticate with Git.
envVal, ok = envs[`HOMEBREW_`+opt.Env]
}
// Currently, empty values are treated as if the environment variable is
// unset. This behavior is technically not correct as there is now no
// way for a user to change a Default value to an empty string from
@@ -172,7 +283,7 @@ func (s *OptionSet) ParseEnv(vs []EnvVar) error {
continue
}
(*s)[i].ValueSource = ValueSourceEnv
(*optSet)[i].ValueSource = ValueSourceEnv
if err := opt.Value.Set(envVal); err != nil {
merr = multierror.Append(
merr, xerrors.Errorf("parse %q: %w", opt.Name, err),
@@ -185,14 +296,14 @@ func (s *OptionSet) ParseEnv(vs []EnvVar) error {
// SetDefaults sets the default values for each Option, skipping values
// that already have a value source.
func (s *OptionSet) SetDefaults() error {
if s == nil {
func (optSet *OptionSet) SetDefaults() error {
if optSet == nil {
return nil
}
var merr *multierror.Error
for i, opt := range *s {
for i, opt := range *optSet {
// Skip values that may have already been set by the user.
if opt.ValueSource != ValueSourceNone {
continue
@@ -212,7 +323,7 @@ func (s *OptionSet) SetDefaults() error {
)
continue
}
(*s)[i].ValueSource = ValueSourceDefault
(*optSet)[i].ValueSource = ValueSourceDefault
if err := opt.Value.Set(opt.Default); err != nil {
merr = multierror.Append(
merr, xerrors.Errorf("parse %q: %w", opt.Name, err),
@@ -224,9 +335,9 @@ func (s *OptionSet) SetDefaults() error {
// ByName returns the Option with the given name, or nil if no such option
// exists.
func (s *OptionSet) ByName(name string) *Option {
for i := range *s {
opt := &(*s)[i]
func (optSet *OptionSet) ByName(name string) *Option {
for i := range *optSet {
opt := &(*optSet)[i]
if opt.Name == name {
return opt
}
+223 -1
View File
@@ -1,11 +1,17 @@
package clibase_test
import (
"bytes"
"encoding/json"
"regexp"
"testing"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"github.com/coder/coder/cli/clibase"
"github.com/coder/coder/v2/cli/clibase"
"github.com/coder/coder/v2/coderd/coderdtest"
"github.com/coder/coder/v2/codersdk"
)
func TestOptionSet_ParseFlags(t *testing.T) {
@@ -72,6 +78,40 @@ func TestOptionSet_ParseFlags(t *testing.T) {
err := os.FlagSet().Parse([]string{"--some-unknown", "foo"})
require.Error(t, err)
})
t.Run("RegexValid", func(t *testing.T) {
t.Parallel()
var regexpString clibase.Regexp
os := clibase.OptionSet{
clibase.Option{
Name: "RegexpString",
Value: &regexpString,
Flag: "regexp-string",
},
}
err := os.FlagSet().Parse([]string{"--regexp-string", "$test^"})
require.NoError(t, err)
})
t.Run("RegexInvalid", func(t *testing.T) {
t.Parallel()
var regexpString clibase.Regexp
os := clibase.OptionSet{
clibase.Option{
Name: "RegexpString",
Value: &regexpString,
Flag: "regexp-string",
},
}
err := os.FlagSet().Parse([]string{"--regexp-string", "(("})
require.Error(t, err)
})
}
func TestOptionSet_ParseEnv(t *testing.T) {
@@ -166,4 +206,186 @@ func TestOptionSet_ParseEnv(t *testing.T) {
require.NoError(t, err)
require.EqualValues(t, expected, actual.Value)
})
t.Run("Homebrew", func(t *testing.T) {
t.Parallel()
var agentToken clibase.String
os := clibase.OptionSet{
clibase.Option{
Name: "Agent Token",
Value: &agentToken,
Env: "AGENT_TOKEN",
},
}
err := os.ParseEnv([]clibase.EnvVar{
{Name: "HOMEBREW_AGENT_TOKEN", Value: "foo"},
})
require.NoError(t, err)
require.EqualValues(t, "foo", agentToken)
})
}
func TestOptionSet_JsonMarshal(t *testing.T) {
t.Parallel()
// This unit test ensures if the source optionset is missing the option
// and cannot determine the type, it will not panic. The unmarshal will
// succeed with a best effort.
t.Run("MissingSrcOption", func(t *testing.T) {
t.Parallel()
var str clibase.String = "something"
var arr clibase.StringArray = []string{"foo", "bar"}
opts := clibase.OptionSet{
clibase.Option{
Name: "StringOpt",
Value: &str,
},
clibase.Option{
Name: "ArrayOpt",
Value: &arr,
},
}
data, err := json.Marshal(opts)
require.NoError(t, err, "marshal option set")
tgt := clibase.OptionSet{}
err = json.Unmarshal(data, &tgt)
require.NoError(t, err, "unmarshal option set")
for i := range opts {
compareOptionsExceptValues(t, opts[i], tgt[i])
require.Empty(t, tgt[i].Value.String(), "unknown value types are empty")
}
})
t.Run("RegexCase", func(t *testing.T) {
t.Parallel()
val := clibase.Regexp(*regexp.MustCompile(".*"))
opts := clibase.OptionSet{
clibase.Option{
Name: "Regex",
Value: &val,
Default: ".*",
},
}
data, err := json.Marshal(opts)
require.NoError(t, err, "marshal option set")
var foundVal clibase.Regexp
newOpts := clibase.OptionSet{
clibase.Option{
Name: "Regex",
Value: &foundVal,
},
}
err = json.Unmarshal(data, &newOpts)
require.NoError(t, err, "unmarshal option set")
require.EqualValues(t, opts[0].Value.String(), newOpts[0].Value.String())
})
t.Run("AllValues", func(t *testing.T) {
t.Parallel()
vals := coderdtest.DeploymentValues(t)
opts := vals.Options()
sources := []clibase.ValueSource{
clibase.ValueSourceNone,
clibase.ValueSourceFlag,
clibase.ValueSourceEnv,
clibase.ValueSourceYAML,
clibase.ValueSourceDefault,
}
for i := range opts {
opts[i].ValueSource = sources[i%len(sources)]
}
data, err := json.Marshal(opts)
require.NoError(t, err, "marshal option set")
newOpts := (&codersdk.DeploymentValues{}).Options()
err = json.Unmarshal(data, &newOpts)
require.NoError(t, err, "unmarshal option set")
for i := range opts {
exp := opts[i]
found := newOpts[i]
compareOptionsExceptValues(t, exp, found)
compareValues(t, exp, found)
}
thirdOpts := (&codersdk.DeploymentValues{}).Options()
data, err = json.Marshal(newOpts)
require.NoError(t, err, "marshal option set")
err = json.Unmarshal(data, &thirdOpts)
require.NoError(t, err, "unmarshal option set")
// Compare to the original opts again
for i := range opts {
exp := opts[i]
found := thirdOpts[i]
compareOptionsExceptValues(t, exp, found)
compareValues(t, exp, found)
}
})
}
func compareOptionsExceptValues(t *testing.T, exp, found clibase.Option) {
t.Helper()
require.Equalf(t, exp.Name, found.Name, "option name %q", exp.Name)
require.Equalf(t, exp.Description, found.Description, "option description %q", exp.Name)
require.Equalf(t, exp.Required, found.Required, "option required %q", exp.Name)
require.Equalf(t, exp.Flag, found.Flag, "option flag %q", exp.Name)
require.Equalf(t, exp.FlagShorthand, found.FlagShorthand, "option flag shorthand %q", exp.Name)
require.Equalf(t, exp.Env, found.Env, "option env %q", exp.Name)
require.Equalf(t, exp.YAML, found.YAML, "option yaml %q", exp.Name)
require.Equalf(t, exp.Default, found.Default, "option default %q", exp.Name)
require.Equalf(t, exp.ValueSource, found.ValueSource, "option value source %q", exp.Name)
require.Equalf(t, exp.Hidden, found.Hidden, "option hidden %q", exp.Name)
require.Equalf(t, exp.Annotations, found.Annotations, "option annotations %q", exp.Name)
require.Equalf(t, exp.Group, found.Group, "option group %q", exp.Name)
// UseInstead is the same comparison problem, just check the length
require.Equalf(t, len(exp.UseInstead), len(found.UseInstead), "option use instead %q", exp.Name)
}
func compareValues(t *testing.T, exp, found clibase.Option) {
t.Helper()
if (exp.Value == nil || found.Value == nil) || (exp.Value.String() != found.Value.String() && found.Value.String() == "") {
// If the string values are different, this can be a "nil" issue.
// So only run this case if the found string is the empty string.
// We use MarshalYAML for struct strings, and it will return an
// empty string '""' for nil slices/maps/etc.
// So use json to compare.
expJSON, err := json.Marshal(exp.Value)
require.NoError(t, err, "marshal")
foundJSON, err := json.Marshal(found.Value)
require.NoError(t, err, "marshal")
expJSON = normalizeJSON(expJSON)
foundJSON = normalizeJSON(foundJSON)
assert.Equalf(t, string(expJSON), string(foundJSON), "option value %q", exp.Name)
} else {
assert.Equal(t,
exp.Value.String(),
found.Value.String(),
"option value %q", exp.Name)
}
}
// normalizeJSON handles the fact that an empty map/slice is not the same
// as a nil empty/slice. For our purposes, they are the same.
func normalizeJSON(data []byte) []byte {
if bytes.Equal(data, []byte("[]")) || bytes.Equal(data, []byte("{}")) {
return []byte("null")
}
return data
}
+86
View File
@@ -7,6 +7,7 @@ import (
"net"
"net/url"
"reflect"
"regexp"
"strconv"
"strings"
"time"
@@ -429,6 +430,35 @@ func (discardValue) Type() string {
return "discard"
}
func (discardValue) UnmarshalJSON([]byte) error {
return nil
}
// jsonValue is intentionally not exported. It is just used to store the raw JSON
// data for a value to defer it's unmarshal. It implements the pflag.Value to be
// usable in an Option.
type jsonValue json.RawMessage
func (jsonValue) Set(string) error {
return xerrors.Errorf("json value is read-only")
}
func (jsonValue) String() string {
return ""
}
func (jsonValue) Type() string {
return "json"
}
func (j *jsonValue) UnmarshalJSON(data []byte) error {
if j == nil {
return xerrors.New("json.RawMessage: UnmarshalJSON on nil pointer")
}
*j = append((*j)[0:0], data...)
return nil
}
var _ pflag.Value = (*Enum)(nil)
type Enum struct {
@@ -461,6 +491,62 @@ func (e *Enum) String() string {
return *e.Value
}
type Regexp regexp.Regexp
func (r *Regexp) MarshalJSON() ([]byte, error) {
return json.Marshal(r.String())
}
func (r *Regexp) UnmarshalJSON(data []byte) error {
var source string
err := json.Unmarshal(data, &source)
if err != nil {
return err
}
exp, err := regexp.Compile(source)
if err != nil {
return xerrors.Errorf("invalid regex expression: %w", err)
}
*r = Regexp(*exp)
return nil
}
func (r *Regexp) MarshalYAML() (interface{}, error) {
return yaml.Node{
Kind: yaml.ScalarNode,
Value: r.String(),
}, nil
}
func (r *Regexp) UnmarshalYAML(n *yaml.Node) error {
return r.Set(n.Value)
}
func (r *Regexp) Set(v string) error {
exp, err := regexp.Compile(v)
if err != nil {
return xerrors.Errorf("invalid regex expression: %w", err)
}
*r = Regexp(*exp)
return nil
}
func (r Regexp) String() string {
return r.Value().String()
}
func (r *Regexp) Value() *regexp.Regexp {
if r == nil {
return nil
}
return (*regexp.Regexp)(r)
}
func (Regexp) Type() string {
return "regexp"
}
var _ pflag.Value = (*YAMLConfigPath)(nil)
// YAMLConfigPath is a special value type that encodes a path to a YAML
+5 -5
View File
@@ -51,12 +51,12 @@ func deepMapNode(n *yaml.Node, path []string, headComment string) *yaml.Node {
// the stack.
//
// It is isomorphic with FromYAML.
func (s *OptionSet) MarshalYAML() (any, error) {
func (optSet *OptionSet) MarshalYAML() (any, error) {
root := yaml.Node{
Kind: yaml.MappingNode,
}
for _, opt := range *s {
for _, opt := range *optSet {
if opt.YAML == "" {
continue
}
@@ -222,7 +222,7 @@ func (o *Option) setFromYAMLNode(n *yaml.Node) error {
// UnmarshalYAML converts the given YAML node into the option set.
// It is isomorphic with ToYAML.
func (s *OptionSet) UnmarshalYAML(rootNode *yaml.Node) error {
func (optSet *OptionSet) UnmarshalYAML(rootNode *yaml.Node) error {
// The rootNode will be a DocumentNode if it's read from a file. We do
// not support multiple documents in a single file.
if rootNode.Kind == yaml.DocumentNode {
@@ -240,8 +240,8 @@ func (s *OptionSet) UnmarshalYAML(rootNode *yaml.Node) error {
matchedNodes := make(map[string]*yaml.Node, len(yamlNodes))
var merr error
for i := range *s {
opt := &(*s)[i]
for i := range *optSet {
opt := &(*optSet)[i]
if opt.YAML == "" {
continue
}
+1 -1
View File
@@ -8,7 +8,7 @@ import (
"golang.org/x/exp/slices"
"gopkg.in/yaml.v3"
"github.com/coder/coder/cli/clibase"
"github.com/coder/coder/v2/cli/clibase"
)
func TestOptionSet_YAML(t *testing.T) {
+8 -8
View File
@@ -19,17 +19,17 @@ import (
"cdr.dev/slog"
"cdr.dev/slog/sloggers/slogtest"
"github.com/coder/coder/cli"
"github.com/coder/coder/cli/clibase"
"github.com/coder/coder/cli/config"
"github.com/coder/coder/codersdk"
"github.com/coder/coder/provisioner/echo"
"github.com/coder/coder/testutil"
"github.com/coder/coder/v2/cli"
"github.com/coder/coder/v2/cli/clibase"
"github.com/coder/coder/v2/cli/config"
"github.com/coder/coder/v2/codersdk"
"github.com/coder/coder/v2/provisioner/echo"
"github.com/coder/coder/v2/testutil"
)
// New creates a CLI instance with a configuration pointed to a
// temporary testing directory.
func New(t *testing.T, args ...string) (*clibase.Invocation, config.Root) {
func New(t testing.TB, args ...string) (*clibase.Invocation, config.Root) {
var root cli.RootCmd
cmd, err := root.Command(root.AGPL())
@@ -56,7 +56,7 @@ func (l *logWriter) Write(p []byte) (n int, err error) {
}
func NewWithCommand(
t *testing.T, cmd *clibase.Cmd, args ...string,
t testing.TB, cmd *clibase.Cmd, args ...string,
) (*clibase.Invocation, config.Root) {
configDir := config.Root(t.TempDir())
logger := slogtest.Make(t, nil)
+3 -3
View File
@@ -5,9 +5,9 @@ import (
"go.uber.org/goleak"
"github.com/coder/coder/cli/clitest"
"github.com/coder/coder/coderd/coderdtest"
"github.com/coder/coder/pty/ptytest"
"github.com/coder/coder/v2/cli/clitest"
"github.com/coder/coder/v2/coderd/coderdtest"
"github.com/coder/coder/v2/pty/ptytest"
)
func TestMain(m *testing.M) {
+10 -20
View File
@@ -11,16 +11,14 @@ import (
"strings"
"testing"
"github.com/charmbracelet/lipgloss"
"github.com/muesli/termenv"
"github.com/stretchr/testify/require"
"github.com/coder/coder/cli/clibase"
"github.com/coder/coder/cli/config"
"github.com/coder/coder/coderd/coderdtest"
"github.com/coder/coder/coderd/database/dbtestutil"
"github.com/coder/coder/codersdk"
"github.com/coder/coder/testutil"
"github.com/coder/coder/v2/cli/clibase"
"github.com/coder/coder/v2/cli/config"
"github.com/coder/coder/v2/coderd/coderdtest"
"github.com/coder/coder/v2/coderd/database/dbtestutil"
"github.com/coder/coder/v2/codersdk"
"github.com/coder/coder/v2/testutil"
)
// UpdateGoldenFiles indicates golden files should be updated.
@@ -28,7 +26,7 @@ import (
// make update-golden-files
var UpdateGoldenFiles = flag.Bool("update", false, "update .golden files")
var timestampRegex = regexp.MustCompile(`(?i)\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}(.\d+)?Z`)
var timestampRegex = regexp.MustCompile(`(?i)\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}(.\d+)?(Z|[+-]\d+:\d+)`)
type CommandHelpCase struct {
Name string
@@ -50,16 +48,8 @@ func DefaultCases() []CommandHelpCase {
// TestCommandHelp will test the help output of the given commands
// using golden files.
//
//nolint:tparallel,paralleltest
func TestCommandHelp(t *testing.T, getRoot func(t *testing.T) *clibase.Cmd, cases []CommandHelpCase) {
ogColorProfile := lipgloss.ColorProfile()
// ANSI256 escape codes are far easier for humans to parse in a diff,
// but TrueColor is probably more popular with modern terminals.
lipgloss.SetColorProfile(termenv.ANSI)
t.Cleanup(func() {
lipgloss.SetColorProfile(ogColorProfile)
})
t.Parallel()
rootClient, replacements := prepareTestData(t)
root := getRoot(t)
@@ -192,14 +182,14 @@ func prepareTestData(t *testing.T) (*codersdk.Client, map[string]string) {
})
require.NoError(t, err)
version := coderdtest.CreateTemplateVersion(t, rootClient, firstUser.OrganizationID, nil)
version = coderdtest.AwaitTemplateVersionJob(t, rootClient, version.ID)
version = coderdtest.AwaitTemplateVersionJobCompleted(t, rootClient, version.ID)
template := coderdtest.CreateTemplate(t, rootClient, firstUser.OrganizationID, version.ID, func(req *codersdk.CreateTemplateRequest) {
req.Name = "test-template"
})
workspace := coderdtest.CreateWorkspace(t, rootClient, firstUser.OrganizationID, template.ID, func(req *codersdk.CreateWorkspaceRequest) {
req.Name = "test-workspace"
})
workspaceBuild := coderdtest.AwaitWorkspaceBuildJob(t, rootClient, workspace.LatestBuild.ID)
workspaceBuild := coderdtest.AwaitWorkspaceBuildJobCompleted(t, rootClient, workspace.LatestBuild.ID)
replacements := map[string]string{
firstUser.UserID.String(): "[first user ID]",
+1 -1
View File
@@ -3,7 +3,7 @@ package clitest
import (
"testing"
"github.com/coder/coder/cli/clibase"
"github.com/coder/coder/v2/cli/clibase"
)
// HandlersOK asserts that all commands have a handler.
+20 -6
View File
@@ -8,7 +8,7 @@ import (
"github.com/google/uuid"
"golang.org/x/xerrors"
"github.com/coder/coder/codersdk"
"github.com/coder/coder/v2/codersdk"
)
var errAgentShuttingDown = xerrors.New("agent is shutting down")
@@ -80,6 +80,10 @@ func Agent(ctx context.Context, writer io.Writer, agentID uuid.UUID, opts AgentO
if err != nil {
return xerrors.Errorf("fetch: %w", err)
}
logSources := map[uuid.UUID]codersdk.WorkspaceAgentLogSource{}
for _, source := range agent.LogSources {
logSources[source.ID] = source
}
sw := &stageWriter{w: writer}
@@ -123,7 +127,7 @@ func Agent(ctx context.Context, writer io.Writer, agentID uuid.UUID, opts AgentO
return nil
}
stage := "Running workspace agent startup script"
stage := "Running workspace agent startup scripts"
follow := opts.Wait
if !follow {
stage += " (non-blocking)"
@@ -173,7 +177,12 @@ func Agent(ctx context.Context, writer io.Writer, agentID uuid.UUID, opts AgentO
return nil
}
for _, log := range logs {
sw.Log(log.CreatedAt, log.Level, log.Output)
source, hasSource := logSources[log.SourceID]
output := log.Output
if hasSource && source.DisplayName != "" {
output = source.DisplayName + ": " + output
}
sw.Log(log.CreatedAt, log.Level, output)
lastLog = log
}
}
@@ -192,16 +201,19 @@ func Agent(ctx context.Context, writer io.Writer, agentID uuid.UUID, opts AgentO
switch agent.LifecycleState {
case codersdk.WorkspaceAgentLifecycleReady:
sw.Complete(stage, agent.ReadyAt.Sub(*agent.StartedAt))
case codersdk.WorkspaceAgentLifecycleStartTimeout:
sw.Fail(stage, 0)
sw.Log(time.Time{}, codersdk.LogLevelWarn, "Warning: A startup script timed out and your workspace may be incomplete.")
case codersdk.WorkspaceAgentLifecycleStartError:
sw.Fail(stage, agent.ReadyAt.Sub(*agent.StartedAt))
// Use zero time (omitted) to separate these from the startup logs.
sw.Log(time.Time{}, codersdk.LogLevelWarn, "Warning: The startup script exited with an error and your workspace may be incomplete.")
sw.Log(time.Time{}, codersdk.LogLevelWarn, "Warning: A startup script exited with an error and your workspace may be incomplete.")
sw.Log(time.Time{}, codersdk.LogLevelWarn, troubleshootingMessage(agent, "https://coder.com/docs/v2/latest/templates#startup-script-exited-with-an-error"))
default:
switch {
case agent.LifecycleState.Starting():
// Use zero time (omitted) to separate these from the startup logs.
sw.Log(time.Time{}, codersdk.LogLevelWarn, "Notice: The startup script is still running and your workspace may be incomplete.")
sw.Log(time.Time{}, codersdk.LogLevelWarn, "Notice: The startup scripts are still running and your workspace may be incomplete.")
sw.Log(time.Time{}, codersdk.LogLevelWarn, troubleshootingMessage(agent, "https://coder.com/docs/v2/latest/templates#your-workspace-may-be-incomplete"))
// Note: We don't complete or fail the stage here, it's
// intentionally left open to indicate this stage didn't
@@ -225,12 +237,14 @@ func Agent(ctx context.Context, writer io.Writer, agentID uuid.UUID, opts AgentO
sw.Start(stage)
sw.Log(time.Now(), codersdk.LogLevelWarn, "Wait for it to reconnect or restart your workspace.")
sw.Log(time.Now(), codersdk.LogLevelWarn, troubleshootingMessage(agent, "https://coder.com/docs/v2/latest/templates#agent-connection-issues"))
disconnectedAt := *agent.DisconnectedAt
for agent.Status == codersdk.WorkspaceAgentDisconnected {
if agent, err = fetch(); err != nil {
return xerrors.Errorf("fetch: %w", err)
}
}
sw.Complete(stage, agent.LastConnectedAt.Sub(*agent.DisconnectedAt))
sw.Complete(stage, agent.LastConnectedAt.Sub(disconnectedAt))
}
}
}
+58 -25
View File
@@ -14,12 +14,12 @@ import (
"github.com/stretchr/testify/require"
"golang.org/x/xerrors"
"github.com/coder/coder/cli/clibase"
"github.com/coder/coder/cli/clitest"
"github.com/coder/coder/cli/cliui"
"github.com/coder/coder/coderd/util/ptr"
"github.com/coder/coder/codersdk"
"github.com/coder/coder/testutil"
"github.com/coder/coder/v2/cli/clibase"
"github.com/coder/coder/v2/cli/clitest"
"github.com/coder/coder/v2/cli/cliui"
"github.com/coder/coder/v2/coderd/util/ptr"
"github.com/coder/coder/v2/codersdk"
"github.com/coder/coder/v2/testutil"
)
func TestAgent(t *testing.T) {
@@ -52,11 +52,36 @@ func TestAgent(t *testing.T) {
want: []string{
"⧗ Waiting for the workspace agent to connect",
"✔ Waiting for the workspace agent to connect",
"⧗ Running workspace agent startup script (non-blocking)",
"Notice: The startup script is still running and your workspace may be incomplete.",
"⧗ Running workspace agent startup scripts (non-blocking)",
"Notice: The startup scripts are still running and your workspace may be incomplete.",
"For more information and troubleshooting, see",
},
},
{
name: "Start timeout",
opts: cliui.AgentOptions{
FetchInterval: time.Millisecond,
},
iter: []func(context.Context, *codersdk.WorkspaceAgent, chan []codersdk.WorkspaceAgentLog) error{
func(_ context.Context, agent *codersdk.WorkspaceAgent, _ chan []codersdk.WorkspaceAgentLog) error {
agent.Status = codersdk.WorkspaceAgentConnecting
return nil
},
func(_ context.Context, agent *codersdk.WorkspaceAgent, logs chan []codersdk.WorkspaceAgentLog) error {
agent.Status = codersdk.WorkspaceAgentConnected
agent.LifecycleState = codersdk.WorkspaceAgentLifecycleStartTimeout
agent.FirstConnectedAt = ptr.Ref(time.Now())
return nil
},
},
want: []string{
"⧗ Waiting for the workspace agent to connect",
"✔ Waiting for the workspace agent to connect",
"⧗ Running workspace agent startup scripts (non-blocking)",
"✘ Running workspace agent startup scripts (non-blocking)",
"Warning: A startup script timed out and your workspace may be incomplete.",
},
},
{
name: "Initial connection timeout",
opts: cliui.AgentOptions{
@@ -86,8 +111,8 @@ func TestAgent(t *testing.T) {
"The workspace agent is having trouble connecting, wait for it to connect or restart your workspace.",
"For more information and troubleshooting, see",
"✔ Waiting for the workspace agent to connect",
"⧗ Running workspace agent startup script (non-blocking)",
"✔ Running workspace agent startup script (non-blocking)",
"⧗ Running workspace agent startup scripts (non-blocking)",
"✔ Running workspace agent startup scripts (non-blocking)",
},
},
{
@@ -108,6 +133,7 @@ func TestAgent(t *testing.T) {
},
func(_ context.Context, agent *codersdk.WorkspaceAgent, _ chan []codersdk.WorkspaceAgentLog) error {
agent.Status = codersdk.WorkspaceAgentConnected
agent.DisconnectedAt = nil
agent.LastConnectedAt = ptr.Ref(time.Now())
return nil
},
@@ -120,7 +146,7 @@ func TestAgent(t *testing.T) {
},
},
{
name: "Startup script logs",
name: "Startup Logs",
opts: cliui.AgentOptions{
FetchInterval: time.Millisecond,
Wait: true,
@@ -131,10 +157,15 @@ func TestAgent(t *testing.T) {
agent.FirstConnectedAt = ptr.Ref(time.Now())
agent.LifecycleState = codersdk.WorkspaceAgentLifecycleStarting
agent.StartedAt = ptr.Ref(time.Now())
agent.LogSources = []codersdk.WorkspaceAgentLogSource{{
ID: uuid.Nil,
DisplayName: "testing",
}}
logs <- []codersdk.WorkspaceAgentLog{
{
CreatedAt: time.Now(),
Output: "Hello world",
SourceID: uuid.Nil,
},
}
return nil
@@ -152,10 +183,10 @@ func TestAgent(t *testing.T) {
},
},
want: []string{
"⧗ Running workspace agent startup script",
"Hello world",
"⧗ Running workspace agent startup scripts",
"testing: Hello world",
"Bye now",
"✔ Running workspace agent startup script",
"✔ Running workspace agent startup scripts",
},
},
{
@@ -181,10 +212,10 @@ func TestAgent(t *testing.T) {
},
},
want: []string{
"⧗ Running workspace agent startup script",
"⧗ Running workspace agent startup scripts",
"Hello world",
"✘ Running workspace agent startup script",
"Warning: The startup script exited with an error and your workspace may be incomplete.",
"✘ Running workspace agent startup scripts",
"Warning: A startup script exited with an error and your workspace may be incomplete.",
"For more information and troubleshooting, see",
},
},
@@ -229,9 +260,9 @@ func TestAgent(t *testing.T) {
},
},
want: []string{
"⧗ Running workspace agent startup script",
"⧗ Running workspace agent startup scripts",
"Hello world",
"✔ Running workspace agent startup script",
"✔ Running workspace agent startup scripts",
},
wantErr: true,
},
@@ -288,11 +319,10 @@ func TestAgent(t *testing.T) {
var buf bytes.Buffer
agent := codersdk.WorkspaceAgent{
ID: uuid.New(),
Status: codersdk.WorkspaceAgentConnecting,
StartupScriptBehavior: codersdk.WorkspaceAgentStartupScriptBehaviorNonBlocking,
CreatedAt: time.Now(),
LifecycleState: codersdk.WorkspaceAgentLifecycleCreated,
ID: uuid.New(),
Status: codersdk.WorkspaceAgentConnecting,
CreatedAt: time.Now(),
LifecycleState: codersdk.WorkspaceAgentLifecycleCreated,
}
logs := make(chan []codersdk.WorkspaceAgentLog, 1)
@@ -340,7 +370,10 @@ func TestAgent(t *testing.T) {
line := s.Text()
t.Log(line)
if len(tc.want) == 0 {
require.Fail(t, "unexpected line: "+line)
for i := 0; i < 5; i++ {
t.Log(line)
}
require.Fail(t, "unexpected line", line)
}
require.Contains(t, line, tc.want[0])
tc.want = tc.want[1:]
+131 -36
View File
@@ -1,12 +1,15 @@
package cliui
import (
"flag"
"os"
"sync"
"time"
"github.com/charmbracelet/charm/ui/common"
"github.com/charmbracelet/lipgloss"
"github.com/muesli/termenv"
"golang.org/x/xerrors"
"github.com/coder/pretty"
)
var Canceled = xerrors.New("canceled")
@@ -15,55 +18,147 @@ var Canceled = xerrors.New("canceled")
var DefaultStyles Styles
type Styles struct {
Bold,
Checkmark,
Code,
Crossmark,
DateTimeStamp,
Error,
Field,
Keyword,
Paragraph,
Placeholder,
Prompt,
FocusedPrompt,
Fuchsia,
Logo,
Warn,
Wrap lipgloss.Style
Wrap pretty.Style
}
var (
color termenv.Profile
colorOnce sync.Once
)
var (
Green = Color("#04B575")
Red = Color("#ED567A")
Fuchsia = Color("#EE6FF8")
Yellow = Color("#ECFD65")
Blue = Color("#5000ff")
)
// Color returns a color for the given string.
func Color(s string) termenv.Color {
colorOnce.Do(func() {
color = termenv.NewOutput(os.Stdout).ColorProfile()
if flag.Lookup("test.v") != nil {
// Use a consistent colorless profile in tests so that results
// are deterministic.
color = termenv.Ascii
}
})
return color.Color(s)
}
func isTerm() bool {
return color != termenv.Ascii
}
// Bold returns a formatter that renders text in bold
// if the terminal supports it.
func Bold(s string) string {
if !isTerm() {
return s
}
return pretty.Sprint(pretty.Bold(), s)
}
// BoldFmt returns a formatter that renders text in bold
// if the terminal supports it.
func BoldFmt() pretty.Formatter {
if !isTerm() {
return pretty.Style{}
}
return pretty.Bold()
}
// Timestamp formats a timestamp for display.
func Timestamp(t time.Time) string {
return pretty.Sprint(DefaultStyles.DateTimeStamp, t.Format(time.Stamp))
}
// Keyword formats a keyword for display.
func Keyword(s string) string {
return pretty.Sprint(DefaultStyles.Keyword, s)
}
// Placeholder formats a placeholder for display.
func Placeholder(s string) string {
return pretty.Sprint(DefaultStyles.Placeholder, s)
}
// Wrap prevents the text from overflowing the terminal.
func Wrap(s string) string {
return pretty.Sprint(DefaultStyles.Wrap, s)
}
// Code formats code for display.
func Code(s string) string {
return pretty.Sprint(DefaultStyles.Code, s)
}
// Field formats a field for display.
func Field(s string) string {
return pretty.Sprint(DefaultStyles.Field, s)
}
func ifTerm(fmt pretty.Formatter) pretty.Formatter {
if !isTerm() {
return pretty.Nop
}
return fmt
}
func init() {
lipgloss.SetDefaultRenderer(
lipgloss.NewRenderer(os.Stdout, termenv.WithColorCache(true)),
)
// All Styles are set after we change the DefaultRenderer so that the ColorCache
// is in effect, mitigating the severe performance issue seen here:
// https://github.com/coder/coder/issues/7884.
charmStyles := common.DefaultStyles()
// We do not adapt the color based on whether the terminal is light or dark.
// Doing so would require a round-trip between the program and the terminal
// due to the OSC query and response.
DefaultStyles = Styles{
Bold: lipgloss.NewStyle().Bold(true),
Checkmark: charmStyles.Checkmark,
Code: charmStyles.Code,
Crossmark: charmStyles.Error.Copy().SetString("✘"),
DateTimeStamp: charmStyles.LabelDim,
Error: charmStyles.Error,
Field: charmStyles.Code.Copy().Foreground(lipgloss.AdaptiveColor{Light: "#000000", Dark: "#FFFFFF"}),
Keyword: charmStyles.Keyword,
Paragraph: charmStyles.Paragraph,
Placeholder: lipgloss.NewStyle().Foreground(lipgloss.AdaptiveColor{Light: "#585858", Dark: "#4d46b3"}),
Prompt: charmStyles.Prompt.Copy().Foreground(lipgloss.AdaptiveColor{Light: "#9B9B9B", Dark: "#5C5C5C"}),
FocusedPrompt: charmStyles.FocusedPrompt.Copy().Foreground(lipgloss.Color("#651fff")),
Fuchsia: charmStyles.SelectedMenuItem.Copy(),
Logo: charmStyles.Logo.Copy().SetString("Coder"),
Warn: lipgloss.NewStyle().Foreground(
lipgloss.AdaptiveColor{Light: "#04B575", Dark: "#ECFD65"},
),
Wrap: lipgloss.NewStyle().Width(80),
Code: pretty.Style{
ifTerm(pretty.XPad(1, 1)),
pretty.FgColor(Red),
pretty.BgColor(color.Color("#2c2c2c")),
},
DateTimeStamp: pretty.Style{
pretty.FgColor(color.Color("#7571F9")),
},
Error: pretty.Style{
pretty.FgColor(Red),
},
Field: pretty.Style{
pretty.XPad(1, 1),
pretty.FgColor(color.Color("#FFFFFF")),
pretty.BgColor(color.Color("#2b2a2a")),
},
Keyword: pretty.Style{
pretty.FgColor(Green),
},
Placeholder: pretty.Style{
pretty.FgColor(color.Color("#4d46b3")),
},
Prompt: pretty.Style{
pretty.FgColor(color.Color("#5C5C5C")),
pretty.Wrap("> ", ""),
},
Warn: pretty.Style{
pretty.FgColor(Yellow),
},
Wrap: pretty.Style{
pretty.LineWrap(80),
},
}
DefaultStyles.FocusedPrompt = append(
DefaultStyles.Prompt,
pretty.FgColor(Blue),
)
}
// ValidateNotEmpty is a helper function to disallow empty inputs!
@@ -8,15 +8,15 @@ import (
"github.com/briandowns/spinner"
"github.com/coder/coder/codersdk"
"github.com/coder/coder/v2/codersdk"
)
type GitAuthOptions struct {
Fetch func(context.Context) ([]codersdk.TemplateVersionGitAuth, error)
type ExternalAuthOptions struct {
Fetch func(context.Context) ([]codersdk.TemplateVersionExternalAuth, error)
FetchInterval time.Duration
}
func GitAuth(ctx context.Context, writer io.Writer, opts GitAuthOptions) error {
func ExternalAuth(ctx context.Context, writer io.Writer, opts ExternalAuthOptions) error {
if opts.FetchInterval == 0 {
opts.FetchInterval = 500 * time.Millisecond
}
@@ -38,7 +38,7 @@ func GitAuth(ctx context.Context, writer io.Writer, opts GitAuthOptions) error {
return nil
}
_, _ = fmt.Fprintf(writer, "You must authenticate with %s to create a workspace with this template. Visit:\n\n\t%s\n\n", auth.Type.Pretty(), auth.AuthenticateURL)
_, _ = fmt.Fprintf(writer, "You must authenticate with %s to create a workspace with this template. Visit:\n\n\t%s\n\n", auth.DisplayName, auth.AuthenticateURL)
ticker.Reset(opts.FetchInterval)
spin.Start()
@@ -66,7 +66,7 @@ func GitAuth(ctx context.Context, writer io.Writer, opts GitAuthOptions) error {
}
}
spin.Stop()
_, _ = fmt.Fprintf(writer, "Successfully authenticated with %s!\n\n", auth.Type.Pretty())
_, _ = fmt.Fprintf(writer, "Successfully authenticated with %s!\n\n", auth.DisplayName)
}
return nil
}
@@ -8,14 +8,14 @@ import (
"github.com/stretchr/testify/assert"
"github.com/coder/coder/cli/clibase"
"github.com/coder/coder/cli/cliui"
"github.com/coder/coder/codersdk"
"github.com/coder/coder/pty/ptytest"
"github.com/coder/coder/testutil"
"github.com/coder/coder/v2/cli/clibase"
"github.com/coder/coder/v2/cli/cliui"
"github.com/coder/coder/v2/codersdk"
"github.com/coder/coder/v2/pty/ptytest"
"github.com/coder/coder/v2/testutil"
)
func TestGitAuth(t *testing.T) {
func TestExternalAuth(t *testing.T) {
t.Parallel()
ctx, cancel := context.WithTimeout(context.Background(), testutil.WaitShort)
@@ -25,12 +25,13 @@ func TestGitAuth(t *testing.T) {
cmd := &clibase.Cmd{
Handler: func(inv *clibase.Invocation) error {
var fetched atomic.Bool
return cliui.GitAuth(inv.Context(), inv.Stdout, cliui.GitAuthOptions{
Fetch: func(ctx context.Context) ([]codersdk.TemplateVersionGitAuth, error) {
return cliui.ExternalAuth(inv.Context(), inv.Stdout, cliui.ExternalAuthOptions{
Fetch: func(ctx context.Context) ([]codersdk.TemplateVersionExternalAuth, error) {
defer fetched.Store(true)
return []codersdk.TemplateVersionGitAuth{{
return []codersdk.TemplateVersionExternalAuth{{
ID: "github",
Type: codersdk.GitProviderGitHub,
DisplayName: "GitHub",
Type: codersdk.EnhancedExternalAuthProviderGitHub.String(),
Authenticated: fetched.Load(),
AuthenticateURL: "https://example.com/gitauth/github",
}}, nil
+7 -7
View File
@@ -5,12 +5,12 @@ import (
"io"
"strings"
"github.com/charmbracelet/lipgloss"
"github.com/coder/pretty"
)
// cliMessage provides a human-readable message for CLI errors and messages.
type cliMessage struct {
Style lipgloss.Style
Style pretty.Style
Header string
Prefix string
Lines []string
@@ -21,13 +21,13 @@ func (m cliMessage) String() string {
var str strings.Builder
if m.Prefix != "" {
_, _ = str.WriteString(m.Style.Bold(true).Render(m.Prefix))
_, _ = str.WriteString(Bold(m.Prefix))
}
_, _ = str.WriteString(m.Style.Bold(false).Render(m.Header))
pretty.Fprint(&str, m.Style, m.Header)
_, _ = str.WriteString("\r\n")
for _, line := range m.Lines {
_, _ = fmt.Fprintf(&str, " %s %s\r\n", m.Style.Render("|"), line)
_, _ = fmt.Fprintf(&str, " %s %s\r\n", pretty.Sprint(m.Style, "|"), line)
}
return str.String()
}
@@ -35,7 +35,7 @@ func (m cliMessage) String() string {
// Warn writes a log to the writer provided.
func Warn(wtr io.Writer, header string, lines ...string) {
_, _ = fmt.Fprint(wtr, cliMessage{
Style: DefaultStyles.Warn.Copy(),
Style: DefaultStyles.Warn,
Prefix: "WARN: ",
Header: header,
Lines: lines,
@@ -63,7 +63,7 @@ func Infof(wtr io.Writer, fmtStr string, args ...interface{}) {
// Error writes a log to the writer provided.
func Error(wtr io.Writer, header string, lines ...string) {
_, _ = fmt.Fprint(wtr, cliMessage{
Style: DefaultStyles.Error.Copy(),
Style: DefaultStyles.Error,
Prefix: "ERROR: ",
Header: header,
Lines: lines,
+1 -1
View File
@@ -9,7 +9,7 @@ import (
"golang.org/x/xerrors"
"github.com/coder/coder/cli/clibase"
"github.com/coder/coder/v2/cli/clibase"
)
type OutputFormat interface {
+2 -2
View File
@@ -8,8 +8,8 @@ import (
"github.com/stretchr/testify/require"
"github.com/coder/coder/cli/clibase"
"github.com/coder/coder/cli/cliui"
"github.com/coder/coder/v2/cli/clibase"
"github.com/coder/coder/v2/cli/cliui"
)
type format struct {
+11 -7
View File
@@ -5,8 +5,9 @@ import (
"fmt"
"strings"
"github.com/coder/coder/cli/clibase"
"github.com/coder/coder/codersdk"
"github.com/coder/coder/v2/cli/clibase"
"github.com/coder/coder/v2/codersdk"
"github.com/coder/pretty"
)
func RichParameter(inv *clibase.Invocation, templateVersionParameter codersdk.TemplateVersionParameter) (string, error) {
@@ -16,10 +17,10 @@ func RichParameter(inv *clibase.Invocation, templateVersionParameter codersdk.Te
}
if templateVersionParameter.Ephemeral {
label += DefaultStyles.Warn.Render(" (build option)")
label += pretty.Sprint(DefaultStyles.Warn, " (build option)")
}
_, _ = fmt.Fprintln(inv.Stdout, DefaultStyles.Bold.Render(label))
_, _ = fmt.Fprintln(inv.Stdout, Bold(label))
if templateVersionParameter.DescriptionPlaintext != "" {
_, _ = fmt.Fprintln(inv.Stdout, " "+strings.TrimSpace(strings.Join(strings.Split(templateVersionParameter.DescriptionPlaintext, "\n"), "\n "))+"\n")
@@ -45,7 +46,10 @@ func RichParameter(inv *clibase.Invocation, templateVersionParameter codersdk.Te
}
_, _ = fmt.Fprintln(inv.Stdout)
_, _ = fmt.Fprintln(inv.Stdout, " "+DefaultStyles.Prompt.String()+DefaultStyles.Field.Render(strings.Join(values, ", ")))
pretty.Fprintf(
inv.Stdout,
DefaultStyles.Prompt, "%s\n", strings.Join(values, ", "),
)
value = string(v)
}
} else if len(templateVersionParameter.Options) > 0 {
@@ -59,7 +63,7 @@ func RichParameter(inv *clibase.Invocation, templateVersionParameter codersdk.Te
})
if err == nil {
_, _ = fmt.Fprintln(inv.Stdout)
_, _ = fmt.Fprintln(inv.Stdout, " "+DefaultStyles.Prompt.String()+DefaultStyles.Field.Render(richParameterOption.Name))
pretty.Fprintf(inv.Stdout, DefaultStyles.Prompt, "%s\n", richParameterOption.Name)
value = richParameterOption.Value
}
} else {
@@ -70,7 +74,7 @@ func RichParameter(inv *clibase.Invocation, templateVersionParameter codersdk.Te
text += ":"
value, err = Prompt(inv, PromptOptions{
Text: DefaultStyles.Bold.Render(text),
Text: Bold(text),
Validate: func(value string) error {
return validateRichPrompt(value, templateVersionParameter)
},
+13 -9
View File
@@ -13,7 +13,8 @@ import (
"github.com/mattn/go-isatty"
"golang.org/x/xerrors"
"github.com/coder/coder/cli/clibase"
"github.com/coder/coder/v2/cli/clibase"
"github.com/coder/pretty"
)
// PromptOptions supply a set of options to the prompt.
@@ -55,21 +56,24 @@ func Prompt(inv *clibase.Invocation, opts PromptOptions) (string, error) {
}
}
_, _ = fmt.Fprint(inv.Stdout, DefaultStyles.FocusedPrompt.String()+opts.Text+" ")
pretty.Fprintf(inv.Stdout, DefaultStyles.FocusedPrompt, "")
pretty.Fprintf(inv.Stdout, pretty.Nop, "%s ", opts.Text)
if opts.IsConfirm {
if len(opts.Default) == 0 {
opts.Default = ConfirmYes
}
renderedYes := DefaultStyles.Placeholder.Render(ConfirmYes)
renderedNo := DefaultStyles.Placeholder.Render(ConfirmNo)
var (
renderedYes = pretty.Sprint(DefaultStyles.Placeholder, ConfirmYes)
renderedNo = pretty.Sprint(DefaultStyles.Placeholder, ConfirmNo)
)
if opts.Default == ConfirmYes {
renderedYes = DefaultStyles.Bold.Render(ConfirmYes)
renderedYes = Bold(ConfirmYes)
} else {
renderedNo = DefaultStyles.Bold.Render(ConfirmNo)
renderedNo = Bold(ConfirmNo)
}
_, _ = fmt.Fprint(inv.Stdout, DefaultStyles.Placeholder.Render("("+renderedYes+DefaultStyles.Placeholder.Render("/"+renderedNo+DefaultStyles.Placeholder.Render(") "))))
pretty.Fprintf(inv.Stdout, DefaultStyles.Placeholder, "(%s/%s)", renderedYes, renderedNo)
} else if opts.Default != "" {
_, _ = fmt.Fprint(inv.Stdout, DefaultStyles.Placeholder.Render("("+opts.Default+") "))
_, _ = fmt.Fprint(inv.Stdout, pretty.Sprint(DefaultStyles.Placeholder, "("+opts.Default+") "))
}
interrupt := make(chan os.Signal, 1)
@@ -126,7 +130,7 @@ func Prompt(inv *clibase.Invocation, opts PromptOptions) (string, error) {
if opts.Validate != nil {
err := opts.Validate(line)
if err != nil {
_, _ = fmt.Fprintln(inv.Stdout, DefaultStyles.Error.Render(err.Error()))
_, _ = fmt.Fprintln(inv.Stdout, pretty.Sprint(DefaultStyles.Error, err.Error()))
return Prompt(inv, opts)
}
}
+5 -5
View File
@@ -11,11 +11,11 @@ import (
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"github.com/coder/coder/cli/clibase"
"github.com/coder/coder/cli/cliui"
"github.com/coder/coder/pty"
"github.com/coder/coder/pty/ptytest"
"github.com/coder/coder/testutil"
"github.com/coder/coder/v2/cli/clibase"
"github.com/coder/coder/v2/cli/cliui"
"github.com/coder/coder/v2/pty"
"github.com/coder/coder/v2/pty/ptytest"
"github.com/coder/coder/v2/testutil"
)
func TestPrompt(t *testing.T) {
+14 -9
View File
@@ -14,7 +14,8 @@ import (
"github.com/google/uuid"
"golang.org/x/xerrors"
"github.com/coder/coder/codersdk"
"github.com/coder/coder/v2/codersdk"
"github.com/coder/pretty"
)
func WorkspaceBuild(ctx context.Context, writer io.Writer, client *codersdk.Client, build uuid.UUID) error {
@@ -54,7 +55,7 @@ func (err *ProvisionerJobError) Error() string {
}
// ProvisionerJob renders a provisioner job with interactive cancellation.
func ProvisionerJob(ctx context.Context, writer io.Writer, opts ProvisionerJobOptions) error {
func ProvisionerJob(ctx context.Context, wr io.Writer, opts ProvisionerJobOptions) error {
if opts.FetchInterval == 0 {
opts.FetchInterval = time.Second
}
@@ -70,7 +71,7 @@ func ProvisionerJob(ctx context.Context, writer io.Writer, opts ProvisionerJobOp
jobMutex sync.Mutex
)
sw := &stageWriter{w: writer, verbose: opts.Verbose, silentLogs: opts.Silent}
sw := &stageWriter{w: wr, verbose: opts.Verbose, silentLogs: opts.Silent}
printStage := func() {
sw.Start(currentStage)
@@ -127,7 +128,11 @@ func ProvisionerJob(ctx context.Context, writer io.Writer, opts ProvisionerJobOp
return
}
}
_, _ = fmt.Fprintf(writer, DefaultStyles.FocusedPrompt.String()+DefaultStyles.Bold.Render("Gracefully canceling...")+"\n\n")
pretty.Fprintf(
wr,
DefaultStyles.FocusedPrompt.With(BoldFmt()),
"Gracefully canceling...\n\n",
)
err := opts.Cancel()
if err != nil {
errChan <- xerrors.Errorf("cancel: %w", err)
@@ -236,7 +241,7 @@ func (s *stageWriter) Log(createdAt time.Time, level codersdk.LogLevel, line str
w = &s.logBuf
}
render := func(s ...string) string { return strings.Join(s, " ") }
var style pretty.Style
var lines []string
if !createdAt.IsZero() {
@@ -249,14 +254,14 @@ func (s *stageWriter) Log(createdAt time.Time, level codersdk.LogLevel, line str
if !s.verbose {
return
}
render = DefaultStyles.Placeholder.Render
style = DefaultStyles.Placeholder
case codersdk.LogLevelError:
render = DefaultStyles.Error.Render
style = DefaultStyles.Error
case codersdk.LogLevelWarn:
render = DefaultStyles.Warn.Render
style = DefaultStyles.Warn
case codersdk.LogLevelInfo:
}
_, _ = fmt.Fprintf(w, "%s\n", render(lines...))
pretty.Fprintf(w, style, "%s\n", strings.Join(lines, " "))
}
func (s *stageWriter) flushLogs() {
+12 -12
View File
@@ -11,11 +11,11 @@ import (
"github.com/stretchr/testify/assert"
"github.com/coder/coder/cli/clibase"
"github.com/coder/coder/cli/cliui"
"github.com/coder/coder/coderd/database"
"github.com/coder/coder/codersdk"
"github.com/coder/coder/pty/ptytest"
"github.com/coder/coder/v2/cli/clibase"
"github.com/coder/coder/v2/cli/cliui"
"github.com/coder/coder/v2/coderd/database/dbtime"
"github.com/coder/coder/v2/codersdk"
"github.com/coder/coder/v2/pty/ptytest"
)
// This cannot be ran in parallel because it uses a signal.
@@ -29,13 +29,13 @@ func TestProvisionerJob(t *testing.T) {
<-test.Next
test.JobMutex.Lock()
test.Job.Status = codersdk.ProvisionerJobRunning
now := database.Now()
now := dbtime.Now()
test.Job.StartedAt = &now
test.JobMutex.Unlock()
<-test.Next
test.JobMutex.Lock()
test.Job.Status = codersdk.ProvisionerJobSucceeded
now = database.Now()
now = dbtime.Now()
test.Job.CompletedAt = &now
close(test.Logs)
test.JobMutex.Unlock()
@@ -56,17 +56,17 @@ func TestProvisionerJob(t *testing.T) {
<-test.Next
test.JobMutex.Lock()
test.Job.Status = codersdk.ProvisionerJobRunning
now := database.Now()
now := dbtime.Now()
test.Job.StartedAt = &now
test.Logs <- codersdk.ProvisionerJobLog{
CreatedAt: database.Now(),
CreatedAt: dbtime.Now(),
Stage: "Something",
}
test.JobMutex.Unlock()
<-test.Next
test.JobMutex.Lock()
test.Job.Status = codersdk.ProvisionerJobSucceeded
now = database.Now()
now = dbtime.Now()
test.Job.CompletedAt = &now
close(test.Logs)
test.JobMutex.Unlock()
@@ -99,7 +99,7 @@ func TestProvisionerJob(t *testing.T) {
<-test.Next
test.JobMutex.Lock()
test.Job.Status = codersdk.ProvisionerJobCanceled
now := database.Now()
now := dbtime.Now()
test.Job.CompletedAt = &now
close(test.Logs)
test.JobMutex.Unlock()
@@ -123,7 +123,7 @@ type provisionerJobTest struct {
func newProvisionerJob(t *testing.T) provisionerJobTest {
job := &codersdk.ProvisionerJob{
Status: codersdk.ProvisionerJobPending,
CreatedAt: database.Now(),
CreatedAt: dbtime.Now(),
}
jobLock := sync.Mutex{}
logs := make(chan codersdk.ProvisionerJobLog, 1)
+21 -21
View File
@@ -9,9 +9,9 @@ import (
"github.com/jedib0t/go-pretty/v6/table"
"golang.org/x/mod/semver"
"github.com/coder/coder/coderd/database"
"github.com/coder/coder/codersdk"
"github.com/coder/coder/v2/coderd/database/dbtime"
"github.com/coder/coder/v2/codersdk"
"github.com/coder/pretty"
)
type WorkspaceResourcesOptions struct {
@@ -79,7 +79,7 @@ func WorkspaceResources(writer io.Writer, resources []codersdk.WorkspaceResource
// Display a line for the resource.
tableWriter.AppendRow(table.Row{
DefaultStyles.Bold.Render(resourceAddress),
Bold(resourceAddress),
"",
"",
"",
@@ -108,7 +108,7 @@ func WorkspaceResources(writer io.Writer, resources []codersdk.WorkspaceResource
if totalAgents > 1 {
sshCommand += "." + agent.Name
}
sshCommand = DefaultStyles.Code.Render(sshCommand)
sshCommand = pretty.Sprint(DefaultStyles.Code, sshCommand)
row = append(row, sshCommand)
}
tableWriter.AppendRow(row)
@@ -122,32 +122,32 @@ func WorkspaceResources(writer io.Writer, resources []codersdk.WorkspaceResource
func renderAgentStatus(agent codersdk.WorkspaceAgent) string {
switch agent.Status {
case codersdk.WorkspaceAgentConnecting:
since := database.Now().Sub(agent.CreatedAt)
return DefaultStyles.Warn.Render("⦾ connecting") + " " +
DefaultStyles.Placeholder.Render("["+strconv.Itoa(int(since.Seconds()))+"s]")
since := dbtime.Now().Sub(agent.CreatedAt)
return pretty.Sprint(DefaultStyles.Warn, "⦾ connecting") + " " +
pretty.Sprint(DefaultStyles.Placeholder, "["+strconv.Itoa(int(since.Seconds()))+"s]")
case codersdk.WorkspaceAgentDisconnected:
since := database.Now().Sub(*agent.DisconnectedAt)
return DefaultStyles.Error.Render("⦾ disconnected") + " " +
DefaultStyles.Placeholder.Render("["+strconv.Itoa(int(since.Seconds()))+"s]")
since := dbtime.Now().Sub(*agent.DisconnectedAt)
return pretty.Sprint(DefaultStyles.Error, "⦾ disconnected") + " " +
pretty.Sprint(DefaultStyles.Placeholder, "["+strconv.Itoa(int(since.Seconds()))+"s]")
case codersdk.WorkspaceAgentTimeout:
since := database.Now().Sub(agent.CreatedAt)
since := dbtime.Now().Sub(agent.CreatedAt)
return fmt.Sprintf(
"%s %s",
DefaultStyles.Warn.Render("⦾ timeout"),
DefaultStyles.Placeholder.Render("["+strconv.Itoa(int(since.Seconds()))+"s]"),
pretty.Sprint(DefaultStyles.Warn, "⦾ timeout"),
pretty.Sprint(DefaultStyles.Placeholder, "["+strconv.Itoa(int(since.Seconds()))+"s]"),
)
case codersdk.WorkspaceAgentConnected:
return DefaultStyles.Keyword.Render("⦿ connected")
return pretty.Sprint(DefaultStyles.Keyword, "⦿ connected")
default:
return DefaultStyles.Warn.Render("○ unknown")
return pretty.Sprint(DefaultStyles.Warn, "○ unknown")
}
}
func renderAgentHealth(agent codersdk.WorkspaceAgent) string {
if agent.Health.Healthy {
return DefaultStyles.Keyword.Render("✔ healthy")
return pretty.Sprint(DefaultStyles.Keyword, "✔ healthy")
}
return DefaultStyles.Error.Render("✘ " + agent.Health.Reason)
return pretty.Sprint(DefaultStyles.Error, "✘ "+agent.Health.Reason)
}
func renderAgentVersion(agentVersion, serverVersion string) string {
@@ -155,11 +155,11 @@ func renderAgentVersion(agentVersion, serverVersion string) string {
agentVersion = "(unknown)"
}
if !semver.IsValid(serverVersion) || !semver.IsValid(agentVersion) {
return DefaultStyles.Placeholder.Render(agentVersion)
return pretty.Sprint(DefaultStyles.Placeholder, agentVersion)
}
outdated := semver.Compare(agentVersion, serverVersion) < 0
if outdated {
return DefaultStyles.Warn.Render(agentVersion + " (outdated)")
return pretty.Sprint(DefaultStyles.Warn, agentVersion+" (outdated)")
}
return DefaultStyles.Keyword.Render(agentVersion)
return pretty.Sprint(DefaultStyles.Keyword, agentVersion)
}
+1 -1
View File
@@ -44,7 +44,7 @@ func TestRenderAgentVersion(t *testing.T) {
t.Run(testCase.name, func(t *testing.T) {
t.Parallel()
actual := renderAgentVersion(testCase.agentVersion, testCase.serverVersion)
assert.Equal(t, testCase.expected, actual)
assert.Equal(t, testCase.expected, (actual))
})
}
}
+6 -6
View File
@@ -6,10 +6,10 @@ import (
"github.com/stretchr/testify/assert"
"github.com/coder/coder/cli/cliui"
"github.com/coder/coder/coderd/database"
"github.com/coder/coder/codersdk"
"github.com/coder/coder/pty/ptytest"
"github.com/coder/coder/v2/cli/cliui"
"github.com/coder/coder/v2/coderd/database/dbtime"
"github.com/coder/coder/v2/codersdk"
"github.com/coder/coder/v2/pty/ptytest"
)
func TestWorkspaceResources(t *testing.T) {
@@ -44,7 +44,7 @@ func TestWorkspaceResources(t *testing.T) {
t.Run("MultipleStates", func(t *testing.T) {
t.Parallel()
ptty := ptytest.New(t)
disconnected := database.Now().Add(-4 * time.Second)
disconnected := dbtime.Now().Add(-4 * time.Second)
done := make(chan struct{})
go func() {
err := cliui.WorkspaceResources(ptty.Output(), []codersdk.WorkspaceResource{{
@@ -60,7 +60,7 @@ func TestWorkspaceResources(t *testing.T) {
Type: "google_compute_instance",
Name: "dev",
Agents: []codersdk.WorkspaceAgent{{
CreatedAt: database.Now().Add(-10 * time.Second),
CreatedAt: dbtime.Now().Add(-10 * time.Second),
Status: codersdk.WorkspaceAgentConnecting,
LifecycleState: codersdk.WorkspaceAgentLifecycleCreated,
Name: "dev",
+2 -2
View File
@@ -10,8 +10,8 @@ import (
"github.com/AlecAivazis/survey/v2/terminal"
"golang.org/x/xerrors"
"github.com/coder/coder/cli/clibase"
"github.com/coder/coder/codersdk"
"github.com/coder/coder/v2/cli/clibase"
"github.com/coder/coder/v2/codersdk"
)
func init() {

Some files were not shown because too many files have changed in this diff Show More